#include "code.h"
#include "opcodes.h"
#include "compiler.h"
-#include "ast.h"
+#include "expr.h"
+#include "initcode.h"
extern int a3_lex();
%type <code> INTERFACE_DECLARATION
%type <code> VOIDEXPRESSION
%type <value> EXPRESSION NONCOMMAEXPRESSION
-%type <value> MAYBEEXPRESSION
+%type <node> MAYBEEXPRESSION
%type <value> DELETE
-%type <node> E
+%type <node> E COMMA_EXPRESSION
+%type <node> VAR_READ
%type <code> FOR FOR_IN IF WHILE DO_WHILE MAYBEELSE BREAK RETURN CONTINUE TRY
%type <value> INNERFUNCTION
%type <code> USE_NAMESPACE
%type <classinfo> TYPE
//%type <token> VARIABLE
-%type <value> VAR_READ MEMBER
+%type <value> MEMBER
%type <value> NEW
//%type <token> T_IDENTIFIER
%type <value> FUNCTIONCALL
-%type <value_list> MAYBE_EXPRESSION_LIST EXPRESSION_LIST EXPRESSION_LIST_AND_COMMA MAYBE_PARAM_VALUES MAYBE_EXPRPAIR_LIST EXPRPAIR_LIST WITH_HEAD
+%type <value_list> MAYBE_EXPRESSION_LIST EXPRESSION_LIST EXPRESSION_LIST_AND_COMMA MAYBE_PARAM_VALUES
+%type <value_list> MAYBE_DICT_EXPRPAIR_LIST DICT_EXPRPAIR_LIST WITH_HEAD
+%type <code> DICTLH
// precedence: from low to high
int switch_var;
dict_t*vars;
+ dict_t*allvars; // also contains variables from sublevels
} state_t;
typedef struct _global {
abc_file_t*file;
- abc_script_t*init;
+
+ parsedclass_list_t*classes;
+ abc_script_t*classinit;
+
+ abc_script_t*init; //package-level code
+
dict_t*token2info;
dict_t*file2token2info;
} global_t;
DECLARE_LIST(state);
-#define MULTINAME(m,x) \
- multiname_t m;\
- namespace_t m##_ns;\
- (x)->package; \
- registry_fill_multiname(&m, &m##_ns, (slotinfo_t*)(x));
-
#define MEMBER_MULTINAME(m,f,n) \
multiname_t m;\
namespace_t m##_ns;\
dict_destroy(state->imports);state->imports=0;
}
if(state->vars) {
- int t;
- for(t=0;t<state->vars->hashsize;t++) {
- dictentry_t*e =state->vars->slots[t];
- while(e) {
- free(e->data);e->data=0;
- e = e->next;
- }
- }
dict_destroy(state->vars);state->vars=0;
}
+ if(state->new_vars && state->allvars) {
+ parserassert(!state->old || state->old->allvars != state->allvars);
+ DICT_ITERATE_DATA(state->allvars, void*, data) {
+ free(data);
+ }
+ dict_destroy(state->allvars);
+ }
list_free(state->active_namespace_urls)
state->active_namespace_urls = 0;
new_state();
state->package = internal_filename_package = strdup(filename);
+ state->allvars = dict_new();
global->token2info = dict_lookup(global->file2token2info,
current_filename // use long version
if(!state->method)
syntaxerror("internal error: skewed tokencount");
function_initvars(state->method, 0, 0, 1);
+ global->classinit = abc_initscript(global->file);
global->init = abc_initscript(global->file);
}
}
{
dict_free_all(global->file2token2info, 1, (void*)dict_destroy);
global->token2info=0;
+
+ initcode_add_classlist(global->classinit, global->classes);
+
return global->file;
}
static variable_t* find_variable(state_t*s, char*name)
{
+ state_t*top = s;
while(s) {
variable_t*v = 0;
v = dict_lookup(s->vars, name);
if(s->new_vars) break;
s = s->old;
}
- return 0;
+ return dict_lookup(top->allvars, name);
}
static variable_t* find_slot(state_t*s, const char*name)
{
v->type = type;
v->init = init;
- if(name)
+ if(name) {
dict_put(state->vars, name, v);
+ dict_put(state->allvars, name, v);
+ }
return v;
}
int gettempvar()
{
variable_t*v = find_variable(state, TEMPVARNAME);
+ int i;
if(v)
- return v->index;
- return new_variable(TEMPVARNAME, 0, 0, 0);
+ i = v->index;
+ else
+ i = new_variable(TEMPVARNAME, 0, 0, 0);
+ parserassert(i);
+ return i;
}
static code_t* var_block(code_t*body)
index = new_variable((flags&FLAG_STATIC)?"class":"this", state->cls?state->cls->info:0, 0, 0);
else
index = new_variable("globalscope", 0, 0, 0);
- if(index)
- *(int*)0=0;
parserassert(!index);
}
state->cls = rfx_calloc(sizeof(classstate_t));
state->cls->init = rfx_calloc(sizeof(methodstate_t));
state->cls->static_init = rfx_calloc(sizeof(methodstate_t));
+ state->cls->static_init->variable_count=1;
/* notice: we make no effort to initialize the top variable (local0) here,
even though it has special meaning. We just rely on the facat
that pass 1 won't do anything with variables */
int num_interfaces = (list_length(implements));
state->cls->info = classinfo_register(access, package, classname, num_interfaces);
state->cls->info->flags |= mod->flags & (FLAG_DYNAMIC|FLAG_INTERFACE|FLAG_FINAL);
+ state->cls->info->superclass = extends;
int pos = 0;
classinfo_list_t*l = implements;
pos++;
}
- /* fill out interfaces and extends (we couldn't resolve those during the first pass) */
- state->cls->info->superclass = extends;
-
/* generate the abc code for this class */
MULTINAME(classname2,state->cls->info);
multiname_t*extends2 = sig2mname(extends);
-
state->cls->abc = abc_class_new(global->file, &classname2, extends2);
+ multiname_destroy(extends2);
+
if(state->cls->info->flags&FLAG_FINAL) abc_class_final(state->cls->abc);
if(!(state->cls->info->flags&FLAG_DYNAMIC)) abc_class_sealed(state->cls->abc);
if(state->cls->info->flags&FLAG_INTERFACE) {
abc_class_add_interface(state->cls->abc, &m);
}
- /* write the construction code for this class to the global init
- function */
- int slotindex = abc_initscript_addClassTrait(global->init, &classname2, state->cls->abc);
-
- abc_method_body_t*m = global->init->method->body;
- __ getglobalscope(m);
- classinfo_t*s = extends;
-
- int count=0;
-
- while(s) {
- //TODO: take a look at the current scope stack, maybe
- // we can re-use something
- s = s->superclass;
- if(!s)
- break;
-
- multiname_t*s2 = sig2mname(s);
- __ getlex2(m, s2);
- multiname_destroy(s2);
-
- __ pushscope(m); count++;
- m->code = m->code->prev->prev; // invert
- }
- /* continue appending after last op end */
- while(m->code && m->code->next) m->code = m->code->next;
-
- /* TODO: if this is one of *our* classes, we can also
- do a getglobalscope/getslot <nr> (which references
- the init function's slots) */
- if(extends2) {
- __ getlex2(m, extends2);
- __ dup(m);
- /* notice: we get a Verify Error #1107 if the top elemnt on the scope
- stack is not the superclass */
- __ pushscope(m);count++;
- } else {
- __ pushnull(m);
- /* notice: we get a verify error #1107 if the top element on the scope
- stack is not the global object */
- __ getlocal_0(m);
- __ pushscope(m);count++;
- }
- __ newclass(m,state->cls->abc);
- while(count--) {
- __ popscope(m);
- }
- __ setslot(m, slotindex);
- multiname_destroy(extends2);
+ NEW(parsedclass_t,p);
+ p->cls = state->cls->info;
+ p->abc = state->cls->abc;
+ list_append(global->classes, p);
/* flash.display.MovieClip handling */
-
if(!as3_globalclass && (mod->flags&FLAG_PUBLIC) && slotinfo_equals((slotinfo_t*)registry_getMovieClip(),(slotinfo_t*)extends)) {
if(state->package && state->package[0]) {
as3_globalclass = concat3(state->package, ".", classname);
if(!state->cls) {
//package method
minfo = methodinfo_register_global(ns.access, state->package, name);
- minfo->return_type = 0; // save this for pass 2
+ minfo->return_type = return_type;
} else if(getset != KW_GET && getset != KW_SET) {
//class method
memberinfo_t* m = registry_findmember(state->cls->info, ns.name, name, 0);
syntaxerror("class already contains a %s '%s'", infotypename((slotinfo_t*)m), m->name);
}
minfo = methodinfo_register_onclass(state->cls->info, ns.access, ns.name, name);
- minfo->return_type = 0; // save this for pass 2
+ minfo->return_type = return_type;
// getslot on a member slot only returns "undefined", so no need
// to actually store these
//state->minfo->slot = state->method->abc->method->trait->slot_id;
// not sure wether to look into superclasses here, too
minfo = (methodinfo_t*)registry_findmember(state->cls->info, ns.name, name, 1);
if(minfo) {
- if(minfo->kind!=INFOTYPE_SLOT)
+ if(minfo->kind!=INFOTYPE_VAR)
syntaxerror("class already contains a method called '%s'", name);
if(!(minfo->subtype & (SUBTYPE_GETSET)))
syntaxerror("class already contains a field called '%s'", name);
}*/
} else {
minfo = methodinfo_register_onclass(state->cls->info, ns.access, ns.name, name);
- minfo->kind = INFOTYPE_SLOT; //hack
+ minfo->kind = INFOTYPE_VAR; //hack
minfo->subtype = gs;
- minfo->return_type = 0;
+ minfo->return_type = return_type;
}
+
/* can't assign a slot as getter and setter might have different slots */
//minfo->slot = slot;
}
new_state();
state->new_vars = 1;
+ state->allvars = dict_new();
if(as3_pass == 1) {
state->method = rfx_calloc(sizeof(methodstate_t));
}
new_state();
state->new_vars = 1;
-
+ state->allvars = dict_new();
+
if(as3_pass == 1) {
state->method = rfx_calloc(sizeof(methodstate_t));
state->method->has_super = 0;
state->cls->has_constructor |= state->method->is_constructor;
}
- state->method->info->return_type = return_type;
function_initvars(state->method, params, mod->flags, 1);
}
}
}
state->method->uses_slots = i;
dict_destroy(state->vars);state->vars = 0;
+ parserassert(state->new_vars);
+ dict_destroy(state->allvars);state->allvars = 0;
}
old_state();
return 0;
MAYBECODE: CODE {$$=$1;}
MAYBECODE: {$$=code_new();}
-CODE: CODE CODEPIECE {$$=code_append($1,$2);}
+CODE: CODE CODEPIECE {
+ $$=code_append($1,$2);
+}
CODE: CODEPIECE {$$=$1;}
// code which may appear outside of methods
CODEPIECE: CONTINUE
CODEPIECE: RETURN
CODEPIECE: THROW
-CODEPIECE: CONDITIONAL_COMPILATION '{' CODE '}' {PASS_ALWAYS as3_pass=$1;}
+CODEPIECE: CONDITIONAL_COMPILATION '{' CODE '}' {
+ PASS_ALWAYS
+ if(as3_pass) {
+ $$ = $3;
+ } else {
+ $$ = 0;
+ }
+ as3_pass=$1;
+}
//CODEBLOCK : '{' CODE '}' {$$=$2;}
//CODEBLOCK : '{' '}' {$$=0;}
}
};
-MAYBEEXPRESSION : '=' NONCOMMAEXPRESSION {$$=$2;}
- | {$$.c=abc_pushundefined(0);
- $$.t=TYPE_ANY;
- }
+MAYBEEXPRESSION : '=' E {$$=$2;}
+ | {$$=mkdummynode();}
VARIABLE_DECLARATION : "var" VARIABLE_LIST {$$=$2;}
VARIABLE_DECLARATION : "const" VARIABLE_LIST {$$=$2;}
new_variable($1, 0, 1, 0);
PASS2
- if(!is_subtype_of($3.t, $2)) {
- syntaxerror("Can't convert %s to %s", $3.t->name,
- $2->name);
- }
-
char slot = 0;
int index = 0;
if(state->method->uses_slots) {
$$ = slot?abc_getscopeobject(0, 1):0;
+ typedcode_t v = node_read($3);
+ if(!is_subtype_of(v.t, $2)) {
+ syntaxerror("Can't convert %s to %s", v.t->name, $2->name);
+ }
if($2) {
- if($3.c->prev || $3.c->opcode != OPCODE_PUSHUNDEFINED) {
- $$ = code_append($$, $3.c);
- $$ = converttype($$, $3.t, $2);
+ if(v.c->prev || v.c->opcode != OPCODE_PUSHUNDEFINED) {
+ $$ = code_append($$, v.c);
+ $$ = converttype($$, v.t, $2);
} else {
- code_free($3.c);
+ code_free(v.c);
$$ = defaultvalue($$, $2);
}
} else {
- if($3.c->prev || $3.c->opcode != OPCODE_PUSHUNDEFINED) {
- $$ = code_append($$, $3.c);
+ if(v.c->prev || v.c->opcode != OPCODE_PUSHUNDEFINED) {
+ $$ = code_append($$, v.c);
$$ = abc_coerce_a($$);
} else {
// don't do anything
- code_free($3.c);
+ code_free(v.c);
code_free($$);
$$ = 0;
break;
t = trait_new_member(traits, 0, multiname_clone(&mname), 0);
}
info->slot = t->slot_id;
-
- /* initalization code (if needed) */
- code_t*c = 0;
- if($3.c && !is_pushundefined($3.c)) {
- c = abc_getlocal_0(c);
- c = code_append(c, $3.c);
- c = converttype(c, $3.t, $2);
- c = abc_setslot(c, t->slot_id);
+
+ constant_t cval = $3->type->eval($3);
+ if(cval.type!=CONSTANT_UNKNOWN) {
+ /* compile time constant */
+ t->value = malloc(sizeof(constant_t));
+ memcpy(t->value, &cval, sizeof(constant_t));
+ info->value = constant_clone(t->value);
+ } else {
+ typedcode_t v = node_read($3);
+ /* initalization code (if needed) */
+ code_t*c = 0;
+ if(v.c && !is_pushundefined(v.c)) {
+ c = abc_getlocal_0(c);
+ c = code_append(c, v.c);
+ c = converttype(c, v.t, $2);
+ c = abc_setslot(c, t->slot_id);
+ }
+ *code = code_append(*code, c);
}
- *code = code_append(*code, c);
-
if(slotstate_varconst==KW_CONST) {
t->kind= TRAIT_CONST;
+ info->flags |= FLAG_CONST;
}
}
/* ------------ constants -------------------------------------- */
MAYBECONSTANT: {$$=0;}
-MAYBECONSTANT: '=' CONSTANT {$$=$2;}
+MAYBECONSTANT: '=' E {
+ $$ = malloc(sizeof(constant_t));
+ *$$ = node_eval($2);
+ if($$->type == CONSTANT_UNKNOWN)
+ syntaxerror("can't evaluate default parameter value (needs to be a compile-time constant)");
+}
//CONSTANT : T_NAMESPACE {$$ = constant_new_namespace($1);}
CONSTANT : T_INT {$$ = constant_new_int($1);}
CLASS_SPEC_LIST : CLASS_SPEC_LIST ',' CLASS_SPEC {PASS12 $$=$1;list_append($$,$3);}
TYPE : CLASS_SPEC {PASS12 $$=$1;}
- | '*' {PASS12 $$=registry_getanytype();}
- | "void" {PASS12 $$=registry_getanytype();}
+ | '*' {PASS12 $$=TYPE_ANY;}
+ | "void" {PASS12 $$=TYPE_ANY;}
/*
| "String" {$$=registry_getstringclass();}
| "int" {$$=registry_getintclass();}
if(TYPE_IS_FUNCTION(v.t) && v.t->data) {
$$.t = ((methodinfo_t*)(v.t->data))->return_type;
+ } else if(TYPE_IS_CLASS(v.t) && v.t->data) {
+ // calling a class is like a typecast
+ $$.t = (classinfo_t*)v.t->data;
} else {
$$.c = abc_coerce_a($$.c);
$$.t = TYPE_ANY;
// ----------------------- expression types -------------------------------------
-NONCOMMAEXPRESSION : E %prec below_minus {$$ = node_read($1);}
-EXPRESSION : E %prec below_minus {$$ = node_read($1);}
-EXPRESSION : EXPRESSION ',' E %prec below_minus {
- $$.c = $1.c;
- $$.c = cut_last_push($$.c);
- typedcode_t v = node_read($3);
- $$.c = code_append($$.c,v.c);
- $$.t = v.t;
+NONCOMMAEXPRESSION : E %prec below_minus {
+ $$ = node_read($1);
+}
+EXPRESSION : COMMA_EXPRESSION {
+ $$ = node_read($1);
+}
+COMMA_EXPRESSION : E %prec below_minus {
+ $$ = mkmultinode(&node_comma, $1);
+}
+COMMA_EXPRESSION : COMMA_EXPRESSION ',' E %prec below_minus {
+ $$ = multinode_extend($1, $3);
+}
+VOIDEXPRESSION : E %prec below_minus {
+ $$ = node_exec($1);
}
-VOIDEXPRESSION : E %prec below_minus { $$=node_exec($1); }
VOIDEXPRESSION : VOIDEXPRESSION ',' E %prec below_minus {
$$ = $1;
$$ = code_append($$, node_exec($3));
}
-MAYBE_EXPRPAIR_LIST : {$$.cc=0;$$.number=0;}
-MAYBE_EXPRPAIR_LIST : EXPRPAIR_LIST {$$=$1;}
+MAYBE_DICT_EXPRPAIR_LIST : {$$.cc=0;$$.number=0;}
+MAYBE_DICT_EXPRPAIR_LIST : DICT_EXPRPAIR_LIST {$$=$1;}
+
+DICTLH: T_IDENTIFIER {$$=abc_pushstring(0,$1);}
+DICTLH: T_STRING {$$=abc_pushstring2(0,&$1);}
-EXPRPAIR_LIST : NONCOMMAEXPRESSION ':' NONCOMMAEXPRESSION {
+DICT_EXPRPAIR_LIST : DICTLH ':' NONCOMMAEXPRESSION {
$$.cc = 0;
- $$.cc = code_append($$.cc, $1.c);
+ $$.cc = code_append($$.cc, $1);
$$.cc = code_append($$.cc, $3.c);
$$.number = 2;
}
-EXPRPAIR_LIST : EXPRPAIR_LIST ',' NONCOMMAEXPRESSION ':' NONCOMMAEXPRESSION {
+DICT_EXPRPAIR_LIST : DICT_EXPRPAIR_LIST ',' DICTLH ':' NONCOMMAEXPRESSION {
$$.cc = $1.cc;
$$.number = $1.number+2;
- $$.cc = code_append($$.cc, $3.c);
+ $$.cc = code_append($$.cc, $3);
$$.cc = code_append($$.cc, $5.c);
}
// ----------------------- expression evaluation -------------------------------------
E : INNERFUNCTION %prec prec_none {$$ = mkcodenode($1);}
-E : VAR_READ %prec T_IDENTIFIER {$$ = mkcodenode($1);}
E : MEMBER %prec '.' {$$ = mkcodenode($1);}
E : NEW {$$ = mkcodenode($1);}
E : DELETE {$$ = mkcodenode($1);}
E : FUNCTIONCALL {$$ = mkcodenode($1);}
+E : VAR_READ %prec T_IDENTIFIER {$$ = $1;}
E : CONSTANT {
$$ = mkconstnode($1);
}
/* dictionary */
-E : "{ (dictionary)" MAYBE_EXPRPAIR_LIST '}' {
+E : "{ (dictionary)" MAYBE_DICT_EXPRPAIR_LIST '}' {
typedcode_t v;
v.c = code_new();
v.c = code_append(v.c, $2.cc);
E : "typeof" '(' E ')' {$$ = mknode1(&node_typeof, $3);}
E : "void" E {$$ = mknode1(&node_void, $2);}
E : "void" { $$ = mkconstnode(constant_new_undefined());}
-E : '(' EXPRESSION ')' { /*allow commas in here, too */ $$=mkcodenode($2);}
+E : '(' COMMA_EXPRESSION ')' { $$=$2;}
E : '-' E {$$ = mknode1(&node_neg, $2);}
E : E '[' E ']' {$$ = mknode2(&node_arraylookup, $1,$3);}
E : E "*=" E {$$ = mknode2(&node_muleq, $1, $3);}
$$.c = abc_getslot($$.c, f->slot);
} else {
if(!f) {
- as3_warning("Access of undefined property '%s' in %s", $3, t->name);
+ as3_softwarning("Access of undefined property '%s' in %s", $3, t->name);
}
-
MEMBER_MULTINAME(m, f, $3);
$$.c = abc_getproperty2($$.c, &m);
}
$$.t = slotinfo_gettype((slotinfo_t*)f);
if(!$$.t)
$$.c = abc_coerce_a($$.c);
+
} else if(v1.c && v1.c->opcode == OPCODE___PUSHPACKAGE__) {
string_t*package = v1.c->data[0];
char*package2 = concat3(package->str, ".", $3);
multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $3};
$$.c = abc_getproperty2($$.c, &m);
$$.c = abc_coerce_a($$.c);
- $$.t = registry_getanytype();
+ $$.t = TYPE_ANY;
}
}
as3_schedule_class_noerror(state->package, $1);
PASS2
- $$.t = 0;
- $$.c = 0;
+ typedcode_t o;
+ o.t = 0;
+ o.c = 0;
+ $$ = 0;
+
slotinfo_t*a = 0;
memberinfo_t*f = 0;
/* look at variables */
if((v = find_variable(state, $1))) {
// $1 is a local variable
- $$.c = abc_getlocal($$.c, v->index);
- $$.t = v->type;
+ o.c = abc_getlocal(o.c, v->index);
+ o.t = v->type;
+ $$ = mkcodenode(o);
break;
}
if((v = find_slot(state, $1))) {
- $$.c = abc_getscopeobject($$.c, 1);
- $$.c = abc_getslot($$.c, v->index);
- $$.t = v->type;
+ o.c = abc_getscopeobject(o.c, 1);
+ o.c = abc_getslot(o.c, v->index);
+ o.t = v->type;
+ $$ = mkcodenode(o);
break;
}
/* look at current class' members */
if(!state->method->inner &&
state->cls &&
- (f = findmember_nsset(state->cls->info, $1, 1)) &&
- (f->flags&FLAG_STATIC) >= i_am_static)
+ (f = findmember_nsset(state->cls->info, $1, 1)))
{
- // $1 is a function in this class
+ // $1 is a member or attribute in this class
int var_is_static = (f->flags&FLAG_STATIC);
- if(f->kind == INFOTYPE_METHOD) {
- $$.t = TYPE_FUNCTION(f);
- } else {
- $$.t = f->type;
- }
- if(var_is_static && !i_am_static) {
- /* access to a static member from a non-static location.
- do this via findpropstrict:
- there doesn't seem to be any non-lookup way to access
- static properties of a class */
- state->method->late_binding = 1;
- $$.t = f->type;
- namespace_t ns = {f->access, f->package};
- multiname_t m = {QNAME, &ns, 0, $1};
- $$.c = abc_findpropstrict2($$.c, &m);
- $$.c = abc_getproperty2($$.c, &m);
- break;
- } else if(f->slot>0) {
- $$.c = abc_getlocal_0($$.c);
- $$.c = abc_getslot($$.c, f->slot);
- break;
- } else {
- namespace_t ns = {f->access, f->package};
- multiname_t m = {QNAME, &ns, 0, $1};
- $$.c = abc_getlocal_0($$.c);
- $$.c = abc_getproperty2($$.c, &m);
- break;
+ if(f->kind == INFOTYPE_VAR && (f->flags&FLAG_CONST)) {
+ /* if the variable is a constant (and we know what is evaluates to), we
+ can just use the value itself */
+ varinfo_t*v = (varinfo_t*)f;
+ if(v->value) {
+ $$ = mkconstnode(v->value);
+ break;
+ }
+ }
+
+ if(var_is_static >= i_am_static) {
+ if(f->kind == INFOTYPE_METHOD) {
+ o.t = TYPE_FUNCTION(f);
+ } else {
+ o.t = f->type;
+ }
+
+ if(var_is_static && !i_am_static) {
+ /* access to a static member from a non-static location.
+ do this via findpropstrict:
+ there doesn't seem to be any non-lookup way to access
+ static properties of a class */
+ state->method->late_binding = 1;
+ o.t = f->type;
+ namespace_t ns = {f->access, f->package};
+ multiname_t m = {QNAME, &ns, 0, $1};
+ o.c = abc_findpropstrict2(o.c, &m);
+ o.c = abc_getproperty2(o.c, &m);
+ $$ = mkcodenode(o);
+ break;
+ } else if(f->slot>0) {
+ o.c = abc_getlocal_0(o.c);
+ o.c = abc_getslot(o.c, f->slot);
+ $$ = mkcodenode(o);
+ break;
+ } else {
+ namespace_t ns = {f->access, f->package};
+ multiname_t m = {QNAME, &ns, 0, $1};
+ o.c = abc_getlocal_0(o.c);
+ o.c = abc_getproperty2(o.c, &m);
+ $$ = mkcodenode(o);
+ break;
+ }
}
}
/* look at actual classes, in the current package and imported */
if((a = find_class($1))) {
- $$ = push_class(a);
+ o = push_class(a);
+ $$ = mkcodenode(o);
break;
}
/* look through package prefixes */
if(dict_contains(state->import_toplevel_packages, $1) ||
registry_ispackage($1)) {
- $$.c = abc___pushpackage__($$.c, $1);
- $$.t = 0;
+ o.c = abc___pushpackage__(o.c, $1);
+ o.t = 0;
+ $$ = mkcodenode(o); //?
break;
}
multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $1};
- $$.t = 0;
- $$.c = abc_findpropstrict2($$.c, &m);
- $$.c = abc_getproperty2($$.c, &m);
+ o.t = 0;
+ o.c = abc_findpropstrict2(o.c, &m);
+ o.c = abc_getproperty2(o.c, &m);
+ $$ = mkcodenode(o);
+ break;
}
}
syntaxerror("Couldn't resolve namespace %s", $3->name);
}
- if(!s || s->kind != INFOTYPE_SLOT)
+ if(!s || s->kind != INFOTYPE_VAR)
syntaxerror("%s.%s is not a public namespace (%d)", $3->package, $3->name, s?s->kind:-1);
if(!s->value || !NS_TYPE(s->value->type))
syntaxerror("%s.%s is not a namespace", $3->package, $3->name);