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