X-Git-Url: http://git.asbjorn.it/?a=blobdiff_plain;f=lib%2Fas3%2Fparser.y;h=1364b0e380d8b8ffc3f17b8956e5ac29fccc7a5a;hb=0fb5f216b69c3385216d4038a7caffaecc0100b9;hp=5aeee2833286693c3c19e8704b6065db81a7cd1b;hpb=afb504ad3b746c1d23cf84db675b20473976300e;p=swftools.git diff --git a/lib/as3/parser.y b/lib/as3/parser.y index 5aeee28..1364b0e 100644 --- a/lib/as3/parser.y +++ b/lib/as3/parser.y @@ -81,6 +81,7 @@ %token KW_NATIVE %token KW_FUNCTION "function" %token KW_UNDEFINED "undefined" +%token KW_CONTINUE "continue" %token KW_FOR "for" %token KW_CLASS "class" %token KW_CONST "const" @@ -114,6 +115,7 @@ %token KW_BREAK "break" %token KW_IS "is" %token KW_AS "as" +%token KW_DO "do" %token T_EQEQ "==" %token T_EQEQEQ "===" @@ -140,7 +142,7 @@ %token T_USHR ">>>" %token T_SHR ">>" -%type X_IDENTIFIER PACKAGE +%type X_IDENTIFIER PACKAGE MAYBELABEL %type VARCONST %type CODE %type CODEPIECE @@ -156,7 +158,7 @@ %type MAYBEEXPRESSION %type E DELETE %type CONSTANT -%type FOR IF WHILE MAYBEELSE BREAK RETURN +%type FOR IF WHILE DO_WHILE MAYBEELSE BREAK RETURN CONTINUE %type USE_NAMESPACE %type FOR_INIT %type IMPORT @@ -250,6 +252,7 @@ typedef struct _classstate { abc_class_t*abc; code_t*init; code_t*static_init; + char has_constructor; } classstate_t; typedef struct _methodstate { @@ -528,7 +531,11 @@ 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(interface) abc_class_interface(state->cls->abc); + if(interface) { + state->cls->info->flags |= CLASS_INTERFACE; + abc_class_interface(state->cls->abc); + } + abc_class_protectedNS(state->cls->abc, classname); for(mlist=implements;mlist;mlist=mlist->next) { @@ -609,6 +616,13 @@ static code_t* wrap_function(code_t*c,code_t*initcode, code_t*body) static void endclass() { + if(!state->cls->has_constructor && !(state->cls->info->flags&CLASS_INTERFACE)) { + code_t*c = 0; + c = abc_getlocal_0(c); + c = abc_constructsuper(c, 0); + state->cls->init = code_append(state->cls->init, c); + } + if(state->cls->init) { abc_method_t*m = abc_class_getconstructor(state->cls->abc, 0); m->body->code = wrap_function(0, state->cls->init, m->body->code); @@ -695,6 +709,21 @@ code_t* killvars(code_t*c) return c; } +void check_code_for_break(code_t*c) +{ + while(c) { + if(c->opcode == OPCODE___BREAK__) { + char*name = string_cstr(c->data[0]); + syntaxerror("Unresolved \"break %s\"", name); + } + if(c->opcode == OPCODE___CONTINUE__) { + char*name = string_cstr(c->data[0]); + syntaxerror("Unresolved \"continue %s\"", name); + } + c=c->prev; + } +} + static void check_constant_against_type(classinfo_t*t, constant_t*c) { @@ -789,6 +818,8 @@ static void startfunction(token_t*ns, int flags, enum yytokentype getset, char*n state->method->initcode = 0; state->method->is_constructor = !strcmp(state->cls->info->name,name); state->method->has_super = 0; + + state->cls->has_constructor |= state->method->is_constructor; global->variable_count = 0; @@ -844,7 +875,13 @@ static void endfunction(token_t*ns, int flags, enum yytokentype getset, char*nam syntaxerror("non-optional parameter not allowed after optional parameters"); } } - f->body->code = body; + check_code_for_break(body); + + if(f->body) + f->body->code = body; + else //interface + if(body) + syntaxerror("interface methods can't have a method body"); old_state(); } @@ -856,16 +893,30 @@ char is_subtype_of(classinfo_t*type, classinfo_t*supertype) return 1; // FIXME } -void breakjumpsto(code_t*c, code_t*jump) +void breakjumpsto(code_t*c, char*name, code_t*jump) { - while(c->prev) - c=c->prev; while(c) { if(c->opcode == OPCODE___BREAK__) { - c->opcode = OPCODE_JUMP; - c->branch = jump; + string_t*name2 = c->data[0]; + if(!name2->len || !strncmp(name2->str, name, name2->len)) { + c->opcode = OPCODE_JUMP; + c->branch = jump; + } } - c = c->next; + c=c->prev; + } +} +void continuejumpsto(code_t*c, char*name, code_t*jump) +{ + while(c) { + if(c->opcode == OPCODE___CONTINUE__) { + string_t*name2 = c->data[0]; + if(!name2->len || !strncmp(name2->str, name, name2->len)) { + c->opcode = OPCODE_JUMP; + c->branch = jump; + } + } + c = c->prev; } } @@ -1149,8 +1200,12 @@ PROGRAM: MAYBECODE MAYBECODE: CODE {$$=$1;/*TODO: do something with this code if we're not in a function*/} MAYBECODE: {$$=code_new();} -CODE: CODE CODEPIECE {$$=code_append($1,$2);} -CODE: CODEPIECE {$$=$1;} +CODE: CODE CODEPIECE { + $$=code_append($1,$2); +} +CODE: CODEPIECE { + $$=$1; +} CODEPIECE: PACKAGE_DECLARATION {$$=code_new();/*enters a scope*/} CODEPIECE: CLASS_DECLARATION {$$=code_new();/*enters a scope*/} @@ -1162,7 +1217,9 @@ CODEPIECE: VARIABLE_DECLARATION {$$=$1} CODEPIECE: VOIDEXPRESSION {$$=$1} CODEPIECE: FOR {$$=$1} CODEPIECE: WHILE {$$=$1} +CODEPIECE: DO_WHILE {$$=$1} CODEPIECE: BREAK {$$=$1} +CODEPIECE: CONTINUE {$$=$1} CODEPIECE: RETURN {$$=$1} CODEPIECE: IF {$$=$1} CODEPIECE: NAMESPACE_DECLARATION {/*TODO*/$$=code_new();} @@ -1255,43 +1312,73 @@ IF : "if" '(' {new_state();} EXPRESSION ')' CODEBLOCK MAYBEELSE { $$ = killvars($$);old_state(); } +MAYBELABEL : T_IDENTIFIER ':' {$$=$1;} +MAYBELABEL : {$$="";} + FOR_INIT : {$$=code_new();} FOR_INIT : VARIABLE_DECLARATION FOR_INIT : VOIDEXPRESSION -FOR : "for" '(' {new_state();} FOR_INIT ';' EXPRESSION ';' VOIDEXPRESSION ')' CODEBLOCK { +FOR : MAYBELABEL "for" '(' {new_state();} FOR_INIT ';' EXPRESSION ';' VOIDEXPRESSION ')' CODEBLOCK { $$ = code_new(); - $$ = code_append($$, $4); + $$ = code_append($$, $5); code_t*loopstart = $$ = abc_label($$); - $$ = code_append($$, $6.c); + $$ = code_append($$, $7.c); code_t*myif = $$ = abc_iffalse($$, 0); - $$ = code_append($$, $10); - $$ = code_append($$, $8); + $$ = code_append($$, $11); + code_t*cont = $$ = abc_nop($$); + $$ = code_append($$, $9); $$ = abc_jump($$, loopstart); code_t*out = $$ = abc_nop($$); - breakjumpsto($$, out); + breakjumpsto($$, $1, out); + continuejumpsto($$, $1, cont); myif->branch = out; $$ = killvars($$);old_state(); } -WHILE : "while" '(' {new_state();} EXPRESSION ')' CODEBLOCK { +WHILE : MAYBELABEL "while" '(' {new_state();} EXPRESSION ')' CODEBLOCK { $$ = code_new(); code_t*myjmp = $$ = abc_jump($$, 0); code_t*loopstart = $$ = abc_label($$); - $$ = code_append($$, $6); + $$ = code_append($$, $7); myjmp->branch = $$ = abc_nop($$); - $$ = code_append($$, $4.c); + $$ = code_append($$, $5.c); $$ = abc_iftrue($$, loopstart); code_t*out = $$ = abc_nop($$); - breakjumpsto($$, out); + breakjumpsto($$, $1, out); + continuejumpsto($$, $1, loopstart); - $$ = killvars($$);old_state(); + $$ = killvars($$); + old_state(); } -BREAK : "break" { - $$ = abc___break__(0); +DO_WHILE : MAYBELABEL "do" {new_state();} CODEBLOCK "while" '(' EXPRESSION ')' { + $$ = code_new(); + code_t*loopstart = $$ = abc_label($$); + $$ = code_append($$, $4); + code_t*cont = $$ = abc_nop($$); + $$ = code_append($$, $7.c); + $$ = abc_iftrue($$, loopstart); + code_t*out = $$ = abc_nop($$); + breakjumpsto($$, $1, out); + continuejumpsto($$, $1, cont); + $$ = killvars($$); + old_state(); +} + +BREAK : "break" %prec prec_none { + $$ = abc___break__(0, ""); +} +BREAK : "break" T_IDENTIFIER { + $$ = abc___break__(0, $2); +} +CONTINUE : "continue" %prec prec_none { + $$ = abc___continue__(0, ""); +} +CONTINUE : "continue" T_IDENTIFIER { + $$ = abc___continue__(0, $2); } /* ------------ packages and imports ---------------- */ @@ -1617,8 +1704,7 @@ FUNCTIONCALL : E '(' MAYBE_EXPRESSION_LIST ')' { int slot = (int)(ptroff_t)$$.c->data[0]; trait_t*t = abc_class_find_slotid(state->cls->abc,slot);//FIXME if(t->kind!=TRAIT_METHOD) { - //flash allows to assign closures to members. - //syntaxerror("not a function"); + //ok: flash allows to assign closures to members. } name = t->name; $$.c = code_cutlast($$.c); @@ -1939,6 +2025,17 @@ E : E '[' E ']' { $$.t = 0; // array elements have unknown type } +E : '[' MAYBE_EXPRESSION_LIST ']' { + $$.c = code_new(); + typedcode_list_t*l = 0; + int len = 0; + for(l=$2;l;l=l->next) { + $$.c = code_append($$.c, l->typedcode->c);len++; + } + $$.c = abc_newarray($$.c, len); + $$.t = registry_getarrayclass(); +} + E : E "*=" E { code_t*c = $3.c; if(BOTH_INT($1,$3)) { @@ -2172,14 +2269,21 @@ VAR_READ : T_IDENTIFIER { /* look at classes in the current package and imported classes */ } else if((a = find_class($1))) { - if(a->slot) { - $$.c = abc_getglobalscope($$.c); - $$.c = abc_getslot($$.c, a->slot); - } else { + if(a->flags & FLAG_METHOD) { MULTINAME(m, a); - $$.c = abc_getlex2($$.c, &m); + $$.c = abc_findpropstrict2($$.c, &m); + $$.c = abc_getproperty2($$.c, &m); + $$.t = TYPE_FUNCTION(a->function); + } else { + if(a->slot) { + $$.c = abc_getglobalscope($$.c); + $$.c = abc_getslot($$.c, a->slot); + } else { + MULTINAME(m, a); + $$.c = abc_getlex2($$.c, &m); + } + $$.t = TYPE_CLASS(a); } - $$.t = TYPE_CLASS(a); /* unknown object, let the avm2 resolve it */ } else {