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