implemented asset resolving
[swftools.git] / lib / as3 / parser.y
index b1e81e8..b181866 100644 (file)
@@ -1,4 +1,4 @@
-/* parser.lex
+/* parser.y
 
    Routines for compiling Flash2 AVM2 ABC Actionscript
 
@@ -77,7 +77,7 @@ extern int a3_lex();
 }
 
 
-%token<id> T_IDENTIFIER T_NAMESPACE
+%token<id> T_IDENTIFIER
 %token<str> T_STRING
 %token<regexp> T_REGEXP
 %token<token> T_EMPTY
@@ -138,6 +138,7 @@ extern int a3_lex();
 %token<token> KW_NUMBER "Number"
 %token<token> KW_STRING "String"
 %token<token> KW_DEFAULT "default"
+%token<token> KW_DEFAULT_XML "default xml"
 %token<token> KW_DELETE "delete"
 %token<token> KW_IF "if"
 %token<token> KW_ELSE  "else"
@@ -175,14 +176,14 @@ extern int a3_lex();
 %token<token> T_USHR ">>>"
 %token<token> T_SHR ">>"
 
-%type <number_int> CONDITIONAL_COMPILATION
+%type <number_int> CONDITIONAL_COMPILATION EMBED_START
 %type <for_start> FOR_START
 %type <id> X_IDENTIFIER PACKAGE FOR_IN_INIT MAYBE_IDENTIFIER ID_OR_NS SUBNODE
 %type <namespace_decl>  NAMESPACE_ID
 %type <token> VARCONST
 %type <code> CODE
 %type <code> CODEPIECE CODE_STATEMENT
-%type <code> CODEBLOCK MAYBECODE MAYBE_CASE_LIST CASE_LIST DEFAULT CASE SWITCH WITH
+%type <code> CODEBLOCK IF_CODEBLOCK MAYBECODE MAYBE_CASE_LIST CASE_LIST DEFAULT CASE SWITCH WITH
 %type <code> PACKAGE_DECLARATION SLOT_DECLARATION SLOT_LIST ONE_SLOT
 %type <code> FUNCTION_DECLARATION PACKAGE_INITCODE
 %type <code> VARIABLE_DECLARATION ONE_VARIABLE VARIABLE_LIST THROW
@@ -199,7 +200,7 @@ extern int a3_lex();
 %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 <code> USE_NAMESPACE DEFAULT_NAMESPACE
 %type <code> FOR_INIT
 %type <code> IMPORT
 %type <classinfo> MAYBETYPE
@@ -216,7 +217,7 @@ extern int a3_lex();
 %type <classinfo_list> EXTENDS_LIST
 %type <classinfo> CLASS PACKAGEANDCLASS
 %type <classinfo_list> CLASS_SPEC_LIST
-%type <id> XML XML2 XMLNODE XMLATTRIBUTE XMLATTRIBUTES MAYBE_XMLATTRIBUTES XMLTEXT XML_ID_OR_EXPR XMLEXPR1 XMLEXPR2
+%type <node>  XMLEXPR1 XMLEXPR2 XML2 XMLNODE XMLATTRIBUTE XMLATTRIBUTES MAYBE_XMLATTRIBUTES XMLTEXT XML_ID_OR_EXPR XML
 %type <classinfo> TYPE
 //%type <token> VARIABLE
 %type <value> MEMBER
@@ -265,11 +266,10 @@ extern int a3_lex();
 
 // needed for "return" precedence:
 %nonassoc T_STRING T_REGEXP
-%nonassoc T_INT T_UINT T_FLOAT KW_NAN
+%nonassoc T_INT T_UINT T_FLOAT KW_NAN 
 %nonassoc "false" "true" "null" "undefined" "super" "function"
 %left above_function
 
-
      
 %{
 
@@ -327,6 +327,7 @@ typedef struct _classstate {
     methodstate_t*static_init;
     //code_t*init;
     //code_t*static_init;
+    parsedclass_t*dependencies;
 
     char has_constructor;
 } classstate_t;
@@ -343,9 +344,11 @@ struct _methodstate {
     int variable_count;
 
     dict_t*unresolved_variables;
+    dict_t*allvars; // all variables (in all sublevels, but not for inner functions)
 
     char inner;
     char uses_parent_function;
+    char no_variable_scoping;
     int uses_slots;
     dict_t*slots;
     int activation_var;
@@ -365,6 +368,23 @@ struct _methodstate {
     methodstate_list_t*innerfunctions;
 };
 
+methodstate_t*methodstate_new()
+{
+    NEW(methodstate_t,m);
+    m->allvars = dict_new();
+    return m;
+}
+void methodstate_destroy(methodstate_t*m) 
+{
+    dict_destroy(m->unresolved_variables); m->unresolved_variables = 0;
+    list_free(m->innerfunctions);m->innerfunctions=0;
+
+    if(m->allvars) {
+        DICT_ITERATE_DATA(m->allvars, void*, data) {free(data);}
+        m->allvars = 0;
+    }
+}
+
 typedef struct _state {
     struct _state*old;
     int level;
@@ -374,6 +394,7 @@ typedef struct _state {
     dict_t*import_toplevel_packages;
     dict_t*imports;
 
+    dict_t*namespaces;
     namespace_list_t*active_namespace_urls;
     
     char has_own_imports;
@@ -388,7 +409,6 @@ typedef struct _state {
     int switch_var;
     
     dict_t*vars;
-    dict_t*allvars; // also contains variables from sublevels
 } state_t;
 
 typedef struct _global {
@@ -482,7 +502,7 @@ static void new_state()
     state->old = oldstate;
     state->new_vars = 0;
 
-    trie_remember(active_namespaces);
+    state->namespaces = dict_new();
    
     if(oldstate)
         state->active_namespace_urls = list_clone(oldstate->active_namespace_urls);
@@ -500,13 +520,6 @@ static void state_destroy(state_t*state)
     if(state->vars) {
         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;
@@ -516,8 +529,6 @@ static void state_destroy(state_t*state)
 
 static void old_state()
 {
-    trie_rollback(active_namespaces);
-
     if(!state || !state->old)
         syntaxerror("invalid nesting");
     state_t*leaving = state;
@@ -525,8 +536,7 @@ static void old_state()
     state = state->old;
 
     if(as3_pass>1 && leaving->method && leaving->method != state->method && !leaving->method->inner) {
-        free(leaving->method);
-        leaving->method=0;
+        methodstate_destroy(leaving->method);leaving->method=0;
     }
     if(as3_pass>1 && leaving->cls && leaving->cls != state->cls) {
         free(leaving->cls);
@@ -548,11 +558,8 @@ void initialize_file(char*filename)
         syntaxerror("invalid call to initialize_file during parsing of another file");
     }
     
-    active_namespaces = trie_new();
-
     new_state();
     state->package = internal_filename_package = strdup(filename);
-    state->allvars = dict_new();
     
     global->token2info = dict_lookup(global->file2token2info, 
                                      current_filename // use long version
@@ -566,12 +573,14 @@ void initialize_file(char*filename)
         state->method = rfx_calloc(sizeof(methodstate_t));
         dict_put(global->token2info, (void*)(ptroff_t)as3_tokencount, state->method);
         state->method->late_binding = 1; // init scripts use getglobalscope, so we need a getlocal0/pushscope
+       state->method->allvars = dict_new();
     } else {
         state->method = dict_lookup(global->token2info, (void*)(ptroff_t)as3_tokencount);
+        state->method->variable_count = 0;
         if(!state->method)
             syntaxerror("internal error: skewed tokencount");
         function_initvars(state->method, 0, 0, 0, 1);
-        global->init = abc_initscript(global->file);
+        global->init = 0;
     }
 }
 
@@ -584,9 +593,12 @@ void finish_file()
     if(as3_pass==2) {
         dict_del(global->file2token2info, current_filename);
         code_t*header = method_header(state->method);
-        code_t*c = wrap_function(header, 0, global->init->method->body->code);
-        global->init->method->body->code = abc_returnvoid(c);
-        free(state->method);state->method=0;
+        //if(global->init->method->body->code || global->init->traits) {
+        if(global->init) {
+            code_t*c = wrap_function(header, 0, global->init->method->body->code);
+            global->init->method->body->code = abc_returnvoid(c);
+            free(state->method);state->method=0;
+        }
     }
 
     //free(state->package);state->package=0; // used in registry
@@ -617,26 +629,31 @@ typedef struct _variable {
     int index;
     classinfo_t*type;
     char init;
+    char kill;
     char is_parameter;
     methodstate_t*is_inner_method;
 } variable_t;
 
-static variable_t* find_variable(state_t*s, char*name)
+static variable_t* find_variable(state_t*s, const char*name)
 {
-    state_t*top = s;
-    while(s) {
-        variable_t*v = 0;
-        v = dict_lookup(s->vars, name);
-        if(v) return v;
-        if(s->new_vars) break;
-        s = s->old;
+    if(s->method->no_variable_scoping) {
+        return dict_lookup(s->method->allvars, name);
+    } else {
+        state_t*top = s;
+        while(s) {
+            variable_t*v = 0;
+            v = dict_lookup(s->vars, name);
+            if(v) return v;
+            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)
+static variable_t* find_slot(methodstate_t*m, const char*name)
 {
-    if(s->method && s->method->slots)
-        return dict_lookup(s->method->slots, name);
+    if(m && m->slots)
+        return dict_lookup(m->slots, name);
     return 0;
 }
 
@@ -655,6 +672,7 @@ static char variable_exists(char*name)
 
 static code_t*defaultvalue(code_t*c, classinfo_t*type)
 {
+    parserassert(!type || type->kind!=INFOTYPE_UNRESOLVED);
     if(TYPE_IS_INT(type)) {
        c = abc_pushbyte(c, 0);
     } else if(TYPE_IS_UINT(type)) {
@@ -663,6 +681,9 @@ static code_t*defaultvalue(code_t*c, classinfo_t*type)
        c = abc_pushnan(c);
     } else if(TYPE_IS_BOOLEAN(type)) {
        c = abc_pushfalse(c);
+    } else if(TYPE_IS_STRING(type)) {
+       c = abc_pushnull(c);
+       c = abc_coerce_s(c);
     } else if(!type) {
        //c = abc_pushundefined(c);
         syntaxerror("internal error: can't generate default value for * type");
@@ -679,29 +700,47 @@ static int alloc_local()
     return state->method->variable_count++;
 }
 
-static variable_t* new_variable2(const char*name, classinfo_t*type, char init, char maybeslot)
+static variable_t* new_variable2(methodstate_t*method, const char*name, classinfo_t*type, char init, char maybeslot)
 {
     if(maybeslot) {
-        variable_t*v = find_slot(state, name);
-        if(v)
+        variable_t*v = find_slot(method, name);
+        if(v) {
+            alloc_local(); 
             return v;
+        }
     }
 
     NEW(variable_t, v);
     v->index = alloc_local();
     v->type = type;
-    v->init = init;
+    v->init = v->kill = init;
  
     if(name) {
-        dict_put(state->vars, name, v);
-        dict_put(state->allvars, name, v);
+        if(!method->no_variable_scoping) 
+        {
+            if(dict_contains(state->vars, name)) {
+                syntaxerror("variable %s already defined", name);
+            }
+            dict_put(state->vars, name, v);
+        }
+        if(method->no_variable_scoping && 
+           as3_pass==2 && 
+           dict_contains(state->method->allvars, name)) 
+        {
+            variable_t*v = dict_lookup(state->method->allvars, name);
+            if(v->type != type && (!v->type || v->type->kind!=INFOTYPE_UNRESOLVED)) {
+                syntaxerror("variable %s already defined.", name);
+           }
+            return v;
+        }
+        dict_put(state->method->allvars, name, v);
     }
 
     return v;
 }
-static int new_variable(const char*name, classinfo_t*type, char init, char maybeslot)
+static int new_variable(methodstate_t*method, const char*name, classinfo_t*type, char init, char maybeslot)
 {
-    return new_variable2(name, type, init, maybeslot)->index;
+    return new_variable2(method, name, type, init, maybeslot)->index;
 }
 
 #define TEMPVARNAME "__as3_temp__"
@@ -712,28 +751,23 @@ int gettempvar()
     if(v) 
         i = v->index;
     else
-        i = new_variable(TEMPVARNAME, 0, 0, 0);
+        i = new_variable(state->method, TEMPVARNAME, 0, 0, 0);
     parserassert(i);
     return i;
 }
 
-static code_t* var_block(code_t*body) 
+static code_t* var_block(code_t*body, dict_t*vars) 
 {
     code_t*c = 0;
     code_t*k = 0;
     int t;
-    int num=0;
-    for(t=0;t<state->vars->hashsize;t++) {
-        dictentry_t*e = state->vars->slots[t];
-        while(e) {
-            variable_t*v = (variable_t*)e->data;
-            if(v->type && v->init) {
-                c = defaultvalue(c, v->type);
-                c = abc_setlocal(c, v->index);
-                k = abc_kill(k, v->index); 
-                num++;
-            }
-            e = e->next;
+    DICT_ITERATE_DATA(vars, variable_t*, v) {
+        if(v->type && v->init) {
+            c = defaultvalue(c, v->type);
+            c = abc_setlocal(c, v->index);
+        }
+        if(v->type && v->kill) {
+            k = abc_kill(k, v->index); 
         }
     }
 
@@ -771,7 +805,7 @@ static void unknown_variable(char*name)
 
 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
+    if(m->uses_slots || m->innerfunctions || (m->late_binding && !m->inner)) {
         c = abc_getlocal_0(c);
         c = abc_pushscope(c);
     }
@@ -847,7 +881,7 @@ static code_t* method_header(methodstate_t*m)
 static code_t* wrap_function(code_t*c,code_t*header, code_t*body)
 {
     c = code_append(c, header);
-    c = code_append(c, var_block(body));
+    c = code_append(c, var_block(body, state->method->no_variable_scoping?state->method->allvars:state->vars));
     /* append return if necessary */
     if(!c || (c->opcode != OPCODE_RETURNVOID && 
               c->opcode != OPCODE_RETURNVALUE)) {
@@ -874,6 +908,29 @@ static void endpackage()
 #define FLAG_PACKAGEINTERNAL 2048
 #define FLAG_NAMESPACE 4096
 
+static slotinfo_t* find_class(const char*name);
+
+const char* lookup_namespace(const char*name)
+{
+    state_t*s = state;
+    while(s) {
+       const char*url = dict_lookup(s->namespaces, name);
+       if(url) 
+           return url;
+       s = s->old;
+    }
+    varinfo_t*a;
+    registry_find(state->package, name);
+    if(( a = (varinfo_t*)find_class(name) )) {
+       if(a->kind == INFOTYPE_VAR) {
+           if(!a->value || !NS_TYPE(a->value->type)) 
+               syntaxerror("%s.%s is not a namespace", a->package, a->name);
+           return a->value->ns->name;
+       }
+    }
+    return 0;
+}
+
 static namespace_t modifiers2access(modifiers_t*mod)
 {
     namespace_t ns;
@@ -883,14 +940,14 @@ static namespace_t modifiers2access(modifiers_t*mod)
         if(mod->flags&(FLAG_PRIVATE|FLAG_PROTECTED|FLAG_PACKAGEINTERNAL)) 
             syntaxerror("invalid combination of access levels and namespaces");
         ns.access = ACCESS_NAMESPACE;
-        state_t*s = state;
-        const char*url = (const char*)trie_lookup(active_namespaces, mod->ns);
-        if(!url) {
-            /* shouldn't happen- the tokenizer only reports something as a namespace
-               if it was already registered */
-            trie_dump(active_namespaces);
-            syntaxerror("unknown namespace: %s", mod->ns);
-        }
+       const char*url = lookup_namespace(mod->ns);
+       if(!url) {
+           if(as3_pass>1) {
+               syntaxerror("unknown namespace: %s (pass %d)", mod->ns, as3_pass);
+           } else {
+               url = mod->ns;
+           }
+       }
         ns.name = url;
     } else if(mod->flags&FLAG_PUBLIC)  {
         if(mod->flags&(FLAG_PRIVATE|FLAG_PROTECTED|FLAG_PACKAGEINTERNAL)) 
@@ -909,11 +966,25 @@ static namespace_t modifiers2access(modifiers_t*mod)
     }
     return ns;
 }
