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