abc_class_t*abc;
code_t*init;
code_t*static_init;
+ char has_constructor;
} classstate_t;
typedef struct _methodstate {
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(!(flags&FLAG_DYNAMIC)) abc_class_sealed(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) {
MULTINAME(m, mlist->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;
+ 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);
}
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();
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;
multiname_t*type2 = sig2mname(return_type);
int slot = 0;
if(state->method->is_constructor) {
- f = abc_class_constructor(state->cls->abc, type2);
+ f = abc_class_getconstructor(state->cls->abc, type2);
} else {
if(flags&FLAG_STATIC)
f = abc_class_staticmethod(state->cls->abc, type2, &mname);
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();
$$ = code_append($$, $10);
$$ = code_append($$, $8);
$$ = abc_jump($$, loopstart);
- code_t*out = $$ = abc_label($$);
+ code_t*out = $$ = abc_nop($$);
breakjumpsto($$, out);
myif->branch = out;
WHILE : "while" '(' {new_state();} EXPRESSION ')' CODEBLOCK {
$$ = 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();
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);
}
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);
$$.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)) {
/* 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 {