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