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