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