fixed tests ok/namespaces1.as, ok/packagestr.as
[swftools.git] / lib / as3 / parser.y
1 /* parser.lex
2
3    Routines for compiling Flash2 AVM2 ABC Actionscript
4
5    Extension module for the rfxswf library.
6    Part of the swftools package.
7
8    Copyright (c) 2008 Matthias Kramm <kramm@quiss.org>
9  
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
23 %{
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <memory.h>
27 #include "abc.h"
28 #include "pool.h"
29 #include "files.h"
30 #include "tokenizer.h"
31 #include "registry.h"
32 #include "code.h"
33 #include "opcodes.h"
34 #include "compiler.h"
35
36 extern int a3_lex();
37
38 %}
39
40 //%glr-parser
41 //%expect-rr 1
42 %error-verbose
43
44 %union tokenunion {
45     enum yytokentype token;
46
47     classinfo_t*classinfo;
48     classinfo_list_t*classinfo_list;
49     slotinfo_t*slotinfo;
50     slotinfo_list_t*slotinfo_list;
51
52     int number_int;
53     unsigned int number_uint;
54     double number_float;
55     code_t*code;
56     typedcode_t value;
57     //typedcode_list_t*value_list;
58     codeandnumber_t value_list;
59     param_t* param;
60     params_t params;
61     string_t str;
62     char*id;
63     constant_t*constant;
64     for_start_t for_start;
65     abc_exception_t *exception;
66     regexp_t regexp;
67     modifiers_t flags;
68     namespace_decl_t* namespace_decl;
69     struct {
70         abc_exception_list_t *l;
71         code_t*finally;
72     } catch_list;
73 }
74
75
76 %token<id> T_IDENTIFIER T_NAMESPACE
77 %token<str> T_STRING
78 %token<regexp> T_REGEXP
79 %token<token> T_EMPTY
80 %token<number_int> T_INT
81 %token<number_uint> T_UINT
82 %token<number_uint> T_BYTE
83 %token<number_uint> T_SHORT
84 %token<number_float> T_FLOAT
85
86 %token<id> T_FOR "for"
87 %token<id> T_WHILE "while"
88 %token<id> T_DO "do"
89 %token<id> T_SWITCH "switch"
90
91 %token<token> KW_IMPLEMENTS "implements"
92 %token<token> KW_NAMESPACE "namespace"
93 %token<token> KW_PACKAGE "package"
94 %token<token> KW_PROTECTED "protected"
95 %token<token> KW_PUBLIC "public"
96 %token<token> KW_PRIVATE "private"
97 %token<token> KW_USE "use"
98 %token<token> KW_INTERNAL "internal"
99 %token<token> KW_NEW "new"
100 %token<token> KW_NATIVE "native"
101 %token<token> KW_FUNCTION "function"
102 %token<token> KW_FINALLY "finally"
103 %token<token> KW_UNDEFINED "undefined"
104 %token<token> KW_CONTINUE "continue"
105 %token<token> KW_CLASS "class"
106 %token<token> KW_CONST "const"
107 %token<token> KW_CATCH "catch"
108 %token<token> KW_CASE "case"
109 %token<token> KW_SET "set"
110 %token<token> KW_VOID "void"
111 %token<token> KW_THROW "throw"
112 %token<token> KW_STATIC "static"
113 %token<token> KW_WITH "with"
114 %token<token> KW_INSTANCEOF "instanceof"
115 %token<token> KW_IMPORT "import"
116 %token<token> KW_RETURN "return"
117 %token<token> KW_TYPEOF "typeof"
118 %token<token> KW_INTERFACE "interface"
119 %token<token> KW_NULL "null"
120 %token<token> KW_VAR "var"
121 %token<token> KW_DYNAMIC "dynamic"
122 %token<token> KW_OVERRIDE "override"
123 %token<token> KW_FINAL "final"
124 %token<token> KW_EACH "each"
125 %token<token> KW_GET "get"
126 %token<token> KW_TRY "try"
127 %token<token> KW_SUPER "super"
128 %token<token> KW_EXTENDS "extends"
129 %token<token> KW_FALSE "false"
130 %token<token> KW_TRUE "true"
131 %token<token> KW_BOOLEAN "Boolean"
132 %token<token> KW_UINT "uint"
133 %token<token> KW_INT "int"
134 %token<token> KW_NUMBER "Number"
135 %token<token> KW_STRING "String"
136 %token<token> KW_DEFAULT "default"
137 %token<token> KW_DELETE "delete"
138 %token<token> KW_IF "if"
139 %token<token> KW_ELSE  "else"
140 %token<token> KW_BREAK   "break"
141 %token<token> KW_IS "is"
142 %token<token> KW_IN "in"
143 %token<token> KW_AS "as"
144
145 %token<token> T_DICTSTART "{ (dictionary)"
146 %token<token> T_EQEQ "=="
147 %token<token> T_EQEQEQ "==="
148 %token<token> T_NE "!="
149 %token<token> T_NEE "!=="
150 %token<token> T_LE "<="
151 %token<token> T_GE ">="
152 %token<token> T_ORBY "|=" 
153 %token<token> T_DIVBY "/=" 
154 %token<token> T_MODBY "%="
155 %token<token> T_MULBY "*="
156 %token<token> T_PLUSBY "+=" 
157 %token<token> T_MINUSBY "-="
158 %token<token> T_XORBY "^="
159 %token<token> T_SHRBY ">>="
160 %token<token> T_SHLBY "<<="
161 %token<token> T_USHRBY ">>>="
162 %token<token> T_OROR "||"
163 %token<token> T_ANDAND "&&"
164 %token<token> T_COLONCOLON "::"
165 %token<token> T_MINUSMINUS "--"
166 %token<token> T_PLUSPLUS "++"
167 %token<token> T_DOTDOT ".."
168 %token<token> T_DOTDOTDOT "..."
169 %token<token> T_SHL "<<"
170 %token<token> T_USHR ">>>"
171 %token<token> T_SHR ">>"
172
173 %type <for_start> FOR_START
174 %type <id> X_IDENTIFIER PACKAGE FOR_IN_INIT MAYBE_IDENTIFIER
175 %type <namespace_decl>  NAMESPACE_ID
176 %type <token> VARCONST
177 %type <code> CODE
178 %type <code> CODEPIECE CODE_STATEMENT
179 %type <code> CODEBLOCK MAYBECODE MAYBE_CASE_LIST CASE_LIST DEFAULT CASE SWITCH WITH
180 %type <code> PACKAGE_DECLARATION SLOT_DECLARATION SLOT_LIST ONE_SLOT
181 %type <code> FUNCTION_DECLARATION PACKAGE_INITCODE
182 %type <code> VARIABLE_DECLARATION ONE_VARIABLE VARIABLE_LIST THROW
183 %type <exception> CATCH FINALLY
184 %type <catch_list> CATCH_LIST CATCH_FINALLY_LIST
185 %type <code> CLASS_DECLARATION
186 %type <code> NAMESPACE_DECLARATION
187 %type <code> INTERFACE_DECLARATION
188 %type <code> VOIDEXPRESSION
189 %type <value> EXPRESSION NONCOMMAEXPRESSION
190 %type <value> MAYBEEXPRESSION
191 %type <value> E DELETE
192 %type <value> CONSTANT
193 %type <code> FOR FOR_IN IF WHILE DO_WHILE MAYBEELSE BREAK RETURN CONTINUE TRY 
194 %type <value> INNERFUNCTION
195 %type <code> USE_NAMESPACE
196 %type <code> FOR_INIT
197 %type <code> IMPORT
198 %type <classinfo> MAYBETYPE
199 %type <token> GETSET
200 %type <param> PARAM
201 %type <params> PARAM_LIST
202 %type <params> MAYBE_PARAM_LIST
203 %type <flags> MAYBE_MODIFIERS
204 %type <flags> MODIFIER_LIST
205 %type <flags> MODIFIER
206 %type <constant> STATICCONSTANT MAYBESTATICCONSTANT
207 %type <classinfo_list> IMPLEMENTS_LIST
208 %type <classinfo> EXTENDS CLASS_SPEC
209 %type <classinfo_list> EXTENDS_LIST
210
211 %type <classinfo> CLASS PACKAGEANDCLASS
212 %type <classinfo_list> CLASS_SPEC_LIST
213
214 %type <classinfo> TYPE
215 //%type <token> VARIABLE
216 %type <value> VAR_READ
217 %type <value> NEW
218 //%type <token> T_IDENTIFIER
219 %type <value> FUNCTIONCALL
220 %type <value_list> MAYBE_EXPRESSION_LIST EXPRESSION_LIST EXPRESSION_LIST_AND_COMMA MAYBE_PARAM_VALUES MAYBE_EXPRPAIR_LIST EXPRPAIR_LIST WITH_HEAD
221
222 // precedence: from low to high
223
224 %left prec_none
225
226 %left below_semicolon
227 %left ';'
228 %left ','
229 %nonassoc below_assignment // for ?:, contrary to spec
230 %right '=' "*=" "/=" "%=" "+=" "-=" "<<=" ">>=" ">>>=" "&=" "^=" "|="
231 %right '?' ':'
232 %left "||"
233 %left "&&"
234 %left '|'
235 %left '^'
236 %nonassoc '&'
237 %nonassoc "==" "!=" "===" "!=="
238 %nonassoc "is" "as" "in"
239 %nonassoc "<=" '<' ">=" '>' "instanceof" // TODO: support "a < b < c" syntax?
240 %left "<<" ">>" ">>>" 
241 %left below_minus
242 %left '-' '+'
243 %left '/' '*' '%'
244 %left plusplus_prefix minusminus_prefix '~' '!' "void" "delete" "typeof" //FIXME: *unary* + - should be here, too
245 %left "--" "++" 
246 %nonassoc below_curly
247
248 %left '('
249 %left new2
250 %left '[' ']' "new" '{' "{ (dictionary)" '.' ".." "::" '@'
251
252 %left T_IDENTIFIER
253 %left above_identifier
254 %left below_else
255 %nonassoc "else"
256
257 // needed for "return" precedence:
258 %nonassoc T_STRING T_REGEXP
259 %nonassoc T_INT T_UINT T_BYTE T_SHORT T_FLOAT
260 %nonassoc "false" "true" "null" "undefined" "super" "function"
261 %left above_function
262
263
264      
265 %{
266
267 static int a3_error(char*s)
268 {
269    syntaxerror("%s", s); 
270    return 0; //make gcc happy
271 }
272
273
274 static char* concat2(const char* t1, const char* t2)
275 {
276     int l1 = strlen(t1);
277     int l2 = strlen(t2);
278     char*text = malloc(l1+l2+1);
279     memcpy(text   , t1, l1);
280     memcpy(text+l1, t2, l2);
281     text[l1+l2] = 0;
282     return text;
283 }
284 static char* concat3(const char* t1, const char* t2, const char* t3)
285 {
286     int l1 = strlen(t1);
287     int l2 = strlen(t2);
288     int l3 = strlen(t3);
289     char*text = malloc(l1+l2+l3+1);
290     memcpy(text   , t1, l1);
291     memcpy(text+l1, t2, l2);
292     memcpy(text+l1+l2, t3, l3);
293     text[l1+l2+l3] = 0;
294     return text;
295 }
296
297 typedef struct _import {
298     char*package;
299 } import_t;
300
301 DECLARE_LIST(import);
302
303 DECLARE(methodstate);
304 DECLARE_LIST(methodstate);
305
306 typedef struct _classstate {
307     /* class data */
308     classinfo_t*info;
309     abc_class_t*abc;
310    
311     methodstate_t*init;
312     methodstate_t*static_init;
313     //code_t*init;
314     //code_t*static_init;
315
316     char has_constructor;
317 } classstate_t;
318
319 struct _methodstate {
320     /* method data */
321     methodinfo_t*info;
322     char has_exceptions;
323     char late_binding;
324     char is_constructor;
325     char has_super;
326     char is_global;
327     int variable_count;
328
329     dict_t*unresolved_variables;
330
331     char inner;
332     char uses_parent_function;
333     int uses_slots;
334     dict_t*slots;
335
336     abc_method_t*abc;
337     int var_index; // for inner methods
338     int slot_index; // for inner methods
339     char is_a_slot; // for inner methods
340
341     code_t*header;
342
343     code_t*scope_code;
344     abc_exception_list_t*exceptions;
345     
346     methodstate_list_t*innerfunctions;
347 };
348
349 typedef struct _state {
350     struct _state*old;
351     int level;
352     
353     char*package;     
354     import_list_t*wildcard_imports;
355     dict_t*import_toplevel_packages;
356     dict_t*imports;
357
358     namespace_list_t*active_namespace_urls;
359     
360     char has_own_imports;
361     char new_vars; // e.g. transition between two functions
362   
363     classstate_t*cls;   
364     methodstate_t*method;
365
366     char*exception_name;
367
368     int switch_var;
369     
370     dict_t*vars;
371 } state_t;
372
373 typedef struct _global {
374     abc_file_t*file;
375     abc_script_t*init;
376     dict_t*token2info;
377     dict_t*file2token2info;
378 } global_t;
379
380 static global_t*global = 0;
381 static state_t* state = 0;
382
383 DECLARE_LIST(state);
384
385 #define MULTINAME(m,x) \
386     multiname_t m;\
387     namespace_t m##_ns;\
388     (x)->package; \
389     registry_fill_multiname(&m, &m##_ns, (slotinfo_t*)(x));
390                     
391 #define MEMBER_MULTINAME(m,f,n) \
392     multiname_t m;\
393     namespace_t m##_ns;\
394     if(f) { \
395         if((m##_ns.access = ((slotinfo_t*)(f))->access)==ACCESS_NAMESPACE) \
396             m##_ns.name = ((slotinfo_t*)(f))->package; \
397         else \
398             m##_ns.name = ""; \
399         m.type = QNAME; \
400         m.ns = &m##_ns; \
401         m.namespace_set = 0; \
402         m.name = ((slotinfo_t*)(f))->name; \
403     } else { \
404         m.type = MULTINAME; \
405         m.ns =0; \
406         m.namespace_set = &nopackage_namespace_set; \
407         m.name = n; \
408     }
409
410 /* warning: list length of namespace set is undefined */
411 #define MULTINAME_LATE(m, access, package) \
412     namespace_t m##_ns = {access, package}; \
413     namespace_set_t m##_nsset; \
414     namespace_list_t m##_l;m##_l.next = 0; \
415     m##_nsset.namespaces = &m##_l; \
416     m##_nsset = m##_nsset; \
417     m##_l.namespace = &m##_ns; \
418     multiname_t m = {MULTINAMEL, 0, &m##_nsset, 0};
419
420 static namespace_t ns1 = {ACCESS_PRIVATE, ""};
421 static namespace_t ns2 = {ACCESS_PROTECTED, ""};
422 static namespace_t ns3 = {ACCESS_PACKAGEINTERNAL, ""};
423 static namespace_t ns4 = {ACCESS_PACKAGE, ""};
424 static namespace_list_t nl4 = {&ns4,0};
425 static namespace_list_t nl3 = {&ns3,&nl4};
426 static namespace_list_t nl2 = {&ns2,&nl3};
427 static namespace_list_t nl1 = {&ns1,&nl2};
428 static namespace_set_t nopackage_namespace_set = {&nl1};
429
430 static void new_state()
431 {
432     NEW(state_t, s);
433     state_t*oldstate = state;
434     if(state)
435         memcpy(s, state, sizeof(state_t)); //shallow copy
436     if(!s->imports) {
437         s->imports = dict_new();
438     }
439     if(!s->import_toplevel_packages) {
440         s->import_toplevel_packages = dict_new(); 
441     }
442     state = s;
443     state->level++;
444     state->has_own_imports = 0;    
445     state->vars = dict_new(); 
446     state->old = oldstate;
447     state->new_vars = 0;
448
449     trie_remember(active_namespaces);
450    
451     if(oldstate)
452         state->active_namespace_urls = list_clone(oldstate->active_namespace_urls);
453 }
454 static void state_has_imports()
455 {
456     state->wildcard_imports = list_clone(state->wildcard_imports);
457     state->imports = dict_clone(state->imports);
458     state->has_own_imports = 1;
459 }
460 static void import_toplevel(const char*package)
461 {
462     char* s = strdup(package);
463     while(1) {
464         dict_put(state->import_toplevel_packages, s, 0);
465         char*x = strrchr(s, '.');
466         if(!x)
467             break;
468         *x = 0;
469     }
470     free(s);
471 }
472
473 static void state_destroy(state_t*state)
474 {
475     if(state->has_own_imports) {
476         list_free(state->wildcard_imports);
477         dict_destroy(state->imports);state->imports=0;
478     }
479     if(state->imports && (!state->old || state->old->imports!=state->imports)) {
480         dict_destroy(state->imports);state->imports=0;
481     }
482     if(state->vars) {
483         int t;
484         for(t=0;t<state->vars->hashsize;t++) {
485             dictentry_t*e =state->vars->slots[t];
486             while(e) {
487                 free(e->data);e->data=0;
488                 e = e->next;
489             }
490         }
491         dict_destroy(state->vars);state->vars=0;
492     }
493     
494     list_free(state->active_namespace_urls)
495     state->active_namespace_urls = 0;
496     
497     free(state);
498 }
499
500 static void old_state()
501 {
502     trie_rollback(active_namespaces);
503
504     if(!state || !state->old)
505         syntaxerror("invalid nesting");
506     state_t*leaving = state;
507     
508     state = state->old;
509
510     if(as3_pass>1 && leaving->method && leaving->method != state->method && !leaving->method->inner) {
511         free(leaving->method);
512         leaving->method=0;
513     }
514     if(as3_pass>1 && leaving->cls && leaving->cls != state->cls) {
515         free(leaving->cls);
516         leaving->cls=0;
517     }
518
519     state_destroy(leaving);
520 }
521
522 static code_t* method_header(methodstate_t*m);
523 static code_t* wrap_function(code_t*c,code_t*header, code_t*body);
524 static void function_initvars(methodstate_t*m, params_t*params, int flags, char var0);
525
526
527 static char* internal_filename_package = 0;
528 void initialize_file(char*filename)
529 {
530     if(state) {
531         syntaxerror("invalid call to initialize_file during parsing of another file");
532     }
533     
534     active_namespaces = trie_new();
535
536     new_state();
537     state->package = internal_filename_package = strdup(filename);
538     
539     global->token2info = dict_lookup(global->file2token2info, 
540                                      current_filename // use long version
541                                     );
542     if(!global->token2info) {
543         global->token2info = dict_new2(&ptr_type);
544         dict_put(global->file2token2info, current_filename, global->token2info);
545     }
546   
547     if(as3_pass==1) {
548         state->method = rfx_calloc(sizeof(methodstate_t));
549         dict_put(global->token2info, (void*)(ptroff_t)as3_tokencount, state->method);
550         state->method->late_binding = 1; // init scripts use getglobalscope, so we need a getlocal0/pushscope
551     } else {
552         state->method = dict_lookup(global->token2info, (void*)(ptroff_t)as3_tokencount);
553         function_initvars(state->method, 0, 0, 1);
554         global->init = abc_initscript(global->file);
555     }
556 }
557
558 void finish_file()
559 {
560     if(!state || state->level!=1) {
561         syntaxerror("unexpected end of file in pass %d", as3_pass);
562     }
563
564     if(as3_pass==2) {
565         code_t*header = method_header(state->method);
566         code_t*c = wrap_function(header, 0, global->init->method->body->code);
567         global->init->method->body->code = c;
568         free(state->method);state->method=0;
569     }
570
571     //free(state->package);state->package=0; // used in registry
572     state_destroy(state);state=0;
573 }
574
575 void initialize_parser()
576 {
577     global = rfx_calloc(sizeof(global_t));
578     global->file = abc_file_new();
579     global->file->flags &= ~ABCFILE_LAZY;
580     global->file2token2info = dict_new();
581     global->token2info = 0;
582 }
583
584 void* finish_parser()
585 {
586     dict_free_all(global->file2token2info, 1, (void*)dict_destroy);
587
588     global->token2info=0;
589
590     return global->file;
591 }
592
593
594 static void xx_scopetest() 
595 {
596     /* findpropstrict doesn't just return a scope object- it
597        also makes it "active" somehow. Push local_0 on the
598        scope stack and read it back with findpropstrict, it'll
599        contain properties like "trace". Trying to find the same
600        property on a "vanilla" local_0 yields only a "undefined" */
601     //c = abc_findpropstrict(c, "[package]::trace");
602     
603     /*c = abc_getlocal_0(c);
604     c = abc_findpropstrict(c, "[package]::trace");
605     c = abc_coerce_a(c);
606     c = abc_setlocal_1(c);
607
608     c = abc_pushbyte(c, 0);
609     c = abc_setlocal_2(c);
610    
611     code_t*xx = c = abc_label(c);
612     c = abc_findpropstrict(c, "[package]::trace");
613     c = abc_pushstring(c, "prop:");
614     c = abc_hasnext2(c, 1, 2);
615     c = abc_dup(c);
616     c = abc_setlocal_3(c);
617     c = abc_callpropvoid(c, "[package]::trace", 2);
618     c = abc_getlocal_3(c);
619     c = abc_kill(c, 3);
620     c = abc_iftrue(c,xx);*/
621 }
622
623 typedef struct _variable {
624     int index;
625     classinfo_t*type;
626     char init;
627     methodstate_t*is_inner_method;
628 } variable_t;
629
630 static variable_t* find_variable(state_t*s, char*name)
631 {
632     while(s) {
633         variable_t*v = 0;
634         v = dict_lookup(s->vars, name);
635         if(v) return v;
636         if(s->new_vars) break;
637         s = s->old;
638     }
639     return 0;
640 }
641 static variable_t* find_slot(state_t*s, const char*name)
642 {
643     if(s->method && s->method->slots)
644         return dict_lookup(s->method->slots, name);
645     return 0;
646 }
647
648 static variable_t* find_variable_safe(state_t*s, char*name)
649 {
650     variable_t* v = find_variable(s, name);
651     if(!v)
652         syntaxerror("undefined variable: %s", name);
653     return v;
654 }
655 static char variable_exists(char*name) 
656 {
657     return dict_contains(state->vars, name);
658 }
659 code_t*defaultvalue(code_t*c, classinfo_t*type);
660
661 static int alloc_local()
662 {
663     return state->method->variable_count++;
664 }
665
666 static variable_t* new_variable2(const char*name, classinfo_t*type, char init, char maybeslot)
667 {
668     if(maybeslot) {
669         variable_t*v = find_slot(state, name);
670         if(v)
671             return v;
672     }
673
674     NEW(variable_t, v);
675     v->index = alloc_local();
676     v->type = type;
677     v->init = init;
678  
679     if(name) 
680         dict_put(state->vars, name, v);
681
682     return v;
683 }
684 static int new_variable(const char*name, classinfo_t*type, char init, char maybeslot)
685 {
686     return new_variable2(name, type, init, maybeslot)->index;
687 }
688
689 #define TEMPVARNAME "__as3_temp__"
690 static int gettempvar()
691 {
692     variable_t*v = find_variable(state, TEMPVARNAME);
693     if(v) 
694         return v->index;
695     return new_variable(TEMPVARNAME, 0, 0, 0);
696 }
697
698 code_t* var_block(code_t*body) 
699 {
700     code_t*c = 0;
701     code_t*k = 0;
702     int t;
703     int num=0;
704     for(t=0;t<state->vars->hashsize;t++) {
705         dictentry_t*e = state->vars->slots[t];
706         while(e) {
707             variable_t*v = (variable_t*)e->data;
708             if(v->type && v->init) {
709                 c = defaultvalue(c, v->type);
710                 c = abc_setlocal(c, v->index);
711                 k = abc_kill(k, v->index); 
712                 num++;
713             }
714             e = e->next;
715         }
716     }
717
718     if(k) {
719         code_t*x = body;
720         while(x) {
721             if(x->opcode== OPCODE___BREAK__ ||
722                x->opcode== OPCODE___CONTINUE__) {
723                /* link kill code before break/continue */
724                 code_t*e = code_dup(k);
725                 code_t*s = code_start(e);
726                 s->prev = x->prev;
727                 if(x->prev) {
728                     x->prev->next = s;
729                 }
730                 e->next = x;
731                 x->prev = e;
732             }
733             x = x->prev;
734         }
735     }
736     
737     c = code_append(c, body);
738     c = code_append(c, k);
739     return c;
740 }
741
742 void unknown_variable(char*name) 
743 {
744     if(!state->method->unresolved_variables)
745         state->method->unresolved_variables = dict_new();
746     if(!dict_contains(state->method->unresolved_variables, name))
747         dict_put(state->method->unresolved_variables, name, 0);
748 }
749
750 #define parserassert(b) {if(!(b)) parsererror(__FILE__, __LINE__,__func__);}
751
752 static void parsererror(const char*file, int line, const char*f)
753 {
754     syntaxerror("internal error in %s, %s:%d", f, file, line);
755 }
756
757    
758 static code_t* add_scope_code(code_t*c, methodstate_t*m)
759 {
760     if(m->uses_slots || (m->late_binding && !m->inner)) {
761         c = abc_getlocal_0(c);
762         c = abc_pushscope(c);
763     }
764     if(m->uses_slots) {
765         /* FIXME: does this need to be the same activation object as
766                   in the function header? */
767         c = abc_newactivation(c);
768         c = abc_pushscope(c);
769     }
770     return c;
771 }
772
773 static code_t* method_header(methodstate_t*m)
774 {
775     code_t*c = 0;
776
777     c = add_scope_code(c, m);
778
779     methodstate_list_t*l = m->innerfunctions;
780     while(l) {
781         parserassert(l->methodstate->abc);
782         if(m->uses_slots && l->methodstate->is_a_slot) {
783             c = abc_getscopeobject(c, 1);
784             c = abc_newfunction(c, l->methodstate->abc);
785             c = abc_dup(c);
786             c = abc_setlocal(c, l->methodstate->var_index);
787             c = abc_setslot(c, l->methodstate->slot_index);
788         } else {
789             c = abc_newfunction(c, l->methodstate->abc);
790             c = abc_setlocal(c, l->methodstate->var_index);
791         }
792         free(l->methodstate);l->methodstate=0;
793         l = l->next;
794     }
795     if(m->header) {
796         c = code_append(c, m->header);
797         m->header = 0;
798     }
799     if(m->is_constructor && !m->has_super) {
800         // call default constructor
801         c = abc_getlocal_0(c);
802         c = abc_constructsuper(c, 0);
803     }
804     list_free(m->innerfunctions);
805     m->innerfunctions = 0;
806     return c;
807 }
808     
809
810 static code_t* wrap_function(code_t*c,code_t*header, code_t*body)
811 {
812     c = code_append(c, header);
813     c = code_append(c, var_block(body));
814     /* append return if necessary */
815     if(!c || (c->opcode != OPCODE_RETURNVOID && 
816               c->opcode != OPCODE_RETURNVALUE)) {
817         c = abc_returnvoid(c);
818     }
819     return c;
820 }
821
822
823 static void startpackage(char*name)
824 {
825     new_state();
826     /*printf("entering package \"%s\"\n", name);*/
827     state->package = strdup(name);
828 }
829 static void endpackage()
830 {
831     /*printf("leaving package \"%s\"\n", state->package);*/
832
833     //used e.g. in classinfo_register:
834     //free(state->package);state->package=0;
835
836     old_state();
837 }
838
839 #define FLAG_PUBLIC 256
840 #define FLAG_PROTECTED 512
841 #define FLAG_PRIVATE 1024
842 #define FLAG_PACKAGEINTERNAL 2048
843 #define FLAG_NAMESPACE 4096
844
845 static namespace_t modifiers2access(modifiers_t*mod)
846 {
847     namespace_t ns;
848     ns.access = 0;
849     ns.name = "";
850     if(mod->flags&FLAG_NAMESPACE)  {
851         if(mod->flags&(FLAG_PRIVATE|FLAG_PROTECTED|FLAG_PACKAGEINTERNAL)) 
852             syntaxerror("invalid combination of access levels and namespaces");
853         ns.access = ACCESS_NAMESPACE;
854         state_t*s = state;
855         const char*url = (const char*)trie_lookup(active_namespaces, mod->ns);
856         if(!url) {
857             /* shouldn't happen- the tokenizer only reports something as a namespace
858                if it was already registered */
859             trie_dump(active_namespaces);
860             syntaxerror("unknown namespace: %s", mod->ns);
861         }
862         ns.name = url;
863     } else if(mod->flags&FLAG_PUBLIC)  {
864         if(mod->flags&(FLAG_PRIVATE|FLAG_PROTECTED|FLAG_PACKAGEINTERNAL)) 
865             syntaxerror("invalid combination of access levels");
866         ns.access = ACCESS_PACKAGE;
867     } else if(mod->flags&FLAG_PRIVATE) {
868         if(mod->flags&(FLAG_PUBLIC|FLAG_PROTECTED|FLAG_PACKAGEINTERNAL)) 
869             syntaxerror("invalid combination of access levels");
870         ns.access = ACCESS_PRIVATE;
871     } else if(mod->flags&FLAG_PROTECTED) {
872         if(mod->flags&(FLAG_PUBLIC|FLAG_PRIVATE|FLAG_PACKAGEINTERNAL)) 
873             syntaxerror("invalid combination of access levels");
874         ns.access = ACCESS_PROTECTED;
875     } else {
876         ns.access = ACCESS_PACKAGEINTERNAL;
877     }
878     return ns;
879 }
880 static slotinfo_t* find_class(const char*name);
881
882 static memberinfo_t* findmember_nsset(classinfo_t*cls, const char*name, char recurse)
883 {
884     return registry_findmember_nsset(cls, state->active_namespace_urls, name, recurse);
885 }
886
887 void add_active_url(const char*url)
888 {
889     NEW(namespace_t,n);
890     n->name = url;
891     list_append(state->active_namespace_urls, n);
892 }
893
894 static void function_initvars(methodstate_t*m, params_t*params, int flags, char var0)
895 {
896     if(var0) {
897         int index = -1;
898         if(m->inner)
899             index = new_variable("this", 0, 0, 0);
900         else if(!m->is_global)
901             index = new_variable((flags&FLAG_STATIC)?"class":"this", state->cls?state->cls->info:0, 0, 0);
902         else
903             index = new_variable("globalscope", 0, 0, 0);
904         if(index)
905             *(int*)0=0;
906         parserassert(!index);
907     }
908
909     if(m->uses_slots) {
910         /* as variables and slots share the same number, make sure
911            that those variable indices are reserved. It's up to the
912            optimizer to later shuffle the variables down to lower
913            indices */
914         m->variable_count = m->uses_slots;
915     }
916
917     if(params) {
918         param_list_t*p=0;
919         for(p=params->list;p;p=p->next) {
920             new_variable(p->param->name, p->param->type, 0, 1);
921         }
922     }
923
924     if(as3_pass==2) {
925         m->scope_code = add_scope_code(m->scope_code, m);
926     }
927
928     
929     methodstate_list_t*l = m->innerfunctions;
930     while(l) {
931         methodstate_t*m = l->methodstate;
932         
933         variable_t* v = new_variable2(m->info->name, TYPE_FUNCTION(m->info), 0, 1);
934         m->var_index = v->index;
935         m->slot_index = v->index;
936         v->is_inner_method = m;
937
938         l = l->next;
939     }
940     
941     if(as3_pass==2 && m->slots) {
942         /* exchange unresolved identifiers with the actual objects */
943         DICT_ITERATE_ITEMS(m->slots, char*, name, variable_t*, v) {
944             if(v->type && v->type->kind == INFOTYPE_UNRESOLVED) {
945                 v->type = (classinfo_t*)registry_resolve((slotinfo_t*)v->type);
946                 if(!v->type || v->type->kind != INFOTYPE_CLASS) {
947                     syntaxerror("Couldn't find class %s", v->type->name);
948                 }
949             }
950         }
951     }
952 }
953
954
955 char*as3_globalclass=0;
956 static void startclass(modifiers_t* mod, char*classname, classinfo_t*extends, classinfo_list_t*implements)
957 {
958     if(state->cls) {
959         syntaxerror("inner classes now allowed"); 
960     }
961
962     new_state();
963     token_list_t*t=0;
964     classinfo_list_t*mlist=0;
965
966     if(mod->flags&~(FLAG_PACKAGEINTERNAL|FLAG_PUBLIC|FLAG_FINAL|FLAG_DYNAMIC|FLAG_INTERFACE))
967         syntaxerror("invalid modifier(s)");
968
969     if((mod->flags&(FLAG_PUBLIC|FLAG_PACKAGEINTERNAL)) == (FLAG_PUBLIC|FLAG_PACKAGEINTERNAL))
970         syntaxerror("public and internal not supported at the same time.");
971     
972     //if(!(mod->flags&FLAG_INTERFACE) && !extends) {
973     if(!(mod->flags&FLAG_INTERFACE) && !extends) {
974         // all classes extend object
975         extends = registry_getobjectclass();
976     }
977
978     /* create the class name, together with the proper attributes */
979     int access=0;
980     char*package=0;
981
982     if(!(mod->flags&FLAG_PUBLIC) && state->package==internal_filename_package) {
983         access = ACCESS_PRIVATE; package = internal_filename_package;
984     } else if(!(mod->flags&FLAG_PUBLIC) && state->package!=internal_filename_package) {
985         access = ACCESS_PACKAGEINTERNAL; package = state->package;
986     } else if(state->package!=internal_filename_package) {
987         access = ACCESS_PACKAGE; package = state->package;
988     } else {
989         syntaxerror("public classes only allowed inside a package");
990     }
991
992     if(as3_pass==1) {
993         state->cls = rfx_calloc(sizeof(classstate_t));
994         state->cls->init = rfx_calloc(sizeof(methodstate_t));
995         state->cls->static_init = rfx_calloc(sizeof(methodstate_t));
996         /* notice: we make no effort to initialize the top variable (local0) here,
997            even though it has special meaning. We just rely on the facat
998            that pass 1 won't do anything with variables */
999         
1000         dict_put(global->token2info, (void*)(ptroff_t)as3_tokencount, state->cls);
1001
1002         /* set current method to constructor- all code within the class-level (except
1003            static variable initializations) will be executed during construction time */
1004         state->method = state->cls->init;
1005
1006         if(registry_find(package, classname)) {
1007             syntaxerror("Package \"%s\" already contains a class called \"%s\"", package, classname);
1008         }
1009         /* build info struct */
1010         int num_interfaces = (list_length(implements));
1011         state->cls->info = classinfo_register(access, package, classname, num_interfaces);
1012         state->cls->info->flags |= mod->flags & (FLAG_DYNAMIC|FLAG_INTERFACE|FLAG_FINAL);
1013         
1014         int pos = 0;
1015         classinfo_list_t*l = implements;
1016         for(l=implements;l;l=l->next) {
1017             state->cls->info->interfaces[pos++] = l->classinfo;
1018         }
1019     }
1020     
1021     if(as3_pass == 2) {
1022         state->cls = dict_lookup(global->token2info, (void*)(ptroff_t)as3_tokencount);
1023         
1024         state->method = state->cls->init;
1025         parserassert(state->cls && state->cls->info);
1026        
1027         function_initvars(state->cls->init, 0, 0, 1);
1028         function_initvars(state->cls->static_init, 0, 0, 0);
1029
1030         if(extends && (extends->flags & FLAG_FINAL))
1031             syntaxerror("Can't extend final class '%s'", extends->name);
1032         
1033         int pos = 0;
1034         while(state->cls->info->interfaces[pos]) {
1035             if(!(state->cls->info->interfaces[pos]->flags & FLAG_INTERFACE))
1036                 syntaxerror("'%s' is not an interface", 
1037                     state->cls->info->interfaces[pos]->name);
1038             pos++;
1039         }
1040
1041         /* fill out interfaces and extends (we couldn't resolve those during the first pass) */
1042         state->cls->info->superclass = extends;
1043
1044         /* generate the abc code for this class */
1045         MULTINAME(classname2,state->cls->info);
1046         multiname_t*extends2 = sig2mname(extends);
1047
1048         state->cls->abc = abc_class_new(global->file, &classname2, extends2);
1049         if(state->cls->info->flags&FLAG_FINAL) abc_class_final(state->cls->abc);
1050         if(!(state->cls->info->flags&FLAG_DYNAMIC)) abc_class_sealed(state->cls->abc);
1051         if(state->cls->info->flags&FLAG_INTERFACE) {
1052             abc_class_interface(state->cls->abc);
1053         }
1054
1055         abc_class_protectedNS(state->cls->abc, classname);
1056
1057         for(mlist=implements;mlist;mlist=mlist->next) {
1058             MULTINAME(m, mlist->classinfo);
1059             abc_class_add_interface(state->cls->abc, &m);
1060         }
1061
1062         /* write the construction code for this class to the global init
1063            function */
1064         int slotindex = abc_initscript_addClassTrait(global->init, &classname2, state->cls->abc);
1065
1066         abc_method_body_t*m = global->init->method->body;
1067         __ getglobalscope(m);
1068         classinfo_t*s = extends;
1069
1070         int count=0;
1071         
1072         while(s) {
1073             //TODO: take a look at the current scope stack, maybe 
1074             //      we can re-use something
1075             s = s->superclass;
1076             if(!s) 
1077             break;
1078            
1079             multiname_t*s2 = sig2mname(s);
1080             __ getlex2(m, s2);
1081             multiname_destroy(s2);
1082
1083             __ pushscope(m); count++;
1084             m->code = m->code->prev->prev; // invert
1085         }
1086         /* continue appending after last op end */
1087         while(m->code && m->code->next) m->code = m->code->next; 
1088
1089         /* TODO: if this is one of *our* classes, we can also 
1090                  do a getglobalscope/getslot <nr> (which references
1091                  the init function's slots) */
1092         if(extends2) {
1093             __ getlex2(m, extends2);
1094             __ dup(m);
1095             /* notice: we get a Verify Error #1107 if the top elemnt on the scope
1096                stack is not the superclass */
1097             __ pushscope(m);count++;
1098         } else {
1099             __ pushnull(m);
1100             /* notice: we get a verify error #1107 if the top element on the scope 
1101                stack is not the global object */
1102             __ getlocal_0(m);
1103             __ pushscope(m);count++;
1104         }
1105         __ newclass(m,state->cls->abc);
1106         while(count--) {
1107             __ popscope(m);
1108         }
1109         __ setslot(m, slotindex);
1110         multiname_destroy(extends2);
1111
1112         /* flash.display.MovieClip handling */
1113
1114         if(!as3_globalclass && (mod->flags&FLAG_PUBLIC) && slotinfo_equals((slotinfo_t*)registry_getMovieClip(),(slotinfo_t*)extends)) {
1115             if(state->package && state->package[0]) {
1116                 as3_globalclass = concat3(state->package, ".", classname);
1117             } else {
1118                 as3_globalclass = strdup(classname);
1119             }
1120         }
1121     }
1122 }
1123
1124 static int slotstate_varconst = 0;
1125 static modifiers_t*slotstate_flags = 0;
1126 static void setslotstate(modifiers_t* flags, int varconst)
1127 {
1128     slotstate_varconst = varconst;
1129     slotstate_flags = flags;
1130     if(state->cls) {
1131         if(flags && flags->flags&FLAG_STATIC) {
1132             state->method = state->cls->static_init;
1133         } else {
1134             state->method = state->cls->init;
1135         }
1136     } else {
1137         parserassert(state->method);
1138     }
1139 }
1140
1141 static void endclass()
1142 {
1143     if(as3_pass == 2) {
1144         if(!state->cls->has_constructor && !(state->cls->info->flags&FLAG_INTERFACE)) {
1145             code_t*c = 0;
1146             c = abc_getlocal_0(c);
1147             c = abc_constructsuper(c, 0);
1148             state->cls->init->header = code_append(state->cls->init->header, c);
1149             state->cls->has_constructor=1;
1150         }
1151         if(state->cls->init) {
1152             if(state->cls->info->flags&FLAG_INTERFACE) {
1153                 if(state->cls->init->header) 
1154                     syntaxerror("interface can not have class-level code");
1155             } else {
1156                 abc_method_t*m = abc_class_getconstructor(state->cls->abc, 0);
1157                 code_t*c = method_header(state->cls->init);
1158                 m->body->code = wrap_function(c, 0, m->body->code);
1159             }
1160         }
1161         if(state->cls->static_init) {
1162             abc_method_t*m = abc_class_getstaticconstructor(state->cls->abc, 0);
1163             code_t*c = method_header(state->cls->static_init);
1164             m->body->code = wrap_function(c, 0, m->body->code);
1165         }
1166     }
1167
1168     old_state();
1169 }
1170
1171 void check_code_for_break(code_t*c)
1172 {
1173     while(c) {
1174         if(c->opcode == OPCODE___BREAK__) {
1175             char*name = string_cstr(c->data[0]);
1176             syntaxerror("Unresolved \"break %s\"", name);
1177         }
1178         if(c->opcode == OPCODE___CONTINUE__) {
1179             char*name = string_cstr(c->data[0]);
1180             syntaxerror("Unresolved \"continue %s\"", name);
1181         }
1182         if(c->opcode == OPCODE___PUSHPACKAGE__) {
1183             char*name = string_cstr(c->data[0]);
1184             syntaxerror("Can't reference a package (%s) as such", name);
1185         }
1186         c=c->prev;
1187     }
1188 }
1189
1190
1191 static void check_constant_against_type(classinfo_t*t, constant_t*c)
1192 {
1193     return;
1194 #define xassert(b) if(!(b)) syntaxerror("Invalid default value %s for type '%s'", constant_tostring(c), t->name)
1195    if(TYPE_IS_NUMBER(t)) {
1196         xassert(c->type == CONSTANT_FLOAT
1197              || c->type == CONSTANT_INT
1198              || c->type == CONSTANT_UINT);
1199    } else if(TYPE_IS_UINT(t)) {
1200         xassert(c->type == CONSTANT_UINT ||
1201                (c->type == CONSTANT_INT && c->i>=0));
1202    } else if(TYPE_IS_INT(t)) {
1203         xassert(c->type == CONSTANT_INT);
1204    } else if(TYPE_IS_BOOLEAN(t)) {
1205         xassert(c->type == CONSTANT_TRUE
1206              || c->type == CONSTANT_FALSE);
1207    }
1208 }
1209
1210 static void check_override(memberinfo_t*m, int flags)
1211 {
1212     if(!m)
1213         return;
1214     if(m->parent == state->cls->info)
1215         syntaxerror("class '%s' already contains a method/slot '%s'", m->parent->name, m->name);
1216     if(!m->parent)
1217         syntaxerror("internal error: overriding method %s, which doesn't have parent", m->name);
1218     if(m->access==ACCESS_PRIVATE)
1219         return;
1220     if(m->flags & FLAG_FINAL)
1221         syntaxerror("can't override final member %s", m->name);
1222     
1223     /* allow this. it's no issue.
1224     if((m->flags & FLAG_STATIC) && !(flags&FLAG_STATIC))
1225         syntaxerror("can't override static member %s", m->name);*/
1226
1227     if(!(m->flags & FLAG_STATIC) && (flags&FLAG_STATIC))
1228         syntaxerror("can't override non-static member %s with static declaration", m->name);
1229
1230     if(!(flags&FLAG_OVERRIDE) && !(flags&FLAG_STATIC) && !(m->flags&FLAG_STATIC)) {
1231         if(m->parent && !(m->parent->flags&FLAG_INTERFACE)) {
1232             if(m->kind == INFOTYPE_METHOD)
1233                 syntaxerror("can't override without explicit 'override' declaration");
1234             else
1235                 syntaxerror("can't override '%s'", m->name);
1236         }
1237     }
1238 }
1239
1240 static methodinfo_t*registerfunction(enum yytokentype getset, modifiers_t*mod, char*name, params_t*params, classinfo_t*return_type, int slot)
1241 {
1242     methodinfo_t*minfo = 0;
1243     namespace_t ns = modifiers2access(mod);
1244     if(!state->cls) {
1245         //package method
1246         minfo = methodinfo_register_global(ns.access, state->package, name);
1247         minfo->return_type = 0; // save this for pass 2
1248     } else if(getset != KW_GET && getset != KW_SET) {
1249         //class method
1250         memberinfo_t* m = registry_findmember(state->cls->info, ns.name, name, 0);
1251         if(m) {
1252             printf("%s.%s | %s.%s\n", 
1253                 m->package, m->name,
1254                 ns.name, name);
1255             syntaxerror("class already contains a %s '%s'", infotypename((slotinfo_t*)m), m->name);
1256         }
1257         minfo = methodinfo_register_onclass(state->cls->info, ns.access, ns.name, name);
1258         minfo->return_type = 0; // save this for pass 2 
1259         // getslot on a member slot only returns "undefined", so no need
1260         // to actually store these
1261         //state->minfo->slot = state->method->abc->method->trait->slot_id;
1262     } else {
1263         //class getter/setter
1264         int gs = getset==KW_GET?SUBTYPE_GET:SUBTYPE_SET;
1265         classinfo_t*type=0;
1266         if(getset == KW_GET) {
1267             type = return_type;
1268         } else if(params->list && params->list->param && !params->list->next) {
1269             type = params->list->param->type;
1270         } else
1271             syntaxerror("setter function needs to take exactly one argument");
1272         // not sure wether to look into superclasses here, too
1273         minfo = (methodinfo_t*)registry_findmember(state->cls->info, ns.name, name, 1);
1274         if(minfo) {
1275             if(minfo->kind!=INFOTYPE_SLOT)
1276                 syntaxerror("class already contains a method called '%s'", name);
1277             if(!(minfo->subtype & (SUBTYPE_GETSET)))
1278                 syntaxerror("class already contains a field called '%s'", name);
1279             if(minfo->subtype & gs)
1280                 syntaxerror("getter/setter for '%s' already defined", name);
1281             /* make a setter or getter into a getset */
1282             minfo->subtype |= gs;
1283             
1284             /*
1285             FIXME: this check needs to be done in pass 2
1286             
1287             if((!minfo->return_type != !type) ||
1288                 (minfo->return_type && type && 
1289                  !strcmp(minfo->return_type->name, type->name))) {
1290                 syntaxerror("different type in getter and setter: %s and %s", 
1291                     minfo->return_type?minfo->return_type->name:"*", 
1292                     type?type->name:"*");
1293             }*/
1294         } else {
1295             minfo = methodinfo_register_onclass(state->cls->info, ns.access, ns.name, name);
1296             minfo->kind = INFOTYPE_SLOT; //hack
1297             minfo->subtype = gs;
1298             minfo->return_type = 0;
1299         }
1300         /* can't assign a slot as getter and setter might have different slots */
1301         //minfo->slot = slot;
1302     }
1303     if(mod->flags&FLAG_FINAL) minfo->flags |= FLAG_FINAL;
1304     if(mod->flags&FLAG_STATIC) minfo->flags |= FLAG_STATIC;
1305     if(mod->flags&FLAG_OVERRIDE) minfo->flags |= FLAG_OVERRIDE;
1306
1307     return minfo;
1308 }
1309
1310 static void innerfunction(char*name, params_t*params, classinfo_t*return_type)
1311 {
1312     //parserassert(state->method && state->method->info);
1313
1314     methodstate_t*parent_method = state->method;
1315
1316     if(as3_pass==1) {
1317         return_type = 0; // not valid in pass 1
1318     }
1319
1320     new_state();
1321     state->new_vars = 1;
1322    
1323     if(as3_pass == 1) {
1324         state->method = rfx_calloc(sizeof(methodstate_t));
1325         state->method->inner = 1;
1326         state->method->variable_count = 0;
1327         state->method->abc = rfx_calloc(sizeof(abc_method_t));
1328
1329         NEW(methodinfo_t,minfo);
1330         minfo->kind = INFOTYPE_METHOD;
1331         minfo->access = ACCESS_PACKAGEINTERNAL;
1332         minfo->name = name;
1333         state->method->info = minfo;
1334
1335         if(parent_method)
1336             list_append(parent_method->innerfunctions, state->method);
1337
1338         dict_put(global->token2info, (void*)(ptroff_t)as3_tokencount, state->method);
1339     
1340         function_initvars(state->method, params, 0, 1);
1341     }
1342
1343     if(as3_pass == 2) {
1344         state->method = dict_lookup(global->token2info, (void*)(ptroff_t)as3_tokencount);
1345         state->method->variable_count = 0;
1346         parserassert(state->method);
1347
1348         state->method->info->return_type = return_type;
1349         function_initvars(state->method, params, 0, 1);
1350     }
1351 }
1352
1353 static void startfunction(modifiers_t*mod, enum yytokentype getset, char*name,
1354                           params_t*params, classinfo_t*return_type)
1355 {
1356     if(state->method && state->method->info) {
1357         syntaxerror("not able to start another method scope");
1358     }
1359     new_state();
1360     state->new_vars = 1;
1361     
1362     if(as3_pass == 1) {
1363         state->method = rfx_calloc(sizeof(methodstate_t));
1364         state->method->has_super = 0;
1365
1366         if(state->cls) {
1367             state->method->is_constructor = !strcmp(state->cls->info->name,name);
1368         } else {
1369             state->method->is_global = 1;
1370             state->method->late_binding = 1; // for global methods, always push local_0 on the scope stack
1371         }
1372         if(state->method->is_constructor)
1373             name = "__as3_constructor__";
1374
1375         state->method->info = registerfunction(getset, mod, name, params, return_type, 0);
1376        
1377         function_initvars(state->method, params, mod->flags, 1);
1378         
1379         dict_put(global->token2info, (void*)(ptroff_t)as3_tokencount, state->method);
1380     }
1381
1382     if(as3_pass == 2) {
1383         state->method = dict_lookup(global->token2info, (void*)(ptroff_t)as3_tokencount);
1384         state->method->variable_count = 0;
1385         parserassert(state->method);
1386                 
1387         if(state->cls) {
1388             memberinfo_t*m = registry_findmember(state->cls->info, mod->ns, name, 2);
1389             check_override(m, mod->flags);
1390         }
1391             
1392         if(state->cls) { 
1393             state->cls->has_constructor |= state->method->is_constructor;
1394         }
1395         
1396         state->method->info->return_type = return_type;
1397         function_initvars(state->method, params, mod->flags, 1);
1398     } 
1399 }
1400
1401 static abc_method_t* endfunction(modifiers_t*mod, enum yytokentype getset, char*name,
1402                           params_t*params, classinfo_t*return_type, code_t*body)
1403 {
1404     if(as3_pass==1) {
1405         // store inner methods in variables
1406         function_initvars(state->method, 0, 0, 0);
1407
1408         methodstate_list_t*ml = state->method->innerfunctions;
1409         
1410         dict_t*xvars = dict_new();
1411
1412         while(ml) {
1413             methodstate_t*m = ml->methodstate;
1414             parserassert(m->inner);
1415             if(m->unresolved_variables) {
1416                 dict_t*d = m->unresolved_variables;
1417                 int t;
1418                 for(t=0;t<d->hashsize;t++) {
1419                     dictentry_t*l = d->slots[t]; 
1420                     while(l) {
1421                         /* check parent method's variables */
1422                         variable_t*v;
1423                         if((v=find_variable(state, l->key))) {
1424                             m->uses_parent_function = 1;
1425                             state->method->uses_slots = 1;
1426                             dict_put(xvars, l->key, 0);
1427                         }
1428                         l = l->next;
1429                     }
1430                     if(l) break;
1431                 }
1432
1433                 dict_destroy(m->unresolved_variables);
1434                 m->unresolved_variables = 0;
1435             }
1436             ml = ml->next;
1437         }
1438         
1439         if(state->method->uses_slots) {
1440             state->method->slots = dict_new();
1441             int i = 1;
1442             DICT_ITERATE_ITEMS(state->vars, char*, name, variable_t*, v) {
1443                 if(!name) syntaxerror("internal error");
1444                 if(v->index && dict_contains(xvars, name)) {
1445                     v->init = 0;
1446                     v->index = i++;
1447                     if(v->is_inner_method) {
1448                         v->is_inner_method->is_a_slot = 1;
1449                     }
1450                     //v->type = 0;
1451                     dict_put(state->method->slots, name, v);
1452                 }
1453             }
1454             state->method->uses_slots = i;
1455             dict_destroy(state->vars);state->vars = 0;
1456         }
1457         old_state();
1458         return 0;
1459     }
1460
1461     if(as3_pass==2) {
1462         /*if(state->method->uses_parent_function){
1463             syntaxerror("accessing variables of parent function from inner functions not supported yet");
1464         }*/
1465
1466         abc_method_t*f = 0;
1467
1468         multiname_t*type2 = sig2mname(return_type);
1469         int slot = 0;
1470         if(state->method->inner) {
1471             f = state->method->abc;
1472             abc_method_init(f, global->file, type2, 1);
1473         } else if(state->method->is_constructor) {
1474             f = abc_class_getconstructor(state->cls->abc, type2);
1475         } else if(!state->method->is_global) {
1476             namespace_t mname_ns = modifiers2access(mod);
1477             multiname_t mname = {QNAME, &mname_ns, 0, name};
1478
1479             if(mod->flags&FLAG_STATIC)
1480                 f = abc_class_staticmethod(state->cls->abc, type2, &mname);
1481             else
1482                 f = abc_class_method(state->cls->abc, type2, &mname);
1483             slot = f->trait->slot_id;
1484         } else {
1485             namespace_t mname_ns = {state->method->info->access, state->package};
1486             multiname_t mname = {QNAME, &mname_ns, 0, name};
1487
1488             f = abc_method_new(global->file, type2, 1);
1489             trait_t*t = trait_new_method(&global->init->traits, multiname_clone(&mname), f);
1490             //abc_code_t*c = global->init->method->body->code;
1491         }
1492         //flash doesn't seem to allow us to access function slots
1493         //state->method->info->slot = slot;
1494
1495         if(mod && mod->flags&FLAG_OVERRIDE) f->trait->attributes |= TRAIT_ATTR_OVERRIDE;
1496         if(getset == KW_GET) f->trait->kind = TRAIT_GETTER;
1497         if(getset == KW_SET) f->trait->kind = TRAIT_SETTER;
1498         if(params->varargs) f->flags |= METHOD_NEED_REST;
1499
1500         char opt=0;
1501         param_list_t*p=0;
1502         for(p=params->list;p;p=p->next) {
1503             if(params->varargs && !p->next) {
1504                 break; //varargs: omit last parameter in function signature
1505             }
1506             multiname_t*m = sig2mname(p->param->type);
1507             list_append(f->parameters, m);
1508             if(p->param->value) {
1509                 check_constant_against_type(p->param->type, p->param->value);
1510                 opt=1;list_append(f->optional_parameters, p->param->value);
1511             } else if(opt) {
1512                 syntaxerror("non-optional parameter not allowed after optional parameters");
1513             }
1514         }
1515         if(state->method->slots) {
1516             DICT_ITERATE_ITEMS(state->method->slots, char*, name, variable_t*, v) {
1517                 if(v->index) {
1518                     multiname_t*mname = multiname_new(namespace_new(ACCESS_PACKAGE, ""), name);
1519                     multiname_t*type = sig2mname(v->type);
1520                     trait_t*t = trait_new_member(&f->body->traits, type, mname, 0);
1521                     t->slot_id = v->index;
1522                 }
1523             }
1524         }
1525
1526         check_code_for_break(body);
1527
1528         /* Seems this works now.
1529         if(state->method->exceptions && state->method->uses_slots) {
1530            as3_warning("try/catch and activation not supported yet within the same method");
1531         }*/
1532
1533         if(f->body) {
1534             f->body->code = body;
1535             f->body->exceptions = state->method->exceptions;
1536         } else { //interface
1537             if(body)
1538                 syntaxerror("interface methods can't have a method body");
1539         }
1540
1541         old_state();
1542         return f;
1543     }
1544         
1545     return 0;
1546 }
1547
1548 char is_subtype_of(classinfo_t*type, classinfo_t*supertype)
1549 {
1550     return 1; // FIXME
1551 }
1552
1553 void breakjumpsto(code_t*c, char*name, code_t*jump) 
1554 {
1555     while(c) {
1556         if(c->opcode == OPCODE___BREAK__) {
1557             string_t*name2 = c->data[0];
1558             if(!name2->len || !strncmp(name2->str, name, name2->len)) {
1559                 c->opcode = OPCODE_JUMP;
1560                 c->branch = jump;
1561             }
1562         }
1563         c=c->prev;
1564     }
1565 }
1566 void continuejumpsto(code_t*c, char*name, code_t*jump) 
1567 {
1568     while(c) {
1569         if(c->opcode == OPCODE___CONTINUE__) {
1570             string_t*name2 = c->data[0];
1571             if(!name2->len || !strncmp(name2->str, name, name2->len)) {
1572                 c->opcode = OPCODE_JUMP;
1573                 c->branch = jump;
1574             }
1575         }
1576         c = c->prev;
1577     }
1578 }
1579
1580 #define IS_INT(a) (TYPE_IS_INT((a)) || TYPE_IS_UINT((a)))
1581 #define IS_NUMBER_OR_INT(a) (TYPE_IS_INT((a)) || TYPE_IS_UINT((a)) || TYPE_IS_NUMBER((a)))
1582 #define BOTH_INT(a,b) (IS_INT(a) && IS_INT(b))
1583
1584 classinfo_t*join_types(classinfo_t*type1, classinfo_t*type2, char op)
1585 {
1586     if(!type1 || !type2) 
1587         return registry_getanytype();
1588     if(TYPE_IS_ANY(type1) || TYPE_IS_ANY(type2))
1589         return registry_getanytype();
1590
1591     if(op=='+') {
1592         if(IS_NUMBER_OR_INT(type1) && IS_NUMBER_OR_INT(type2)) {
1593             return TYPE_NUMBER;
1594         } else {
1595             return TYPE_ANY;
1596         }
1597     }
1598
1599     if(type1 == type2)
1600         return type1;
1601     return registry_getanytype();
1602 }
1603 code_t*converttype(code_t*c, classinfo_t*from, classinfo_t*to)
1604 {
1605     if(from==to)
1606         return c;
1607     if(!to) {
1608         return abc_coerce_a(c);
1609     }
1610     MULTINAME(m, to);
1611     if(!from) {
1612         // cast an "any" type to a specific type. subject to
1613         // runtime exceptions
1614         return abc_coerce2(c, &m);
1615     }
1616     
1617     if((TYPE_IS_NUMBER(from) || TYPE_IS_UINT(from) || TYPE_IS_INT(from)) &&
1618        (TYPE_IS_NUMBER(to) || TYPE_IS_UINT(to) || TYPE_IS_INT(to))) {
1619         // allow conversion between number types
1620         return abc_coerce2(c, &m);
1621     }
1622     //printf("%s.%s\n", from.package, from.name);
1623     //printf("%s.%s\n", to.package, to.name);
1624
1625     classinfo_t*supertype = from;
1626     while(supertype) {
1627         if(supertype == to) {
1628              // target type is one of from's superclasses
1629              return abc_coerce2(c, &m);
1630         }
1631         int t=0;
1632         while(supertype->interfaces[t]) {
1633             if(supertype->interfaces[t]==to) {
1634                 // target type is one of from's interfaces
1635                 return abc_coerce2(c, &m);
1636             }
1637             t++;
1638         }
1639         supertype = supertype->superclass;
1640     }
1641     if(TYPE_IS_FUNCTION(from) && TYPE_IS_FUNCTION(to))
1642         return c;
1643     if(TYPE_IS_CLASS(from) && TYPE_IS_CLASS(to))
1644         return c;
1645     if(TYPE_IS_NULL(from) && !IS_NUMBER_OR_INT(to))
1646         return c;
1647
1648     as3_error("can't convert type %s%s%s to %s%s%s", 
1649         from->package, from->package?".":"", from->name, 
1650         to->package, to->package?".":"", to->name);
1651     return c;
1652 }
1653
1654 code_t*defaultvalue(code_t*c, classinfo_t*type)
1655 {
1656     if(TYPE_IS_INT(type)) {
1657        c = abc_pushbyte(c, 0);
1658     } else if(TYPE_IS_UINT(type)) {
1659        c = abc_pushuint(c, 0);
1660     } else if(TYPE_IS_FLOAT(type)) {
1661        c = abc_pushnan(c);
1662     } else if(TYPE_IS_BOOLEAN(type)) {
1663        c = abc_pushfalse(c);
1664     } else if(!type) {
1665        //c = abc_pushundefined(c);
1666     } else {
1667        c = abc_pushnull(c);
1668        MULTINAME(m, type);
1669        c = abc_coerce2(c, &m);
1670     }
1671     return c;
1672 }
1673
1674 char is_pushundefined(code_t*c)
1675 {
1676     return (c && !c->prev && !c->next && c->opcode == OPCODE_PUSHUNDEFINED);
1677 }
1678
1679 static const char* get_package_from_name(const char*name)
1680 {
1681     /* try explicit imports */
1682     dictentry_t* e = dict_get_slot(state->imports, name);
1683     while(e) {
1684         if(!strcmp(e->key, name)) {
1685             slotinfo_t*c = (slotinfo_t*)e->data;
1686             if(c) return c->package;
1687         }
1688         e = e->next;
1689     }
1690     return 0;
1691 }
1692 static namespace_list_t*get_current_imports()
1693 {
1694     namespace_list_t*searchlist = 0;
1695     
1696     list_append(searchlist, namespace_new_package(state->package));
1697
1698     import_list_t*l = state->wildcard_imports;
1699     while(l) {
1700         namespace_t*ns = namespace_new_package(l->import->package);
1701         list_append(searchlist, ns);
1702         l = l->next;
1703     }
1704     list_append(searchlist, namespace_new_package(""));
1705     list_append(searchlist, namespace_new_package(internal_filename_package));
1706     return searchlist;
1707 }
1708
1709 static slotinfo_t* find_class(const char*name)
1710 {
1711     slotinfo_t*c=0;
1712
1713     c = registry_find(state->package, name);
1714     if(c) return c;
1715
1716     /* try explicit imports */
1717     dictentry_t* e = dict_get_slot(state->imports, name);
1718     if(c) return c;
1719     while(e) {
1720         if(!strcmp(e->key, name)) {
1721             c = (slotinfo_t*)e->data;
1722             if(c) return c;
1723         }
1724         e = e->next;
1725     }
1726
1727     /* try package.* imports */
1728     import_list_t*l = state->wildcard_imports;
1729     while(l) {
1730         //printf("does package %s contain a class %s?\n", l->import->package, name);
1731         c = registry_find(l->import->package, name);
1732         if(c) return c;
1733         l = l->next;
1734     }
1735
1736     /* try global package */
1737     c = registry_find("", name);
1738     if(c) return c;
1739   
1740     /* try local "filename" package */
1741     c = registry_find(internal_filename_package, name);
1742     if(c) return c;
1743
1744     return 0;
1745 }
1746 typedcode_t push_class(slotinfo_t*a)
1747 {
1748     typedcode_t x;
1749     x.c = 0;
1750     x.t = 0;
1751     if(a->access == ACCESS_PACKAGEINTERNAL &&
1752        strcmp(a->package, state->package) &&
1753        strcmp(a->package, internal_filename_package)
1754        ) {
1755        syntaxerror("Can't access internal %s %s in package '%s' from package '%s'",
1756             infotypename(a), a->name, a->package, state->package);
1757     }
1758
1759     if(a->kind != INFOTYPE_CLASS) {
1760         MULTINAME(m, a);
1761         x.c = abc_findpropstrict2(x.c, &m);
1762         x.c = abc_getproperty2(x.c, &m);
1763         if(a->kind == INFOTYPE_METHOD) {
1764             methodinfo_t*f = (methodinfo_t*)a;
1765             x.t = TYPE_FUNCTION(f);
1766         } else {
1767             varinfo_t*v = (varinfo_t*)a;
1768             x.t = v->type;
1769         }
1770     } else {
1771         classinfo_t*c = (classinfo_t*)a;
1772         if(c->slot) {
1773             x.c = abc_getglobalscope(x.c);
1774             x.c = abc_getslot(x.c, c->slot);
1775         } else {
1776             MULTINAME(m, c);
1777             x.c = abc_getlex2(x.c, &m);
1778         }
1779         x.t = TYPE_CLASS(c);
1780     }
1781     return x;
1782 }
1783
1784 static char is_getlocal(code_t*c)
1785 {
1786     if(!c || c->prev || c->next)
1787         return 0;
1788     return(c->opcode == OPCODE_GETLOCAL
1789         || c->opcode == OPCODE_GETLOCAL_0
1790         || c->opcode == OPCODE_GETLOCAL_1
1791         || c->opcode == OPCODE_GETLOCAL_2
1792         || c->opcode == OPCODE_GETLOCAL_3);
1793 }
1794 static int getlocalnr(code_t*c)
1795 {
1796     if(c->opcode == OPCODE_GETLOCAL) {return (ptroff_t)c->data[0];}
1797     else if(c->opcode == OPCODE_GETLOCAL_0) {return 0;}
1798     else if(c->opcode == OPCODE_GETLOCAL_1) {return 1;}
1799     else if(c->opcode == OPCODE_GETLOCAL_2) {return 2;}
1800     else if(c->opcode == OPCODE_GETLOCAL_3) {return 3;}
1801     else syntaxerror("Internal error: opcode %02x is not a getlocal call", c->opcode);
1802     return 0;
1803 }
1804
1805 static code_t* toreadwrite(code_t*in, code_t*middlepart, char justassign, char readbefore)
1806 {
1807     /* converts this:
1808
1809        [prefix code] [read instruction]
1810
1811        to this:
1812
1813        [prefix code] ([dup]) [read instruction] [middlepart] [setvar] [write instruction] [getvar]
1814     */
1815     if(in && in->opcode == OPCODE_COERCE_A) {
1816         in = code_cutlast(in);
1817     }
1818     if(in->next)
1819         syntaxerror("internal error");
1820
1821     /* chop off read instruction */
1822     code_t*prefix = in;
1823     code_t*r = in;
1824     if(r->prev) {
1825         prefix = r->prev;r->prev = 0;
1826         prefix->next=0;
1827     } else {
1828         prefix = 0;
1829     }
1830         
1831     char use_temp_var = readbefore;
1832
1833     /* generate the write instruction, and maybe append a dup to the prefix code */
1834     code_t* write = abc_nop(0);
1835     if(r->opcode == OPCODE_GETPROPERTY) {
1836         write->opcode = OPCODE_SETPROPERTY;
1837         multiname_t*m = (multiname_t*)r->data[0];
1838         write->data[0] = multiname_clone(m);
1839         if(m->type == QNAME || m->type == MULTINAME) {
1840             if(!justassign) {
1841                 prefix = abc_dup(prefix); // we need the object, too
1842             }
1843             use_temp_var = 1;
1844         } else if(m->type == MULTINAMEL) {
1845             if(!justassign) {
1846                 /* dupping two values on the stack requires 5 operations and one register- 
1847                    couldn't adobe just have given us a dup2? */
1848                 int temp = gettempvar();
1849                 prefix = abc_setlocal(prefix, temp);
1850                 prefix = abc_dup(prefix);
1851                 prefix = abc_getlocal(prefix, temp);
1852                 prefix = abc_swap(prefix);
1853                 prefix = abc_getlocal(prefix, temp);
1854                 if(!use_temp_var);
1855                     prefix = abc_kill(prefix, temp);
1856             }
1857             use_temp_var = 1;
1858         } else {
1859             syntaxerror("illegal lvalue: can't assign a value to this expression (not a qname/multiname)");
1860         }
1861     } else if(r->opcode == OPCODE_GETSLOT) {
1862         write->opcode = OPCODE_SETSLOT;
1863         write->data[0] = r->data[0];
1864         if(!justassign) {
1865             prefix = abc_dup(prefix); // we need the object, too
1866         }
1867         use_temp_var = 1;
1868     } else if(r->opcode == OPCODE_GETLOCAL) { 
1869         write->opcode = OPCODE_SETLOCAL;
1870         write->data[0] = r->data[0];
1871     } else if(r->opcode == OPCODE_GETLOCAL_0) { 
1872         write->opcode = OPCODE_SETLOCAL_0;
1873     } else if(r->opcode == OPCODE_GETLOCAL_1) { 
1874         write->opcode = OPCODE_SETLOCAL_1;
1875     } else if(r->opcode == OPCODE_GETLOCAL_2) { 
1876         write->opcode = OPCODE_SETLOCAL_2;
1877     } else if(r->opcode == OPCODE_GETLOCAL_3) { 
1878         write->opcode = OPCODE_SETLOCAL_3;
1879     } else if(r->opcode == OPCODE_GETSUPER) { 
1880         write->opcode = OPCODE_SETSUPER;
1881         multiname_t*m = (multiname_t*)r->data[0];
1882         write->data[0] = multiname_clone(m);
1883     } else {
1884         code_dump(r);
1885         syntaxerror("illegal lvalue: can't assign a value to this expression");
1886     }
1887     code_t* c = 0;
1888     
1889     int temp = -1;
1890     if(!justassign) {
1891         if(use_temp_var) {
1892             /* with getproperty/getslot, we have to be extra careful not
1893                to execute the read code twice, as it might have side-effects
1894                (e.g. if the property is in fact a setter/getter combination)
1895
1896                So read the value, modify it, and write it again,
1897                using prefix only once and making sure (by using a temporary
1898                register) that the return value is what we just wrote */
1899             temp = gettempvar();
1900             c = code_append(c, prefix);
1901             c = code_append(c, r);
1902             if(readbefore) {
1903                 c = abc_dup(c);
1904                 c = abc_setlocal(c, temp);
1905             }
1906             c = code_append(c, middlepart);
1907             if(!readbefore) {
1908                 c = abc_dup(c);
1909                 c = abc_setlocal(c, temp);
1910             }
1911             c = code_append(c, write);
1912             c = abc_getlocal(c, temp);
1913             c = abc_kill(c, temp);
1914         } else {
1915             /* if we're allowed to execute the read code twice *and*
1916                the middlepart doesn't modify the code, things are easier.
1917             */
1918             code_t* r2 = code_dup(r);
1919             //c = code_append(c, prefix);
1920             parserassert(!prefix);
1921             c = code_append(c, r);
1922             c = code_append(c, middlepart);
1923             c = code_append(c, write);
1924             c = code_append(c, r2);
1925         }
1926     } else {
1927         /* even smaller version: overwrite the value without reading
1928            it out first */
1929         if(!use_temp_var) {
1930             if(prefix) {
1931                 c = code_append(c, prefix);
1932                 c = abc_dup(c);
1933             }
1934             c = code_append(c, middlepart);
1935             c = code_append(c, write);
1936             c = code_append(c, r);
1937         } else {
1938             code_free(r);r=0;
1939             temp = gettempvar();
1940             if(prefix) {
1941                 c = code_append(c, prefix);
1942             }
1943             c = code_append(c, middlepart);
1944             c = abc_dup(c);
1945             c = abc_setlocal(c, temp);
1946             c = code_append(c, write);
1947             c = abc_getlocal(c, temp);
1948             c = abc_kill(c, temp);
1949         }
1950     }
1951     return c;
1952 }
1953
1954 char is_break_or_jump(code_t*c)
1955 {
1956     if(!c)
1957         return 0;
1958     if(c->opcode == OPCODE_JUMP ||
1959        c->opcode == OPCODE___BREAK__ ||
1960        c->opcode == OPCODE___CONTINUE__ ||
1961        c->opcode == OPCODE_THROW ||
1962        c->opcode == OPCODE_RETURNVOID ||
1963        c->opcode == OPCODE_RETURNVALUE) {
1964        return 1;
1965     }
1966     return 0;
1967 }
1968
1969 #define IS_FINALLY_TARGET(op) \
1970         ((op) == OPCODE___CONTINUE__ || \
1971          (op) == OPCODE___BREAK__ || \
1972          (op) == OPCODE_RETURNVOID || \
1973          (op) == OPCODE_RETURNVALUE || \
1974          (op) == OPCODE___RETHROW__)
1975
1976 static code_t* insert_finally_lookup(code_t*c, code_t*finally, int tempvar)
1977 {
1978 #define NEED_EXTRA_STACK_ARG
1979     code_t*finally_label = abc_nop(0);
1980     NEW(lookupswitch_t, l);
1981     //_lookupswitch
1982
1983     code_t*i = c;
1984     int count=0;
1985     while(i) {
1986         code_t*prev = i->prev;
1987         if(IS_FINALLY_TARGET(i->opcode)) {
1988            code_t*p = prev;
1989            char needvalue=0;
1990            if(i->opcode == OPCODE___RETHROW__ ||
1991               i->opcode == OPCODE_RETURNVALUE) {
1992                if(i->opcode == OPCODE___RETHROW__)
1993                  i->opcode = OPCODE_THROW;
1994                needvalue=1;
1995                p = abc_coerce_a(p);
1996                p = abc_setlocal(p, tempvar);
1997            }
1998            p = abc_pushbyte(p, count++);
1999            p = abc_jump(p, finally_label);
2000            code_t*target = p = abc_label(p);
2001 #ifdef NEED_EXTRA_STACK_ARG
2002            p = abc_pop(p);
2003 #endif
2004            if(needvalue) {
2005                p = abc_getlocal(p, tempvar);
2006            }
2007
2008            p->next = i;i->prev = p;
2009            list_append(l->targets, target);
2010         }
2011         i = prev;
2012     }
2013
2014     code_t*j,*f;
2015     c = abc_pushbyte(c, -1);
2016     c = code_append(c, finally_label);
2017     c = code_append(c, finally);
2018
2019 #ifdef NEED_EXTRA_STACK_ARG
2020     c = abc_dup(c);
2021 #endif
2022     c = abc_lookupswitch(c, l);
2023     c = l->def = abc_label(c);
2024 #ifdef NEED_EXTRA_STACK_ARG
2025     c = abc_pop(c);
2026 #endif
2027
2028     return c;
2029 }
2030
2031 static code_t* insert_finally_simple(code_t*c, code_t*finally, int tempvar)
2032 {
2033     code_t*i = c;
2034     while(i) {
2035         code_t*prev = i->prev;
2036         if(IS_FINALLY_TARGET(i->opcode)) {
2037            if(i->opcode == OPCODE___RETHROW__)
2038                 i->opcode = OPCODE_THROW;
2039            code_t*end = code_dup(finally);
2040            code_t*start = code_start(end);
2041            if(prev) prev->next = start;
2042            start->prev = prev;
2043            i->prev = end;
2044            end->next = i;
2045         }
2046         i = prev;
2047     }
2048     return code_append(c, finally);
2049 }
2050
2051 code_t* insert_finally(code_t*c, code_t*finally, int tempvar)
2052 {
2053     if(!finally)
2054         return c;
2055     code_t*i = c;
2056     char cantdup=0;
2057     int num_insertion_points=0;
2058     while(i) {
2059         if(IS_FINALLY_TARGET(i->opcode))
2060             num_insertion_points++;
2061         i = i->prev;
2062     }
2063     i = finally;
2064     int code_size=0;
2065     while(i) {
2066         code_size++;
2067         if(i->branch || i->opcode == OPCODE_LOOKUPSWITCH) {
2068             cantdup=1;
2069         }
2070         i = i->prev;
2071     }
2072     int simple_version_cost = (1+num_insertion_points)*code_size;
2073     int lookup_version_cost = 4*num_insertion_points + 5;
2074
2075     if(cantdup || simple_version_cost > lookup_version_cost) {
2076         //printf("(use lookup) simple=%d > lookup=%d\n", simple_version_cost, lookup_version_cost);
2077         return insert_finally_lookup(c, finally, tempvar);
2078     } else {
2079         //printf("(use simple) simple=%d < lookup=%d\n", simple_version_cost, lookup_version_cost);
2080         return insert_finally_simple(c, finally, tempvar);
2081     }
2082 }
2083
2084 #define PASS1 }} if(as3_pass == 1) {{
2085 #define PASS1END }} if(as3_pass == 2) {{
2086 #define PASS2 }} if(as3_pass == 2) {{
2087 #define PASS12 }} {{
2088 #define PASS12END }} if(as3_pass == 2) {{
2089
2090 %}
2091
2092 %%
2093
2094 /* ------------ code blocks / statements ---------------- */
2095
2096 PROGRAM: MAYBE_PROGRAM_CODE_LIST
2097
2098 MAYBE_PROGRAM_CODE_LIST: | PROGRAM_CODE_LIST 
2099 PROGRAM_CODE_LIST: PROGRAM_CODE 
2100                  | PROGRAM_CODE_LIST PROGRAM_CODE
2101
2102 PROGRAM_CODE: PACKAGE_DECLARATION 
2103             | INTERFACE_DECLARATION 
2104             | CLASS_DECLARATION
2105             | FUNCTION_DECLARATION
2106             | SLOT_DECLARATION
2107             | PACKAGE_INITCODE
2108             | CONDITIONAL_COMPILATION '{' MAYBE_PROGRAM_CODE_LIST '}' // conditional compilation
2109             | ';'
2110
2111 MAYBE_INPACKAGE_CODE_LIST: | INPACKAGE_CODE_LIST
2112 INPACKAGE_CODE_LIST: INPACKAGE_CODE 
2113                    | INPACKAGE_CODE_LIST INPACKAGE_CODE
2114
2115 INPACKAGE_CODE: INTERFACE_DECLARATION 
2116               | CLASS_DECLARATION
2117               | FUNCTION_DECLARATION
2118               | SLOT_DECLARATION
2119               | PACKAGE_INITCODE
2120               | CONDITIONAL_COMPILATION '{' MAYBE_INPACKAGE_CODE_LIST '}' // conditional compilation
2121               | ';'
2122
2123 MAYBECODE: CODE {$$=$1;}
2124 MAYBECODE: {$$=code_new();}
2125
2126 CODE: CODE CODEPIECE {$$=code_append($1,$2);}
2127 CODE: CODEPIECE {$$=$1;}
2128
2129 // code which may appear outside of methods
2130 CODE_STATEMENT: IMPORT 
2131 CODE_STATEMENT: FOR 
2132 CODE_STATEMENT: FOR_IN 
2133 CODE_STATEMENT: WHILE 
2134 CODE_STATEMENT: DO_WHILE 
2135 CODE_STATEMENT: SWITCH 
2136 CODE_STATEMENT: IF
2137 CODE_STATEMENT: WITH
2138 CODE_STATEMENT: TRY
2139 CODE_STATEMENT: VOIDEXPRESSION 
2140 CODE_STATEMENT: USE_NAMESPACE
2141 CODE_STATEMENT: NAMESPACE_DECLARATION
2142 CODE_STATEMENT: '{' CODE '}' {$$=$2;}
2143 CODE_STATEMENT: '{' '}' {$$=0;}
2144
2145 // code which may appear in methods
2146 CODEPIECE: ';' {$$=0;}
2147 CODEPIECE: CODE_STATEMENT
2148 CODEPIECE: VARIABLE_DECLARATION
2149 CODEPIECE: BREAK
2150 CODEPIECE: CONTINUE
2151 CODEPIECE: RETURN
2152 CODEPIECE: THROW
2153 CODEPIECE: CONDITIONAL_COMPILATION '{' CODE '}' {$$=$3;}
2154
2155 //CODEBLOCK :  '{' CODE '}' {$$=$2;}
2156 //CODEBLOCK :  '{' '}'      {$$=0;}
2157 CODEBLOCK :  CODEPIECE ';'             {$$=$1;}
2158 CODEBLOCK :  CODEPIECE %prec below_semicolon {$$=$1;}
2159
2160 /* ------------ package init code ------------------- */
2161
2162 PACKAGE_INITCODE: CODE_STATEMENT {
2163     code_t**cc = &global->init->method->body->code;
2164     *cc = code_append(*cc, $1);
2165 }
2166
2167 /* ------------ conditional compilation ------------- */
2168
2169 CONDITIONAL_COMPILATION: T_IDENTIFIER "::" T_IDENTIFIER 
2170
2171 /* ------------ variables --------------------------- */
2172
2173 MAYBEEXPRESSION : '=' NONCOMMAEXPRESSION {$$=$2;}
2174                 |                {$$.c=abc_pushundefined(0);
2175                                   $$.t=TYPE_ANY;
2176                                  }
2177
2178 VARIABLE_DECLARATION : "var" VARIABLE_LIST {$$=$2;}
2179 VARIABLE_DECLARATION : "const" VARIABLE_LIST {$$=$2;}
2180
2181 VARIABLE_LIST: ONE_VARIABLE                   {$$ = $1;}
2182 VARIABLE_LIST: VARIABLE_LIST ',' ONE_VARIABLE {$$ = code_append($1, $3);}
2183
2184 ONE_VARIABLE: T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION
2185 {
2186 PASS12
2187     if(variable_exists($1))
2188         syntaxerror("Variable %s already defined", $1);
2189 PASS1
2190     new_variable($1, 0, 1, 0);
2191 PASS2
2192    
2193     if(!is_subtype_of($3.t, $2)) {
2194         syntaxerror("Can't convert %s to %s", $3.t->name, 
2195                                               $2->name);
2196     }
2197
2198     char slot = 0;
2199     int index = 0;
2200     if(state->method->uses_slots) {
2201         variable_t* v = find_slot(state, $1);
2202         if(v && !v->init) {
2203             // this variable is stored in a slot
2204             v->init = 1;
2205             v->type = $2;
2206             slot = 1;
2207             index = v->index;
2208         }
2209     }
2210     if(!index) {
2211         index = new_variable($1, $2, 1, 0);
2212     }
2213
2214     $$ = slot?abc_getscopeobject(0, 1):0;
2215     
2216     if($2) {
2217         if($3.c->prev || $3.c->opcode != OPCODE_PUSHUNDEFINED) {
2218             $$ = code_append($$, $3.c);
2219             $$ = converttype($$, $3.t, $2);
2220         } else {
2221             code_free($3.c);
2222             $$ = defaultvalue($$, $2);
2223         }
2224     } else {
2225         if($3.c->prev || $3.c->opcode != OPCODE_PUSHUNDEFINED) {
2226             $$ = code_append($$, $3.c);
2227             $$ = abc_coerce_a($$);
2228         } else {
2229             // don't do anything
2230             code_free($3.c);
2231             code_free($$);
2232             $$ = 0;
2233             break;
2234         }
2235     }
2236     if(slot) {
2237         $$ = abc_setslot($$, index);
2238     } else {
2239         $$ = abc_setlocal($$, index);
2240     }
2241 }
2242
2243 /* ------------ control flow ------------------------- */
2244
2245 MAYBEELSE:  %prec below_else {$$ = code_new();}
2246 MAYBEELSE: "else" CODEBLOCK {$$=$2;}
2247 //MAYBEELSE: ';' "else" CODEBLOCK {$$=$3;}
2248
2249 IF : "if" '(' {PASS12 new_state();} EXPRESSION ')' CODEBLOCK MAYBEELSE {
2250      
2251     $$ = code_new();
2252     $$ = code_append($$, $4.c);
2253     code_t*myjmp,*myif = $$ = abc_iffalse($$, 0);
2254    
2255     $$ = code_append($$, $6);
2256     if($7) {
2257         myjmp = $$ = abc_jump($$, 0);
2258     }
2259     myif->branch = $$ = abc_nop($$);
2260     if($7) {
2261         $$ = code_append($$, $7);
2262         myjmp->branch = $$ = abc_nop($$);
2263     }
2264     $$ = var_block($$);
2265     PASS12 old_state();
2266 }
2267
2268 FOR_INIT : {$$=code_new();}
2269 FOR_INIT : VARIABLE_DECLARATION
2270 FOR_INIT : VOIDEXPRESSION
2271
2272 // TODO: why doesn't an %prec above_identifier resolve the r-r conflict here?
2273 //       (I don't see any easy way to revolve this conflict otherwise, as we
2274 //        can't touch VAR_READ without upsetting the precedence about "return")
2275 FOR_IN_INIT : "var" T_IDENTIFIER MAYBETYPE {
2276     PASS1 $$=$2;new_variable($2,0,1,0);
2277     PASS2 $$=$2;new_variable($2,$3,1,0);
2278 }
2279 FOR_IN_INIT : T_IDENTIFIER {
2280     PASS12
2281     $$=$1;
2282 }
2283
2284 FOR_START : T_FOR '(' {PASS12 new_state();$$.name=$1;$$.each=0;}
2285 FOR_START : T_FOR "each" '(' {PASS12 new_state();$$.name=$1;$$.each=1;}
2286
2287 FOR : FOR_START FOR_INIT ';' EXPRESSION ';' VOIDEXPRESSION ')' CODEBLOCK {
2288     if($1.each) syntaxerror("invalid syntax: ; not allowed in for each statement");
2289     $$ = code_new();
2290     $$ = code_append($$, $2);
2291     code_t*loopstart = $$ = abc_label($$);
2292     $$ = code_append($$, $4.c);
2293     code_t*myif = $$ = abc_iffalse($$, 0);
2294     $$ = code_append($$, $8);
2295     code_t*cont = $$ = abc_nop($$);
2296     $$ = code_append($$, $6);
2297     $$ = abc_jump($$, loopstart);
2298     code_t*out = $$ = abc_nop($$);
2299     breakjumpsto($$, $1.name, out);
2300     continuejumpsto($$, $1.name, cont);
2301     myif->branch = out;
2302
2303     $$ = var_block($$);
2304     PASS12 old_state();
2305 }
2306
2307 FOR_IN : FOR_START FOR_IN_INIT "in" EXPRESSION ')' CODEBLOCK {
2308     variable_t*var = find_variable(state, $2);
2309     if(!var) {
2310         syntaxerror("variable %s not known in this scope", $2);
2311     }
2312
2313     char*tmp1name = concat2($2, "__tmp1__");
2314     int it = new_variable(tmp1name, TYPE_INT, 0, 0);
2315     char*tmp2name = concat2($2, "__array__");
2316     int array = new_variable(tmp1name, 0, 0, 0);
2317
2318     $$ = code_new();
2319     $$ = code_append($$, $4.c);
2320     $$ = abc_coerce_a($$);
2321     $$ = abc_setlocal($$, array);
2322     $$ = abc_pushbyte($$, 0);
2323     $$ = abc_setlocal($$, it);
2324
2325     code_t*loopstart = $$ = abc_label($$);
2326     
2327     $$ = abc_hasnext2($$, array, it);
2328     code_t*myif = $$ = abc_iffalse($$, 0);
2329     $$ = abc_getlocal($$, array);
2330     $$ = abc_getlocal($$, it);
2331     if(!$1.each)
2332         $$ = abc_nextname($$);
2333     else
2334         $$ = abc_nextvalue($$);
2335     $$ = converttype($$, 0, var->type);
2336     $$ = abc_setlocal($$, var->index);
2337
2338     $$ = code_append($$, $6);
2339     $$ = abc_jump($$, loopstart);
2340     
2341     code_t*out = $$ = abc_nop($$);
2342     breakjumpsto($$, $1.name, out);
2343     continuejumpsto($$, $1.name, loopstart);
2344     
2345     myif->branch = out;
2346
2347     $$ = var_block($$);
2348
2349     free(tmp1name);
2350     free(tmp2name);
2351
2352     PASS12 old_state();
2353 }
2354
2355 WHILE : T_WHILE '(' {PASS12 new_state();} EXPRESSION ')' CODEBLOCK {
2356
2357     $$ = code_new();
2358
2359     code_t*myjmp = $$ = abc_jump($$, 0);
2360     code_t*loopstart = $$ = abc_label($$);
2361     $$ = code_append($$, $6);
2362     code_t*cont = $$ = abc_nop($$);
2363     myjmp->branch = cont;
2364     $$ = code_append($$, $4.c);
2365     $$ = abc_iftrue($$, loopstart);
2366     code_t*out = $$ = abc_nop($$);
2367     breakjumpsto($$, $1, out);
2368     continuejumpsto($$, $1, cont);
2369
2370     $$ = var_block($$);
2371     PASS12 old_state();
2372 }
2373
2374 DO_WHILE : T_DO {PASS12 new_state();} CODEBLOCK "while" '(' EXPRESSION ')' {
2375     $$ = code_new();
2376     code_t*loopstart = $$ = abc_label($$);
2377     $$ = code_append($$, $3);
2378     code_t*cont = $$ = abc_nop($$);
2379     $$ = code_append($$, $6.c);
2380     $$ = abc_iftrue($$, loopstart);
2381     code_t*out = $$ = abc_nop($$);
2382     breakjumpsto($$, $1, out);
2383     continuejumpsto($$, $1, cont);
2384     
2385     $$ = var_block($$);
2386     PASS12 old_state();
2387 }
2388
2389 BREAK : "break" %prec prec_none {
2390     $$ = abc___break__(0, "");
2391 }
2392 BREAK : "break" T_IDENTIFIER {
2393     $$ = abc___break__(0, $2);
2394 }
2395 CONTINUE : "continue" %prec prec_none {
2396     $$ = abc___continue__(0, "");
2397 }
2398 CONTINUE : "continue" T_IDENTIFIER {
2399     $$ = abc___continue__(0, $2);
2400 }
2401
2402 MAYBE_CASE_LIST :           {$$=0;}
2403 MAYBE_CASE_LIST : CASE_LIST {$$=$1;}
2404 MAYBE_CASE_LIST : DEFAULT   {$$=$1;}
2405 MAYBE_CASE_LIST : CASE_LIST DEFAULT {$$=code_append($1,$2);}
2406 CASE_LIST: CASE             {$$=$1;}
2407 CASE_LIST: CASE_LIST CASE   {$$=code_append($$,$2);}
2408
2409 CASE: "case" E ':' MAYBECODE {
2410     $$ = abc_getlocal(0, state->switch_var);
2411     $$ = code_append($$, $2.c);
2412     code_t*j = $$ = abc_ifne($$, 0);
2413     $$ = code_append($$, $4);
2414     if($$->opcode != OPCODE___BREAK__) {
2415         $$ = abc___fallthrough__($$, "");
2416     }
2417     code_t*e = $$ = abc_nop($$);
2418     j->branch = e;
2419 }
2420 DEFAULT: "default" ':' MAYBECODE {
2421     $$ = $3;
2422 }
2423 SWITCH : T_SWITCH '(' {PASS12 new_state();state->switch_var=alloc_local();} E ')' '{' MAYBE_CASE_LIST '}' {
2424     $$=$4.c;
2425     $$ = abc_setlocal($$, state->switch_var);
2426     $$ = code_append($$, $7);
2427
2428     code_t*out = $$ = abc_kill($$, state->switch_var);
2429     breakjumpsto($$, $1, out);
2430     
2431     code_t*c = $$,*lastblock=0;
2432     while(c) {
2433         if(c->opcode == OPCODE_IFNE) {
2434             if(!c->next) syntaxerror("internal error in fallthrough handling");
2435             lastblock=c->next;
2436         } else if(c->opcode == OPCODE___FALLTHROUGH__) {
2437             if(lastblock) {
2438                 c->opcode = OPCODE_JUMP;
2439                 c->branch = lastblock;
2440             } else {
2441                 /* fall through end of switch */
2442                 c->opcode = OPCODE_NOP;
2443             }
2444         }
2445         c=c->prev;
2446     }
2447    
2448     $$ = var_block($$);
2449     PASS12 old_state();
2450 }
2451
2452 /* ------------ try / catch /finally ---------------- */
2453
2454 CATCH: "catch" '(' T_IDENTIFIER MAYBETYPE ')' {PASS12 new_state();
2455                                                       state->exception_name=$3;
2456                                                PASS1 new_variable($3, 0, 0, 0);
2457                                                PASS2 new_variable($3, $4, 0, 0);
2458                                               } 
2459         '{' MAYBECODE '}' {
2460     namespace_t name_ns = {ACCESS_PACKAGE, ""};
2461     multiname_t name = {QNAME, &name_ns, 0, $3};
2462     
2463     NEW(abc_exception_t, e)
2464     e->exc_type = sig2mname($4);
2465     e->var_name = multiname_clone(&name);
2466     $$ = e;
2467
2468     code_t*c = 0;
2469     int i = find_variable_safe(state, $3)->index;
2470     e->target = c = abc_nop(0);
2471     c = abc_setlocal(c, i);
2472     c = code_append(c, code_dup(state->method->scope_code));
2473     c = code_append(c, $8);
2474     c = abc_kill(c, i);
2475
2476     c = var_block(c);
2477     PASS12 old_state();
2478 }
2479 FINALLY: "finally" '{' {PASS12 new_state();state->exception_name=0;} MAYBECODE '}' {
2480     $4 = var_block($4);
2481     if(!$4) {
2482         $$=0;
2483     } else {
2484         NEW(abc_exception_t, e)
2485         e->exc_type = 0; //all exceptions
2486         e->var_name = 0; //no name
2487         e->target = 0;
2488         e->to = abc_nop(0);
2489         e->to = code_append(e->to, $4);
2490         $$ = e;
2491     }
2492     PASS12 old_state();
2493 }
2494
2495 CATCH_LIST: CATCH {$$.l=list_new();$$.finally=0;list_append($$.l,$1);}
2496 CATCH_LIST: CATCH_LIST CATCH {$$=$1;list_append($$.l,$2);}
2497 CATCH_FINALLY_LIST: CATCH_LIST {$$=$1;}
2498 CATCH_FINALLY_LIST: CATCH_LIST FINALLY {
2499     $$ = $1;
2500     $$.finally = 0;
2501     if($2) {
2502         list_append($$.l,$2);
2503         $$.finally = $2->to;$2->to=0;
2504     }
2505 }
2506 CATCH_FINALLY_LIST: FINALLY {
2507     $$.l=list_new();
2508     $$.finally = 0;
2509     if($1) {
2510         list_append($$.l,$1);
2511         $$.finally = $1->to;$1->to=0;
2512     }
2513 }
2514
2515 TRY : "try" '{' {PASS12 new_state();
2516                  state->method->has_exceptions=1;
2517                  state->method->late_binding=1;//for invariant scope_code
2518                 } MAYBECODE '}' CATCH_FINALLY_LIST {
2519     code_t*out = abc_nop(0);
2520
2521     code_t*start = abc_nop(0);
2522     $$ = code_append(start, $4);
2523     if(!is_break_or_jump($4)) {
2524         $$ = abc_jump($$, out);
2525     }
2526     code_t*end = $$ = abc_nop($$);
2527   
2528     int tmp;
2529     if($6.finally)
2530         tmp = new_variable("__finally__", 0, 0, 0);
2531     
2532     abc_exception_list_t*l = $6.l;
2533     int count=0;
2534     while(l) {
2535         abc_exception_t*e = l->abc_exception;
2536         if(e->var_name) {
2537             $$ = code_append($$, e->target);
2538             $$ = abc_jump($$, out);
2539         } else {
2540             parserassert((ptroff_t)$6.finally);
2541             // finally block
2542             e->target = $$ = abc_nop($$);
2543             $$ = code_append($$, code_dup(state->method->scope_code));
2544             $$ = abc___rethrow__($$);
2545         }
2546         
2547         e->from = start;
2548         e->to = end;
2549
2550         l = l->next;
2551     }
2552     $$ = code_append($$, out);
2553
2554     $$ = insert_finally($$, $6.finally, tmp);
2555         
2556     list_concat(state->method->exceptions, $6.l);
2557    
2558     $$ = var_block($$);
2559     PASS12 old_state();
2560 }
2561
2562 /* ------------ throw ------------------------------- */
2563
2564 THROW : "throw" EXPRESSION {
2565     $$=$2.c;
2566     $$=abc_throw($$);
2567 }
2568 THROW : "throw" %prec prec_none {
2569     if(!state->exception_name)
2570         syntaxerror("re-throw only possible within a catch block");
2571     variable_t*v = find_variable(state, state->exception_name);
2572     $$=code_new();
2573     $$=abc_getlocal($$, v->index);
2574     $$=abc_throw($$);
2575 }
2576
2577 /* ------------ with -------------------------------- */
2578
2579 WITH_HEAD : "with" '(' EXPRESSION ')' {
2580      new_state();
2581      if(state->method->has_exceptions) {
2582          int v = alloc_local();
2583          state->method->scope_code = abc_getlocal(state->method->scope_code, v);
2584          state->method->scope_code = abc_pushwith(state->method->scope_code);
2585          $$.number = v;
2586      }
2587      $$.cc = $3.c;
2588
2589 WITH : WITH_HEAD CODEBLOCK {
2590      /* remove getlocal;pushwith from scope code again */
2591      state->method->scope_code = code_cutlast(code_cutlast(state->method->scope_code));
2592
2593      $$ = $1.cc;
2594      if(state->method->has_exceptions) {
2595          $$ = abc_dup($$);
2596          $$ = abc_setlocal($$, $1.number);
2597      }
2598      $$ = abc_pushwith($$);
2599      $$ = code_append($$, $2);
2600      $$ = abc_popscope($$);
2601      old_state();
2602 }
2603
2604 /* ------------ packages and imports ---------------- */
2605
2606 X_IDENTIFIER: T_IDENTIFIER
2607             | "package" {PASS12 $$="package";}
2608             | T_NAMESPACE {PASS12 $$=$1;}
2609
2610 PACKAGE: PACKAGE '.' X_IDENTIFIER {PASS12 $$ = concat3($1,".",$3);free($1);$1=0;}
2611 PACKAGE: X_IDENTIFIER             {PASS12 $$=strdup($1);}
2612
2613 PACKAGE_DECLARATION : "package" PACKAGE '{' {PASS12 startpackage($2);free($2);$2=0;}
2614                                 MAYBE_INPACKAGE_CODE_LIST '}' {PASS12 endpackage();$$=0;}
2615 PACKAGE_DECLARATION : "package" '{' {PASS12 startpackage("");} 
2616                                 MAYBE_INPACKAGE_CODE_LIST '}' {PASS12 endpackage();$$=0;}
2617
2618 IMPORT : "import" PACKAGEANDCLASS {
2619        PASS12
2620        slotinfo_t*s = registry_find($2->package, $2->name);
2621        if(!s && as3_pass==1) {// || !(s->flags&FLAG_BUILTIN)) {
2622            as3_schedule_class($2->package, $2->name);
2623        }
2624
2625        PASS2
2626        classinfo_t*c = $2;
2627        if(!c) 
2628             syntaxerror("Couldn't import class\n");
2629        state_has_imports();
2630        dict_put(state->imports, c->name, c);
2631        import_toplevel(c->package);
2632        $$=0;
2633 }
2634 IMPORT : "import" PACKAGE '.' '*' {
2635        PASS12
2636        if(strncmp("flash.", $2, 6) && as3_pass==1) {
2637            as3_schedule_package($2);
2638        }
2639
2640        PASS2
2641        NEW(import_t,i);
2642        i->package = $2;
2643        state_has_imports();
2644        list_append(state->wildcard_imports, i);
2645        import_toplevel(i->package);
2646        $$=0;
2647 }
2648
2649 /* ------------ classes and interfaces (header) -------------- */
2650
2651 MAYBE_MODIFIERS : %prec above_function {PASS12 $$.flags=0;$$.ns=0;}
2652 MAYBE_MODIFIERS : MODIFIER_LIST        {PASS12 $$=$1;}
2653 MODIFIER_LIST : MODIFIER               {PASS12 $$=$1;}
2654 MODIFIER_LIST : MODIFIER_LIST MODIFIER {
2655     PASS12 
2656     $$.flags=$1.flags|$2.flags;
2657     if($1.ns && $2.ns) syntaxerror("only one namespace allowed in one declaration");
2658     $$.ns=$1.ns?$1.ns:$2.ns;
2659
2660 }
2661 MODIFIER : KW_PUBLIC {PASS12 $$.flags=FLAG_PUBLIC;$$.ns=0;}
2662          | KW_PRIVATE {PASS12 $$.flags=FLAG_PRIVATE;$$.ns=0;}
2663          | KW_PROTECTED {PASS12 $$.flags=FLAG_PROTECTED;$$.ns=0;}
2664          | KW_STATIC {PASS12 $$.flags=FLAG_STATIC;$$.ns=0;}
2665          | KW_DYNAMIC {PASS12 $$.flags=FLAG_DYNAMIC;$$.ns=0;}
2666          | KW_FINAL {PASS12 $$.flags=FLAG_FINAL;$$.ns=0;}
2667          | KW_OVERRIDE {PASS12 $$.flags=FLAG_OVERRIDE;$$.ns=0;}
2668          | KW_NATIVE {PASS12 $$.flags=FLAG_NATIVE;$$.ns=0;}
2669          | KW_INTERNAL {PASS12 $$.flags=FLAG_PACKAGEINTERNAL;$$.ns=0;}
2670          | T_NAMESPACE {PASS12 $$.flags=FLAG_NAMESPACE;
2671                                $$.ns=$1;
2672                        }
2673
2674 EXTENDS : {PASS12 $$=0;}
2675 EXTENDS : KW_EXTENDS CLASS_SPEC {PASS12 $$=$2;}
2676
2677 EXTENDS_LIST : {PASS12 $$=list_new();}
2678 EXTENDS_LIST : KW_EXTENDS CLASS_SPEC_LIST {PASS12 $$=$2;}
2679
2680 IMPLEMENTS_LIST : {PASS12 $$=list_new();}
2681 IMPLEMENTS_LIST : KW_IMPLEMENTS CLASS_SPEC_LIST {PASS12 $$=$2;}
2682
2683 CLASS_DECLARATION : MAYBE_MODIFIERS "class" T_IDENTIFIER 
2684                               EXTENDS IMPLEMENTS_LIST 
2685                               '{' {PASS12 startclass(&$1,$3,$4,$5);} 
2686                               MAYBE_CLASS_BODY 
2687                               '}' {PASS12 endclass();$$=0;}
2688
2689 INTERFACE_DECLARATION : MAYBE_MODIFIERS "interface" T_IDENTIFIER 
2690                               EXTENDS_LIST 
2691                               '{' {PASS12 $1.flags|=FLAG_INTERFACE;
2692                                           startclass(&$1,$3,0,$4);}
2693                               MAYBE_INTERFACE_BODY 
2694                               '}' {PASS12 endclass();$$=0;}
2695
2696 /* ------------ classes and interfaces (body) -------------- */
2697
2698 MAYBE_CLASS_BODY : 
2699 MAYBE_CLASS_BODY : CLASS_BODY
2700 CLASS_BODY : CLASS_BODY_ITEM
2701 CLASS_BODY : CLASS_BODY CLASS_BODY_ITEM
2702 CLASS_BODY_ITEM : ';'
2703 CLASS_BODY_ITEM : CONDITIONAL_COMPILATION '{' MAYBE_CLASS_BODY '}'
2704 CLASS_BODY_ITEM : SLOT_DECLARATION
2705 CLASS_BODY_ITEM : FUNCTION_DECLARATION
2706
2707 CLASS_BODY_ITEM : CODE_STATEMENT {
2708     code_t*c = state->cls->static_init->header;
2709     c = code_append(c, $1);  
2710     state->cls->static_init->header = c;
2711 }
2712
2713 MAYBE_INTERFACE_BODY : 
2714 MAYBE_INTERFACE_BODY : INTERFACE_BODY
2715 INTERFACE_BODY : IDECLARATION
2716 INTERFACE_BODY : INTERFACE_BODY IDECLARATION
2717 IDECLARATION : ';'
2718 IDECLARATION : "var" T_IDENTIFIER {
2719     syntaxerror("variable declarations not allowed in interfaces");
2720 }
2721 IDECLARATION : MAYBE_MODIFIERS "function" GETSET T_IDENTIFIER '(' MAYBE_PARAM_LIST ')' MAYBETYPE {
2722     PASS12
2723     $1.flags |= FLAG_PUBLIC;
2724     if($1.flags&(FLAG_PRIVATE|FLAG_PACKAGEINTERNAL|FLAG_PROTECTED)) {
2725         syntaxerror("invalid method modifiers: interface methods always need to be public");
2726     }
2727     startfunction(&$1,$3,$4,&$6,$8);
2728     endfunction(&$1,$3,$4,&$6,$8, 0);
2729     list_deep_free($6.list);
2730 }
2731
2732 /* ------------ classes and interfaces (body, slots ) ------- */
2733
2734 VARCONST: "var" | "const"
2735
2736 SLOT_DECLARATION: MAYBE_MODIFIERS VARCONST {setslotstate(&$1,$2);} SLOT_LIST {$$=$4;setslotstate(0, 0);}
2737
2738 SLOT_LIST: ONE_SLOT               {$$ = $1;}
2739 SLOT_LIST: SLOT_LIST ',' ONE_SLOT {$$ = code_append($1, $3);}
2740
2741 ONE_SLOT: T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION
2742 {
2743     int flags = slotstate_flags->flags;
2744     namespace_t ns = modifiers2access(slotstate_flags);
2745
2746     varinfo_t* info = 0;
2747     if(state->cls) {
2748         memberinfo_t*i = registry_findmember(state->cls->info, ns.name, $1, 1);
2749         if(i) {
2750             check_override(i, flags);
2751         }
2752         info = varinfo_register_onclass(state->cls->info, ns.access, ns.name, $1);
2753     } else {
2754         slotinfo_t*i = registry_find(state->package, $1);
2755         if(i) {
2756             syntaxerror("package %s already contains '%s'", state->package, $1);
2757         }
2758         if(ns.name && ns.name[0]) {
2759             syntaxerror("namespaces not allowed on package-level variables");
2760         }
2761         info = varinfo_register_global(ns.access, state->package, $1);
2762     }
2763
2764     info->type = $2;
2765     info->flags = flags;
2766
2767     /* slot name */
2768     multiname_t mname = {QNAME, &ns, 0, $1};
2769   
2770     trait_list_t**traits;
2771     code_t**code;
2772     if(!state->cls) {
2773         // global variable
2774         ns.name = state->package;
2775         traits = &global->init->traits;
2776         code = &global->init->method->body->code;
2777     } else if(flags&FLAG_STATIC) {
2778         // static variable
2779         traits = &state->cls->abc->static_traits;
2780         code = &state->cls->static_init->header;
2781     } else {
2782         // instance variable
2783         traits = &state->cls->abc->traits;
2784         code = &state->cls->init->header;
2785     }
2786     
2787     trait_t*t=0;
2788     if($2) {
2789         MULTINAME(m, $2);
2790         t = trait_new_member(traits, multiname_clone(&m), multiname_clone(&mname), 0);
2791     } else {
2792         t = trait_new_member(traits, 0, multiname_clone(&mname), 0);
2793     }
2794     info->slot = t->slot_id;
2795     
2796     /* initalization code (if needed) */
2797     code_t*c = 0;
2798     if($3.c && !is_pushundefined($3.c)) {
2799         c = abc_getlocal_0(c);
2800         c = code_append(c, $3.c);
2801         c = converttype(c, $3.t, $2);
2802         c = abc_setslot(c, t->slot_id);
2803     }
2804
2805     *code = code_append(*code, c);
2806
2807     if(slotstate_varconst==KW_CONST) {
2808         t->kind= TRAIT_CONST;
2809     }
2810
2811     $$=0;
2812 }
2813
2814 /* ------------ constants -------------------------------------- */
2815
2816 MAYBESTATICCONSTANT: {$$=0;}
2817 MAYBESTATICCONSTANT: '=' STATICCONSTANT {$$=$2;}
2818
2819 STATICCONSTANT : T_BYTE {$$ = constant_new_int($1);}
2820 STATICCONSTANT : T_INT {$$ = constant_new_int($1);}
2821 STATICCONSTANT : T_UINT {$$ = constant_new_uint($1);}
2822 STATICCONSTANT : T_FLOAT {$$ = constant_new_float($1);}
2823 STATICCONSTANT : T_STRING {$$ = constant_new_string2($1.str,$1.len);free((char*)$1.str);}
2824 //STATICCONSTANT : T_NAMESPACE {$$ = constant_new_namespace($1);}
2825 STATICCONSTANT : "true" {$$ = constant_new_true($1);}
2826 STATICCONSTANT : "false" {$$ = constant_new_false($1);}
2827 STATICCONSTANT : "null" {$$ = constant_new_null($1);}
2828 STATICCONSTANT : T_IDENTIFIER {
2829     if(!strcmp($1, "NaN")) {
2830         $$ = constant_new_float(__builtin_nan(""));
2831     } else {
2832         as3_warning("Couldn't evaluate constant value of %s", $1);
2833         $$ = constant_new_null($1);
2834     }
2835 }
2836
2837 /* ------------ classes and interfaces (body, functions) ------- */
2838
2839 // non-vararg version
2840 MAYBE_PARAM_LIST: {
2841     PASS12
2842     memset(&$$,0,sizeof($$));
2843 }
2844 MAYBE_PARAM_LIST: PARAM_LIST {
2845     PASS12
2846     $$=$1;
2847 }
2848
2849 // vararg version
2850 MAYBE_PARAM_LIST: "..." PARAM {
2851     PASS12
2852     memset(&$$,0,sizeof($$));
2853     $$.varargs=1;
2854     list_append($$.list, $2);
2855 }
2856 MAYBE_PARAM_LIST: PARAM_LIST ',' "..." PARAM {
2857     PASS12
2858     $$ =$1;
2859     $$.varargs=1;
2860     list_append($$.list, $4);
2861 }
2862
2863 // non empty
2864 PARAM_LIST: PARAM_LIST ',' PARAM {
2865     PASS12
2866     $$ = $1;
2867     list_append($$.list, $3);
2868 }
2869 PARAM_LIST: PARAM {
2870     PASS12
2871     memset(&$$,0,sizeof($$));
2872     list_append($$.list, $1);
2873 }
2874
2875 PARAM:  T_IDENTIFIER ':' TYPE MAYBESTATICCONSTANT {
2876      PASS12
2877      $$ = rfx_calloc(sizeof(param_t));
2878      $$->name=$1;
2879      $$->type = $3;
2880      PASS2
2881      $$->value = $4;
2882 }
2883 PARAM:  T_IDENTIFIER MAYBESTATICCONSTANT {
2884      PASS12
2885      $$ = rfx_calloc(sizeof(param_t));
2886      $$->name=$1;
2887      $$->type = TYPE_ANY;
2888      PASS2
2889      $$->value = $2;
2890 }
2891 GETSET : "get"
2892        | "set"
2893        | {PASS12 $$=0;}
2894
2895 FUNCTION_DECLARATION: MAYBE_MODIFIERS "function" GETSET T_IDENTIFIER '(' MAYBE_PARAM_LIST ')' 
2896                       MAYBETYPE '{' {PASS12 startfunction(&$1,$3,$4,&$6,$8);} MAYBECODE '}' 
2897 {
2898     PASS1 
2899     endfunction(&$1,$3,$4,&$6,0,0);
2900     PASS2
2901     if(!state->method->info) syntaxerror("internal error");
2902     
2903     code_t*c = method_header(state->method);
2904     c = wrap_function(c, 0, $11);
2905
2906     endfunction(&$1,$3,$4,&$6,$8,c);
2907     PASS12
2908     list_deep_free($6.list);
2909     $$=0;
2910 }
2911
2912 MAYBE_IDENTIFIER: T_IDENTIFIER
2913 MAYBE_IDENTIFIER: {PASS12 $$=0;}
2914 INNERFUNCTION: "function" MAYBE_IDENTIFIER '(' MAYBE_PARAM_LIST ')' MAYBETYPE 
2915                '{' {PASS12 innerfunction($2,&$4,$6);} MAYBECODE '}'
2916 {
2917     PASS1
2918     endfunction(0,0,$2,&$4,0,0);
2919     PASS2
2920     methodinfo_t*f = state->method->info;
2921     if(!f || !f->kind) syntaxerror("internal error");
2922     
2923     code_t*c = method_header(state->method);
2924     c = wrap_function(c, 0, $9);
2925
2926     int index = state->method->var_index;
2927     endfunction(0,0,$2,&$4,$6,c);
2928     
2929     $$.c = abc_getlocal(0, index);
2930     $$.t = TYPE_FUNCTION(f);
2931
2932     PASS12 list_deep_free($4.list);
2933 }
2934
2935
2936 /* ------------- package + class ids --------------- */
2937
2938 CLASS: X_IDENTIFIER {
2939     PASS1 NEW(unresolvedinfo_t,c);
2940           memset(c, 0, sizeof(*c));
2941           c->kind = INFOTYPE_UNRESOLVED;
2942           c->name = $1;
2943           c->package = get_package_from_name($1);
2944           if(!c->package) {
2945               c->nsset = get_current_imports();
2946               /* make the compiler look for this class in the current directory,
2947                  just in case: */
2948               //as3_schedule_class_noerror(state->package, $1);
2949           }
2950           $$ = (classinfo_t*)c;
2951     PASS2
2952     slotinfo_t*s = find_class($1);
2953     if(!s) syntaxerror("Could not find class/method %s (current package: %s)\n", $1, state->package);
2954     $$ = (classinfo_t*)s;
2955 }
2956
2957 PACKAGEANDCLASS : PACKAGE '.' X_IDENTIFIER {
2958     PASS1 NEW(unresolvedinfo_t,c);
2959           memset(c, 0, sizeof(*c));
2960           c->kind = INFOTYPE_UNRESOLVED;
2961           c->package = $1;
2962           c->name = $3;
2963           $$ = (classinfo_t*)c;
2964     PASS2
2965     slotinfo_t*s = registry_find($1, $3);
2966     if(!s) syntaxerror("Couldn't find class/method %s.%s\n", $1, $3);
2967     free($1);$1=0;
2968     $$ = (classinfo_t*)s;
2969 }
2970
2971 CLASS_SPEC: PACKAGEANDCLASS
2972           | CLASS
2973
2974 CLASS_SPEC_LIST : CLASS_SPEC {PASS12 $$=list_new();list_append($$, $1);}
2975 CLASS_SPEC_LIST : CLASS_SPEC_LIST ',' CLASS_SPEC {PASS12 $$=$1;list_append($$,$3);}
2976
2977 TYPE : CLASS_SPEC {PASS12 $$=$1;}
2978      | '*'        {PASS12 $$=registry_getanytype();}
2979      | "void"     {PASS12 $$=registry_getanytype();}
2980     /*
2981      |  "String"  {$$=registry_getstringclass();}
2982      |  "int"     {$$=registry_getintclass();}
2983      |  "uint"    {$$=registry_getuintclass();}
2984      |  "Boolean" {$$=registry_getbooleanclass();}
2985      |  "Number"  {$$=registry_getnumberclass();}
2986     */
2987
2988 MAYBETYPE: ':' TYPE {PASS12 $$=$2;}
2989 MAYBETYPE:          {PASS12 $$=0;}
2990
2991 /* ----------function calls, delete, constructor calls ------ */
2992
2993 MAYBE_PARAM_VALUES :  %prec prec_none {$$.cc=0;$$.number=0;}
2994 MAYBE_PARAM_VALUES : '(' MAYBE_EXPRESSION_LIST ')' {$$=$2;}
2995
2996 MAYBE_EXPRESSION_LIST : {$$.cc=0;$$.number=0;}
2997 MAYBE_EXPRESSION_LIST : EXPRESSION_LIST
2998 MAYBE_EXPRESSION_LIST : EXPRESSION_LIST_AND_COMMA
2999
3000 EXPRESSION_LIST : NONCOMMAEXPRESSION             {$$.number=1;
3001                                                   $$.cc = $1.c;
3002                                                  }
3003
3004 EXPRESSION_LIST_AND_COMMA: EXPRESSION_LIST ',' {$$ = $1;}
3005 EXPRESSION_LIST : EXPRESSION_LIST_AND_COMMA NONCOMMAEXPRESSION {
3006                                                   $$.number= $1.number+1;
3007                                                   $$.cc = code_append($1.cc, $2.c);
3008                                                   }
3009                
3010 XX : %prec new2
3011 NEW : "new" E XX MAYBE_PARAM_VALUES {
3012     $$.c = $2.c;
3013     if($$.c->opcode == OPCODE_COERCE_A) $$.c = code_cutlast($$.c);
3014     
3015     code_t*paramcode = $4.cc;
3016     if($$.c->opcode == OPCODE_GETPROPERTY) {
3017         multiname_t*name = $$.c->data[0];$$.c->data[0]=0;
3018         $$.c = code_cutlast($$.c);
3019         $$.c = code_append($$.c, paramcode);
3020         $$.c = abc_constructprop2($$.c, name, $4.number);
3021         multiname_destroy(name);
3022     } else if($$.c->opcode == OPCODE_GETSLOT) {
3023         int slot = (int)(ptroff_t)$$.c->data[0];
3024         trait_t*t = traits_find_slotid(state->cls->abc->traits,slot);//FIXME
3025         multiname_t*name = t->name;
3026         $$.c = code_cutlast($$.c);
3027         $$.c = code_append($$.c, paramcode);
3028         $$.c = abc_constructprop2($$.c, name, $4.number);
3029     } else {
3030         $$.c = code_append($$.c, paramcode);
3031         $$.c = abc_construct($$.c, $4.number);
3032     }
3033    
3034     $$.t = TYPE_ANY;
3035     if(TYPE_IS_CLASS($2.t) && $2.t->data) {
3036         $$.t = $2.t->data;
3037     } else {
3038         $$.c = abc_coerce_a($$.c);
3039         $$.t = TYPE_ANY;
3040     }
3041 }
3042
3043 /* TODO: use abc_call (for calling local variables),
3044          abc_callstatic (for calling own methods) 
3045          call (for closures)
3046 */
3047 FUNCTIONCALL : E '(' MAYBE_EXPRESSION_LIST ')' {
3048     
3049     $$.c = $1.c;
3050     if($$.c->opcode == OPCODE_COERCE_A) {
3051         $$.c = code_cutlast($$.c);
3052     }
3053     code_t*paramcode = $3.cc;
3054
3055     $$.t = TYPE_ANY;
3056     if($$.c->opcode == OPCODE_GETPROPERTY) {
3057         multiname_t*name = $$.c->data[0];$$.c->data[0]=0;
3058         $$.c = code_cutlast($$.c);
3059         $$.c = code_append($$.c, paramcode);
3060         $$.c = abc_callproperty2($$.c, name, $3.number);
3061         multiname_destroy(name);
3062     } else if($$.c->opcode == OPCODE_GETSLOT && $$.c->prev->opcode != OPCODE_GETSCOPEOBJECT) {
3063         int slot = (int)(ptroff_t)$$.c->data[0];
3064         trait_t*t = traits_find_slotid(state->cls->abc->traits,slot);
3065         if(t->kind!=TRAIT_METHOD) {
3066             //ok: flash allows to assign closures to members.
3067         }
3068         multiname_t*name = t->name;
3069         $$.c = code_cutlast($$.c);
3070         $$.c = code_append($$.c, paramcode);
3071         //$$.c = abc_callmethod($$.c, t->method, len); //#1051 illegal early access binding
3072         $$.c = abc_callproperty2($$.c, name, $3.number);
3073     } else if($$.c->opcode == OPCODE_GETSUPER) {
3074         multiname_t*name = $$.c->data[0];$$.c->data[0]=0;
3075         $$.c = code_cutlast($$.c);
3076         $$.c = code_append($$.c, paramcode);
3077         $$.c = abc_callsuper2($$.c, name, $3.number);
3078         multiname_destroy(name);
3079     } else {
3080         $$.c = abc_getglobalscope($$.c);
3081         $$.c = code_append($$.c, paramcode);
3082         $$.c = abc_call($$.c, $3.number);
3083     }
3084    
3085     if(TYPE_IS_FUNCTION($1.t) && $1.t->data) {
3086         $$.t = ((methodinfo_t*)($1.t->data))->return_type;
3087     } else {
3088         $$.c = abc_coerce_a($$.c);
3089         $$.t = TYPE_ANY;
3090     }
3091 }
3092
3093 FUNCTIONCALL : "super" '(' MAYBE_EXPRESSION_LIST ')' {
3094     if(!state->cls) syntaxerror("super() not allowed outside of a class");
3095     if(!state->method) syntaxerror("super() not allowed outside of a function");
3096     if(!state->method->is_constructor) syntaxerror("super() not allowed outside of a constructor");
3097
3098     $$.c = code_new();
3099     $$.c = abc_getlocal_0($$.c);
3100
3101     $$.c = code_append($$.c, $3.cc);
3102     /*
3103     this is dependent on the control path, check this somewhere else
3104     if(state->method->has_super)
3105         syntaxerror("constructor may call super() only once");
3106     */
3107     state->method->has_super = 1;
3108
3109     $$.c = abc_constructsuper($$.c, $3.number);
3110     $$.c = abc_pushundefined($$.c);
3111     $$.t = TYPE_ANY;
3112 }
3113
3114 DELETE: "delete" E {
3115     $$.c = $2.c;
3116     if($$.c->opcode == OPCODE_COERCE_A) {
3117         $$.c = code_cutlast($$.c);
3118     }
3119     multiname_t*name = 0;
3120     if($$.c->opcode == OPCODE_GETPROPERTY) {
3121         $$.c->opcode = OPCODE_DELETEPROPERTY;
3122     } else if($$.c->opcode == OPCODE_GETSLOT) {
3123         int slot = (int)(ptroff_t)$$.c->data[0];
3124         multiname_t*name = traits_find_slotid(state->cls->abc->traits,slot)->name;
3125         $$.c = code_cutlast($$.c);
3126         $$.c = abc_deleteproperty2($$.c, name);
3127     } else {
3128         $$.c = abc_getlocal_0($$.c);
3129         MULTINAME_LATE(m, $2.t?$2.t->access:ACCESS_PACKAGE, "");
3130         $$.c = abc_deleteproperty2($$.c, &m);
3131     }
3132     $$.t = TYPE_BOOLEAN;
3133 }
3134
3135 RETURN: "return" %prec prec_none {
3136     $$ = abc_returnvoid(0);
3137 }
3138 RETURN: "return" EXPRESSION {
3139     $$ = $2.c;
3140     $$ = abc_returnvalue($$);
3141 }
3142
3143 // ----------------------- expression types -------------------------------------
3144
3145 NONCOMMAEXPRESSION : E        %prec below_minus {$$=$1;}
3146 EXPRESSION : E                %prec below_minus {$$ = $1;}
3147 EXPRESSION : EXPRESSION ',' E %prec below_minus {
3148     $$.c = $1.c;
3149     $$.c = cut_last_push($$.c);
3150     $$.c = code_append($$.c,$3.c);
3151     $$.t = $3.t;
3152 }
3153 VOIDEXPRESSION : EXPRESSION %prec below_minus {
3154     $$=cut_last_push($1.c);
3155 }
3156
3157 // ----------------------- expression evaluation -------------------------------------
3158
3159 E : INNERFUNCTION %prec prec_none {$$ = $1;}
3160 //V : CONSTANT                    {$$ = 0;}
3161 E : CONSTANT
3162 //V : VAR_READ %prec T_IDENTIFIER {$$ = 0;}
3163 E : VAR_READ %prec T_IDENTIFIER {$$ = $1;}
3164 //V : NEW                         {$$ = $1.c;}
3165 E : NEW                         {$$ = $1;}
3166 //V : DELETE                      {$$ = $1.c;}
3167 E : DELETE                      {$$ = $1;}
3168
3169 E : FUNCTIONCALL
3170
3171 E : T_REGEXP {
3172     $$.c = 0;
3173     namespace_t ns = {ACCESS_PACKAGE, ""};
3174     multiname_t m = {QNAME, &ns, 0, "RegExp"};
3175     if(!$1.options) {
3176         $$.c = abc_getlex2($$.c, &m);
3177         $$.c = abc_pushstring($$.c, $1.pattern);
3178         $$.c = abc_construct($$.c, 1);
3179     } else {
3180         $$.c = abc_getlex2($$.c, &m);
3181         $$.c = abc_pushstring($$.c, $1.pattern);
3182         $$.c = abc_pushstring($$.c, $1.options);
3183         $$.c = abc_construct($$.c, 2);
3184     }
3185     $$.t = TYPE_REGEXP;
3186 }
3187
3188 CONSTANT : T_BYTE {$$.c = abc_pushbyte(0, $1);
3189                    //MULTINAME(m, registry_getintclass());
3190                    //$$.c = abc_coerce2($$.c, &m); // FIXME
3191                    $$.t = TYPE_INT;
3192                   }
3193 CONSTANT : T_SHORT {$$.c = abc_pushshort(0, $1);
3194                     $$.t = TYPE_INT;
3195                    }
3196 CONSTANT : T_INT {$$.c = abc_pushint(0, $1);
3197                   $$.t = TYPE_INT;
3198                  }
3199 CONSTANT : T_UINT {$$.c = abc_pushuint(0, $1);
3200                    $$.t = TYPE_UINT;
3201                   }
3202 CONSTANT : T_FLOAT {$$.c = abc_pushdouble(0, $1);
3203                     $$.t = TYPE_FLOAT;
3204                    }
3205 CONSTANT : T_STRING {$$.c = abc_pushstring2(0, &$1);free((char*)$1.str);
3206                      $$.t = TYPE_STRING;
3207                     }
3208 CONSTANT : "undefined" {$$.c = abc_pushundefined(0);
3209                     $$.t = TYPE_ANY;
3210                    }
3211 CONSTANT : "true" {$$.c = abc_pushtrue(0);
3212                     $$.t = TYPE_BOOLEAN;
3213                    }
3214 CONSTANT : "false" {$$.c = abc_pushfalse(0);
3215                      $$.t = TYPE_BOOLEAN;
3216                     }
3217 CONSTANT : "null" {$$.c = abc_pushnull(0);
3218                     $$.t = TYPE_NULL;
3219                    }
3220
3221 E : E '<' E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterequals($$.c);$$.c=abc_not($$.c);
3222              $$.t = TYPE_BOOLEAN;
3223             }
3224 E : E '>' E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterthan($$.c);
3225              $$.t = TYPE_BOOLEAN;
3226             }
3227 E : E "<=" E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterthan($$.c);$$.c=abc_not($$.c);
3228               $$.t = TYPE_BOOLEAN;
3229              }
3230 E : E ">=" E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterequals($$.c);
3231               $$.t = TYPE_BOOLEAN;
3232              }
3233 E : E "==" E {$$.c = code_append($1.c,$3.c);$$.c = abc_equals($$.c);
3234               $$.t = TYPE_BOOLEAN;
3235              }
3236 E : E "===" E {$$.c = code_append($1.c,$3.c);$$.c = abc_strictequals($$.c);
3237               $$.t = TYPE_BOOLEAN;
3238               }
3239 E : E "!==" E {$$.c = code_append($1.c,$3.c);$$.c = abc_strictequals($$.c);$$.c = abc_not($$.c);
3240               $$.t = TYPE_BOOLEAN;
3241              }
3242 E : E "!=" E {$$.c = code_append($1.c,$3.c);$$.c = abc_equals($$.c);$$.c = abc_not($$.c);
3243               $$.t = TYPE_BOOLEAN;
3244              }
3245
3246 E : E "||" E {$$.t = join_types($1.t, $3.t, 'O');
3247               $$.c = $1.c;
3248               $$.c = converttype($$.c, $1.t, $$.t);
3249               $$.c = abc_dup($$.c);
3250               code_t*jmp = $$.c = abc_iftrue($$.c, 0);
3251               $$.c = cut_last_push($$.c);
3252               $$.c = code_append($$.c,$3.c);
3253               $$.c = converttype($$.c, $3.t, $$.t);
3254               code_t*label = $$.c = abc_label($$.c);
3255               jmp->branch = label;
3256              }
3257 E : E "&&" E {
3258               $$.t = join_types($1.t, $3.t, 'A');
3259               /*printf("%08x:\n",$1.t);
3260               code_dump($1.c, 0, 0, "", stdout);
3261               printf("%08x:\n",$3.t);
3262               code_dump($3.c, 0, 0, "", stdout);
3263               printf("joining %08x and %08x to %08x\n", $1.t, $3.t, $$.t);*/
3264               $$.c = $1.c;
3265               $$.c = converttype($$.c, $1.t, $$.t);
3266               $$.c = abc_dup($$.c);
3267               code_t*jmp = $$.c = abc_iffalse($$.c, 0);
3268               $$.c = cut_last_push($$.c);
3269               $$.c = code_append($$.c,$3.c);
3270               $$.c = converttype($$.c, $3.t, $$.t);
3271               code_t*label = $$.c = abc_label($$.c);
3272               jmp->branch = label;              
3273              }
3274
3275 E : '!' E    {$$.c=$2.c;
3276               $$.c = abc_not($$.c);
3277               $$.t = TYPE_BOOLEAN;
3278              }
3279
3280 E : '~' E    {$$.c=$2.c;
3281               $$.c = abc_bitnot($$.c);
3282               $$.t = TYPE_INT;
3283              }
3284
3285 E : E '&' E {$$.c = code_append($1.c,$3.c);
3286              $$.c = abc_bitand($$.c);
3287              $$.t = TYPE_INT;
3288             }
3289
3290 E : E '^' E {$$.c = code_append($1.c,$3.c);
3291              $$.c = abc_bitxor($$.c);
3292              $$.t = TYPE_INT;
3293             }
3294
3295 E : E '|' E {$$.c = code_append($1.c,$3.c);
3296              $$.c = abc_bitor($$.c);
3297              $$.t = TYPE_INT;
3298             }
3299
3300 E : E ">>" E {$$.c = code_append($1.c,$3.c);
3301              $$.c = abc_rshift($$.c);
3302              $$.t = TYPE_INT;
3303             }
3304 E : E ">>>" E {$$.c = code_append($1.c,$3.c);
3305              $$.c = abc_urshift($$.c);
3306              $$.t = TYPE_INT;
3307             }
3308 E : E "<<" E {$$.c = code_append($1.c,$3.c);
3309              $$.c = abc_lshift($$.c);
3310              $$.t = TYPE_INT;
3311             }
3312
3313 E : E '/' E {$$.c = code_append($1.c,$3.c);
3314              $$.c = abc_divide($$.c);
3315              $$.t = TYPE_NUMBER;
3316             }
3317 E : E '%' E {$$.c = code_append($1.c,$3.c);
3318              $$.c = abc_modulo($$.c);
3319              $$.t = TYPE_NUMBER;
3320             }
3321 E : E '+' E {$$.c = code_append($1.c,$3.c);
3322              if(BOTH_INT($1.t, $3.t)) {
3323                 $$.c = abc_add_i($$.c);
3324                 $$.t = TYPE_INT;
3325              } else {
3326                 $$.c = abc_add($$.c);
3327                 $$.t = join_types($1.t,$3.t,'+');
3328              }
3329             }
3330 E : E '-' E {$$.c = code_append($1.c,$3.c);
3331              if(BOTH_INT($1.t,$3.t)) {
3332                 $$.c = abc_subtract_i($$.c);
3333                 $$.t = TYPE_INT;
3334              } else {
3335                 $$.c = abc_subtract($$.c);
3336                 $$.t = TYPE_NUMBER;
3337              }
3338             }
3339 E : E '*' E {$$.c = code_append($1.c,$3.c);
3340              if(BOTH_INT($1.t,$3.t)) {
3341                 $$.c = abc_multiply_i($$.c);
3342                 $$.t = TYPE_INT;
3343              } else {
3344                 $$.c = abc_multiply($$.c);
3345                 $$.t = TYPE_NUMBER;
3346              }
3347             }
3348
3349 E : E "in" E {$$.c = code_append($1.c,$3.c);
3350               $$.c = abc_in($$.c);
3351               $$.t = TYPE_BOOLEAN;
3352              }
3353
3354 E : E "as" E {char use_astype=0; // flash player's astype works differently than astypelate
3355               if(use_astype && TYPE_IS_CLASS($3.t) && $3.t->data) {
3356                 MULTINAME(m, (classinfo_t*)($3.t->data));
3357                 $$.c = abc_astype2($1.c, &m);
3358                 $$.t = $3.t->data;
3359               } else {
3360                 $$.c = code_append($1.c, $3.c);
3361                 $$.c = abc_astypelate($$.c);
3362                 $$.t = TYPE_ANY;
3363               }
3364              }
3365
3366 E : E "instanceof" E 
3367              {$$.c = code_append($1.c, $3.c);
3368               $$.c = abc_instanceof($$.c);
3369               $$.t = TYPE_BOOLEAN;
3370              }
3371
3372 E : E "is" E {$$.c = code_append($1.c, $3.c);
3373               $$.c = abc_istypelate($$.c);
3374               $$.t = TYPE_BOOLEAN;
3375              }
3376
3377 E : "typeof" '(' E ')' {
3378               $$.c = $3.c;
3379               $$.c = abc_typeof($$.c);
3380               $$.t = TYPE_STRING;
3381              }
3382
3383 E : "void" E {
3384               $$.c = cut_last_push($2.c);
3385               $$.c = abc_pushundefined($$.c);
3386               $$.t = TYPE_ANY;
3387              }
3388
3389 E : "void" { $$.c = abc_pushundefined(0);
3390              $$.t = TYPE_ANY;
3391            }
3392
3393 E : '(' EXPRESSION ')' {$$=$2;} //allow commas in here, too
3394
3395 E : '-' E {
3396   $$=$2;
3397   if(IS_INT($2.t)) {
3398    $$.c=abc_negate_i($$.c);
3399    $$.t = TYPE_INT;
3400   } else {
3401    $$.c=abc_negate($$.c);
3402    $$.t = TYPE_NUMBER;
3403   }
3404 }
3405
3406 E : E '[' E ']' {
3407   $$.c = $1.c;
3408   $$.c = code_append($$.c, $3.c);
3409
3410   MULTINAME_LATE(m, $1.t?$1.t->access:ACCESS_PACKAGE, "");
3411   $$.c = abc_getproperty2($$.c, &m);
3412   $$.t = 0; // array elements have unknown type
3413 }
3414
3415 E : '[' MAYBE_EXPRESSION_LIST ']' {
3416     $$.c = code_new();
3417     $$.c = code_append($$.c, $2.cc);
3418     $$.c = abc_newarray($$.c, $2.number);
3419     $$.t = registry_getarrayclass();
3420 }
3421
3422 MAYBE_EXPRPAIR_LIST : {$$.cc=0;$$.number=0;}
3423 MAYBE_EXPRPAIR_LIST : EXPRPAIR_LIST {$$=$1;}
3424
3425 EXPRPAIR_LIST : NONCOMMAEXPRESSION ':' NONCOMMAEXPRESSION {
3426     $$.cc = 0;
3427     $$.cc = code_append($$.cc, $1.c);
3428     $$.cc = code_append($$.cc, $3.c);
3429     $$.number = 2;
3430 }
3431 EXPRPAIR_LIST : EXPRPAIR_LIST ',' NONCOMMAEXPRESSION ':' NONCOMMAEXPRESSION {
3432     $$.cc = $1.cc;
3433     $$.number = $1.number+2;
3434     $$.cc = code_append($$.cc, $3.c);
3435     $$.cc = code_append($$.cc, $5.c);
3436 }
3437 //MAYBECOMMA: ','
3438 //MAYBECOMMA:
3439
3440 E : "{ (dictionary)" MAYBE_EXPRPAIR_LIST '}' {
3441     $$.c = code_new();
3442     $$.c = code_append($$.c, $2.cc);
3443     $$.c = abc_newobject($$.c, $2.number/2);
3444     $$.t = registry_getobjectclass();
3445 }
3446
3447 E : E "*=" E { 
3448                code_t*c = $3.c;
3449                if(BOTH_INT($1.t,$3.t)) {
3450                 c=abc_multiply_i(c);
3451                } else {
3452                 c=abc_multiply(c);
3453                }
3454                c=converttype(c, join_types($1.t, $3.t, '*'), $1.t);
3455                $$.c = toreadwrite($1.c, c, 0, 0);
3456                $$.t = $1.t;
3457               }
3458
3459 E : E "%=" E { 
3460                code_t*c = abc_modulo($3.c);
3461                c=converttype(c, join_types($1.t, $3.t, '%'), $1.t);
3462                $$.c = toreadwrite($1.c, c, 0, 0);
3463                $$.t = $1.t;
3464               }
3465 E : E "<<=" E { 
3466                code_t*c = abc_lshift($3.c);
3467                c=converttype(c, join_types($1.t, $3.t, '<'), $1.t);
3468                $$.c = toreadwrite($1.c, c, 0, 0);
3469                $$.t = $1.t;
3470               }
3471 E : E ">>=" E { 
3472                code_t*c = abc_rshift($3.c);
3473                c=converttype(c, join_types($1.t, $3.t, '>'), $1.t);
3474                $$.c = toreadwrite($1.c, c, 0, 0);
3475                $$.t = $1.t;
3476               }
3477 E : E ">>>=" E { 
3478                code_t*c = abc_urshift($3.c);
3479                c=converttype(c, join_types($1.t, $3.t, 'U'), $1.t);
3480                $$.c = toreadwrite($1.c, c, 0, 0);
3481                $$.t = $1.t;
3482               }
3483 E : E "/=" E { 
3484                code_t*c = abc_divide($3.c);
3485                c=converttype(c, join_types($1.t, $3.t, '/'), $1.t);
3486                $$.c = toreadwrite($1.c, c, 0, 0);
3487                $$.t = $1.t;
3488               }
3489 E : E "|=" E { 
3490                code_t*c = abc_bitor($3.c);
3491                c=converttype(c, TYPE_INT, $1.t);
3492                $$.c = toreadwrite($1.c, c, 0, 0);
3493                $$.t = $1.t;
3494               }
3495 E : E "^=" E { 
3496                code_t*c = abc_bitxor($3.c);
3497                c=converttype(c, TYPE_INT, $1.t);
3498                $$.c = toreadwrite($1.c, c, 0, 0);
3499                $$.t = $1.t;
3500               }
3501 E : E "+=" E { 
3502                code_t*c = $3.c;
3503
3504                if(TYPE_IS_INT($1.t)) {
3505                 c=abc_add_i(c);
3506                } else {
3507                 c=abc_add(c);
3508                 c=converttype(c, join_types($1.t, $3.t, '+'), $1.t);
3509                }
3510                
3511                $$.c = toreadwrite($1.c, c, 0, 0);
3512                $$.t = $1.t;
3513               }
3514 E : E "-=" E { code_t*c = $3.c; 
3515                if(TYPE_IS_INT($1.t)) {
3516                 c=abc_subtract_i(c);
3517                } else {
3518                 c=abc_subtract(c);
3519                 c=converttype(c, join_types($1.t, $3.t, '-'), $1.t);
3520                }
3521                
3522                $$.c = toreadwrite($1.c, c, 0, 0);
3523                $$.t = $1.t;
3524              }
3525 E : E '=' E { code_t*c = 0;
3526               c = code_append(c, $3.c);
3527               c = converttype(c, $3.t, $1.t);
3528               $$.c = toreadwrite($1.c, c, 1, 0);
3529               $$.t = $1.t;
3530             }
3531
3532 E : E '?' E ':' E %prec below_assignment { 
3533               $$.t = join_types($3.t,$5.t,'?');
3534               $$.c = $1.c;
3535               code_t*j1 = $$.c = abc_iffalse($$.c, 0);
3536               $$.c = code_append($$.c, $3.c);
3537               $$.c = converttype($$.c, $3.t, $$.t);
3538               code_t*j2 = $$.c = abc_jump($$.c, 0);
3539               $$.c = j1->branch = abc_label($$.c);
3540               $$.c = code_append($$.c, $5.c);
3541               $$.c = converttype($$.c, $5.t, $$.t);
3542               $$.c = j2->branch = abc_label($$.c);
3543             }
3544
3545 E : E "++" { code_t*c = 0;
3546              classinfo_t*type = $1.t;
3547              if(is_getlocal($1.c) && (TYPE_IS_INT($1.t) || TYPE_IS_NUMBER($1.t))) {
3548                  int nr = getlocalnr($1.c);
3549                  code_free($1.c);$1.c=0;
3550                  if(TYPE_IS_INT($1.t)) {
3551                     $$.c = abc_getlocal(0, nr);
3552                     $$.c = abc_inclocal_i($$.c, nr);
3553                  } else if(TYPE_IS_NUMBER($1.t)) {
3554                     $$.c = abc_getlocal(0, nr);
3555                     $$.c = abc_inclocal($$.c, nr);
3556                  } else syntaxerror("internal error");
3557              } else {
3558                  if(TYPE_IS_INT(type) || TYPE_IS_UINT(type)) {
3559                      c=abc_increment_i(c);
3560                      type = TYPE_INT;
3561                  } else {
3562                      c=abc_increment(c);
3563                      type = TYPE_NUMBER;
3564                  }
3565                  c=converttype(c, type, $1.t);
3566                  $$.c = toreadwrite($1.c, c, 0, 1);
3567                  $$.t = $1.t;
3568              }
3569            }
3570
3571 // TODO: use inclocal, like with ++
3572 E : E "--" { code_t*c = 0;
3573              classinfo_t*type = $1.t;
3574              if(TYPE_IS_INT(type) || TYPE_IS_UINT(type)) {
3575                  c=abc_decrement_i(c);
3576                  type = TYPE_INT;
3577              } else {
3578                  c=abc_decrement(c);
3579                  type = TYPE_NUMBER;
3580              }
3581              c=converttype(c, type, $1.t);
3582              $$.c = toreadwrite($1.c, c, 0, 1);
3583              $$.t = $1.t;
3584             }
3585
3586 E : "++" %prec plusplus_prefix E { code_t*c = 0;
3587              classinfo_t*type = $2.t;
3588              if(TYPE_IS_INT(type) || TYPE_IS_UINT(type)) {
3589                  c=abc_increment_i(c);
3590                  type = TYPE_INT;
3591              } else {
3592                  c=abc_increment(c);
3593                  type = TYPE_NUMBER;
3594              }
3595              c=converttype(c, type, $2.t);
3596              $$.c = toreadwrite($2.c, c, 0, 0);
3597              $$.t = $2.t;
3598            }
3599
3600 E : "--" %prec minusminus_prefix E { code_t*c = 0;
3601              classinfo_t*type = $2.t;
3602              if(TYPE_IS_INT(type) || TYPE_IS_UINT(type)) {
3603                  c=abc_decrement_i(c);
3604                  type = TYPE_INT;
3605              } else {
3606                  c=abc_decrement(c);
3607                  type = TYPE_NUMBER;
3608              }
3609              c=converttype(c, type, $2.t);
3610              $$.c = toreadwrite($2.c, c, 0, 0);
3611              $$.t = $2.t;
3612            }
3613
3614 E : "super" '.' T_IDENTIFIER 
3615            { if(!state->cls->info)
3616                   syntaxerror("super keyword not allowed outside a class");
3617               classinfo_t*t = state->cls->info->superclass;
3618               if(!t) t = TYPE_OBJECT;
3619
3620               memberinfo_t*f = findmember_nsset(t, $3, 1);
3621
3622               MEMBER_MULTINAME(m, f, $3);
3623               $$.c = 0;
3624               $$.c = abc_getlocal_0($$.c);
3625               $$.c = abc_getsuper2($$.c, &m);
3626               $$.t = slotinfo_gettype((slotinfo_t*)f);
3627            }
3628
3629 E : '@' T_IDENTIFIER {
3630               // attribute TODO
3631               $$.c = abc_pushundefined(0);
3632               $$.t = 0;
3633               as3_warning("ignored @ operator");
3634            }
3635
3636 E : E '.' '@' T_IDENTIFIER {
3637               // child attribute  TODO
3638               $$.c = abc_pushundefined(0);
3639               $$.t = 0;
3640               as3_warning("ignored .@ operator");
3641            }
3642
3643 E : E '.' T_IDENTIFIER "::" T_IDENTIFIER {
3644               // namespace declaration TODO
3645               $$.c = abc_pushundefined(0);
3646               $$.t = 0;
3647               as3_warning("ignored :: operator");
3648            }
3649
3650 E : E ".." T_IDENTIFIER {
3651               // descendants TODO
3652               $$.c = abc_pushundefined(0);
3653               $$.t = 0;
3654               as3_warning("ignored .. operator");
3655            }
3656
3657 E : E '.' '(' E ')' {
3658               // filter TODO
3659               $$.c = abc_pushundefined(0);
3660               $$.t = 0;
3661               as3_warning("ignored .() operator");
3662            }
3663
3664 //VARIABLE : VARIABLE "::" '[' EXPRESSION ']' // qualified expression
3665
3666
3667
3668 E : E '.' T_IDENTIFIER {
3669     $$.c = $1.c;
3670     classinfo_t*t = $1.t;
3671     char is_static = 0;
3672     if(TYPE_IS_CLASS(t) && t->data) {
3673         t = t->data;
3674         is_static = 1;
3675     }
3676     if(t) {
3677         if(t->subtype==INFOTYPE_UNRESOLVED) {
3678             syntaxerror("syntaxerror: trying to resolve property '%s' on incomplete object '%s'", $3, t->name);
3679         }
3680         memberinfo_t*f = findmember_nsset(t, $3, 1);
3681         char noslot = 0;
3682         if(f && !is_static != !(f->flags&FLAG_STATIC))
3683            noslot=1;
3684         if(f && f->slot && !noslot) {
3685             $$.c = abc_getslot($$.c, f->slot);
3686         } else {
3687             MEMBER_MULTINAME(m, f, $3);
3688             $$.c = abc_getproperty2($$.c, &m);
3689         }
3690         /* determine type */
3691         $$.t = slotinfo_gettype((slotinfo_t*)f);
3692         if(!$$.t)
3693            $$.c = abc_coerce_a($$.c);
3694     } else if($1.c && $1.c->opcode == OPCODE___PUSHPACKAGE__) {
3695         string_t*package = $1.c->data[0];
3696         char*package2 = concat3(package->str, ".", $3);
3697
3698         slotinfo_t*a = registry_find(package->str, $3);
3699         if(a) {
3700             $$ = push_class(a);
3701         } else if(dict_contains(state->import_toplevel_packages, package2) ||
3702                   registry_ispackage(package2)) {
3703             $$.c = $1.c;
3704             $$.c->data[0] = string_new4(package2);
3705             $$.t = 0;
3706         } else {
3707             syntaxerror("couldn't resolve %s", package2);
3708         }
3709     } else {
3710         /* when resolving a property on an unknown type, we do know the
3711            name of the property (and don't seem to need the package), but
3712            we need to make avm2 try out all access modes */
3713         multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $3};
3714         $$.c = abc_getproperty2($$.c, &m);
3715         $$.c = abc_coerce_a($$.c);
3716         $$.t = registry_getanytype();
3717     }
3718 }
3719
3720 VAR_READ : T_IDENTIFIER {
3721     PASS1
3722     /* Queue unresolved identifiers for checking against the parent
3723        function's variables.
3724        We consider everything which is not a local variable "unresolved".
3725        This encompasses class names, members of the surrounding class
3726        etc. which is *correct* because local variables of the parent function
3727        would shadow those.
3728        */
3729     if(state->method->inner && !find_variable(state, $1)) {
3730         unknown_variable($1);
3731     }
3732    
3733     /* let the compiler know that it might want to check the current directory/package
3734        for this identifier- maybe there's a file $1.as defining $1. */
3735     //as3_schedule_class_noerror(state->package, $1);
3736     PASS2
3737
3738     $$.t = 0;
3739     $$.c = 0;
3740     slotinfo_t*a = 0;
3741     memberinfo_t*f = 0;
3742
3743     variable_t*v;
3744     /* look at variables */
3745     if((v = find_variable(state, $1))) {
3746         // $1 is a local variable
3747         $$.c = abc_getlocal($$.c, v->index);
3748         $$.t = v->type;
3749         break;
3750     }
3751     if((v = find_slot(state, $1))) {
3752         $$.c = abc_getscopeobject($$.c, 1);
3753         $$.c = abc_getslot($$.c, v->index);
3754         $$.t = v->type;
3755         break;
3756     }
3757
3758     int i_am_static = (state->method && state->method->info)?(state->method->info->flags&FLAG_STATIC):FLAG_STATIC;
3759
3760     /* look at current class' members */
3761     if(state->cls && (f = findmember_nsset(state->cls->info, $1, 1)) &&
3762         (f->flags&FLAG_STATIC) >= i_am_static) {
3763         // $1 is a function in this class
3764         int var_is_static = (f->flags&FLAG_STATIC);
3765
3766         if(f->kind == INFOTYPE_METHOD) {
3767             $$.t = TYPE_FUNCTION(f);
3768         } else {
3769             $$.t = f->type;
3770         }
3771         if(var_is_static && !i_am_static) {
3772         /* access to a static member from a non-static location.
3773            do this via findpropstrict:
3774            there doesn't seem to be any non-lookup way to access
3775            static properties of a class */
3776             state->method->late_binding = 1;
3777             $$.t = f->type;
3778             namespace_t ns = {f->access, ""};
3779             multiname_t m = {QNAME, &ns, 0, $1};
3780             $$.c = abc_findpropstrict2($$.c, &m);
3781             $$.c = abc_getproperty2($$.c, &m);
3782             break;
3783         } else if(f->slot>0) {
3784             $$.c = abc_getlocal_0($$.c);
3785             $$.c = abc_getslot($$.c, f->slot);
3786             break;
3787         } else {
3788             namespace_t ns = {f->access, ""};
3789             multiname_t m = {QNAME, &ns, 0, $1};
3790             $$.c = abc_getlocal_0($$.c);
3791             $$.c = abc_getproperty2($$.c, &m);
3792             break;
3793         }
3794     } 
3795     
3796     /* look at actual classes, in the current package and imported */
3797     if((a = find_class($1))) {
3798         $$ = push_class(a);
3799         break;
3800     }
3801
3802     /* look through package prefixes */
3803     if(dict_contains(state->import_toplevel_packages, $1) || 
3804        registry_ispackage($1)) {
3805         $$.c = abc___pushpackage__($$.c, $1);
3806         $$.t = 0;
3807         break;
3808     }
3809
3810     /* unknown object, let the avm2 resolve it */
3811     if(1) {
3812         //as3_softwarning("Couldn't resolve '%s', doing late binding", $1);
3813         as3_warning("Couldn't resolve '%s', doing late binding", $1);
3814         state->method->late_binding = 1;
3815                 
3816         multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $1};
3817
3818         $$.t = 0;
3819         $$.c = abc_findpropstrict2($$.c, &m);
3820         $$.c = abc_getproperty2($$.c, &m);
3821     }
3822 }
3823
3824 // ----------------- namespaces -------------------------------------------------
3825
3826 NAMESPACE_ID : "namespace" T_IDENTIFIER {
3827     PASS12
3828     NEW(namespace_decl_t,n);
3829     n->name = $2;
3830     n->url = $2;
3831     $$=n;
3832 }
3833 NAMESPACE_ID : "namespace" T_IDENTIFIER '=' T_IDENTIFIER {
3834     PASS12
3835     NEW(namespace_decl_t,n);
3836     n->name = $2;
3837     n->url = $4;
3838     $$=n;
3839 }
3840 NAMESPACE_ID : "namespace" T_IDENTIFIER '=' T_STRING {
3841     PASS12
3842     NEW(namespace_decl_t,n);
3843     n->name = $2;
3844     n->url = $4.str;
3845     $$=n;
3846 }
3847 NAMESPACE_DECLARATION : MAYBE_MODIFIERS NAMESPACE_ID {
3848     PASS12
3849     trie_put(active_namespaces, $2->name, (void*)$2->url);
3850
3851     namespace_t access = modifiers2access(&$1);
3852     varinfo_t* var = varinfo_register_global(access.access, state->package, $2->name);
3853     var->type = TYPE_NAMESPACE;
3854     namespace_t ns;
3855     ns.access = ACCESS_NAMESPACE;
3856     ns.name = $2->url;
3857     var->value = constant_new_namespace(&ns);
3858
3859     $$=0;
3860 }
3861
3862 USE_NAMESPACE : "use" "namespace" CLASS_SPEC {
3863     
3864     const char*url = $3->name;
3865     varinfo_t*s = (varinfo_t*)$3;
3866     if(!s || s->kind != INFOTYPE_SLOT)
3867         syntaxerror("%s.%s is not a public namespace (%d)", $3->package, $3->name, s?s->kind:-1);
3868     if(!s->value || !NS_TYPE(s->value->type))
3869         syntaxerror("%s.%s is not a namespace", $3->package, $3->name);
3870     url = s->value->ns->name;
3871
3872     trie_put(active_namespaces, $3->name, (void*)url);
3873     add_active_url(url);
3874     $$=0;
3875 }
3876