From: kramm Date: Fri, 2 Jan 2009 19:52:56 +0000 (+0000) Subject: implemented global methods X-Git-Tag: release-0-9-0~449 X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=commitdiff_plain;h=dfcf7dbe3ce9a4659c87de042741552b43d41200 implemented global methods --- diff --git a/lib/as3/parser.y b/lib/as3/parser.y index a1edea6..9ed8e40 100644 --- a/lib/as3/parser.y +++ b/lib/as3/parser.y @@ -288,6 +288,7 @@ typedef struct _methodstate { code_t*initcode; char is_constructor; char has_super; + char is_global; } methodstate_t; typedef struct _state { @@ -794,10 +795,39 @@ static void check_constant_against_type(classinfo_t*t, constant_t*c) } } +static int flags2access(int flags) +{ + int access = 0; + if(flags&FLAG_PUBLIC) { + if(access&(FLAG_PRIVATE|FLAG_PROTECTED|FLAG_INTERNAL)) syntaxerror("invalid combination of access levels"); + access = ACCESS_PACKAGE; + } else if(flags&FLAG_PRIVATE) { + if(access&(FLAG_PUBLIC|FLAG_PROTECTED|FLAG_INTERNAL)) syntaxerror("invalid combination of access levels"); + access = ACCESS_PRIVATE; + } else if(flags&FLAG_PROTECTED) { + if(access&(FLAG_PUBLIC|FLAG_PRIVATE|FLAG_INTERNAL)) syntaxerror("invalid combination of access levels"); + access = ACCESS_PROTECTED; + } else { + access = ACCESS_PACKAGEINTERNAL; + } + return access; +} + static memberinfo_t*registerfunction(enum yytokentype getset, int flags, char*name, params_t*params, classinfo_t*return_type, int slot) { memberinfo_t*minfo = 0; - if(getset != KW_GET && getset != KW_SET) { + if(!state->cls) { + //package method + minfo = rfx_calloc(sizeof(memberinfo_t)); + classinfo_t*c = classinfo_register(flags2access(flags), state->package, name, 0); + c->flags |= FLAG_METHOD; + c->function = minfo; + minfo->kind = MEMBER_METHOD; + minfo->name = name; + minfo->flags = FLAG_STATIC; + minfo->return_type = return_type; + } else if(getset != KW_GET && getset != KW_SET) { + //class method if((minfo = registry_findmember(state->cls->info, name, 0))) { if(minfo->parent == state->cls->info) { syntaxerror("class already contains a member/method called '%s'", name); @@ -814,6 +844,7 @@ static memberinfo_t*registerfunction(enum yytokentype getset, int flags, char*na // to actually store these //state->minfo->slot = state->method->abc->method->trait->slot_id; } else { + //class getter/setter int gs = getset==KW_GET?MEMBER_GET:MEMBER_SET; classinfo_t*type=0; if(getset == KW_GET) @@ -849,24 +880,6 @@ static memberinfo_t*registerfunction(enum yytokentype getset, int flags, char*na return minfo; } -static int flags2access(int flags) -{ - int access = 0; - if(flags&FLAG_PUBLIC) { - if(access&(FLAG_PRIVATE|FLAG_PROTECTED|FLAG_INTERNAL)) syntaxerror("invalid combination of access levels"); - access = ACCESS_PACKAGE; - } else if(flags&FLAG_PRIVATE) { - if(access&(FLAG_PUBLIC|FLAG_PROTECTED|FLAG_INTERNAL)) syntaxerror("invalid combination of access levels"); - access = ACCESS_PRIVATE; - } else if(flags&FLAG_PROTECTED) { - if(access&(FLAG_PUBLIC|FLAG_PRIVATE|FLAG_INTERNAL)) syntaxerror("invalid combination of access levels"); - access = ACCESS_PROTECTED; - } else { - access = ACCESS_PACKAGEINTERNAL; - } - return access; -} - static void startfunction(token_t*ns, int flags, enum yytokentype getset, char*name, params_t*params, classinfo_t*return_type) { @@ -876,15 +889,24 @@ static void startfunction(token_t*ns, int flags, enum yytokentype getset, char*n new_state(); state->method = rfx_calloc(sizeof(methodstate_t)); 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; + if(state->cls) { + state->method->is_constructor = !strcmp(state->cls->info->name,name); + state->cls->has_constructor |= state->method->is_constructor; + + new_variable((flags&FLAG_STATIC)?"class":"this", state->cls->info, 0); + } else { + state->method->is_global = 1; + new_variable("globalscope", 0, 0); + + /* for global methods, always push local_0 on the scope stack: */ + state->method->late_binding = 1; + } global->variable_count = 0; /* state->vars is initialized by state_new */ - if(new_variable((flags&FLAG_STATIC)?"class":"this", state->cls->info, 0)!=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, 0); @@ -897,21 +919,28 @@ static void startfunction(token_t*ns, int flags, enum yytokentype getset, char*n static void endfunction(token_t*ns, int flags, enum yytokentype getset, char*name, params_t*params, classinfo_t*return_type, code_t*body) { - namespace_t mname_ns = {flags2access(flags), ""}; - multiname_t mname = {QNAME, &mname_ns, 0, name}; - abc_method_t*f = 0; multiname_t*type2 = sig2mname(return_type); int slot = 0; if(state->method->is_constructor) { f = abc_class_getconstructor(state->cls->abc, type2); - } else { + } else if(!state->method->is_global) { + namespace_t mname_ns = {flags2access(flags), ""}; + multiname_t mname = {QNAME, &mname_ns, 0, name}; + if(flags&FLAG_STATIC) f = abc_class_staticmethod(state->cls->abc, type2, &mname); else f = abc_class_method(state->cls->abc, type2, &mname); slot = f->trait->slot_id; + } else { + namespace_t mname_ns = {flags2access(flags), state->package}; + multiname_t mname = {QNAME, &mname_ns, 0, name}; + + f = abc_method_new(global->file, type2, 1); + trait_t*t = trait_new_method(&global->init->traits, multiname_clone(&mname), f); + //abc_code_t*c = global->init->method->body->code; } //flash doesn't seem to allow us to access function slots //state->method->info->slot = slot; @@ -2407,7 +2436,7 @@ VAR_READ : T_IDENTIFIER { $$.t = v->type; /* look at current class' members */ - } else if((f = registry_findmember(state->cls->info, $1, 1))) { + } else if(state->cls && (f = registry_findmember(state->cls->info, $1, 1))) { // $1 is a function in this class int var_is_static = (f->flags&FLAG_STATIC); int i_am_static = ((state->method && state->method->info)?(state->method->info->flags&FLAG_STATIC):FLAG_STATIC);