X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fas3%2Fparser.y;h=5aeee2833286693c3c19e8704b6065db81a7cd1b;hb=afb504ad3b746c1d23cf84db675b20473976300e;hp=9c762b64f5c661abd78108daec07d70c4c95d8be;hpb=88468a6e138b719215705d5b33050dc04b1eb357;p=swftools.git diff --git a/lib/as3/parser.y b/lib/as3/parser.y index 9c762b6..5aeee28 100644 --- a/lib/as3/parser.y +++ b/lib/as3/parser.y @@ -87,6 +87,7 @@ %token KW_SET "set" %token KW_VOID "void" %token KW_STATIC +%token KW_INSTANCEOF "instanceof" %token KW_IMPORT "import" %token KW_RETURN "return" %token KW_TYPEOF "typeof" @@ -254,7 +255,6 @@ typedef struct _classstate { typedef struct _methodstate { /* method data */ memberinfo_t*info; - dict_t*vars; char late_binding; /* code that needs to be executed at the start of a method (like initializing local registers) */ @@ -273,6 +273,8 @@ typedef struct _state { classstate_t*cls; methodstate_t*method; + + dict_t*vars; } state_t; typedef struct _global { @@ -292,7 +294,7 @@ DECLARE_LIST(state); namespace_t m##_ns;\ registry_fill_multiname(&m, &m##_ns, x); -#define MEMBER_MULTINAME(m,f) \ +#define MEMBER_MULTINAME(m,f,n) \ multiname_t m;\ namespace_t m##_ns;\ if(f) { \ @@ -306,7 +308,7 @@ DECLARE_LIST(state); m.type = MULTINAME; \ m.ns =0; \ m.namespace_set = &nopackage_namespace_set; \ - m.name = f->name; \ + m.name = n; \ } /* warning: list length of namespace set is undefined */ @@ -353,6 +355,7 @@ static void new_state() state = s; state->level++; state->has_own_imports = 0; + state->vars = dict_new(); } static void state_has_imports() { @@ -378,10 +381,6 @@ static void old_state() list_free(oldstate->wildcard_imports); dict_destroy(oldstate->imports);oldstate->imports=0; } - if(state->method) - state->method->initcode = - code_append(state->method->initcode, - oldstate->method->initcode); } void initialize_state() { @@ -528,8 +527,9 @@ static void startclass(int flags, char*classname, classinfo_t*extends, classinfo state->cls->abc = abc_class_new(global->file, &classname2, extends2); if(flags&FLAG_FINAL) abc_class_final(state->cls->abc); - if(flags&FLAG_DYNAMIC) abc_class_sealed(state->cls->abc); + if(!(flags&FLAG_DYNAMIC)) abc_class_sealed(state->cls->abc); if(interface) abc_class_interface(state->cls->abc); + abc_class_protectedNS(state->cls->abc, classname); for(mlist=implements;mlist;mlist=mlist->next) { MULTINAME(m, mlist->classinfo); @@ -595,29 +595,33 @@ static void startclass(int flags, char*classname, classinfo_t*extends, classinfo multiname_destroy(extends2); } +static code_t* wrap_function(code_t*c,code_t*initcode, code_t*body) +{ + c = code_append(c, initcode); + c = code_append(c, body); + /* append return if necessary */ + if(!c || c->opcode != OPCODE_RETURNVOID && + c->opcode != OPCODE_RETURNVALUE) { + c = abc_returnvoid(c); + } + return c; +} + static void endclass() { if(state->cls->init) { - if(!state->cls->abc->constructor) { - abc_method_t*m = abc_class_constructor(state->cls->abc, 0); - m->body->code = code_append(m->body->code, state->cls->init); - m->body->code = abc_returnvoid(m->body->code); - } else { - code_t*c = state->cls->abc->constructor->body->code; - c = code_append(state->cls->init, c); - state->cls->abc->constructor->body->code = c; - - } + abc_method_t*m = abc_class_getconstructor(state->cls->abc, 0); + m->body->code = wrap_function(0, state->cls->init, m->body->code); } if(state->cls->static_init) { - if(!state->cls->abc->static_constructor) { - abc_method_t*m = abc_class_staticconstructor(state->cls->abc, 0); - m->body->code = code_append(m->body->code, state->cls->static_init); - m->body->code = abc_returnvoid(m->body->code); - } else { - state->cls->abc->static_constructor->body->code = - code_append(state->cls->static_init, state->cls->abc->static_constructor->body->code); - } + abc_method_t*m = abc_class_getstaticconstructor(state->cls->abc, 0); + m->body->code = wrap_function(0, state->cls->static_init, m->body->code); + } else { + // handy for scope testing + /*code_t*c = 0; + c = abc_pop(c); + c = abc_pop(c); + abc_class_getstaticconstructor(state->cls->abc,0)->body->code = c;*/ } old_state(); @@ -634,7 +638,7 @@ static int find_variable(char*name, classinfo_t**m) while(s) { variable_t*v = 0; if(s->state->method) - v = dict_lookup(s->state->method->vars, name); + v = dict_lookup(s->state->vars, name); if(v) { if(m) { *m = v->type; @@ -654,14 +658,14 @@ static int find_variable_safe(char*name, classinfo_t**m) } static char variable_exists(char*name) { - return dict_lookup(state->method->vars, name)!=0; + return dict_lookup(state->vars, name)!=0; } static int new_variable(char*name, classinfo_t*type) { NEW(variable_t, v); v->index = global->variable_count; v->type = type; - dict_put(state->method->vars, name, v); + dict_put(state->vars, name, v); return global->variable_count++; } #define TEMPVARNAME "__as3_temp__" @@ -669,17 +673,16 @@ static int gettempvar() { int i = find_variable(TEMPVARNAME, 0); if(i<0) { - return new_variable(TEMPVARNAME, 0); - } else { - return i; + i = new_variable(TEMPVARNAME, 0); } + return i; } code_t* killvars(code_t*c) { int t; - for(t=0;tmethod->vars->hashsize;t++) { - dictentry_t*e =state->method->vars->slots[t]; + for(t=0;tvars->hashsize;t++) { + dictentry_t*e =state->vars->slots[t]; while(e) { variable_t*v = (variable_t*)e->data; //do this always, otherwise register types don't match @@ -722,7 +725,7 @@ static memberinfo_t*registerfunction(enum yytokentype getset, int flags, char*na minfo->return_type = return_type; // getslot on a member slot only returns "undefined", so no need // to actually store these - //state->minfo->slot = state->method->a bc->method->trait->slot_id; + //state->minfo->slot = state->method->abc->method->trait->slot_id; } else { int gs = getset==KW_GET?MEMBER_GET:MEMBER_SET; classinfo_t*type=0; @@ -788,13 +791,15 @@ static void startfunction(token_t*ns, int flags, enum yytokentype getset, char*n state->method->has_super = 0; global->variable_count = 0; - state->method->vars = dict_new(); + /* state->vars is initialized by state_new */ if(new_variable((flags&FLAG_STATIC)?"class":"this", state->cls->info)!=0) syntaxerror("Internal error"); param_list_t*p=0; for(p=params->list;p;p=p->next) { new_variable(p->param->name, p->param->type); } + if(state->method->is_constructor) + name = "__as3_constructor__"; state->method->info = registerfunction(getset, flags, name, params, return_type, 0); } @@ -809,8 +814,7 @@ static void endfunction(token_t*ns, int flags, enum yytokentype getset, char*nam multiname_t*type2 = sig2mname(return_type); int slot = 0; if(state->method->is_constructor) { - f = abc_class_constructor(state->cls->abc, type2); - name = "__as3_constructor__"; + f = abc_class_getconstructor(state->cls->abc, type2); } else { if(flags&FLAG_STATIC) f = abc_class_staticmethod(state->cls->abc, type2, &mname); @@ -818,7 +822,8 @@ static void endfunction(token_t*ns, int flags, enum yytokentype getset, char*nam f = abc_class_method(state->cls->abc, type2, &mname); slot = f->trait->slot_id; } - state->method->info->slot = slot; + //flash doesn't seem to allow us to access function slots + //state->method->info->slot = slot; if(getset == KW_GET) f->trait->kind = TRAIT_GETTER; if(getset == KW_SET) f->trait->kind = TRAIT_SETTER; @@ -927,8 +932,12 @@ code_t*converttype(code_t*c, classinfo_t*from, classinfo_t*to) code_t*defaultvalue(code_t*c, classinfo_t*type) { - if(TYPE_IS_INT(type) || TYPE_IS_UINT(type) || TYPE_IS_FLOAT(type)) { + if(TYPE_IS_INT(type)) { c = abc_pushbyte(c, 0); + } else if(TYPE_IS_UINT(type)) { + c = abc_pushuint(c, 0); + } else if(TYPE_IS_FLOAT(type)) { + c = abc_pushnan(c); } else if(TYPE_IS_BOOLEAN(type)) { c = abc_pushfalse(c); } else { @@ -1229,8 +1238,7 @@ MAYBEELSE: "else" CODEBLOCK {$$=$2;} //MAYBEELSE: ';' "else" CODEBLOCK {$$=$3;} IF : "if" '(' {new_state();} EXPRESSION ')' CODEBLOCK MAYBEELSE { - $$ = state->method->initcode;state->method->initcode=0; - + $$ = code_new(); $$ = code_append($$, $4.c); code_t*myjmp,*myif = $$ = abc_iffalse($$, 0); @@ -1238,10 +1246,10 @@ IF : "if" '(' {new_state();} EXPRESSION ')' CODEBLOCK MAYBEELSE { if($7) { myjmp = $$ = abc_jump($$, 0); } - myif->branch = $$ = abc_label($$); + myif->branch = $$ = abc_nop($$); if($7) { $$ = code_append($$, $7); - myjmp->branch = $$ = abc_label($$); + myjmp->branch = $$ = abc_nop($$); } $$ = killvars($$);old_state(); @@ -1252,8 +1260,7 @@ FOR_INIT : VARIABLE_DECLARATION FOR_INIT : VOIDEXPRESSION FOR : "for" '(' {new_state();} FOR_INIT ';' EXPRESSION ';' VOIDEXPRESSION ')' CODEBLOCK { - $$ = state->method->initcode;state->method->initcode=0; - + $$ = code_new(); $$ = code_append($$, $4); code_t*loopstart = $$ = abc_label($$); $$ = code_append($$, $6.c); @@ -1261,7 +1268,7 @@ FOR : "for" '(' {new_state();} FOR_INIT ';' EXPRESSION ';' VOIDEXPRESSION ')' CO $$ = code_append($$, $10); $$ = code_append($$, $8); $$ = abc_jump($$, loopstart); - code_t*out = $$ = abc_label($$); + code_t*out = $$ = abc_nop($$); breakjumpsto($$, out); myif->branch = out; @@ -1269,15 +1276,15 @@ FOR : "for" '(' {new_state();} FOR_INIT ';' EXPRESSION ';' VOIDEXPRESSION ')' CO } WHILE : "while" '(' {new_state();} EXPRESSION ')' CODEBLOCK { - $$ = state->method->initcode;state->method->initcode=0; + $$ = code_new(); code_t*myjmp = $$ = abc_jump($$, 0); code_t*loopstart = $$ = abc_label($$); $$ = code_append($$, $6); - myjmp->branch = $$ = abc_label($$); + myjmp->branch = $$ = abc_nop($$); $$ = code_append($$, $4.c); $$ = abc_iftrue($$, loopstart); - code_t*out = $$ = abc_label($$); + code_t*out = $$ = abc_nop($$); breakjumpsto($$, out); $$ = killvars($$);old_state(); @@ -1498,19 +1505,11 @@ FUNCTION_DECLARATION: MAYBE_MODIFIERS "function" GETSET T_IDENTIFIER '(' MAYBE_P c = abc_pushscope(c); } if(state->method->is_constructor && !state->method->has_super) { - // generate default constructor + // call default constructor c = abc_getlocal_0(c); c = abc_constructsuper(c, 0); } - - c = code_append(c, state->method->initcode); - c = code_append(c, $11); - - /* append return if necessary */ - if(!c || c->opcode != OPCODE_RETURNVOID && - c->opcode != OPCODE_RETURNVALUE) { - c = abc_returnvoid(c); - } + c = wrap_function(c, state->method->initcode, $11); endfunction(0,$1,$3,$4,&$6,$8,c); } @@ -1658,6 +1657,11 @@ FUNCTIONCALL : "super" '(' MAYBE_EXPRESSION_LIST ')' { for(l=$3;l;l=l->next) { $$.c = code_append($$.c, l->typedcode->c);len++; } + /* + this is dependent on the control path, check this somewhere else + if(state->method->has_super) + syntaxerror("constructor may call super() only once"); + */ state->method->has_super = 1; $$.c = abc_constructsuper($$.c, len); $$.c = abc_pushundefined($$.c); @@ -1886,6 +1890,12 @@ E : E "as" E {char use_astype=0; // flash player's astype works differently than } } +E : E "instanceof" E + {$$.c = code_append($1.c, $3.c); + $$.c = abc_instanceof($$.c); + $$.t = TYPE_BOOLEAN; + } + E : E "is" E {$$.c = code_append($1.c, $3.c); $$.c = abc_istypelate($$.c); $$.t = TYPE_BOOLEAN; @@ -2076,7 +2086,7 @@ E : "super" '.' T_IDENTIFIER memberinfo_t*f = registry_findmember(t, $3); namespace_t ns = {flags2access(f->flags), ""}; - MEMBER_MULTINAME(m, f); + MEMBER_MULTINAME(m, f, $3); $$.c = 0; $$.c = abc_getlocal_0($$.c); $$.c = abc_getsuper2($$.c, &m); @@ -2099,7 +2109,7 @@ E : E '.' T_IDENTIFIER if(f && f->slot && !noslot) { $$.c = abc_getslot($$.c, f->slot); } else { - MEMBER_MULTINAME(m, f); + MEMBER_MULTINAME(m, f, $3); $$.c = abc_getproperty2($$.c, &m); } /* determine type */