as3compile: small bugfixes, added documentation
[swftools.git] / lib / as3 / parser.y
index 0db6e6c..d21da23 100644 (file)
@@ -266,7 +266,8 @@ 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 
+%left T_NAMESPACE
 %nonassoc "false" "true" "null" "undefined" "super" "function"
 %left above_function
 
@@ -570,10 +571,11 @@ void initialize_file(char*filename)
         state->method->late_binding = 1; // init scripts use getglobalscope, so we need a getlocal0/pushscope
     } 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;
     }
 }
 
@@ -586,9 +588,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
@@ -665,6 +670,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");
@@ -1466,6 +1474,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;
         }
@@ -1587,12 +1596,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;
@@ -1618,7 +1633,17 @@ code_t*converttype(code_t*c, classinfo_t*from, classinfo_t*to)
 
     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)
 {
@@ -1960,8 +1985,12 @@ 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);
+    }
 }
 
 /* ------------ conditional compilation ------------- */
@@ -2418,6 +2447,7 @@ WITH : WITH_HEAD CODEBLOCK {
 X_IDENTIFIER: T_IDENTIFIER
             | "package" {PASS12 $$="package";}
             | "namespace" {PASS12 $$="namespace";}
+            | "NaN" {PASS12 $$="NaN";}
             | T_NAMESPACE {PASS12 $$=$1;}
 
 PACKAGE: PACKAGE '.' X_IDENTIFIER {PASS12 $$ = concat3($1,".",$3);free($1);$1=0;}
@@ -2448,18 +2478,24 @@ 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)) {
            as3_schedule_class($2->package, $2->name);
        }
-       classinfo_t*c = $2;
-       if(!c) 
-            syntaxerror("Couldn't import class\n");
        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 '.' '*' {
@@ -2595,6 +2631,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;
@@ -2733,14 +2770,9 @@ 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);
-    }
+/*CONSTANT : T_NAMESPACE {
+    // TODO
+    $$ = constant_new_namespace(namespace_new_namespace($1.url));
 }*/
 
 /* ---------------------------xml ------------------------------ */
@@ -3076,8 +3108,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);
     }
 }
 
@@ -3276,7 +3308,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;}
@@ -3721,6 +3753,7 @@ NAMESPACE_DECLARATION : MAYBE_MODIFIERS NAMESPACE_ID {
 DEFAULT_NAMESPACE : "default xml" "namespace" '=' E 
 {
     as3_warning("default xml namespaces not supported yet");
+    $$ = 0;
 }
 
 USE_NAMESPACE : "use" "namespace" CLASS_SPEC {