%token<token> T_USHR ">>>"
%token<token> T_SHR ">>"
+%type <number_int> CONDITIONAL_COMPILATION
%type <for_start> FOR_START
%type <id> X_IDENTIFIER PACKAGE FOR_IN_INIT MAYBE_IDENTIFIER
%type <namespace_decl> NAMESPACE_ID
static namespace_list_t nl1 = {&ns1,&nl2};
static namespace_set_t nopackage_namespace_set = {&nl1};
+dict_t*conditionals=0;
+void as3_set_definition(const char*c)
+{
+ if(!conditionals)
+ conditionals = dict_new();
+ if(!dict_contains(conditionals,c))
+ dict_put(conditionals,c,0);
+}
+
static void new_state()
{
NEW(state_t, s);
int index;
classinfo_t*type;
char init;
+ char is_parameter;
methodstate_t*is_inner_method;
} variable_t;
c = abc_getlocal_0(c);
c = abc_constructsuper(c, 0);
}
+
+ if(m->slots) {
+ /* all parameters that are used by inner functions
+ need to be copied from local to slot */
+ parserassert(m->activation_var);
+ DICT_ITERATE_ITEMS(m->slots,char*,name,variable_t*,v) {
+ if(v->is_parameter) {
+ c = abc_getlocal(c, m->activation_var);
+ c = abc_getlocal(c, v->index);
+ c = abc_setslot(c, v->index);
+ }
+ }
+ }
list_free(m->innerfunctions);
m->innerfunctions = 0;
return c;
if(params) {
param_list_t*p=0;
for(p=params->list;p;p=p->next) {
- new_variable(p->param->name, p->param->type, 0, 1);
+ variable_t*v = new_variable2(p->param->name, p->param->type, 0, 1);
+ v->is_parameter = 1;
}
}
/* exchange unresolved identifiers with the actual objects */
DICT_ITERATE_ITEMS(m->slots, char*, name, variable_t*, v) {
if(v->type && v->type->kind == INFOTYPE_UNRESOLVED) {
- v->type = (classinfo_t*)registry_resolve((slotinfo_t*)v->type);
- if(!v->type || v->type->kind != INFOTYPE_CLASS) {
- syntaxerror("Couldn't find class %s", v->type->name);
+ classinfo_t*type = (classinfo_t*)registry_resolve((slotinfo_t*)v->type);
+ if(!type || type->kind != INFOTYPE_CLASS) {
+ syntaxerror("Couldn't find class %s::%s (%s)", v->type->package, v->type->name, name);
}
+ v->type = type;
}
}
}
//class method
memberinfo_t* m = registry_findmember(state->cls->info, ns.name, name, 0);
if(m) {
- printf("%s.%s | %s.%s\n",
- m->package, m->name,
- ns.name, name);
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);
as3_error("can't convert type %s%s%s to %s%s%s",
from->package, from->package?".":"", from->name,
to->package, to->package?".":"", to->name);
+
return c;
}
#define PASS1 }} if(as3_pass == 1) {{
#define PASS1END }} if(as3_pass == 2) {{
#define PASS2 }} if(as3_pass == 2) {{
-#define PASS12 }} {{
+#define PASS12 }} if(as3_pass == 1 || as3_pass == 2) {{
#define PASS12END }} if(as3_pass == 2) {{
+#define PASS_ALWAYS }} {{
%}
| FUNCTION_DECLARATION
| SLOT_DECLARATION
| PACKAGE_INITCODE
- | CONDITIONAL_COMPILATION '{' MAYBE_PROGRAM_CODE_LIST '}' // conditional compilation
+ | CONDITIONAL_COMPILATION '{' MAYBE_PROGRAM_CODE_LIST '}' {PASS_ALWAYS as3_pass=$1;}
| ';'
MAYBE_INPACKAGE_CODE_LIST: | INPACKAGE_CODE_LIST
| FUNCTION_DECLARATION
| SLOT_DECLARATION
| PACKAGE_INITCODE
- | CONDITIONAL_COMPILATION '{' MAYBE_INPACKAGE_CODE_LIST '}' // conditional compilation
+ | CONDITIONAL_COMPILATION '{' MAYBE_INPACKAGE_CODE_LIST '}' {PASS_ALWAYS as3_pass=$1;}
| ';'
MAYBECODE: CODE {$$=$1;}
CODEPIECE: CONTINUE
CODEPIECE: RETURN
CODEPIECE: THROW
-CODEPIECE: CONDITIONAL_COMPILATION '{' CODE '}' {$$=$3;}
+CODEPIECE: CONDITIONAL_COMPILATION '{' CODE '}' {PASS_ALWAYS as3_pass=$1;}
//CODEBLOCK : '{' CODE '}' {$$=$2;}
//CODEBLOCK : '{' '}' {$$=0;}
/* ------------ conditional compilation ------------- */
-CONDITIONAL_COMPILATION: T_IDENTIFIER "::" T_IDENTIFIER
+CONDITIONAL_COMPILATION: T_IDENTIFIER "::" T_IDENTIFIER {
+ PASS12
+ $$=as3_pass;
+ char*key = concat3($1,"::",$3);
+ if(!conditionals || !dict_contains(conditionals, key)) {
+ as3_pass=0;
+ }
+ free(key);
+}
/* ------------ variables --------------------------- */
if(!s && as3_pass==1) {// || !(s->flags&FLAG_BUILTIN)) {
as3_schedule_class($2->package, $2->name);
}
-
- PASS2
classinfo_t*c = $2;
if(!c)
syntaxerror("Couldn't import class\n");
as3_schedule_package($2);
}
- PASS2
NEW(import_t,i);
i->package = $2;
state_has_imports();
CLASS_BODY : CLASS_BODY_ITEM
CLASS_BODY : CLASS_BODY CLASS_BODY_ITEM
CLASS_BODY_ITEM : ';'
-CLASS_BODY_ITEM : CONDITIONAL_COMPILATION '{' MAYBE_CLASS_BODY '}'
+CLASS_BODY_ITEM : CONDITIONAL_COMPILATION '{' MAYBE_CLASS_BODY '}' {PASS_ALWAYS as3_pass=$1;}
CLASS_BODY_ITEM : SLOT_DECLARATION
CLASS_BODY_ITEM : FUNCTION_DECLARATION
VARCONST: "var" | "const"
-SLOT_DECLARATION: MAYBE_MODIFIERS VARCONST {setslotstate(&$1,$2);} SLOT_LIST {$$=$4;setslotstate(0, 0);}
+SLOT_DECLARATION: MAYBE_MODIFIERS VARCONST {PASS12 setslotstate(&$1,$2);} SLOT_LIST {PASS12 $$=$4;setslotstate(0, 0);}
-SLOT_LIST: ONE_SLOT {$$ = $1;}
-SLOT_LIST: SLOT_LIST ',' ONE_SLOT {$$ = code_append($1, $3);}
+SLOT_LIST: ONE_SLOT {PASS12 $$=0;}
+SLOT_LIST: SLOT_LIST ',' ONE_SLOT {PASS12 $$=0;}
ONE_SLOT: T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION
{
+PASS12
int flags = slotstate_flags->flags;
namespace_t ns = modifiers2access(slotstate_flags);
- varinfo_t* info = 0;
- if(state->cls) {
- memberinfo_t*i = registry_findmember(state->cls->info, ns.name, $1, 1);
- if(i) {
- check_override(i, flags);
- }
- info = varinfo_register_onclass(state->cls->info, ns.access, ns.name, $1);
- } else {
- slotinfo_t*i = registry_find(state->package, $1);
- if(i) {
- syntaxerror("package %s already contains '%s'", state->package, $1);
- }
- if(ns.name && ns.name[0]) {
- syntaxerror("namespaces not allowed on package-level variables");
- }
- info = varinfo_register_global(ns.access, state->package, $1);
- }
+ if(as3_pass == 1) {
- info->type = $2;
- info->flags = flags;
+ varinfo_t* info = 0;
+ if(state->cls) {
+ memberinfo_t*i = registry_findmember(state->cls->info, ns.name, $1, 1);
+ if(i) {
+ check_override(i, flags);
+ }
+ info = varinfo_register_onclass(state->cls->info, ns.access, ns.name, $1);
+ } else {
+ slotinfo_t*i = registry_find(state->package, $1);
+ if(i) {
+ syntaxerror("package %s already contains '%s'", state->package, $1);
+ }
+ if(ns.name && ns.name[0]) {
+ syntaxerror("namespaces not allowed on package-level variables");
+ }
+ info = varinfo_register_global(ns.access, state->package, $1);
+ }
- /* slot name */
- multiname_t mname = {QNAME, &ns, 0, $1};
-
- trait_list_t**traits;
- code_t**code;
- if(!state->cls) {
- // global variable
- ns.name = state->package;
- traits = &global->init->traits;
- code = &global->init->method->body->code;
- } else if(flags&FLAG_STATIC) {
- // static variable
- traits = &state->cls->abc->static_traits;
- code = &state->cls->static_init->header;
- } else {
- // instance variable
- traits = &state->cls->abc->traits;
- code = &state->cls->init->header;
- }
-
- trait_t*t=0;
- if($2) {
- MULTINAME(m, $2);
- t = trait_new_member(traits, multiname_clone(&m), multiname_clone(&mname), 0);
- } else {
- 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);
+ info->type = $2;
+ info->flags = flags;
+
+ dict_put(global->token2info, (void*)(ptroff_t)as3_tokencount, info);
}
- *code = code_append(*code, c);
+ if(as3_pass == 2) {
+ varinfo_t*info = dict_lookup(global->token2info, (void*)(ptroff_t)as3_tokencount);
+
+ /* slot name */
+ multiname_t mname = {QNAME, &ns, 0, $1};
+
+ trait_list_t**traits;
+ code_t**code;
+ if(!state->cls) {
+ // global variable
+ ns.name = state->package;
+ traits = &global->init->traits;
+ code = &global->init->method->body->code;
+ } else if(flags&FLAG_STATIC) {
+ // static variable
+ traits = &state->cls->abc->static_traits;
+ code = &state->cls->static_init->header;
+ } else {
+ // instance variable
+ traits = &state->cls->abc->traits;
+ code = &state->cls->init->header;
+ }
+
+ trait_t*t=0;
+ if($2) {
+ MULTINAME(m, $2);
+ t = trait_new_member(traits, multiname_clone(&m), multiname_clone(&mname), 0);
+ } else {
+ 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);
+ }
+
+ *code = code_append(*code, c);
- if(slotstate_varconst==KW_CONST) {
- t->kind= TRAIT_CONST;
+ if(slotstate_varconst==KW_CONST) {
+ t->kind= TRAIT_CONST;
+ }
}
$$=0;
c->nsset = get_current_imports();
/* make the compiler look for this class in the current directory,
just in case: */
- //as3_schedule_class_noerror(state->package, $1);
+ as3_schedule_class_noerror(state->package, $1);
}
$$ = (classinfo_t*)c;
PASS2
// ----------------------- expression evaluation -------------------------------------
E : INNERFUNCTION %prec prec_none {$$ = $1;}
-//V : CONSTANT {$$ = 0;}
E : CONSTANT
-//V : VAR_READ %prec T_IDENTIFIER {$$ = 0;}
E : VAR_READ %prec T_IDENTIFIER {$$ = $1;}
-//V : NEW {$$ = $1.c;}
E : NEW {$$ = $1;}
-//V : DELETE {$$ = $1.c;}
E : DELETE {$$ = $1;}
E : FUNCTIONCALL
as3_warning("ignored .() operator");
}
-//VARIABLE : VARIABLE "::" '[' EXPRESSION ']' // qualified expression
-
+//E : E "::" '[' E ']' {
+// // qualified expression TODO
+// $$.c = abc_pushundefined(0);
+// $$.t = 0;
+// as3_warning("ignored ::[] operator");
+// }
E : E '.' T_IDENTIFIER {
if(f && f->slot && !noslot) {
$$.c = abc_getslot($$.c, f->slot);
} else {
+ if(!f) {
+ as3_warning("Access of undefined property '%s' in %s", $3, t->name);
+ }
+
MEMBER_MULTINAME(m, f, $3);
$$.c = abc_getproperty2($$.c, &m);
}
/* when resolving a property on an unknown type, we do know the
name of the property (and don't seem to need the package), but
we need to make avm2 try out all access modes */
+ as3_warning("Resolving %s on unknown type", $3);
multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $3};
$$.c = abc_getproperty2($$.c, &m);
$$.c = abc_coerce_a($$.c);
/* let the compiler know that it might want to check the current directory/package
for this identifier- maybe there's a file $1.as defining $1. */
- //as3_schedule_class_noerror(state->package, $1);
+ as3_schedule_class_noerror(state->package, $1);
PASS2
$$.t = 0;
static properties of a class */
state->method->late_binding = 1;
$$.t = f->type;
- namespace_t ns = {f->access, ""};
+ namespace_t ns = {f->access, f->package};
multiname_t m = {QNAME, &ns, 0, $1};
$$.c = abc_findpropstrict2($$.c, &m);
$$.c = abc_getproperty2($$.c, &m);
$$.c = abc_getslot($$.c, f->slot);
break;
} else {
- namespace_t ns = {f->access, ""};
+ namespace_t ns = {f->access, f->package};
multiname_t m = {QNAME, &ns, 0, $1};
$$.c = abc_getlocal_0($$.c);
$$.c = abc_getproperty2($$.c, &m);
}
USE_NAMESPACE : "use" "namespace" CLASS_SPEC {
-
+ PASS12
const char*url = $3->name;
+
varinfo_t*s = (varinfo_t*)$3;
+ if(s->kind == INFOTYPE_UNRESOLVED) {
+ s = (varinfo_t*)registry_resolve((slotinfo_t*)s);
+ if(!s)
+ syntaxerror("Couldn't resolve namespace %s", $3->name);
+ }
+
if(!s || s->kind != INFOTYPE_SLOT)
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))