fixed segfault during late binding
[swftools.git] / lib / as3 / parser.y
index 318a6d5..9940fa5 100644 (file)
@@ -767,6 +767,7 @@ static void startfunction(token_t*ns, int flags, enum yytokentype getset, char*n
     int slot = 0;
     if(!strcmp(state->clsinfo->name,name)) {
         state->m = abc_class_constructor(state->cls, type2);
+        name = "__as3_constructor__";
     } else {
         if(flags&FLAG_STATIC)
             state->m = abc_class_staticmethod(state->cls, type2, &mname);
@@ -927,6 +928,40 @@ void parserassert(int b)
     if(!b) syntaxerror("internal error: assertion failed");
 }
 
+static classinfo_t* find_class(char*name)
+{
+    classinfo_t*c=0;
+
+    c = registry_findclass(state->package, name);
+
+    /* try explicit imports */
+    dictentry_t* e = dict_get_slot(state->imports, name);
+    while(e) {
+        if(c)
+            break;
+        if(!strcmp(e->key, name)) {
+            c = (classinfo_t*)e->data;
+        }
+        e = e->next;
+    }
+
+    /* try package.* imports */
+    import_list_t*l = state->wildcard_imports;
+    while(l) {
+        if(c)
+            break;
+        //printf("does package %s contain a class %s?\n", l->import->package, name);
+        c = registry_findclass(l->import->package, name);
+        l = l->next;
+    }
+
+    /* try global package */
+    if(!c) {
+        c = registry_findclass("", name);
+    }
+    return c;
+}
+
 static code_t* toreadwrite(code_t*in, code_t*middlepart, char justassign, char readbefore)
 {
     /* converts this:
@@ -1431,34 +1466,7 @@ FUNCTION_DECLARATION: MAYBE_MODIFIERS "function" GETSET T_IDENTIFIER '(' MAYBE_P
 CLASS: T_IDENTIFIER {
 
     /* try current package */
-    $$ = registry_findclass(state->package, $1);
-
-    /* try explicit imports */
-    dictentry_t* e = dict_get_slot(state->imports, $1);
-    while(e) {
-        if($$)
-            break;
-        if(!strcmp(e->key, $1)) {
-            $$ = (classinfo_t*)e->data;
-        }
-        e = e->next;
-    }
-
-    /* try package.* imports */
-    import_list_t*l = state->wildcard_imports;
-    while(l) {
-        if($$)
-            break;
-        //printf("does package %s contain a class %s?\n", l->import->package, $1);
-        $$ = registry_findclass(l->import->package, $1);
-        l = l->next;
-    }
-
-    /* try global package */
-    if(!$$) {
-        $$ = registry_findclass("", $1);
-    }
-
+    $$ = find_class($1);
     if(!$$) syntaxerror("Could not find class %s\n", $1);
 }
 
@@ -1504,8 +1512,12 @@ NEW : "new" CLASS MAYBE_PARAM_VALUES {
     MULTINAME(m, $2);
     $$.c = code_new();
 
-    /* TODO: why do we have to *find* our own classes? */
-    $$.c = abc_findpropstrict2($$.c, &m);
+    if($2->slot) {
+        $$.c = abc_getglobalscope($$.c);
+        $$.c = abc_getslot($$.c, $2->slot);
+    } else {
+        $$.c = abc_findpropstrict2($$.c, &m);
+    }
 
     typedcode_list_t*l = $3;
     int len = 0;
@@ -1514,7 +1526,10 @@ NEW : "new" CLASS MAYBE_PARAM_VALUES {
         l = l->next;
         len ++;
     }
-    $$.c = abc_constructprop2($$.c, &m, len);
+    if($2->slot)
+        $$.c = abc_construct($$.c, len);
+    else
+        $$.c = abc_constructprop2($$.c, &m, len);
     $$.t = $2;
 }
 
@@ -1842,10 +1857,21 @@ E : "--" E { code_t*c = 0;
 
 E : E '.' T_IDENTIFIER
             {$$.c = $1.c;
-             if($$.t) {
-                 memberinfo_t*f = registry_findmember($$.t, $3);
+             classinfo_t*t = $1.t;
+             char is_static = 0;
+             if(TYPE_IS_CLASS(t)) {
+                 memberinfo_t*m = registry_findmember($1.t, "prototype");
+                 if(!m) syntaxerror("identifier '%s' not found in anonymous class", $3);
+                 t = m->type;
+                 is_static = 1;
+             }
+             if(t) {
+                 memberinfo_t*f = registry_findmember(t, $3);
+                 char noslot = 0;
+                 if(f && !is_static != !(f->flags&FLAG_STATIC))
+                    noslot=1;
 
-                 if(f && f->slot) {
+                 if(f && f->slot && !noslot) {
                      $$.c = abc_getslot($$.c, f->slot);
                  } else {
                      if(f) {
@@ -1883,11 +1909,16 @@ VAR_READ : T_IDENTIFIER {
     $$.t = 0;
     $$.c = 0;
     int i;
+    classinfo_t*a = 0;
     memberinfo_t*f = 0;
+
+    /* look at variables */
     if((i = find_variable($1, &$$.t)) >= 0) {
         // $1 is a local variable
         $$.c = abc_getlocal($$.c, i);
-    } else if(f = registry_findmember(state->clsinfo, $1)) {
+
+    /* look at current class' members */
+    } else if((f = registry_findmember(state->clsinfo, $1))) {
         // $1 is a function in this class
         int var_is_static = (f->flags&FLAG_STATIC);
         int i_am_static = (state->minfo?(state->minfo->flags&FLAG_STATIC):FLAG_STATIC);
@@ -1916,8 +1947,20 @@ VAR_READ : T_IDENTIFIER {
         } else {
             $$.t = f->type;
         }
+    
+    /* look at classes in the current package and imported classes */
+    } else if((a = find_class($1))) {
+        if(a->slot) {
+            $$.c = abc_getglobalscope($$.c);
+            $$.c = abc_getslot($$.c, a->slot);
+        } else {
+            MULTINAME(m, a);
+            $$.c = abc_getlex2($$.c, &m);
+        }
+        $$.t = TYPE_CLASS(a);
+
+    /* unknown object, let the avm2 resolve it */
     } else {
-        // let the avm2 resolve $1 
         if(strcmp($1,"trace"))
             warning("Couldn't resolve %s, doing late binding", $1);
         state->late_binding = 1;