%{
-static int yyerror(char*s)
+static int a3_error(char*s)
{
syntaxerror("%s", s);
return 0; //make gcc happy
}
+
static char* concat2(const char* t1, const char* t2)
{
int l1 = strlen(t1);
char is_constructor;
char has_super;
char is_global;
+ char inner;
+ int variable_count;
abc_exception_list_t*exceptions;
} methodstate_t;
typedef struct _global {
abc_file_t*file;
abc_script_t*init;
-
- int variable_count;
} global_t;
static global_t*global = 0;
global = rfx_calloc(sizeof(global_t));
global->file = abc_file_new();
global->file->flags &= ~ABCFILE_LAZY;
- global->variable_count = 1;
+
global->init = abc_initscript(global->file);
code_t*c = global->init->method->body->code;
c = abc_getlocal_0(c);
c = abc_pushscope(c);
- /*c = abc_findpropstrict(c, "[package]::trace");
- c = abc_pushstring(c, "[entering global init function]");
- c = abc_callpropvoid(c, "[package]::trace", 1);*/
global->init->method->body->code = c;
}
{
new_state();
state->package = filename;
- // needed for state->method->late_binding:
+
state->method = rfx_calloc(sizeof(methodstate_t));
+ state->method->variable_count = 1;
}
+
void finish_file()
{
if(!state || state->level!=1) {
static int new_variable(char*name, classinfo_t*type, char init)
{
NEW(variable_t, v);
- v->index = global->variable_count;
+ v->index = state->method->variable_count;
v->type = type;
v->init = init;
dict_put(state->vars, name, v);
- return global->variable_count++;
+ return state->method->variable_count++;
}
#define TEMPVARNAME "__as3_temp__"
static int gettempvar()
new_state();
/*printf("entering package \"%s\"\n", name);*/
state->package = strdup(name);
- global->variable_count = 1;
}
static void endpackage()
{
syntaxerror("inner classes now allowed");
}
new_state();
- global->variable_count = 1;
state->cls = rfx_calloc(sizeof(classstate_t));
state->method = rfx_calloc(sizeof(methodstate_t)); // method state, for static constructor
+ state->method->variable_count = 1;
token_list_t*t=0;
classinfo_list_t*mlist=0;
return minfo;
}
+static void innerfunction(char*name, params_t*params, classinfo_t*return_type)
+{
+ parserassert(state->method && state->method->info);
+ memberinfo_t*parent_method = state->method->info;
+
+ if(as3_pass==1) {
+ // not valid yet
+ params = 0;
+ return_type = 0;
+ }
+
+ new_state();
+ state->method = rfx_calloc(sizeof(methodstate_t));
+ state->method->inner = 1;
+ state->method->variable_count = 0;
+
+ memberinfo_t*minfo = 0;
+
+ /* TODO: we need some better way to pass things from pass1 to pass2 */
+ char myname[200];
+ sprintf(myname, "as3-innerfunction-%d-%d", current_line, current_column);
+
+ if(as3_pass == 1) {
+ minfo = rfx_calloc(sizeof(memberinfo_t));
+ minfo->name = name;
+ if(!parent_method->subfunctions)
+ parent_method->subfunctions = dict_new();
+ if(name)
+ dict_put(parent_method->subfunctions, name, minfo);
+ dict_put(parent_method->subfunctions, myname, minfo);
+ }
+
+ if(as3_pass == 2) {
+ minfo = dict_lookup(parent_method->subfunctions, myname);
+ parserassert(minfo);
+
+ minfo->return_type = return_type;
+
+ new_variable("FIXME", 0, 0); //FIXME: is local_0 "this"?
+ param_list_t*p=0;
+ for(p=params->list;p;p=p->next) {
+ new_variable(p->param->name, p->param->type, 0);
+ }
+ }
+ state->method->info = minfo;
+}
+
static void startfunction(token_t*ns, int flags, enum yytokentype getset, char*name,
params_t*params, classinfo_t*return_type)
{
new_state();
state->method = rfx_calloc(sizeof(methodstate_t));
state->method->has_super = 0;
+ state->method->variable_count = 0;
if(state->cls) {
state->method->is_constructor = !strcmp(state->cls->info->name,name);
else state->method->info = registry_findmember(state->cls->info, name, 0);
state->method->info->return_type = return_type;
- global->variable_count = 0;
/* state->vars is initialized by state_new */
if(!state->method->is_global)
new_variable((flags&FLAG_STATIC)?"class":"this", state->cls->info, 0);
}
}
-static void endfunction(token_t*ns, int flags, enum yytokentype getset, char*name,
+static abc_method_t* endfunction(token_t*ns, int flags, enum yytokentype getset, char*name,
params_t*params, classinfo_t*return_type, code_t*body)
{
if(as3_pass==1) {
old_state();
- return;
+ return 0;
}
abc_method_t*f = 0;
multiname_t*type2 = sig2mname(return_type);
int slot = 0;
- if(state->method->is_constructor) {
+ if(state->method->inner) {
+ f = abc_method_new(global->file, type2, 1);
+ } else if(state->method->is_constructor) {
f = abc_class_getconstructor(state->cls->abc, type2);
} else if(!state->method->is_global) {
namespace_t mname_ns = flags2namespace(flags, "");
}
old_state();
+ return f;
}
-
-
char is_subtype_of(classinfo_t*type, classinfo_t*supertype)
{
return 1; // FIXME
{
PASS1 old_state();
PASS2
+ if(!state->method->info) syntaxerror("internal error");
code_t*c = 0;
if(state->method->late_binding) {
c = abc_getlocal_0(c);
c = abc_getlocal_0(c);
c = abc_constructsuper(c, 0);
}
+
c = wrap_function(c, 0, $11);
endfunction(0,$1,$3,$4,&$6,$8,c);
}
MAYBE_IDENTIFIER: T_IDENTIFIER
-MAYBE_IDENTIFIER: {$$=0;}
-INNERFUNCTION: "function" MAYBE_IDENTIFIER '(' MAYBE_PARAM_LIST ')' MAYBETYPE '{' MAYBECODE '}'
+MAYBE_IDENTIFIER: {PASS12 $$=0;}
+INNERFUNCTION: "function" MAYBE_IDENTIFIER '(' MAYBE_PARAM_LIST ')' MAYBETYPE
+ '{' {PASS12 innerfunction($2,&$4,$6);} MAYBECODE '}'
{
- syntaxerror("nested functions not supported yet");
+ PASS1 old_state();
+ PASS2
+ memberinfo_t*f = state->method->info;
+ if(!f) syntaxerror("internal error");
+
+ code_t*c = 0;
+ c = wrap_function(c, 0, $9);
+
+ abc_method_t*abc = endfunction(0,0,0,$2,&$4,$6,c);
+
+ $$.c = abc_newfunction(0, abc);
+ $$.t = TYPE_FUNCTION(f);
}