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