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