X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fas3%2Fparser.y;h=1d18b7420796de42cc3da03cd4973b965d38e7cc;hb=f5d494794ee290c1a0f1dc4d4b2156b04c9a5a97;hp=5670793a9ed41a8f35622fe4752e0f5f0b1412e5;hpb=15d3df10f09bd780efa101d0c253db96716eb145;p=swftools.git diff --git a/lib/as3/parser.y b/lib/as3/parser.y index 5670793..1d18b74 100644 --- a/lib/as3/parser.y +++ b/lib/as3/parser.y @@ -356,6 +356,7 @@ typedef struct _state { dict_t*imports; namespace_list_t*active_namespaces; namespace_decl_list_t*new_namespaces; + dict_t*namespace2url; char has_own_imports; char new_vars; // e.g. transition between two functions @@ -363,6 +364,8 @@ typedef struct _state { methodstate_t*method; char*exception_name; + + int switch_var; dict_t*vars; } state_t; @@ -443,6 +446,7 @@ static void new_state() state->vars = dict_new(); state->old = oldstate; state->new_vars = 0; + state->namespace2url = 0; } static void state_has_imports() { @@ -500,6 +504,8 @@ static void old_state() tokenizer_unregister_namespace(nl->namespace_decl->name); nl = nl->next; } + if(leaving->namespace2url) + dict_destroy(leaving->namespace2url); if(as3_pass>1 && leaving->method && leaving->method != state->method && !leaving->method->inner) { free(leaving->method); @@ -649,6 +655,11 @@ static char variable_exists(char*name) } code_t*defaultvalue(code_t*c, classinfo_t*type); +static int alloc_local() +{ + return state->method->variable_count++; +} + static variable_t* new_variable2(const char*name, classinfo_t*type, char init, char maybeslot) { if(maybeslot) { @@ -658,7 +669,7 @@ static variable_t* new_variable2(const char*name, classinfo_t*type, char init, c } NEW(variable_t, v); - v->index = state->method->variable_count++; + v->index = alloc_local(); v->type = type; v->init = init; @@ -837,7 +848,14 @@ static namespace_t modifiers2access(modifiers_t*mod) 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*)dict_lookup(state->namespace2url, mod->ns); + if(!url) { + /* shouldn't happen- the tokenizer only reports something as a namespace + if it was already registered */ + 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"); @@ -1367,8 +1385,6 @@ static void startfunction(modifiers_t*mod, enum yytokentype getset, char*name, 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); @@ -1441,10 +1457,10 @@ static abc_method_t* endfunction(modifiers_t*mod, enum yytokentype getset, char* } 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); @@ -1460,7 +1476,7 @@ static abc_method_t* endfunction(modifiers_t*mod, enum yytokentype getset, char* //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->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; @@ -1934,6 +1950,18 @@ char is_break_or_jump(code_t*c) return 0; } +void register_namespace(const char*name, const char*url) +{ + NEW(namespace_decl_t,n); + n->name = name; + n->url = url; + if(!state->namespace2url) { + state->namespace2url = dict_new(); + } + dict_put(state->namespace2url, name, url); + list_append(state->new_namespaces, n); + tokenizer_register_namespace(name); +} #define IS_FINALLY_TARGET(op) \ ((op) == OPCODE___CONTINUE__ || \ @@ -2376,7 +2404,7 @@ CASE_LIST: CASE {$$=$1;} CASE_LIST: CASE_LIST CASE {$$=code_append($$,$2);} CASE: "case" E ':' MAYBECODE { - $$ = abc_dup(0); + $$ = abc_getlocal(0, state->switch_var); $$ = code_append($$, $2.c); code_t*j = $$ = abc_ifne($$, 0); $$ = code_append($$, $4); @@ -2389,10 +2417,12 @@ CASE: "case" E ':' MAYBECODE { DEFAULT: "default" ':' MAYBECODE { $$ = $3; } -SWITCH : T_SWITCH '(' {PASS12 new_state();} E ')' '{' MAYBE_CASE_LIST '}' { +SWITCH : T_SWITCH '(' {PASS12 new_state();state->switch_var=alloc_local();} E ')' '{' MAYBE_CASE_LIST '}' { $$=$4.c; + $$ = abc_setlocal($$, state->switch_var); $$ = code_append($$, $7); - code_t*out = $$ = abc_pop($$); + + code_t*out = $$ = abc_kill($$, state->switch_var); breakjumpsto($$, $1, out); code_t*c = $$,*lastblock=0; @@ -2546,9 +2576,7 @@ THROW : "throw" %prec prec_none { WITH_HEAD : "with" '(' EXPRESSION ')' { new_state(); if(state->method->has_exceptions) { - char var[32]; - sprintf(var, "#with#_%d", as3_tokencount); - int v = new_variable(var,$3.t,0,0); + int v = alloc_local(); state->method->scope_code = abc_getlocal(state->method->scope_code, v); state->method->scope_code = abc_pushwith(state->method->scope_code); $$.number = v; @@ -2574,6 +2602,7 @@ WITH : WITH_HEAD CODEBLOCK { 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);} @@ -2904,7 +2933,7 @@ INNERFUNCTION: "function" MAYBE_IDENTIFIER '(' MAYBE_PARAM_LIST ')' MAYBETYPE /* ------------- package + class ids --------------- */ -CLASS: T_IDENTIFIER { +CLASS: X_IDENTIFIER { PASS1 NEW(unresolvedinfo_t,c); memset(c, 0, sizeof(*c)); c->kind = INFOTYPE_UNRESOLVED; @@ -2923,7 +2952,7 @@ CLASS: T_IDENTIFIER { $$ = (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; @@ -3793,7 +3822,7 @@ NAMESPACE_ID : "namespace" T_IDENTIFIER { PASS12 NEW(namespace_decl_t,n); n->name = $2; - n->url = 0; + n->url = $2; $$=n; } NAMESPACE_ID : "namespace" T_IDENTIFIER '=' T_IDENTIFIER { @@ -3812,20 +3841,23 @@ NAMESPACE_ID : "namespace" T_IDENTIFIER '=' T_STRING { } NAMESPACE_DECLARATION : MAYBE_MODIFIERS NAMESPACE_ID { PASS12 - list_append(state->new_namespaces, $2); - tokenizer_register_namespace($2->name); + register_namespace($2->name, $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); + char*url = 0; + register_namespace($3->name, url); $$=0; }