-static slotinfo_t* find_class(const char*name);
 
-static memberinfo_t* findmember_nsset(classinfo_t*cls, const char*name, char recurse)
+static memberinfo_t* findmember_nsset(classinfo_t*cls, const char*name, char recurse, char is_static)
 {
-    return registry_findmember_nsset(cls, state->active_namespace_urls, name, recurse);
+    return registry_findmember_nsset(cls, state->active_namespace_urls, name, recurse, is_static);
+}
+
+static void innerfunctions2vars(methodstate_t*m)
+{
+    methodstate_list_t*l = m->innerfunctions;
+    while(l) {
+        methodstate_t*m = l->methodstate;
+        
+        variable_t* v = new_variable2(state->method, m->info->name, TYPE_FUNCTION(m->info), 0, 0);
+        m->var_index = v->index;
+        if(m->is_a_slot)
+            m->slot_index = m->is_a_slot;
+        v->is_inner_method = m;
+        l = l->next;
+    }
 }
 
 static void function_initvars(methodstate_t*m, char has_params, params_t*params, int flags, char var0)
@@ -921,61 +992,60 @@ static void function_initvars(methodstate_t*m, char has_params, params_t*params,
     if(var0) {
         int index = -1;
         if(m->inner)
-            index = new_variable("this", 0, 0, 0);
+            index = new_variable(m, "this", 0, 0, 0);
         else if(!m->is_global)
-            index = new_variable((flags&FLAG_STATIC)?"class":"this", state->cls?state->cls->info:0, 0, 0);
+            index = new_variable(m, (flags&FLAG_STATIC)?"class":"this", state->cls?state->cls->info:0, 0, 0);
         else
-            index = new_variable("globalscope", 0, 0, 0);
+            index = new_variable(m, "globalscope", 0, 0, 0);
+        if(index) {
+            DICT_ITERATE_ITEMS(state->vars, char*, name, variable_t*, v) {
+                printf("%s %d\n", name, v->index);
+            }
+        }
         parserassert(!index);
     }
 
     if(has_params) {
         param_list_t*p=0;
         for(p=params->list;p;p=p->next) {
-            variable_t*v = new_variable2(p->param->name, p->param->type, 0, 1);
+            variable_t*v = new_variable2(m, p->param->name, p->param->type, 0, 1);
             v->is_parameter = 1;
         }
-        variable_t*v = new_variable2("arguments", TYPE_ARRAY, 0, 0);
         if(as3_pass==2 && m->need_arguments) {
+            /* arguments can never be used by an innerfunction (the inner functions
+               have their own arguments var), so it's ok to  not initialize this until
+               pass 2. (We don't know whether we need it before, anyway) */
+            variable_t*v = new_variable2(m, "arguments", TYPE_ARRAY, 0, 0);
             m->need_arguments = v->index;
         }
     }
     
-    if(m->uses_slots) {
-        /* as variables and slots share the same number, make sure
-           that those variable indices are reserved. It's up to the
-           optimizer to later shuffle the variables down to lower
-           indices */
-        m->variable_count = m->uses_slots;
-    }
-
-
-    methodstate_list_t*l = m->innerfunctions;
-    while(l) {
-        methodstate_t*m = l->methodstate;
-        
-        variable_t* v = new_variable2(m->info->name, TYPE_FUNCTION(m->info), 0, 1);
-        m->var_index = v->index;
-        m->slot_index = v->index;
-        v->is_inner_method = m;
-
-        l = l->next;
-    }
+    innerfunctions2vars(m);
     
     if(as3_pass==2) {
         m->scope_code = add_scope_code(m->scope_code, m, 0);
-    }
-    
-    if(as3_pass==2 && m->slots) {
-        /* 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) {
-                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);
+        if(m->slots) {
+            /* exchange unresolved identifiers with the actual objects */
+            DICT_ITERATE_ITEMS(m->slots, char*, name, variable_t*, v1) {
+                if(v1->type && v1->type->kind == INFOTYPE_UNRESOLVED) {
+                    classinfo_t*type = (classinfo_t*)registry_resolve((slotinfo_t*)v1->type);
+                    if(!type || type->kind != INFOTYPE_CLASS) {
+                        syntaxerror("Couldn't find class %s::%s (%s)", v1->type->package, v1->type->name, name);
+                    }
+                    v1->type = type;
                 }
-                v->type = type;
             }
+       }
+       if(m->allvars) {
+            DICT_ITERATE_ITEMS(m->allvars, char*, name2, variable_t*, v2) {
+                if(v2->type && v2->type->kind == INFOTYPE_UNRESOLVED) {
+                    classinfo_t*type = (classinfo_t*)registry_resolve((slotinfo_t*)v2->type);
+                    if(!type || type->kind != INFOTYPE_CLASS) {
+                        syntaxerror("Couldn't find class %s::%s (%s)", v2->type->package, v2->type->name, name2);
+                    }
+                    v2->type = type;
+                }
+           }
         }
     }
 }
