import_list_t*wildcard_imports;
dict_t*import_toplevel_packages;
dict_t*imports;
- namespace_list_t*active_namespaces;
- namespace_decl_list_t*new_namespaces;
+
+ namespace_list_t*active_namespace_urls;
+
char has_own_imports;
char new_vars; // e.g. transition between two functions
state = s;
state->level++;
state->has_own_imports = 0;
- state->new_namespaces = 0;
state->vars = dict_new();
state->old = oldstate;
state->new_vars = 0;
+
+ trie_remember(active_namespaces);
+
+ if(oldstate)
+ state->active_namespace_urls = list_clone(oldstate->active_namespace_urls);
}
static void state_has_imports()
{
dict_destroy(state->vars);state->vars=0;
}
+ list_free(state->active_namespace_urls)
+ state->active_namespace_urls = 0;
+
free(state);
}
static void old_state()
{
+ trie_rollback(active_namespaces);
+
if(!state || !state->old)
syntaxerror("invalid nesting");
state_t*leaving = state;
state = state->old;
- namespace_decl_list_t*nl=leaving->new_namespaces;
- while(nl) {
- tokenizer_unregister_namespace(nl->namespace_decl->name);
- nl = nl->next;
- }
-
if(as3_pass>1 && leaving->method && leaving->method != state->method && !leaving->method->inner) {
free(leaving->method);
leaving->method=0;
free(leaving->cls);
leaving->cls=0;
}
-
+
state_destroy(leaving);
}
if(state) {
syntaxerror("invalid call to initialize_file during parsing of another file");
}
+
+ active_namespaces = trie_new();
+
new_state();
state->package = internal_filename_package = strdup(filename);
if(mod->flags&(FLAG_PRIVATE|FLAG_PROTECTED|FLAG_PACKAGEINTERNAL))
syntaxerror("invalid combination of access levels and namespaces");
ns.access = ACCESS_NAMESPACE;
- ns.name = mod->ns;
+ state_t*s = state;
+ const char*url = (const char*)trie_lookup(active_namespaces, mod->ns);
+ if(!url) {
+ /* shouldn't happen- the tokenizer only reports something as a namespace
+ if it was already registered */
+ trie_dump(active_namespaces);
+ syntaxerror("unknown namespace: %s", mod->ns);
+ }
+ ns.name = url;
} else if(mod->flags&FLAG_PUBLIC) {
if(mod->flags&(FLAG_PRIVATE|FLAG_PROTECTED|FLAG_PACKAGEINTERNAL))
syntaxerror("invalid combination of access levels");
}
static slotinfo_t* find_class(const char*name);
+static memberinfo_t* findmember_nsset(classinfo_t*cls, const char*name, char recurse)
+{
+ return registry_findmember_nsset(cls, state->active_namespace_urls, name, recurse);
+}
+
+void add_active_url(const char*url)
+{
+ NEW(namespace_t,n);
+ n->name = url;
+ list_append(state->active_namespace_urls, n);
+}
+
static void function_initvars(methodstate_t*m, params_t*params, int flags, char var0)
{
if(var0) {
static void check_constant_against_type(classinfo_t*t, constant_t*c)
{
+ return;
#define xassert(b) if(!(b)) syntaxerror("Invalid default value %s for type '%s'", constant_tostring(c), t->name)
if(TYPE_IS_NUMBER(t)) {
xassert(c->type == CONSTANT_FLOAT
static abc_method_t* endfunction(modifiers_t*mod, enum yytokentype getset, char*name,
params_t*params, classinfo_t*return_type, code_t*body)
{
- int flags = mod?mod->flags:0;
-
if(as3_pass==1) {
// store inner methods in variables
function_initvars(state->method, 0, 0, 0);
} else if(state->method->is_constructor) {
f = abc_class_getconstructor(state->cls->abc, type2);
} else if(!state->method->is_global) {
- namespace_t mname_ns = {state->method->info->access, ""};
+ namespace_t mname_ns = modifiers2access(mod);
multiname_t mname = {QNAME, &mname_ns, 0, name};
- if(flags&FLAG_STATIC)
+ if(mod->flags&FLAG_STATIC)
f = abc_class_staticmethod(state->cls->abc, type2, &mname);
else
f = abc_class_method(state->cls->abc, type2, &mname);
//flash doesn't seem to allow us to access function slots
//state->method->info->slot = slot;
- if(flags&FLAG_OVERRIDE) f->trait->attributes |= TRAIT_ATTR_OVERRIDE;
+ if(mod && mod->flags&FLAG_OVERRIDE) f->trait->attributes |= TRAIT_ATTR_OVERRIDE;
if(getset == KW_GET) f->trait->kind = TRAIT_GETTER;
if(getset == KW_SET) f->trait->kind = TRAIT_SETTER;
if(params->varargs) f->flags |= METHOD_NEED_REST;
return 0;
}
-
#define IS_FINALLY_TARGET(op) \
((op) == OPCODE___CONTINUE__ || \
(op) == OPCODE___BREAK__ || \
X_IDENTIFIER: T_IDENTIFIER
| "package" {PASS12 $$="package";}
+ | T_NAMESPACE {PASS12 $$=$1;}
PACKAGE: PACKAGE '.' X_IDENTIFIER {PASS12 $$ = concat3($1,".",$3);free($1);$1=0;}
PACKAGE: X_IDENTIFIER {PASS12 $$=strdup($1);}
$$.ns=$1.ns?$1.ns:$2.ns;
}
-
MODIFIER : KW_PUBLIC {PASS12 $$.flags=FLAG_PUBLIC;$$.ns=0;}
| KW_PRIVATE {PASS12 $$.flags=FLAG_PRIVATE;$$.ns=0;}
| KW_PROTECTED {PASS12 $$.flags=FLAG_PROTECTED;$$.ns=0;}
/* ------------- package + class ids --------------- */
-CLASS: T_IDENTIFIER {
+CLASS: X_IDENTIFIER {
PASS1 NEW(unresolvedinfo_t,c);
memset(c, 0, sizeof(*c));
c->kind = INFOTYPE_UNRESOLVED;
c->nsset = get_current_imports();
/* make the compiler look for this class in the current directory,
just in case: */
- as3_schedule_class_noerror(state->package, $1);
+ //as3_schedule_class_noerror(state->package, $1);
}
$$ = (classinfo_t*)c;
PASS2
$$ = (classinfo_t*)s;
}
-PACKAGEANDCLASS : PACKAGE '.' T_IDENTIFIER {
+PACKAGEANDCLASS : PACKAGE '.' X_IDENTIFIER {
PASS1 NEW(unresolvedinfo_t,c);
memset(c, 0, sizeof(*c));
c->kind = INFOTYPE_UNRESOLVED;
classinfo_t*t = state->cls->info->superclass;
if(!t) t = TYPE_OBJECT;
- memberinfo_t*f = registry_findmember_nsset(t, state->active_namespaces, $3, 1);
+ memberinfo_t*f = findmember_nsset(t, $3, 1);
MEMBER_MULTINAME(m, f, $3);
$$.c = 0;
if(t->subtype==INFOTYPE_UNRESOLVED) {
syntaxerror("syntaxerror: trying to resolve property '%s' on incomplete object '%s'", $3, t->name);
}
- memberinfo_t*f = registry_findmember_nsset(t, state->active_namespaces, $3, 1);
+ memberinfo_t*f = findmember_nsset(t, $3, 1);
char noslot = 0;
if(f && !is_static != !(f->flags&FLAG_STATIC))
noslot=1;
} else if($1.c && $1.c->opcode == OPCODE___PUSHPACKAGE__) {
string_t*package = $1.c->data[0];
char*package2 = concat3(package->str, ".", $3);
- if(dict_contains(state->import_toplevel_packages, package2)) {
+
+ slotinfo_t*a = registry_find(package->str, $3);
+ if(a) {
+ $$ = push_class(a);
+ } else if(dict_contains(state->import_toplevel_packages, package2) ||
+ registry_ispackage(package2)) {
$$.c = $1.c;
$$.c->data[0] = string_new4(package2);
$$.t = 0;
} else {
- slotinfo_t*a = registry_find(package->str, $3);
- if(!a)
- syntaxerror("couldn't resolve %s", package2);
- $$ = push_class(a);
+ syntaxerror("couldn't resolve %s", package2);
}
} else {
/* when resolving a property on an unknown type, we do know the
unknown_variable($1);
}
- /* let the compiler know that it might check the current directory/package
+ /* let the compiler know that it might want to check the current directory/package
for this identifier- maybe there's a file $1.as defining $1. */
- as3_schedule_class_noerror(state->package, $1);
+ //as3_schedule_class_noerror(state->package, $1);
PASS2
$$.t = 0;
int i_am_static = (state->method && state->method->info)?(state->method->info->flags&FLAG_STATIC):FLAG_STATIC;
/* look at current class' members */
- if(state->cls && (f = registry_findmember_nsset(state->cls->info, state->active_namespaces, $1, 1)) &&
+ if(state->cls && (f = findmember_nsset(state->cls->info, $1, 1)) &&
(f->flags&FLAG_STATIC) >= i_am_static) {
// $1 is a function in this class
int var_is_static = (f->flags&FLAG_STATIC);
}
/* look through package prefixes */
- if(dict_contains(state->import_toplevel_packages, $1)) {
+ if(dict_contains(state->import_toplevel_packages, $1) ||
+ registry_ispackage($1)) {
$$.c = abc___pushpackage__($$.c, $1);
$$.t = 0;
break;
PASS12
NEW(namespace_decl_t,n);
n->name = $2;
- n->url = 0;
+ n->url = $2;
$$=n;
}
NAMESPACE_ID : "namespace" T_IDENTIFIER '=' T_IDENTIFIER {
}
NAMESPACE_DECLARATION : MAYBE_MODIFIERS NAMESPACE_ID {
PASS12
- list_append(state->new_namespaces, $2);
- tokenizer_register_namespace($2->name);
+ trie_put(active_namespaces, $2->name, (void*)$2->url);
+
+ namespace_t access = modifiers2access(&$1);
+ varinfo_t* var = varinfo_register_global(access.access, state->package, $2->name);
+ var->type = TYPE_NAMESPACE;
+ namespace_t ns;
+ ns.access = ACCESS_NAMESPACE;
+ ns.name = $2->url;
+ var->value = constant_new_namespace(&ns);
+
$$=0;
}
USE_NAMESPACE : "use" "namespace" CLASS_SPEC {
- PASS12
- NEW(namespace_decl_t,n);
- n->name = $3->name;
- n->url = 0;
- /* FIXME: for pass2, we should now try to figure out what the URL of
- this thing is */
- list_append(state->new_namespaces, n);
- tokenizer_register_namespace($3->name);
+
+ const char*url = $3->name;
+ varinfo_t*s = (varinfo_t*)$3;
+ if(!s || s->kind != INFOTYPE_SLOT)
+ syntaxerror("%s.%s is not a public namespace (%d)", $3->package, $3->name, s?s->kind:-1);
+ if(!s->value || !NS_TYPE(s->value->type))
+ syntaxerror("%s.%s is not a namespace", $3->package, $3->name);
+ url = s->value->ns->name;
+
+ trie_put(active_namespaces, $3->name, (void*)url);
+ add_active_url(url);
$$=0;
}