#include "abc.h"
#include "pool.h"
#include "files.h"
+#include "common.h"
#include "tokenizer.h"
#include "registry.h"
#include "code.h"
#include "opcodes.h"
#include "compiler.h"
+#include "ast.h"
extern int a3_lex();
%token<token> T_EMPTY
%token<number_int> T_INT
%token<number_uint> T_UINT
-%token<number_uint> T_BYTE
-%token<number_uint> T_SHORT
%token<number_float> T_FLOAT
%token<id> T_FOR "for"
%token<token> KW_FUNCTION "function"
%token<token> KW_FINALLY "finally"
%token<token> KW_UNDEFINED "undefined"
+%token<token> KW_NAN "NaN"
%token<token> KW_CONTINUE "continue"
%token<token> KW_CLASS "class"
%token<token> KW_CONST "const"
%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
%type <value> EXPRESSION NONCOMMAEXPRESSION
%type <value> MAYBEEXPRESSION
%type <value> E DELETE
-%type <value> CONSTANT
%type <code> FOR FOR_IN IF WHILE DO_WHILE MAYBEELSE BREAK RETURN CONTINUE TRY
%type <value> INNERFUNCTION
%type <code> USE_NAMESPACE
%type <flags> MAYBE_MODIFIERS
%type <flags> MODIFIER_LIST
%type <flags> MODIFIER
-%type <constant> STATICCONSTANT MAYBESTATICCONSTANT
+%type <constant> CONSTANT MAYBECONSTANT
%type <classinfo_list> IMPLEMENTS_LIST
%type <classinfo> EXTENDS CLASS_SPEC
%type <classinfo_list> EXTENDS_LIST
// needed for "return" precedence:
%nonassoc T_STRING T_REGEXP
-%nonassoc T_INT T_UINT T_BYTE T_SHORT T_FLOAT
+%nonassoc T_INT T_UINT T_FLOAT KW_NAN
%nonassoc "false" "true" "null" "undefined" "super" "function"
%left above_function
return 0; //make gcc happy
}
+static void parsererror(const char*file, int line, const char*f)
+{
+ syntaxerror("internal error in %s, %s:%d", f, file, line);
+}
+
+#define parserassert(b) {if(!(b)) parsererror(__FILE__, __LINE__,__func__);}
+
static char* concat2(const char* t1, const char* t2)
{
typedef struct _import {
char*package;
} import_t;
-
DECLARE_LIST(import);
DECLARE(methodstate);
static namespace_list_t nl1 = {&ns1,&nl2};
static namespace_set_t nopackage_namespace_set = {&nl1};
+static dict_t*definitions=0;
+void as3_set_definition(const char*c)
+{
+ if(!definitions)
+ definitions = dict_new();
+ if(!dict_contains(definitions,c))
+ dict_put(definitions,c,0);
+}
+
static void new_state()
{
NEW(state_t, s);
if(oldstate)
state->active_namespace_urls = list_clone(oldstate->active_namespace_urls);
}
-static void state_has_imports()
-{
- state->wildcard_imports = list_clone(state->wildcard_imports);
- state->imports = dict_clone(state->imports);
- state->has_own_imports = 1;
-}
-static void import_toplevel(const char*package)
-{
- char* s = strdup(package);
- while(1) {
- dict_put(state->import_toplevel_packages, s, 0);
- char*x = strrchr(s, '.');
- if(!x)
- break;
- *x = 0;
- }
- free(s);
-}
static void state_destroy(state_t*state)
{
void* finish_parser()
{
dict_free_all(global->file2token2info, 1, (void*)dict_destroy);
-
global->token2info=0;
-
return global->file;
}
-
-static void xx_scopetest()
-{
- /* findpropstrict doesn't just return a scope object- it
- also makes it "active" somehow. Push local_0 on the
- scope stack and read it back with findpropstrict, it'll
- contain properties like "trace". Trying to find the same
- property on a "vanilla" local_0 yields only a "undefined" */
- //c = abc_findpropstrict(c, "[package]::trace");
-
- /*c = abc_getlocal_0(c);
- c = abc_findpropstrict(c, "[package]::trace");
- c = abc_coerce_a(c);
- c = abc_setlocal_1(c);
-
- c = abc_pushbyte(c, 0);
- c = abc_setlocal_2(c);
-
- code_t*xx = c = abc_label(c);
- c = abc_findpropstrict(c, "[package]::trace");
- c = abc_pushstring(c, "prop:");
- c = abc_hasnext2(c, 1, 2);
- c = abc_dup(c);
- c = abc_setlocal_3(c);
- c = abc_callpropvoid(c, "[package]::trace", 2);
- c = abc_getlocal_3(c);
- c = abc_kill(c, 3);
- c = abc_iftrue(c,xx);*/
-}
-
typedef struct _variable {
int index;
classinfo_t*type;
syntaxerror("undefined variable: %s", name);
return v;
}
+
static char variable_exists(char*name)
{
return dict_contains(state->vars, name);
}
-code_t*defaultvalue(code_t*c, classinfo_t*type);
+
+static code_t*defaultvalue(code_t*c, classinfo_t*type)
+{
+ if(TYPE_IS_INT(type)) {
+ c = abc_pushbyte(c, 0);
+ } else if(TYPE_IS_UINT(type)) {
+ c = abc_pushuint(c, 0);
+ } else if(TYPE_IS_FLOAT(type)) {
+ c = abc_pushnan(c);
+ } else if(TYPE_IS_BOOLEAN(type)) {
+ c = abc_pushfalse(c);
+ } else if(!type) {
+ //c = abc_pushundefined(c);
+ syntaxerror("internal error: can't generate default value for * type");
+ } else {
+ c = abc_pushnull(c);
+ MULTINAME(m, type);
+ c = abc_coerce2(c, &m);
+ }
+ return c;
+}
static int alloc_local()
{
return new_variable(TEMPVARNAME, 0, 0, 0);
}
-code_t* var_block(code_t*body)
+static code_t* var_block(code_t*body)
{
code_t*c = 0;
code_t*k = 0;
return c;
}
-void unknown_variable(char*name)
+static void unknown_variable(char*name)
{
if(!state->method->unresolved_variables)
state->method->unresolved_variables = dict_new();
dict_put(state->method->unresolved_variables, name, 0);
}
-#define parserassert(b) {if(!(b)) parsererror(__FILE__, __LINE__,__func__);}
-
-static void parsererror(const char*file, int line, const char*f)
-{
- syntaxerror("internal error in %s, %s:%d", f, file, line);
-}
-
-
static code_t* add_scope_code(code_t*c, methodstate_t*m, char init)
{
if(m->uses_slots || (m->late_binding && !m->inner)) { //???? especially inner functions need the pushscope
return c;
}
-
static void startpackage(char*name)
{
new_state();
- /*printf("entering package \"%s\"\n", name);*/
state->package = strdup(name);
}
static void endpackage()
{
- /*printf("leaving package \"%s\"\n", state->package);*/
-
//used e.g. in classinfo_register:
//free(state->package);state->package=0;
-
old_state();
}
return registry_findmember_nsset(cls, state->active_namespace_urls, name, recurse);
}
-void add_active_url(const char*url)
-{
- NEW(namespace_t,n);
- n->name = url;
- list_append(state->active_namespace_urls, n);
-}
-
static void function_initvars(methodstate_t*m, params_t*params, int flags, char var0)
{
if(var0) {
v->is_parameter = 1;
}
}
- if(m->uses_slots) {
- dict_dump(m->slots, stdout, "");
- }
methodstate_list_t*l = m->innerfunctions;
while(l) {
}
}
-static int slotstate_varconst = 0;
-static modifiers_t*slotstate_flags = 0;
-static void setslotstate(modifiers_t* flags, int varconst)
-{
- slotstate_varconst = varconst;
- slotstate_flags = flags;
- if(state->cls) {
- if(flags && flags->flags&FLAG_STATIC) {
- state->method = state->cls->static_init;
- } else {
- state->method = state->cls->init;
- }
- } else {
- parserassert(state->method);
- }
-}
-
static void endclass()
{
if(as3_pass == 2) {
char*name = string_cstr(c->data[0]);
syntaxerror("Unresolved \"continue %s\"", name);
}
+ if(c->opcode == OPCODE___RETHROW__) {
+ syntaxerror("Unresolved \"rethrow\"");
+ }
+ if(c->opcode == OPCODE___FALLTHROUGH__) {
+ syntaxerror("Unresolved \"fallthrough\"");
+ }
if(c->opcode == OPCODE___PUSHPACKAGE__) {
char*name = string_cstr(c->data[0]);
syntaxerror("Can't reference a package (%s) as such", name);
}
}
-
static void check_constant_against_type(classinfo_t*t, constant_t*c)
{
- return;
#define xassert(b) if(!(b)) syntaxerror("Invalid default value %s for type '%s'", constant_tostring(c), t->name)
if(TYPE_IS_NUMBER(t)) {
xassert(c->type == CONSTANT_FLOAT
//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);
return 0;
}
-char is_subtype_of(classinfo_t*type, classinfo_t*supertype)
-{
- return 1; // FIXME
-}
-
void breakjumpsto(code_t*c, char*name, code_t*jump)
{
while(c) {
}
}
+/* TODO: move this to ast.c */
#define IS_INT(a) (TYPE_IS_INT((a)) || TYPE_IS_UINT((a)))
#define IS_NUMBER_OR_INT(a) (TYPE_IS_INT((a)) || TYPE_IS_UINT((a)) || TYPE_IS_NUMBER((a)))
#define BOTH_INT(a,b) (IS_INT(a) && IS_INT(b))
-
-classinfo_t*join_types(classinfo_t*type1, classinfo_t*type2, char op)
+static classinfo_t*join_types(classinfo_t*type1, classinfo_t*type2, char op)
{
if(!type1 || !type2)
return registry_getanytype();
return type1;
return registry_getanytype();
}
+static char is_getlocal(code_t*c)
+{
+ if(!c || c->prev || c->next)
+ return 0;
+ return(c->opcode == OPCODE_GETLOCAL
+ || c->opcode == OPCODE_GETLOCAL_0
+ || c->opcode == OPCODE_GETLOCAL_1
+ || c->opcode == OPCODE_GETLOCAL_2
+ || c->opcode == OPCODE_GETLOCAL_3);
+}
+static int getlocalnr(code_t*c)
+{
+ if(c->opcode == OPCODE_GETLOCAL) {return (ptroff_t)c->data[0];}
+ else if(c->opcode == OPCODE_GETLOCAL_0) {return 0;}
+ else if(c->opcode == OPCODE_GETLOCAL_1) {return 1;}
+ else if(c->opcode == OPCODE_GETLOCAL_2) {return 2;}
+ else if(c->opcode == OPCODE_GETLOCAL_3) {return 3;}
+ else syntaxerror("Internal error: opcode %02x is not a getlocal call", c->opcode);
+ return 0;
+}
code_t*converttype(code_t*c, classinfo_t*from, classinfo_t*to)
{
if(from==to)
if((TYPE_IS_NUMBER(from) || TYPE_IS_UINT(from) || TYPE_IS_INT(from)) &&
(TYPE_IS_NUMBER(to) || TYPE_IS_UINT(to) || TYPE_IS_INT(to))) {
// allow conversion between number types
+ if(TYPE_IS_UINT(to))
+ return abc_convert_u(c);
+ else if(TYPE_IS_INT(to))
+ return abc_convert_i(c);
+ else if(TYPE_IS_NUMBER(to))
+ return abc_convert_d(c);
return abc_coerce2(c, &m);
}
- //printf("%s.%s\n", from.package, from.name);
- //printf("%s.%s\n", to.package, to.name);
+
+ if(TYPE_IS_BOOLEAN(to))
+ return abc_convert_b(c);
+ if(TYPE_IS_STRING(to))
+ return abc_convert_s(c);
+ if(TYPE_IS_OBJECT(to))
+ return abc_convert_o(c);
classinfo_t*supertype = from;
while(supertype) {
return c;
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;
-}
+ from->package, from->package[0]?".":"", from->name,
+ to->package, to->package[0]?".":"", to->name);
-code_t*defaultvalue(code_t*c, classinfo_t*type)
-{
- if(TYPE_IS_INT(type)) {
- c = abc_pushbyte(c, 0);
- } else if(TYPE_IS_UINT(type)) {
- c = abc_pushuint(c, 0);
- } else if(TYPE_IS_FLOAT(type)) {
- c = abc_pushnan(c);
- } else if(TYPE_IS_BOOLEAN(type)) {
- c = abc_pushfalse(c);
- } else if(!type) {
- //c = abc_pushundefined(c);
- } else {
- c = abc_pushnull(c);
- MULTINAME(m, type);
- c = abc_coerce2(c, &m);
- }
return c;
}
+/* move to ast.c todo end */
char is_pushundefined(code_t*c)
{
return x;
}
-static char is_getlocal(code_t*c)
-{
- if(!c || c->prev || c->next)
- return 0;
- return(c->opcode == OPCODE_GETLOCAL
- || c->opcode == OPCODE_GETLOCAL_0
- || c->opcode == OPCODE_GETLOCAL_1
- || c->opcode == OPCODE_GETLOCAL_2
- || c->opcode == OPCODE_GETLOCAL_3);
-}
-static int getlocalnr(code_t*c)
-{
- if(c->opcode == OPCODE_GETLOCAL) {return (ptroff_t)c->data[0];}
- else if(c->opcode == OPCODE_GETLOCAL_0) {return 0;}
- else if(c->opcode == OPCODE_GETLOCAL_1) {return 1;}
- else if(c->opcode == OPCODE_GETLOCAL_2) {return 2;}
- else if(c->opcode == OPCODE_GETLOCAL_3) {return 3;}
- else syntaxerror("Internal error: opcode %02x is not a getlocal call", c->opcode);
- return 0;
-}
-static code_t* toreadwrite(code_t*in, code_t*middlepart, char justassign, char readbefore)
+code_t* toreadwrite(code_t*in, code_t*middlepart, char justassign, char readbefore, char pushvalue)
{
/* converts this:
temp = gettempvar();
c = code_append(c, prefix);
c = code_append(c, r);
- if(readbefore) {
+ if(pushvalue && readbefore) {
c = abc_dup(c);
c = abc_setlocal(c, temp);
}
c = code_append(c, middlepart);
- if(!readbefore) {
+ if(pushvalue && !readbefore) {
c = abc_dup(c);
c = abc_setlocal(c, temp);
}
c = code_append(c, write);
- c = abc_getlocal(c, temp);
- c = abc_kill(c, temp);
+ if(pushvalue) {
+ c = abc_getlocal(c, temp);
+ c = abc_kill(c, temp);
+ }
} else {
/* if we're allowed to execute the read code twice *and*
the middlepart doesn't modify the code, things are easier.
*/
- code_t* r2 = code_dup(r);
//c = code_append(c, prefix);
parserassert(!prefix);
+ code_t* r2 = 0;
+ if(pushvalue) {
+ r2 = code_dup(r);
+ }
c = code_append(c, r);
c = code_append(c, middlepart);
c = code_append(c, write);
- c = code_append(c, r2);
+ if(pushvalue) {
+ c = code_append(c, r2);
+ }
}
} else {
/* even smaller version: overwrite the value without reading
}
c = code_append(c, middlepart);
c = code_append(c, write);
- c = code_append(c, r);
+ if(pushvalue) {
+ c = code_append(c, r);
+ }
} else {
code_free(r);r=0;
temp = gettempvar();
c = code_append(c, prefix);
}
c = code_append(c, middlepart);
- c = abc_dup(c);
- c = abc_setlocal(c, temp);
+ if(pushvalue) {
+ c = abc_dup(c);
+ c = abc_setlocal(c, temp);
+ }
c = code_append(c, write);
- c = abc_getlocal(c, temp);
- c = abc_kill(c, temp);
+ if(pushvalue) {
+ c = abc_getlocal(c, temp);
+ c = abc_kill(c, temp);
+ }
}
}
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(!definitions || !dict_contains(definitions, key)) {
+ as3_pass=0;
+ }
+ free(key);
+}
/* ------------ variables --------------------------- */
+%code {
+ char is_subtype_of(classinfo_t*type, classinfo_t*supertype)
+ {
+ return 1; // FIXME
+ }
+};
+
MAYBEEXPRESSION : '=' NONCOMMAEXPRESSION {$$=$2;}
| {$$.c=abc_pushundefined(0);
$$.t=TYPE_ANY;
PACKAGE_DECLARATION : "package" '{' {PASS12 startpackage("");}
MAYBE_INPACKAGE_CODE_LIST '}' {PASS12 endpackage();$$=0;}
+%code {
+ static void state_has_imports()
+ {
+ state->wildcard_imports = list_clone(state->wildcard_imports);
+ state->imports = dict_clone(state->imports);
+ state->has_own_imports = 1;
+ }
+ static void import_toplevel(const char*package)
+ {
+ char* s = strdup(package);
+ while(1) {
+ dict_put(state->import_toplevel_packages, s, 0);
+ char*x = strrchr(s, '.');
+ if(!x)
+ break;
+ *x = 0;
+ }
+ free(s);
+ }
+};
IMPORT : "import" PACKAGEANDCLASS {
PASS12
slotinfo_t*s = registry_find($2->package, $2->name);
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
/* ------------ classes and interfaces (body, slots ) ------- */
+%code {
+ static int slotstate_varconst = 0;
+ static modifiers_t*slotstate_flags = 0;
+ static void setslotstate(modifiers_t* flags, int varconst)
+ {
+ slotstate_varconst = varconst;
+ slotstate_flags = flags;
+ if(state->cls) {
+ if(flags && flags->flags&FLAG_STATIC) {
+ state->method = state->cls->static_init;
+ } else {
+ state->method = state->cls->init;
+ }
+ } else {
+ parserassert(state->method);
+ }
+ }
+};
+
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;
/* ------------ constants -------------------------------------- */
-MAYBESTATICCONSTANT: {$$=0;}
-MAYBESTATICCONSTANT: '=' STATICCONSTANT {$$=$2;}
-
-STATICCONSTANT : T_BYTE {$$ = constant_new_int($1);}
-STATICCONSTANT : T_INT {$$ = constant_new_int($1);}
-STATICCONSTANT : T_UINT {$$ = constant_new_uint($1);}
-STATICCONSTANT : T_FLOAT {$$ = constant_new_float($1);}
-STATICCONSTANT : T_STRING {$$ = constant_new_string2($1.str,$1.len);free((char*)$1.str);}
-//STATICCONSTANT : T_NAMESPACE {$$ = constant_new_namespace($1);}
-STATICCONSTANT : "true" {$$ = constant_new_true($1);}
-STATICCONSTANT : "false" {$$ = constant_new_false($1);}
-STATICCONSTANT : "null" {$$ = constant_new_null($1);}
-STATICCONSTANT : T_IDENTIFIER {
+MAYBECONSTANT: {$$=0;}
+MAYBECONSTANT: '=' CONSTANT {$$=$2;}
+
+//CONSTANT : T_NAMESPACE {$$ = constant_new_namespace($1);}
+CONSTANT : T_INT {$$ = constant_new_int($1);}
+CONSTANT : T_UINT {
+ $$ = constant_new_uint($1);
+}
+CONSTANT : T_FLOAT {$$ = constant_new_float($1);}
+CONSTANT : T_STRING {$$ = constant_new_string2($1.str,$1.len);free((char*)$1.str);}
+CONSTANT : "true" {$$ = constant_new_true($1);}
+CONSTANT : "false" {$$ = constant_new_false($1);}
+CONSTANT : "null" {$$ = constant_new_null($1);}
+CONSTANT : "undefined" {$$ = constant_new_undefined($1);}
+CONSTANT : KW_NAN {$$ = constant_new_float(__builtin_nan(""));}
+
+/*
+CONSTANT : T_IDENTIFIER {
if(!strcmp($1, "NaN")) {
$$ = constant_new_float(__builtin_nan(""));
} else {
as3_warning("Couldn't evaluate constant value of %s", $1);
$$ = constant_new_null($1);
}
-}
+}*/
/* ------------ classes and interfaces (body, functions) ------- */
list_append($$.list, $1);
}
-PARAM: T_IDENTIFIER ':' TYPE MAYBESTATICCONSTANT {
+PARAM: T_IDENTIFIER ':' TYPE MAYBECONSTANT {
PASS12
$$ = rfx_calloc(sizeof(param_t));
$$->name=$1;
PASS2
$$->value = $4;
}
-PARAM: T_IDENTIFIER MAYBESTATICCONSTANT {
+PARAM: T_IDENTIFIER MAYBECONSTANT {
PASS12
$$ = rfx_calloc(sizeof(param_t));
$$->name=$1;
// ----------------------- expression evaluation -------------------------------------
E : INNERFUNCTION %prec prec_none {$$ = $1;}
-E : CONSTANT
-E : VAR_READ %prec T_IDENTIFIER {$$ = $1;}
-E : NEW {$$ = $1;}
-E : DELETE {$$ = $1;}
+E : VAR_READ %prec T_IDENTIFIER {$$ = $1;}
+E : NEW {$$ = $1;}
+E : DELETE {$$ = $1;}
E : FUNCTIONCALL
+E : CONSTANT {
+ node_t*n = mkconstnode($1);
+ $$ = node_read(n);
+}
+
E : T_REGEXP {
$$.c = 0;
namespace_t ns = {ACCESS_PACKAGE, ""};
$$.t = TYPE_REGEXP;
}
-CONSTANT : T_BYTE {$$.c = abc_pushbyte(0, $1);
- //MULTINAME(m, registry_getintclass());
- //$$.c = abc_coerce2($$.c, &m); // FIXME
- $$.t = TYPE_INT;
- }
-CONSTANT : T_SHORT {$$.c = abc_pushshort(0, $1);
- $$.t = TYPE_INT;
- }
-CONSTANT : T_INT {$$.c = abc_pushint(0, $1);
- $$.t = TYPE_INT;
- }
-CONSTANT : T_UINT {$$.c = abc_pushuint(0, $1);
- $$.t = TYPE_UINT;
- }
-CONSTANT : T_FLOAT {$$.c = abc_pushdouble(0, $1);
- $$.t = TYPE_FLOAT;
- }
-CONSTANT : T_STRING {$$.c = abc_pushstring2(0, &$1);free((char*)$1.str);
- $$.t = TYPE_STRING;
- }
-CONSTANT : "undefined" {$$.c = abc_pushundefined(0);
- $$.t = TYPE_ANY;
- }
-CONSTANT : "true" {$$.c = abc_pushtrue(0);
- $$.t = TYPE_BOOLEAN;
- }
-CONSTANT : "false" {$$.c = abc_pushfalse(0);
- $$.t = TYPE_BOOLEAN;
- }
-CONSTANT : "null" {$$.c = abc_pushnull(0);
- $$.t = TYPE_NULL;
- }
-
E : E '<' E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterequals($$.c);$$.c=abc_not($$.c);
$$.t = TYPE_BOOLEAN;
}
E : '(' EXPRESSION ')' {$$=$2;} //allow commas in here, too
E : '-' E {
- $$=$2;
+ $$.c = $2.c;
if(IS_INT($2.t)) {
$$.c=abc_negate_i($$.c);
$$.t = TYPE_INT;
c=abc_multiply(c);
}
c=converttype(c, join_types($1.t, $3.t, '*'), $1.t);
- $$.c = toreadwrite($1.c, c, 0, 0);
+ $$.c = toreadwrite($1.c, c, 0, 0, 1);
$$.t = $1.t;
}
E : E "%=" E {
code_t*c = abc_modulo($3.c);
c=converttype(c, join_types($1.t, $3.t, '%'), $1.t);
- $$.c = toreadwrite($1.c, c, 0, 0);
+ $$.c = toreadwrite($1.c, c, 0, 0, 1);
$$.t = $1.t;
}
E : E "<<=" E {
code_t*c = abc_lshift($3.c);
c=converttype(c, join_types($1.t, $3.t, '<'), $1.t);
- $$.c = toreadwrite($1.c, c, 0, 0);
+ $$.c = toreadwrite($1.c, c, 0, 0, 1);
$$.t = $1.t;
}
E : E ">>=" E {
code_t*c = abc_rshift($3.c);
c=converttype(c, join_types($1.t, $3.t, '>'), $1.t);
- $$.c = toreadwrite($1.c, c, 0, 0);
+ $$.c = toreadwrite($1.c, c, 0, 0, 1);
$$.t = $1.t;
}
E : E ">>>=" E {
code_t*c = abc_urshift($3.c);
c=converttype(c, join_types($1.t, $3.t, 'U'), $1.t);
- $$.c = toreadwrite($1.c, c, 0, 0);
+ $$.c = toreadwrite($1.c, c, 0, 0, 1);
$$.t = $1.t;
}
E : E "/=" E {
code_t*c = abc_divide($3.c);
c=converttype(c, join_types($1.t, $3.t, '/'), $1.t);
- $$.c = toreadwrite($1.c, c, 0, 0);
+ $$.c = toreadwrite($1.c, c, 0, 0, 1);
$$.t = $1.t;
}
E : E "|=" E {
code_t*c = abc_bitor($3.c);
c=converttype(c, TYPE_INT, $1.t);
- $$.c = toreadwrite($1.c, c, 0, 0);
+ $$.c = toreadwrite($1.c, c, 0, 0, 1);
$$.t = $1.t;
}
E : E "^=" E {
code_t*c = abc_bitxor($3.c);
c=converttype(c, TYPE_INT, $1.t);
- $$.c = toreadwrite($1.c, c, 0, 0);
+ $$.c = toreadwrite($1.c, c, 0, 0, 1);
$$.t = $1.t;
}
E : E "+=" E {
c=converttype(c, join_types($1.t, $3.t, '+'), $1.t);
}
- $$.c = toreadwrite($1.c, c, 0, 0);
+ $$.c = toreadwrite($1.c, c, 0, 0, 1);
$$.t = $1.t;
}
E : E "-=" E { code_t*c = $3.c;
c=converttype(c, join_types($1.t, $3.t, '-'), $1.t);
}
- $$.c = toreadwrite($1.c, c, 0, 0);
+ $$.c = toreadwrite($1.c, c, 0, 0, 1);
$$.t = $1.t;
}
E : E '=' E { code_t*c = 0;
c = code_append(c, $3.c);
c = converttype(c, $3.t, $1.t);
- $$.c = toreadwrite($1.c, c, 1, 0);
+ $$.c = toreadwrite($1.c, c, 1, 0, 1);
$$.t = $1.t;
}
type = TYPE_NUMBER;
}
c=converttype(c, type, $1.t);
- $$.c = toreadwrite($1.c, c, 0, 1);
+ $$.c = toreadwrite($1.c, c, 0, 1, 1);
$$.t = $1.t;
}
}
type = TYPE_NUMBER;
}
c=converttype(c, type, $1.t);
- $$.c = toreadwrite($1.c, c, 0, 1);
+ $$.c = toreadwrite($1.c, c, 0, 1, 1);
$$.t = $1.t;
}
type = TYPE_NUMBER;
}
c=converttype(c, type, $2.t);
- $$.c = toreadwrite($2.c, c, 0, 0);
+ $$.c = toreadwrite($2.c, c, 0, 0, 1);
$$.t = $2.t;
}
type = TYPE_NUMBER;
}
c=converttype(c, type, $2.t);
- $$.c = toreadwrite($2.c, c, 0, 0);
+ $$.c = toreadwrite($2.c, c, 0, 0, 1);
$$.t = $2.t;
}
if(f && f->slot && !noslot) {
$$.c = abc_getslot($$.c, f->slot);
} else {
- if(!f)
+ if(!f) {
as3_warning("Access of undefined property '%s' in %s", $3, t->name);
+ }
MEMBER_MULTINAME(m, f, $3);
$$.c = abc_getproperty2($$.c, &m);
$$=0;
}
+%code {
+ void add_active_url(const char*url)
+ {
+ NEW(namespace_t,n);
+ n->name = url;
+ list_append(state->active_namespace_urls, n);
+ }
+};
+
USE_NAMESPACE : "use" "namespace" CLASS_SPEC {
PASS12
const char*url = $3->name;