X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fas3%2Fparser.y;h=6f7757032ac86e90ed306dda0d37fe086887538e;hb=72834fe606590dc25a7965bb6989a287ae4d8f40;hp=8da6dd0a67e1796a73da9c60d5249816b0d30a51;hpb=1ae7fbe0e9e5eb492ae3c1fd3b26267aa6b34fcb;p=swftools.git diff --git a/lib/as3/parser.y b/lib/as3/parser.y index 8da6dd0..6f77570 100644 --- a/lib/as3/parser.y +++ b/lib/as3/parser.y @@ -235,18 +235,21 @@ extern int a3_lex(); %left plusplus_prefix minusminus_prefix '~' '!' "void" "delete" "typeof" //FIXME: *unary* + - should be here, too %left "--" "++" %nonassoc below_curly -%left '[' ']' '{' "new" '.' ".." "::" + +%left '(' +%left new2 +%left '[' ']' "new" '{' '.' ".." "::" + %nonassoc T_IDENTIFIER %left above_identifier %left below_else %nonassoc "else" -%left '(' // needed for "return" precedence: %nonassoc T_STRING T_REGEXP %nonassoc T_INT T_UINT T_BYTE T_SHORT T_FLOAT %nonassoc "false" "true" "null" "undefined" "super" "function" -%nonassoc above_function +%left above_function @@ -456,7 +459,7 @@ static void old_state() void initialize_file(char*filename) { new_state(); - state->package = filename; + state->package = strdup(filename); state->method = rfx_calloc(sizeof(methodstate_t)); state->method->variable_count = 1; @@ -467,6 +470,7 @@ void finish_file() if(!state || state->level!=1) { syntaxerror("unexpected end of file in pass %d", as3_pass); } + free(state->package);state->package=0; state_destroy(state);state=0; } @@ -625,6 +629,44 @@ code_t* var_block(code_t*body) return c; } +#define parserassert(b) {if(!(b)) parsererror(__FILE__, __LINE__,__func__);} + +static void parsererror(const char*file, int line, const char*f) +{ + syntaxerror("internal error in %s, %s:%d", f, file, line); +} + + +code_t* method_header() +{ + code_t*c = 0; + if(state->method->late_binding && !state->method->inner) { + c = abc_getlocal_0(c); + c = abc_pushscope(c); + } + /*if(state->method->innerfunctions) { + c = abc_newactivation(c); + c = abc_pushscope(c); + }*/ + if(state->method->is_constructor && !state->method->has_super) { + // call default constructor + c = abc_getlocal_0(c); + c = abc_constructsuper(c, 0); + } + methodstate_list_t*l = state->method->innerfunctions; + while(l) { + parserassert(l->methodstate->abc); + c = abc_newfunction(c, l->methodstate->abc); + c = abc_setlocal(c, l->methodstate->var_index); + free(l->methodstate);l->methodstate=0; + l = l->next; + } + list_free(state->method->innerfunctions); + state->method->innerfunctions = 0; + return c; +} + + static code_t* wrap_function(code_t*c,code_t*header, code_t*body) { c = code_append(c, header); @@ -654,14 +696,6 @@ static void endpackage() old_state(); } -#define _TRACE_ {printf("vfw: %s: %d (%s)\n",__FILE__,__LINE__,__func__);fflush(stdout);} -#define parserassert(b) {if(!(b)) parsererror(__FILE__, __LINE__,__func__);} - -static void parsererror(const char*file, int line, const char*f) -{ - syntaxerror("internal error in %s, %s:%d", f, file, line); -} - char*as3_globalclass=0; static void startclass(int flags, char*classname, classinfo_t*extends, classinfo_list_t*implements, char interface) @@ -2135,6 +2169,7 @@ IDECLARATION : MAYBE_MODIFIERS "function" GETSET T_IDENTIFIER '(' MAYBE_PARAM_LI } startfunction(0,$1,$3,$4,&$6,$8); endfunction(0,$1,$3,$4,&$6,$8, 0); + list_deep_free($6.list); } /* ------------ classes and interfaces (body, slots ) ------- */ @@ -2274,37 +2309,15 @@ GETSET : "get" {$$=$1;} FUNCTION_DECLARATION: MAYBE_MODIFIERS "function" GETSET T_IDENTIFIER '(' MAYBE_PARAM_LIST ')' MAYBETYPE '{' {PASS12 startfunction(0,$1,$3,$4,&$6,$8);} MAYBECODE '}' { - PASS1 old_state(); + PASS1 old_state();list_deep_free($6.list); PASS2 if(!state->method->info) syntaxerror("internal error"); - code_t*c = 0; - if(state->method->late_binding) { - c = abc_getlocal_0(c); - c = abc_pushscope(c); - } - /*if(state->method->innerfunctions) { - c = abc_newactivation(c); - c = abc_pushscope(c); - }*/ - if(state->method->is_constructor && !state->method->has_super) { - // call default constructor - c = abc_getlocal_0(c); - c = abc_constructsuper(c, 0); - } - methodstate_list_t*l = state->method->innerfunctions; - while(l) { - parserassert(l->methodstate->abc); - c = abc_newfunction(c, l->methodstate->abc); - c = abc_setlocal(c, l->methodstate->var_index); - free(l->methodstate);l->methodstate=0; - l = l->next; - } - list_free(state->method->innerfunctions); - state->method->innerfunctions = 0; - + + code_t*c = method_header(); c = wrap_function(c, 0, $11); endfunction(0,$1,$3,$4,&$6,$8,c); + list_deep_free($6.list); $$=0; } @@ -2313,16 +2326,17 @@ MAYBE_IDENTIFIER: {PASS12 $$=0;} INNERFUNCTION: "function" MAYBE_IDENTIFIER '(' MAYBE_PARAM_LIST ')' MAYBETYPE '{' {PASS12 innerfunction($2,&$4,$6);} MAYBECODE '}' { - PASS1 old_state(); + PASS1 old_state();list_deep_free($4.list); PASS2 memberinfo_t*f = state->method->info; if(!f) syntaxerror("internal error"); - - code_t*c = 0; + + code_t*c = method_header(); c = wrap_function(c, 0, $9); int index = state->method->var_index; endfunction(0,0,0,$2,&$4,$6,c); + list_deep_free($4.list); $$.c = abc_getlocal(0, index); $$.t = TYPE_FUNCTION(f); @@ -2381,35 +2395,38 @@ EXPRESSION_LIST : EXPRESSION_LIST ',' NONCOMMAEXPRESSION { $$.len= $1.len+1; $$.cc = code_append($1.cc, $3.c); } - -/*NEW : "new" E { - $$ = $2; - if($2.c->opcode == OPCODE_CALL) - $2.c->opcode = OPCODE_CONSTRUCT; - else if($2.c->opcode == OPCODE_CALLPROPERTY) - $2.c->opcode = OPCODE_CONSTRUCTPROP; - else - as3_error("invalid argument to 'new'"); -}*/ - -NEW : "new" CLASS MAYBE_PARAM_VALUES { - MULTINAME(m, $2); - $$.c = code_new(); - - if($2->slot) { - $$.c = abc_getglobalscope($$.c); - $$.c = abc_getslot($$.c, $2->slot); + +XX : %prec new2 +NEW : "new" E XX MAYBE_PARAM_VALUES { + $$.c = $2.c; + if($$.c->opcode == OPCODE_COERCE_A) $$.c = code_cutlast($$.c); + + code_t*paramcode = $4.cc; + if($$.c->opcode == OPCODE_GETPROPERTY) { + multiname_t*name = $$.c->data[0];$$.c->data[0]=0; + $$.c = code_cutlast($$.c); + $$.c = code_append($$.c, paramcode); + $$.c = abc_constructprop2($$.c, name, $4.len); + multiname_destroy(name); + } else if($$.c->opcode == OPCODE_GETSLOT) { + int slot = (int)(ptroff_t)$$.c->data[0]; + trait_t*t = abc_class_find_slotid(state->cls->abc,slot);//FIXME + multiname_t*name = t->name; + $$.c = code_cutlast($$.c); + $$.c = code_append($$.c, paramcode); + $$.c = abc_constructprop2($$.c, name, $4.len); } else { - $$.c = abc_findpropstrict2($$.c, &m); + $$.c = code_append($$.c, paramcode); + $$.c = abc_construct($$.c, $4.len); + } + + $$.t = TYPE_ANY; + if(TYPE_IS_CLASS($2.t) && $2.t->cls) { + $$.t = $2.t->cls; + } else { + $$.c = abc_coerce_a($$.c); + $$.t = TYPE_ANY; } - - $$.c = code_append($$.c, $3.cc); - - if($2->slot) - $$.c = abc_construct($$.c, $3.len); - else - $$.c = abc_constructprop2($$.c, &m, $3.len); - $$.t = $2; } /* TODO: use abc_call (for calling local variables), @@ -2454,8 +2471,6 @@ FUNCTIONCALL : E '(' MAYBE_EXPRESSION_LIST ')' { $$.c = abc_call($$.c, $3.len); } - memberinfo_t*f = 0; - if(TYPE_IS_FUNCTION($1.t) && $1.t->function) { $$.t = $1.t->function->return_type; } else {