@@ -1023,10 +1093,9 @@ static void startclass(modifiers_t* mod, char*classname, classinfo_t*extends, cl
 
     if(as3_pass==1) {
         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->init = methodstate_new();
+        state->cls->static_init = methodstate_new();
         state->cls->static_init->is_static=FLAG_STATIC;
-        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 fact
            that pass 1 won't do anything with variables */
@@ -1056,10 +1125,12 @@ static void startclass(modifiers_t* mod, char*classname, classinfo_t*extends, cl
     if(as3_pass == 2) {
         state->cls = dict_lookup(global->token2info, (void*)(ptroff_t)as3_tokencount);
     
-        state->method = state->cls->init;
         parserassert(state->cls && state->cls->info);
        
+        state->method = state->cls->static_init;
+
         function_initvars(state->cls->init, 0, 0, 0, 1);
+        state->cls->static_init->variable_count=1;
         function_initvars(state->cls->static_init, 0, 0, 0, 0);
 
         if(extends && (extends->flags & FLAG_FINAL))
@@ -1094,10 +1165,8 @@ static void startclass(modifiers_t* mod, char*classname, classinfo_t*extends, cl
             abc_class_add_interface(state->cls->abc, &m);
         }
 
-        NEW(parsedclass_t,p);
-        p->cls = state->cls->info;
-        p->abc = state->cls->abc;
-        list_append(global->classes, p);
+        state->cls->dependencies = parsedclass_new(state->cls->info, state->cls->abc);
+        list_append(global->classes, state->cls->dependencies);
 
         /* flash.display.MovieClip handling */
         if(!as3_globalclass && (mod->flags&FLAG_PUBLIC) && slotinfo_equals((slotinfo_t*)registry_getMovieClip(),(slotinfo_t*)extends)) {
@@ -1202,7 +1271,7 @@ static void check_override(memberinfo_t*m, int flags)
 {
     if(!m)
         return;
-    if(m->parent == state->cls->info)
+    if(m->parent == state->cls->info && !((flags^m->flags)&FLAG_STATIC))
         syntaxerror("class '%s' already contains a method/slot '%s'", m->parent->name, m->name);
     if(!m->parent)
         syntaxerror("internal error: overriding method %s, which doesn't have parent", m->name);
@@ -1238,11 +1307,11 @@ static methodinfo_t*registerfunction(enum yytokentype getset, modifiers_t*mod, c
         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);
+        memberinfo_t* m = registry_findmember(state->cls->info, ns.name, name, 0, mod->flags&FLAG_STATIC);
         if(m) {
             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 = methodinfo_register_onclass(state->cls->info, ns.access, ns.name, name, mod->flags&FLAG_STATIC);
         minfo->return_type = return_type;
         // getslot on a member slot only returns "undefined", so no need
         // to actually store these
@@ -1258,7 +1327,7 @@ static methodinfo_t*registerfunction(enum yytokentype getset, modifiers_t*mod, c
         } else
             syntaxerror("setter function needs to take exactly one argument");
         // not sure wether to look into superclasses here, too
-        minfo = (methodinfo_t*)registry_findmember(state->cls->info, ns.name, name, 1);
+        minfo = (methodinfo_t*)registry_findmember(state->cls->info, ns.name, name, 1, mod->flags&FLAG_STATIC);
         if(minfo) {
             if(minfo->kind!=INFOTYPE_VAR)
                 syntaxerror("class already contains a method called '%s'", name);
@@ -1280,7 +1349,7 @@ static methodinfo_t*registerfunction(enum yytokentype getset, modifiers_t*mod, c
                     type?type->name:"*");
             }*/
         } else {
-            minfo = methodinfo_register_onclass(state->cls->info, ns.access, ns.name, name);
+            minfo = methodinfo_register_onclass(state->cls->info, ns.access, ns.name, name, mod->flags&FLAG_STATIC);
             minfo->kind = INFOTYPE_VAR; //hack
             minfo->subtype = gs;
             minfo->return_type = type;
@@ -1301,20 +1370,27 @@ static void innerfunction(char*name, params_t*params, classinfo_t*return_type)
     //parserassert(state->method && state->method->info);
 
     methodstate_t*parent_method = state->method;
+    variable_t*v = 0;
 
     if(as3_pass==1) {
         return_type = 0; // not valid in pass 1
+        if(name) {
+            v = new_variable2(parent_method, name, 0, 0, 0);
+        }
     }
 
     new_state();
     state->new_vars = 1;
-    state->allvars = dict_new();
    
     if(as3_pass == 1) {
-        state->method = rfx_calloc(sizeof(methodstate_t));
+        state->method = methodstate_new();
         state->method->inner = 1;
+        state->method->is_static = parent_method->is_static;
         state->method->variable_count = 0;
         state->method->abc = rfx_calloc(sizeof(abc_method_t));
+        if(v) {
+            v->is_inner_method = state->method;
+        }
 
         NEW(methodinfo_t,minfo);
         minfo->kind = INFOTYPE_METHOD;
@@ -1348,10 +1424,9 @@ static void startfunction(modifiers_t*mod, enum yytokentype getset, char*name,
     }
     new_state();
     state->new_vars = 1;
-    state->allvars = dict_new();
 
     if(as3_pass == 1) {
-        state->method = rfx_calloc(sizeof(methodstate_t));
+        state->method = methodstate_new();
         state->method->has_super = 0;
         state->method->is_static = mod->flags&FLAG_STATIC;
 
@@ -1377,7 +1452,7 @@ static void startfunction(modifiers_t*mod, enum yytokentype getset, char*name,
         parserassert(state->method);
                 
         if(state->cls) {
-            memberinfo_t*m = registry_findmember(state->cls->info, mod->ns, name, 2);
+            memberinfo_t*m = registry_findmember(state->cls->info, mod->ns, name, 2, mod->flags&FLAG_STATIC);
             check_override(m, mod->flags);
         }
             
@@ -1389,63 +1464,71 @@ static void startfunction(modifiers_t*mod, enum yytokentype getset, char*name,
     } 
 }
 
+static void insert_unresolved(methodstate_t*m, dict_t*xvars, dict_t*allvars)
+{
+    parserassert(m->inner);
+    if(m->unresolved_variables) {
+        dict_t*d = m->unresolved_variables;
+        int t;
+        DICT_ITERATE_KEY(d, char*, id) {
+            /* check parent method's variables */
+            variable_t*v;
+            if(dict_contains(allvars, id)) {
+                m->uses_parent_function = 1;
+                state->method->uses_slots = 1;
+                dict_put(xvars, id, 0);
+            }
+        }
+    }
+    methodstate_list_t*ml = m->innerfunctions;
+    while(ml) {
+        insert_unresolved(ml->methodstate, xvars, allvars);
+        ml = ml->next;
+    }
+}
+
 static abc_method_t* endfunction(modifiers_t*mod, enum yytokentype getset, char*name,
                           params_t*params, classinfo_t*return_type, code_t*body)
 {
     if(as3_pass==1) {
-        // store inner methods in variables
-        function_initvars(state->method, 0, 0, 0, 0);
-
-        methodstate_list_t*ml = state->method->innerfunctions;
-        
         dict_t*xvars = dict_new();
-
-        while(ml) {
-            methodstate_t*m = ml->methodstate;
-            parserassert(m->inner);
-            if(m->unresolved_variables) {
-                dict_t*d = m->unresolved_variables;
-                int t;
-                for(t=0;t<d->hashsize;t++) {
-                    dictentry_t*l = d->slots[t]; 
-                    while(l) {
-                        /* check parent method's variables */
-                        variable_t*v;
-                        if((v=find_variable(state, l->key))) {
-                            m->uses_parent_function = 1;
-                            state->method->uses_slots = 1;
-                            dict_put(xvars, l->key, 0);
-                        }
-                        l = l->next;
+        
+        if(state->method->unresolved_variables) {
+            DICT_ITERATE_KEY(state->method->unresolved_variables, char*, vname) {
+                if(!state->method->no_variable_scoping && dict_contains(state->method->allvars, vname)) {
+                    variable_t*v = dict_lookup(state->method->allvars, vname);
+                    if(!v->is_inner_method) {
+                        state->method->no_variable_scoping = 1;
+                        as3_warning("function %s uses forward or outer block variable references (%s): switching into compatibility mode", name, vname);
                     }
-                    if(l) break;
                 }
-
-                dict_destroy(m->unresolved_variables);
-                m->unresolved_variables = 0;
             }
+        }
+
+        methodstate_list_t*ml = state->method->innerfunctions;
+        while(ml) {
+            insert_unresolved(ml->methodstate, xvars, state->method->allvars);
             ml = ml->next;
         }
         
         if(state->method->uses_slots) {
             state->method->slots = dict_new();
             int i = 1;
-            DICT_ITERATE_ITEMS(state->vars, char*, name, variable_t*, v) {
+            DICT_ITERATE_ITEMS(state->method->allvars, char*, name, variable_t*, v) {
                 if(!name) syntaxerror("internal error");
                 if(v->index && dict_contains(xvars, name)) {
-                    v->init = 0;
-                    v->index = i++;
+                    v->init = v->kill = 0;
+                    v->index = i;
                     if(v->is_inner_method) {
-                        v->is_inner_method->is_a_slot = 1;
+                        v->is_inner_method->is_a_slot = i;
                     }
-                    //v->type = 0;
+                    i++;
                     dict_put(state->method->slots, name, v);
                 }
             }
             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;
@@ -1478,6 +1561,7 @@ static abc_method_t* endfunction(modifiers_t*mod, enum yytokentype getset, char*
             multiname_t mname = {QNAME, &mname_ns, 0, name};
 
             f = abc_method_new(global->file, type2, 1);
+            if(!global->init) global->init = abc_initscript(global->file);
             trait_t*t = trait_new_method(&global->init->traits, multiname_clone(&mname), f);
             //abc_code_t*c = global->init->method->body->code;
         }
@@ -1502,7 +1586,7 @@ static abc_method_t* endfunction(modifiers_t*mod, enum yytokentype getset, char*
                 check_constant_against_type(p->param->type, p->param->value);
                 opt=1;list_append(f->optional_parameters, p->param->value);
             } else if(opt) {
-                syntaxerror("non-optional parameter not allowed after optional parameters");
+                syntaxerror("function %s: non-optional parameter not allowed after optional parameters", name);
             }
         }
         if(state->method->slots) {
@@ -1599,12 +1683,18 @@ code_t*converttype(code_t*c, classinfo_t*from, classinfo_t*to)
     if(TYPE_IS_STRING(to))
         return abc_convert_s(c);
     if(TYPE_IS_OBJECT(to))
-        return abc_convert_o(c);
+        return abc_coerce2(c, &m);
+    if(TYPE_IS_OBJECT(from) && TYPE_IS_XMLLIST(to))
+        return abc_coerce2(c, &m);
+    if(TYPE_IS_OBJECT(from) && TYPE_IS_ARRAY(to))
+        return abc_coerce2(c, &m);
 
     classinfo_t*supertype = from;
     while(supertype) {
         if(supertype == to) {
-             // target type is one of from's superclasses
+             /* target type is one of from's superclasses.
+                (not sure we need this coerce - as far as the verifier
+                 is concerned, object==object (i think) */
              return abc_coerce2(c, &m);
         }
         int t=0;
@@ -1624,13 +1714,24 @@ code_t*converttype(code_t*c, classinfo_t*from, classinfo_t*to)
     if(TYPE_IS_NULL(from) && !IS_NUMBER_OR_INT(to))
         return c;
 
+
     as3_error("can't convert type %s%s%s to %s%s%s", 
         from->package, from->package[0]?".":"", from->name, 
         to->package, to->package[0]?".":"", to->name);
 
     return c;
 }
-/* move to ast.c todo end */
+code_t* coerce_to_type(code_t*c, classinfo_t*t)
+{
+    if(!t) {
+        return abc_coerce_a(c);
+    } else if(TYPE_IS_STRING(t)) {
+        return abc_coerce_s(c);
+    } else {
+        MULTINAME(m, t);
+        return abc_coerce2(c, &m);
+    }
+}
 
 char is_pushundefined(code_t*c)
 {
@@ -1717,6 +1818,7 @@ typedcode_t push_class(slotinfo_t*a)
             infotypename(a), a->name, a->package, state->package);
     }
 
+
     if(a->kind != INFOTYPE_CLASS) {
         MULTINAME(m, a);
         x.c = abc_findpropstrict2(x.c, &m);
@@ -1728,7 +1830,13 @@ typedcode_t push_class(slotinfo_t*a)
             varinfo_t*v = (varinfo_t*)a;
             x.t = v->type;
         }
+        return x;
     } else {
+        if(state->cls && state->method == state->cls->static_init) {
+            /* we're in the static initializer. 
+               record the fact that we're using this class here */
+            parsedclass_add_dependency(state->cls->dependencies, (classinfo_t*)a);
+        }
         classinfo_t*c = (classinfo_t*)a;
         //if(c->slot) {
         if(0) { //Error #1026: Slot 1 exceeds slotCount=0 of global
@@ -1912,6 +2020,7 @@ INPACKAGE_CODE: INTERFACE_DECLARATION
               | SLOT_DECLARATION
               | PACKAGE_INITCODE
               | CONDITIONAL_COMPILATION '{' MAYBE_INPACKAGE_CODE_LIST '}' {PASS_ALWAYS as3_pass=$1;}
+              | '[' EMBED_START E ']' {PASS_ALWAYS as3_pass=$2;PASS1 as3_warning("embed command ignored");}
               | ';'
 
 MAYBECODE: CODE {$$=$1;}
@@ -1923,6 +2032,7 @@ CODE: CODE CODEPIECE {
 CODE: CODEPIECE {$$=$1;}
 
 // code which may appear outside of methods
+CODE_STATEMENT: DEFAULT_NAMESPACE 
 CODE_STATEMENT: IMPORT 
 CODE_STATEMENT: FOR 
 CODE_STATEMENT: FOR_IN 
@@ -1938,7 +2048,7 @@ CODE_STATEMENT: NAMESPACE_DECLARATION
 CODE_STATEMENT: '{' CODE '}' {$$=$2;}
 CODE_STATEMENT: '{' '}' {$$=0;}
 
-// code which may appear in methods
+// code which may appear in methods (includes the above)
 CODEPIECE: ';' {$$=0;}
 CODEPIECE: CODE_STATEMENT
 CODEPIECE: VARIABLE_DECLARATION
@@ -1964,8 +2074,20 @@ CODEBLOCK :  CODEPIECE %prec below_semicolon {$$=$1;}
 /* ------------ package init code ------------------- */
 
 PACKAGE_INITCODE: CODE_STATEMENT {
-    code_t**cc = &global->init->method->body->code;
-    *cc = code_append(*cc, $1);
+    if($1) {
+        if(!global->init) 
+            global->init = abc_initscript(global->file);
+        code_t**cc = &global->init->method->body->code;
+        *cc = code_append(*cc, $1);
+    }
+}
+
+/* ------------ embed code ------------- */
+
+EMBED_START: %prec above_function {
+    PASS_ALWAYS
+    $$ = as3_pass;
+    as3_pass=0;
 }
 
 /* ------------ conditional compilation ------------- */
@@ -1987,6 +2109,14 @@ CONDITIONAL_COMPILATION: T_IDENTIFIER "::" T_IDENTIFIER {
     {
         return 1; // FIXME
     }
+    char do_init_variable(char*name)
+    {
+        if(!state->method->no_variable_scoping)
+            return 0;
+        if(!state->new_vars)
+            return 1;
+        return 1;
+    }
 };
 
 MAYBEEXPRESSION : '=' E {$$=$2;}
@@ -2001,84 +2131,86 @@ VARIABLE_LIST: VARIABLE_LIST ',' ONE_VARIABLE {$$ = code_append($1, $3);}
 ONE_VARIABLE: T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION
 {
 PASS12
-    if(variable_exists($1))
+    if(variable_exists($1)) 
         syntaxerror("Variable %s already defined", $1);
 PASS1
-    new_variable($1, 0, 1, 0);
+    new_variable(state->method, $1, $2, 1, 0);
 PASS2
    
     char slot = 0;
     int index = 0;
+    variable_t*v = 0;
     if(state->method->uses_slots) {
-        variable_t* v = find_slot(state, $1);
+        v = find_slot(state->method, $1);
         if(v && !v->init) {
             // this variable is stored in a slot
             v->init = 1;
             v->type = $2;
             slot = 1;
-            index = v->index;
         }
     }
-    if(!index) {
-        index = new_variable($1, $2, 1, 0);
+    if(!v) {
+        v = new_variable2(state->method, $1, $2, 1, 0);
     }
 
     $$ = 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);
+    typedcode_t val = node_read($3);
+    if(!is_subtype_of(val.t, $2)) {
+        syntaxerror("Can't convert %s to %s", val.t->name, $2->name);
     }
     if($2) {
-        if(v.c->prev || v.c->opcode != OPCODE_PUSHUNDEFINED) {
-            $$ = code_append($$, v.c);
-            $$ = converttype($$, v.t, $2);
+        if(val.c->prev || val.c->opcode != OPCODE_PUSHUNDEFINED) {
+            $$ = code_append($$, val.c);
+            $$ = converttype($$, val.t, $2);
         } else {
-            code_free(v.c);
+            code_free(val.c);
             $$ = defaultvalue($$, $2);
         }
     } else {
-        if(v.c->prev || v.c->opcode != OPCODE_PUSHUNDEFINED) {
-            $$ = code_append($$, v.c);
+        if(val.c->prev || val.c->opcode != OPCODE_PUSHUNDEFINED) {
+            $$ = code_append($$, val.c);
             $$ = abc_coerce_a($$);
         } else {
             // don't do anything
-            code_free(v.c);
+            code_free(val.c);
             code_free($$);
             $$ = 0;
             break;
         }
     }
     if(slot) {
-        $$ = abc_setslot($$, index);
+        $$ = abc_setslot($$, v->index);
     } else {
-        $$ = abc_setlocal($$, index);
+        $$ = abc_setlocal($$, v->index);
+        v->init = do_init_variable($1);
     }
 }
 
 /* ------------ control flow ------------------------- */
 
+IF_CODEBLOCK: {PASS12 new_state();} CODEBLOCK {
+    $$ = var_block($2, state->vars);
+    PASS12 old_state();
+}
 MAYBEELSE:  %prec below_else {$$ = code_new();}
-MAYBEELSE: "else" CODEBLOCK {$$=$2;}
+MAYBEELSE: "else" IF_CODEBLOCK {$$=$2;}
 //MAYBEELSE: ';' "else" CODEBLOCK {$$=$3;}
 
-IF : "if" '(' {PASS12 new_state();} EXPRESSION ')' CODEBLOCK MAYBEELSE {
-     
+IF : "if" '(' EXPRESSION ')' IF_CODEBLOCK MAYBEELSE {
     $$ = code_new();
-    $$ = code_append($$, $4.c);
+    $$ = code_append($$, $3.c);
     code_t*myjmp,*myif = $$ = abc_iffalse($$, 0);
    
-    $$ = code_append($$, $6);
-    if($7) {
+    $$ = code_append($$, $5);
+    if($6) {
         myjmp = $$ = abc_jump($$, 0);
     }
     myif->branch = $$ = abc_nop($$);
-    if($7) {
-        $$ = code_append($$, $7);
+    if($6) {
+        $$ = code_append($$, $6);
         myjmp->branch = $$ = abc_nop($$);
     }
-    $$ = var_block($$);
-    PASS12 old_state();
 }
 
 FOR_INIT : {$$=code_new();}
@@ -2089,8 +2221,8 @@ FOR_INIT : VOIDEXPRESSION
 //       (I don't see any easy way to revolve this conflict otherwise, as we
 //        can't touch VAR_READ without upsetting the precedence about "return")
 FOR_IN_INIT : "var" T_IDENTIFIER MAYBETYPE {
-    PASS1 $$=$2;new_variable($2,0,1,0);
-    PASS2 $$=$2;new_variable($2,$3,1,0);
+    PASS1 $$=$2;new_variable(state->method, $2,0,1,0);
+    PASS2 $$=$2;new_variable(state->method, $2,$3,1,0);
 }
 FOR_IN_INIT : T_IDENTIFIER {
     PASS12
@@ -2100,7 +2232,7 @@ FOR_IN_INIT : T_IDENTIFIER {
 FOR_START : T_FOR '(' {PASS12 new_state();$$.name=$1;$$.each=0;}
 FOR_START : T_FOR "each" '(' {PASS12 new_state();$$.name=$1;$$.each=1;}
 
-FOR : FOR_START FOR_INIT ';' EXPRESSION ';' VOIDEXPRESSION ')' CODEBLOCK {
+FOR : FOR_START FOR_INIT ';' EXPRESSION ';' VOIDEXPRESSION ')' IF_CODEBLOCK {
     if($1.each) syntaxerror("invalid syntax: ; not allowed in for each statement");
     $$ = code_new();
     $$ = code_append($$, $2);
@@ -2116,20 +2248,16 @@ FOR : FOR_START FOR_INIT ';' EXPRESSION ';' VOIDEXPRESSION ')' CODEBLOCK {
     continuejumpsto($$, $1.name, cont);
     myif->branch = out;
 
-    $$ = var_block($$);
+    $$ = var_block($$, state->vars);
     PASS12 old_state();
 }
 
-FOR_IN : FOR_START FOR_IN_INIT "in" EXPRESSION ')' CODEBLOCK {
-    variable_t*var = find_variable(state, $2);
-    if(!var) {
-        syntaxerror("variable %s not known in this scope", $2);
-    }
-
-    char*tmp1name = concat2($2, "__tmp1__");
-    int it = new_variable(tmp1name, TYPE_INT, 0, 0);
-    char*tmp2name = concat2($2, "__array__");
-    int array = new_variable(tmp1name, 0, 0, 0);
+FOR_IN : FOR_START FOR_IN_INIT "in" EXPRESSION ')' IF_CODEBLOCK {
+    node_t*n = resolve_identifier($2);
+    typedcode_t w = node_write(n);
+    
+    int it = alloc_local();
+    int array = alloc_local();
 
     $$ = code_new();
     $$ = code_append($$, $4.c);
@@ -2148,8 +2276,9 @@ FOR_IN : FOR_START FOR_IN_INIT "in" EXPRESSION ')' CODEBLOCK {
         $$ = abc_nextname($$);
     else
         $$ = abc_nextvalue($$);
-    $$ = converttype($$, 0, var->type);
-    $$ = abc_setlocal($$, var->index);
+
+    $$ = converttype($$, 0, w.t);
+    $$ = code_append($$, w.c);
 
     $$ = code_append($$, $6);
     $$ = abc_jump($$, loopstart);
@@ -2160,46 +2289,39 @@ FOR_IN : FOR_START FOR_IN_INIT "in" EXPRESSION ')' CODEBLOCK {
     
     myif->branch = out;
 
-    $$ = var_block($$);
-
-    free(tmp1name);
-    free(tmp2name);
+    $$ = abc_kill($$, it);
+    $$ = abc_kill($$, array);
 
+    $$ = var_block($$, state->vars);
     PASS12 old_state();
 }
 
-WHILE : T_WHILE '(' {PASS12 new_state();} EXPRESSION ')' CODEBLOCK {
+WHILE : T_WHILE '(' EXPRESSION ')' IF_CODEBLOCK {
 
     $$ = code_new();
 
     code_t*myjmp = $$ = abc_jump($$, 0);
     code_t*loopstart = $$ = abc_label($$);
-    $$ = code_append($$, $6);
+    $$ = code_append($$, $5);
     code_t*cont = $$ = abc_nop($$);
     myjmp->branch = cont;
-    $$ = code_append($$, $4.c);
+    $$ = code_append($$, $3.c);
     $$ = abc_iftrue($$, loopstart);
     code_t*out = $$ = abc_nop($$);
     breakjumpsto($$, $1, out);
     continuejumpsto($$, $1, cont);
-
-    $$ = var_block($$);
-    PASS12 old_state();
 }
 
-DO_WHILE : T_DO {PASS12 new_state();} CODEBLOCK "while" '(' EXPRESSION ')' {
+DO_WHILE : T_DO IF_CODEBLOCK "while" '(' EXPRESSION ')' {
     $$ = code_new();
     code_t*loopstart = $$ = abc_label($$);
-    $$ = code_append($$, $3);
+    $$ = code_append($$, $2);
     code_t*cont = $$ = abc_nop($$);
-    $$ = code_append($$, $6.c);
+    $$ = code_append($$, $5.c);
     $$ = abc_iftrue($$, loopstart);
     code_t*out = $$ = abc_nop($$);
     breakjumpsto($$, $1, out);
     continuejumpsto($$, $1, cont);
-    
-    $$ = var_block($$);
-    PASS12 old_state();
 }
 
 BREAK : "break" %prec prec_none {
@@ -2261,7 +2383,7 @@ SWITCH : T_SWITCH '(' {PASS12 new_state();state->switch_var=alloc_local();} E ')
         c=c->prev;
     }
    
-    $$ = var_block($$);
+    $$ = var_block($$, state->vars);
     PASS12 old_state();
 }
 
@@ -2269,8 +2391,8 @@ SWITCH : T_SWITCH '(' {PASS12 new_state();state->switch_var=alloc_local();} E ')
 
 CATCH: "catch" '(' T_IDENTIFIER MAYBETYPE ')' {PASS12 new_state();
                                                       state->exception_name=$3;
-                                               PASS1 new_variable($3, 0, 0, 0);
-                                               PASS2 new_variable($3, $4, 0, 0);
+                                               PASS1 new_variable(state->method, $3, $4, 0, 0);
+                                               PASS2 new_variable(state->method, $3, $4, 0, 0);
                                               } 
         '{' MAYBECODE '}' {
     namespace_t name_ns = {ACCESS_PACKAGE, ""};
@@ -2289,11 +2411,11 @@ CATCH: "catch" '(' T_IDENTIFIER MAYBETYPE ')' {PASS12 new_state();
     c = code_append(c, $8);
     c = abc_kill(c, i);
 
-    c = var_block(c);
+    c = var_block(c, state->vars);
     PASS12 old_state();
 }
 FINALLY: "finally" '{' {PASS12 new_state();state->exception_name=0;} MAYBECODE '}' {
-    $4 = var_block($4);
+    $4 = var_block($4, state->vars);
     if(!$4) {
         $$=0;
     } else {
@@ -2343,7 +2465,7 @@ TRY : "try" '{' {PASS12 new_state();
   
     int tmp;
     if($6.finally)
-        tmp = new_variable("__finally__", 0, 0, 0);
+        tmp = alloc_local();
     
     abc_exception_list_t*l = $6.l;
     int count=0;
@@ -2371,7 +2493,7 @@ TRY : "try" '{' {PASS12 new_state();
         
     list_concat(state->method->exceptions, $6.l);
    
-    $$ = var_block($$);
+    $$ = var_block($$, state->vars);
     PASS12 old_state();
 }
 
@@ -2421,7 +2543,8 @@ WITH : WITH_HEAD CODEBLOCK {
 
 X_IDENTIFIER: T_IDENTIFIER
             | "package" {PASS12 $$="package";}
-            | T_NAMESPACE {PASS12 $$=$1;}
+            | "namespace" {PASS12 $$="namespace";}
+            | "NaN" {PASS12 $$="NaN";}
 
 PACKAGE: PACKAGE '.' X_IDENTIFIER {PASS12 $$ = concat3($1,".",$3);free($1);$1=0;}
 PACKAGE: X_IDENTIFIER             {PASS12 $$=strdup($1);}
@@ -2451,18 +2574,27 @@ PACKAGE_DECLARATION : "package" '{' {PASS12 startpackage("");}
         free(s);
     }
 };
+
+IMPORT : "import" T_IDENTIFIER {
+       PASS12
+       slotinfo_t*s = registry_find(state->package, $2);
+       if(!s && as3_pass==1) {as3_schedule_class(state->package, $2);}
+       state_has_imports();
+       dict_put(state->imports, state->package, $2);
+       $$=0;
+}
 IMPORT : "import" PACKAGEANDCLASS {
        PASS12
        slotinfo_t*s = registry_find($2->package, $2->name);
-       if(!s && as3_pass==1) {// || !(s->flags&FLAG_BUILTIN)) {
+       if(!s && as3_pass==1) {
            as3_schedule_class($2->package, $2->name);
        }
-       classinfo_t*c = $2;
-       if(!c) 
-            syntaxerror("Couldn't import class\n");
+       /*if(s && s->kind == INFOTYPE_VAR && TYPE_IS_NAMESPACE(s->type)) {
+           trie_put(active_namespaces, (unsigned char*)$2->name, 0);
+       }*/
        state_has_imports();
-       dict_put(state->imports, c->name, c);
-       import_toplevel(c->package);
+       dict_put(state->imports, $2->name, $2);
+       import_toplevel($2->package);
        $$=0;
 }
 IMPORT : "import" PACKAGE '.' '*' {
@@ -2500,7 +2632,7 @@ MODIFIER : KW_PUBLIC {PASS12 $$.flags=FLAG_PUBLIC;$$.ns=0;}
          | KW_OVERRIDE {PASS12 $$.flags=FLAG_OVERRIDE;$$.ns=0;}
          | KW_NATIVE {PASS12 $$.flags=FLAG_NATIVE;$$.ns=0;}
          | KW_INTERNAL {PASS12 $$.flags=FLAG_PACKAGEINTERNAL;$$.ns=0;}
-         | T_NAMESPACE {PASS12 $$.flags=FLAG_NAMESPACE;
+         | T_IDENTIFIER {PASS12 $$.flags=FLAG_NAMESPACE;
                                $$.ns=$1;
                        }
 
@@ -2536,6 +2668,7 @@ CLASS_BODY_ITEM : ';'
 CLASS_BODY_ITEM : CONDITIONAL_COMPILATION '{' MAYBE_CLASS_BODY '}' {PASS_ALWAYS as3_pass=$1;}
 CLASS_BODY_ITEM : SLOT_DECLARATION
 CLASS_BODY_ITEM : FUNCTION_DECLARATION
+CLASS_BODY_ITEM : '[' EMBED_START E ']' {PASS_ALWAYS as3_pass=$2;PASS1 as3_warning("embed command ignored");}
 
 CLASS_BODY_ITEM : CODE_STATEMENT {
     code_t*c = state->cls->static_init->header;
@@ -2598,6 +2731,7 @@ IDECLARATION : MAYBE_MODIFIERS "function" GETSET T_IDENTIFIER '(' MAYBE_PARAM_LI
         code_t**code=0;
         if(!state->cls) {
             // global variable
+            if(!global->init) global->init = abc_initscript(global->file);
             ns.name = state->package;
             traits = &global->init->traits;
             code = &global->init->method->body->code;
@@ -2609,6 +2743,10 @@ IDECLARATION : MAYBE_MODIFIERS "function" GETSET T_IDENTIFIER '(' MAYBE_PARAM_LI
             // instance variable
             traits = &state->cls->abc->traits;
             code = &state->cls->init->header;
+            
+            if(ns.access == ACCESS_PROTECTED) {
+                ns.name = concat3(state->cls->info->package,":",state->cls->info->name);
+            }
         }
         if(c)
             *c = code;
@@ -2636,11 +2774,11 @@ PASS12
 
         varinfo_t* info = 0;
         if(state->cls) {
-            memberinfo_t*i = registry_findmember(state->cls->info, ns.name, $1, 1);
+            memberinfo_t*i = registry_findmember(state->cls->info, ns.name, $1, 1, slotstate_flags->flags&FLAG_STATIC);
             if(i) {
                 check_override(i, flags);
             }
-            info = varinfo_register_onclass(state->cls->info, ns.access, ns.name, $1);
+            info = varinfo_register_onclass(state->cls->info, ns.access, ns.name, $1, slotstate_flags->flags&FLAG_STATIC);
         } else {
             slotinfo_t*i = registry_find(state->package, $1);
             if(i) {
@@ -2719,7 +2857,6 @@ MAYBECONSTANT: '=' E {
   }
 }
 
-//CONSTANT : T_NAMESPACE {$$ = constant_new_namespace($1);}
 CONSTANT : T_INT {$$ = constant_new_int($1);}
 CONSTANT : T_UINT {
     $$ = constant_new_uint($1);
@@ -2732,82 +2869,103 @@ 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);
-    }
-}*/
-
 /* ---------------------------xml ------------------------------ */
 
 %code {
     static int xml_level = 0;
 };
 
-XML: XMLNODE
+XML: XMLNODE {
+   multiname_t m = {QNAME, &stdns, 0, "XML"};
+   typedcode_t v;
+   v.c = 0;
+   v.c = abc_getlex2(v.c, &m);
+   v.c = code_append(v.c, node_read($1).c);
+   v.c = abc_construct(v.c, 1);
+   v.t = TYPE_XML;
+   $$ = mkcodenode(v);
+}
 
 OPEN : '<' {PASS_ALWAYS if(!xml_level++) tokenizer_begin_xml();}
 CLOSE : '>' {PASS_ALWAYS tokenizer_begin_xmltext();}
 CLOSE2 : {PASS_ALWAYS if(!--xml_level) tokenizer_end_xml(); else tokenizer_begin_xmltext();}
 
 XMLEXPR1 : '{' E {PASS_ALWAYS tokenizer_begin_xmltext();} '}' {
-    $$=strdup("{...}");
-    as3_warning("xml string substitution not yet supported");
+    $$ = $2;
 }
 XMLEXPR2 : '{' E {PASS_ALWAYS tokenizer_begin_xml();} '}' {
-    $$=strdup("{...}");
-    as3_warning("xml string substitution not yet supported");
+    $$ = $2;
 }
-XMLTEXT : {$$="";}
+XMLTEXT : {$$=mkstringnode("");}
 XMLTEXT : XMLTEXT XMLEXPR1 {
-    $$ = concat2($1, "{...}");
+    $$ = mkaddnode($1,$2);
+}
+XMLTEXT : XMLTEXT T_STRING {
+    char* str = string_cstr(&$2);
+    $$ = mkaddnode($1,mkstringnode(str));
+    free(str);
+}
+XMLTEXT : XMLTEXT '>' {
+    $$ = mkaddnode($1, mkstringnode(">"));
+}
+XML2 : XMLNODE XMLTEXT {
+    $$ = mkaddnode($1,$2);
+}
+XML2 : XML2 XMLNODE XMLTEXT {
+    $$ = mkaddnode($1, mkaddnode($2,$3));
+}
+XML_ID_OR_EXPR: T_IDENTIFIER {
+    $$ = mkstringnode($1);
+}
+XML_ID_OR_EXPR: XMLEXPR2 {
+    $$ = $1;
 }
-XMLTEXT : XMLTEXT T_STRING {$$=concat2($1, string_cstr(&$2));}
-XMLTEXT : XMLTEXT '>' {$$=concat2($1, ">");}
-
-XML2 : XMLNODE XMLTEXT {$$=concat2($1,$2);}
-XML2 : XML2 XMLNODE XMLTEXT {$$=concat3($1,$2,$3);free($1);free($2);free($3);}
-
-XML_ID_OR_EXPR: T_IDENTIFIER {$$=$1;}
-XML_ID_OR_EXPR: XMLEXPR2      {$$=$1;}
 
-XMLNODE : OPEN XML_ID_OR_EXPR MAYBE_XMLATTRIBUTES CLOSE XMLTEXT '<' '/' XML_ID_OR_EXPR CLOSE2 '>' {
-    $$ = allocprintf("<%s%s>%s</%s>", $2, $3, $5, $8);
-    free($2);free($3);free($5);free($8);
+MAYBE_XMLATTRIBUTES: {
+    $$ = mkstringnode("");
+}
+MAYBE_XMLATTRIBUTES: XMLATTRIBUTES {
+    $$ = mkaddnode(mkstringnode(" "),$1);
 }
+
 XMLNODE : OPEN XML_ID_OR_EXPR MAYBE_XMLATTRIBUTES '/' CLOSE2 '>' {
-    $$ = allocprintf("<%s%s/>", $2, $3);
+    //$$ = allocprintf("<%s%s/>", $2, $3, $5, $8);
+    $$ = mkaddnode(mkaddnode(mkaddnode(mkstringnode("<"),$2),$3),mkstringnode("/>"));
+}
+XMLNODE : OPEN XML_ID_OR_EXPR MAYBE_XMLATTRIBUTES CLOSE XMLTEXT '<' '/' XML_ID_OR_EXPR CLOSE2 '>' {
+    //$$ = allocprintf("<%s%s>%s</%s>", $2, $3, $5, $8);
+    $$ = mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(
+         mkstringnode("<"),$2),$3),mkstringnode(">")),$5),mkstringnode("</")),$8),mkstringnode(">"));
 }
 XMLNODE : OPEN XML_ID_OR_EXPR MAYBE_XMLATTRIBUTES CLOSE XMLTEXT XML2 '<' '/' XML_ID_OR_EXPR CLOSE2 '>' {
-    $$ = allocprintf("<%s%s>%s%s</%s>", $2, $3, $5, $6, $9);
-    free($2);free($3);free($5);free($6);free($9);
+    //$$ = allocprintf("<%s%s>%s%s</%s>", $2, $3, $5, $6, $9);
+    $$ = mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(
+         mkstringnode("<"),$2),$3),mkstringnode(">")),$5),$6),mkstringnode("</")),$9),mkstringnode(">"));
 }
 
-MAYBE_XMLATTRIBUTES:                      {$$=strdup("");}
-MAYBE_XMLATTRIBUTES: XMLATTRIBUTES        {$$=concat2(" ",$1);}
-XMLATTRIBUTES: XMLATTRIBUTE               {$$=$1;}
-XMLATTRIBUTES: XMLATTRIBUTES XMLATTRIBUTE {$$=concat3($1," ",$2);free($1);free($2);}
-
+XMLATTRIBUTES: XMLATTRIBUTE {
+    $$ = $1;
+}
+XMLATTRIBUTES: XMLATTRIBUTES XMLATTRIBUTE {
+    $$ = mkaddnode($1, mkaddnode(mkstringnode(" "),$2));
+}
 XMLATTRIBUTE: XMLEXPR2 {
-    $$ = strdup("{...}");
+    $$ = $1;
 }
 XMLATTRIBUTE: XMLEXPR2 '=' T_STRING {
     char* str = string_cstr(&$3);
-    $$ = concat2("{...}=",str);
+    $$ = mkaddnode($1, mkstringnode(concat2("=",str)));
+    free(str);
 }
 XMLATTRIBUTE: XMLEXPR2 '=' XMLEXPR2 {
-    $$ = strdup("{...}={...}");
+    $$ = mkaddnode($1, mkaddnode(mkstringnode("=\""), mkaddnode($3, mkstringnode("\""))));
 }
 XMLATTRIBUTE: T_IDENTIFIER '=' XMLEXPR2 {
-    $$ = concat2($1,"={...}");
+    $$ = mkaddnode(mkaddnode(mkstringnode(concat2($1,"=\"")), $3), mkstringnode("\""));
 }
 XMLATTRIBUTE: T_IDENTIFIER '=' T_STRING {
     char* str = string_cstr(&$3);
-    $$=allocprintf("%s=\"%s\"", $1,str);
+    $$=mkstringnode(allocprintf("%s=%s", $1,str));
     free(str);
     free($1);free((char*)$3.str);
 }
@@ -2930,6 +3088,7 @@ CLASS: X_IDENTIFIER {
     slotinfo_t*s = find_class($1);
     if(!s) syntaxerror("Could not find class/method %s (current package: %s)\n", $1, state->package);
     $$ = (classinfo_t*)s;
+    registry_use(s);
 }
 
 PACKAGEANDCLASS : PACKAGE '.' X_IDENTIFIER {
@@ -2944,6 +3103,7 @@ PACKAGEANDCLASS : PACKAGE '.' X_IDENTIFIER {
     if(!s) syntaxerror("Couldn't find class/method %s.%s\n", $1, $3);
     free($1);$1=0;
     $$ = (classinfo_t*)s;
+    registry_use(s);
 }
 
 CLASS_SPEC: PACKAGEANDCLASS
@@ -2998,6 +3158,9 @@ NEW : "new" E XX MAYBE_PARAM_VALUES {
         $$.c = code_append($$.c, paramcode);
         $$.c = abc_constructprop2($$.c, name, $4.number);
         multiname_destroy(name);
+    } else if(is_getlocal($$.c)) {
+        $$.c = code_append($$.c, paramcode);
+        $$.c = abc_construct($$.c, $4.number);
     } else if(TYPE_IS_CLASS(v.t) && v.t->data) {
         code_free($$.c);
         classinfo_t*c = v.t->data;
@@ -3075,8 +3238,8 @@ FUNCTIONCALL : E '(' MAYBE_EXPRESSION_LIST ')' {
         // calling a class is like a typecast
         $$.t = (classinfo_t*)v.t->data;
     } else {
-        $$.c = abc_coerce_a($$.c);
         $$.t = TYPE_ANY;
+        $$.c = abc_coerce_a($$.c);
     }
 }
 
@@ -3189,14 +3352,7 @@ E : CONSTANT {
 }
 
 E : XML {
-    typedcode_t v;
-    v.c = 0;
-    multiname_t m = {QNAME, &stdns, 0, "XML"};
-    v.c = abc_getlex2(v.c, &m);
-    v.c = abc_pushstring(v.c, $1);
-    v.c = abc_construct(v.c, 1);
-    v.t = TYPE_XML;
-    $$ = mkcodenode(v);
+    $$ = $1;
 }
 
 /* regexp */
@@ -3275,7 +3431,7 @@ E : E "in" E {$$ = mknode2(&node_in, $1, $3);}
 E : E "as" E {$$ = mknode2(&node_as, $1, $3);}
 E : E "instanceof" E {$$ = mknode2(&node_instanceof, $1, $3);}
 E : E "is" E {$$ = mknode2(&node_is, $1, $3);}
-E : "typeof" '(' E ')' {$$ = mknode1(&node_typeof, $3);}
+E : "typeof" E  {$$ = mknode1(&node_typeof, $2);}
 E : "void" E {$$ = mknode1(&node_void, $2);}
 E : "void" { $$ = mkconstnode(constant_new_undefined());}
 E : '(' COMMA_EXPRESSION ')' { $$=$2;}
@@ -3305,7 +3461,7 @@ E : "super" '.' T_IDENTIFIER
                   syntaxerror("super keyword not allowed outside a class");
               classinfo_t*t = state->cls->info->superclass;
               if(!t) t = TYPE_OBJECT;
-              memberinfo_t*f = findmember_nsset(t, $3, 1);
+              memberinfo_t*f = findmember_nsset(t, $3, 1, 0);
               MEMBER_MULTINAME(m, f, $3);
               typedcode_t v;
               v.c = 0;
@@ -3369,7 +3525,7 @@ E : E '.' '(' {PASS12 new_state();state->xmlfilter=1;} E ')' {
     c = abc_kill(c, result);
     c = abc_kill(c, index);
     
-    c = var_block(c);
+    c = var_block(c, state->vars);
     old_state();
     typedcode_t r;
     r.c = c;
@@ -3378,27 +3534,50 @@ E : E '.' '(' {PASS12 new_state();state->xmlfilter=1;} E ')' {
 }
 
 ID_OR_NS : T_IDENTIFIER {$$=$1;}
-ID_OR_NS : T_NAMESPACE {$$=(char*)$1;}
-SUBNODE: T_IDENTIFIER
+ID_OR_NS : '*' {$$="*";}
+SUBNODE: X_IDENTIFIER
        | '*' {$$="*";}
 
-E : E '.' ID_OR_NS "::" SUBNODE {
-    typedcode_t v = node_read($1);
-    typedcode_t w = node_read(resolve_identifier($3));
-    v.c = code_append(v.c, w.c);
-    if(!TYPE_IS_NAMESPACE(w.t)) {
-        as3_softwarning("%s might not be a namespace", $3);
-    }
-    v.c = converttype(v.c, w.t, TYPE_NAMESPACE);
-    multiname_t m = {RTQNAME, 0, 0, $5};
-    v.c = abc_getproperty2(v.c, &m);
-    if(TYPE_IS_XML(v.t)) {
-        v.t = TYPE_XMLLIST;
-    } else {
-        v.c = abc_coerce_a(v.c);
-        v.t = TYPE_ANY;
+%code {
+    node_t* resolve_identifier(const char*name);
+    node_t* get_descendants(node_t*e,const char*ns,const char*subnode,char multi, char attr)
+    {
+       typedcode_t v = node_read(e);
+       typedcode_t w;
+
+       multiname_t m = {0,0,0,subnode};
+       namespace_t zero = {ZERONAMESPACE,"*"};
+       if(!strcmp(ns,"*")) {
+           m.ns = &zero;
+           m.type = attr?QNAMEA:QNAME;
+       } else {
+           typedcode_t w = node_read(resolve_identifier(ns));
+           if(!TYPE_IS_NAMESPACE(w.t)) {
+               as3_softwarning("%s might not be a namespace", ns);
+           }
+           v.c = code_append(v.c, w.c);
+           v.c = converttype(v.c, w.t, TYPE_NAMESPACE);
+           m.type = attr?RTQNAMEA:RTQNAME;
+       }
+
+       if(!multi) {
+           v.c = abc_getproperty2(v.c, &m);
+       } else {
+           v.c = abc_getdescendants2(v.c, &m);
+       }
+
+       if(TYPE_IS_XML(v.t)) {
+           v.t = TYPE_XMLLIST;
+       } else {
+           v.c = abc_coerce_a(v.c);
+           v.t = TYPE_ANY;
+       }
+       return mkcodenode(v);
     }
-    $$ = mkcodenode(v);
+};
+
+E : E '.' ID_OR_NS "::" SUBNODE {
+    $$ = get_descendants($1, $3, $5, 0, 0);
 }
 E : E ".." SUBNODE {
     typedcode_t v = node_read($1);
@@ -3407,6 +3586,9 @@ E : E ".." SUBNODE {
     v.t = TYPE_XMLLIST;
     $$ = mkcodenode(v);
 }
+E : E ".." ID_OR_NS "::" SUBNODE {
+    $$ = get_descendants($1, $3, $5, 1, 0);
+}
 E : E '.' '[' E ']' {
     typedcode_t v = node_read($1);
     typedcode_t w = node_read($4);
@@ -3425,6 +3607,11 @@ E : E '.' '@' SUBNODE {
     v.t = TYPE_STRING;
     $$ = mkcodenode(v);
 }
+
+E : E '.' '@' ID_OR_NS "::" SUBNODE {
+    $$ = get_descendants($1, $4, $6, 0, 1);
+}
+
 E : E ".." '@' SUBNODE {
     typedcode_t v = node_read($1);
     multiname_t m = {MULTINAMEA, 0, &nopackage_namespace_set, $4};
@@ -3432,6 +3619,10 @@ E : E ".." '@' SUBNODE {
     v.t = TYPE_STRING;
     $$ = mkcodenode(v);
 }
+E : E ".." '@' ID_OR_NS "::" SUBNODE {
+    $$ = get_descendants($1, $4, $6, 1, 1);
+}
+
 E : E '.' '@' '[' E ']' {
     typedcode_t v = node_read($1);
     typedcode_t w = node_read($5);
@@ -3462,7 +3653,7 @@ MEMBER : E '.' SUBNODE {
         t = t->data;
         is_static = 1;
     }
-    if(TYPE_IS_XML(t)) {
+    if(TYPE_IS_XML(t) && !findmember_nsset(t, $3, 1, is_static)) {
         multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $3};
         $$.c = abc_getproperty2($$.c, &m);
         $$.c = abc_coerce_a($$.c);
@@ -3471,7 +3662,7 @@ MEMBER : E '.' SUBNODE {
         if(t->subtype==INFOTYPE_UNRESOLVED) {
             syntaxerror("syntaxerror: trying to resolve property '%s' on incomplete object '%s'", $3, t->name);
         }
-        memberinfo_t*f = findmember_nsset(t, $3, 1);
+        memberinfo_t*f = findmember_nsset(t, $3, 1, is_static);
         char noslot = 0;
         if(f && !is_static != !(f->flags&FLAG_STATIC))
            noslot=1;
@@ -3479,7 +3670,9 @@ MEMBER : E '.' SUBNODE {
             $$.c = abc_getslot($$.c, f->slot);
         } else {
             if(!f) {
-                as3_softwarning("Access of undefined property '%s' in %s", $3, t->name);
+                if(!TYPE_IS_XMLLIST(t)) {
+                    as3_softwarning("Access of undefined property '%s' in %s", $3, t->name);
+                }
             }
             MEMBER_MULTINAME(m, f, $3);
             $$.c = abc_getproperty2($$.c, &m);
@@ -3517,7 +3710,15 @@ MEMBER : E '.' SUBNODE {
 }
 
 %code {
-    node_t* resolve_identifier(char*name)
+    node_t* var_read(variable_t*v)
+    {
+        typedcode_t o;
+       o.c = abc_getlocal(0, v->index);
+       o.t = v->type;
+       return mkcodenode(o);
+    }
+
+    node_t* resolve_identifier(const char*name)
     {
         typedcode_t o;
         o.t = 0;
@@ -3530,11 +3731,9 @@ MEMBER : E '.' SUBNODE {
         /* look at variables */
         if((v = find_variable(state, name))) {
             // name is a local variable
-            o.c = abc_getlocal(o.c, v->index);
-            o.t = v->type;
-            return mkcodenode(o);
+           return var_read(v);
         }
-        if((v = find_slot(state, name))) {
+        if((v = find_slot(state->method, name))) {
             o.c = abc_getscopeobject(o.c, 1);
             o.c = abc_getslot(o.c, v->index);
             o.t = v->type;
@@ -3543,58 +3742,69 @@ MEMBER : E '.' SUBNODE {
 
         int i_am_static = state->method->is_static;
 
-        /* look at current class' members */
-        if(!state->method->inner && 
-           !state->xmlfilter &&
-            state->cls && 
-            (f = findmember_nsset(state->cls->info, name, 1)))
-        {
-            // name is a member or attribute in this class
-            int var_is_static = (f->flags&FLAG_STATIC);
-
-            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) {
-                    return mkconstnode(v->value);
-                }
-            }
-           
-            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, name};
-                    o.c = abc_findpropstrict2(o.c, &m);
-                    o.c = abc_getproperty2(o.c, &m);
-                    return mkcodenode(o);
-                } else if(f->slot>0) {
-                    o.c = abc_getlocal_0(o.c);
-                    o.c = abc_getslot(o.c, f->slot);
-                    return mkcodenode(o);
-                } else {
-                    MEMBER_MULTINAME(m, f, name);
-                    o.c = abc_getlocal_0(o.c);
-                    o.c = abc_getproperty2(o.c, &m);
-                    return mkcodenode(o);
-                }
-            }
-        } 
+        if(!state->method->inner && !state->xmlfilter && state->cls)
+       {
+           /* look at current class' members */
+           if((f = findmember_nsset(state->cls->info, name, 1, i_am_static)))
+           {
+               // name is a member or attribute in this class
+               int var_is_static = (f->flags&FLAG_STATIC);
+
+               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) {
+                       return mkconstnode(v->value);
+                   }
+               }
+              
+               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, name};
+                       o.c = abc_findpropstrict2(o.c, &m);
+                       o.c = abc_getproperty2(o.c, &m);
+                       return mkcodenode(o);
+                   } else if(f->slot>0) {
+                       o.c = abc_getlocal_0(o.c);
+                       o.c = abc_getslot(o.c, f->slot);
+                       return mkcodenode(o);
+                   } else {
+                       MEMBER_MULTINAME(m, f, name);
+                       o.c = abc_getlocal_0(o.c);
+                       o.c = abc_getproperty2(o.c, &m);
+                       return mkcodenode(o);
+                   }
+               }
+           } 
+           /* special case: it's allowed to access non-static constants
+              from a static context */
+           if(i_am_static && (f=findmember_nsset(state->cls->info, name, 1, 0))) {
+               if(f->kind == INFOTYPE_VAR && (f->flags&FLAG_CONST)) {
+                   varinfo_t*v = (varinfo_t*)f;
+                   if(v->value) {
+                       return mkconstnode(v->value);
+                   }
+               }
+           }
+       }
         
         /* look at actual classes, in the current package and imported */
         if(!state->xmlfilter && (a = find_class(name))) {
+           registry_use(a);
             if(state->cls && state->cls->info == (classinfo_t*)a && i_am_static) {
                 o.c = abc_getlocal_0(0);
                 o.t = TYPE_CLASS((classinfo_t*)a);
@@ -3608,7 +3818,7 @@ MEMBER : E '.' SUBNODE {
         if(!state->xmlfilter && 
            (dict_contains(state->import_toplevel_packages, name) || 
             registry_ispackage(name))) {
-            o.c = abc___pushpackage__(o.c, name);
+            o.c = abc___pushpackage__(o.c, (char*)name);
             o.t = 0;
             return mkcodenode(o); //?
         }
@@ -3642,9 +3852,7 @@ VAR_READ : T_IDENTIFIER {
        */
 
     if(!find_variable(state, $1)) {
-        if(state->method->inner) {
-            unknown_variable($1);
-        }
+        unknown_variable($1);
         /* 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);
@@ -3690,7 +3898,7 @@ NAMESPACE_ID : "namespace" T_IDENTIFIER '=' T_STRING {
 }
 NAMESPACE_DECLARATION : MAYBE_MODIFIERS NAMESPACE_ID {
     PASS12
-    trie_put(active_namespaces, $2->name, (void*)$2->url);
+    dict_put(state->namespaces, (unsigned char*)$2->name, (void*)$2->url);
 
     namespace_t access = modifiers2access(&$1);
     varinfo_t* var = varinfo_register_global(access.access, state->package, $2->name);
@@ -3710,9 +3918,15 @@ NAMESPACE_DECLARATION : MAYBE_MODIFIERS NAMESPACE_ID {
     $$=0;
 }
 
+DEFAULT_NAMESPACE : "default xml" "namespace" '=' E 
+{
+    $$ = 0;
+    $$ = code_append($$, node_read($4).c);
+    $$ = abc_dxnslate($$);
+}
+
 USE_NAMESPACE : "use" "namespace" CLASS_SPEC {
     PASS12
-    const char*url = $3->name;
 
     varinfo_t*s = (varinfo_t*)$3;
     if(s->kind == INFOTYPE_UNRESOLVED) {
@@ -3725,9 +3939,9 @@ USE_NAMESPACE : "use" "namespace" CLASS_SPEC {
         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);
-    url = s->value->ns->name;
 
-    trie_put(active_namespaces, $3->name, (void*)url);
+    const char*url = s->value->ns->name;
+    dict_put(state->namespaces, (unsigned char*)$3->name, (void*)url);
     add_active_url(url);
     $$=0;
 }