added some more as3 tests
[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, char is_static)
949 {
950     return registry_findmember_nsset(cls, state->active_namespace_urls, name, recurse, is_static);
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 && !((flags^m->flags)&FLAG_STATIC))
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, mod->flags&FLAG_STATIC);
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, mod->flags&FLAG_STATIC);
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, mod->flags&FLAG_STATIC);
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, mod->flags&FLAG_STATIC);
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, mod->flags&FLAG_STATIC);
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 compatibility 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
1688     as3_error("can't convert type %s%s%s to %s%s%s", 
1689         from->package, from->package[0]?".":"", from->name, 
1690         to->package, to->package[0]?".":"", to->name);
1691
1692     return c;
1693 }
1694 code_t* coerce_to_type(code_t*c, classinfo_t*t)
1695 {
1696     if(!t) {
1697         return abc_coerce_a(c);
1698     } else if(TYPE_IS_STRING(t)) {
1699         return abc_coerce_s(c);
1700     } else {
1701         MULTINAME(m, t);
1702         return abc_coerce2(c, &m);
1703     }
1704 }
1705
1706 char is_pushundefined(code_t*c)
1707 {
1708     return (c && !c->prev && !c->next && c->opcode == OPCODE_PUSHUNDEFINED);
1709 }
1710
1711 static const char* get_package_from_name(const char*name)
1712 {
1713     /* try explicit imports */
1714     dictentry_t* e = dict_get_slot(state->imports, name);
1715     while(e) {
1716         if(!strcmp(e->key, name)) {
1717             slotinfo_t*c = (slotinfo_t*)e->data;
1718             if(c) return c->package;
1719         }
1720         e = e->next;
1721     }
1722     return 0;
1723 }
1724 static namespace_list_t*get_current_imports()
1725 {
1726     namespace_list_t*searchlist = 0;
1727     
1728     list_append(searchlist, namespace_new_package(state->package));
1729
1730     import_list_t*l = state->wildcard_imports;
1731     while(l) {
1732         namespace_t*ns = namespace_new_package(l->import->package);
1733         list_append(searchlist, ns);
1734         l = l->next;
1735     }
1736     list_append(searchlist, namespace_new_package(""));
1737     list_append(searchlist, namespace_new_package(internal_filename_package));
1738     return searchlist;
1739 }
1740
1741 static slotinfo_t* find_class(const char*name)
1742 {
1743     slotinfo_t*c=0;
1744
1745     c = registry_find(state->package, name);
1746     if(c) return c;
1747
1748     /* try explicit imports */
1749     dictentry_t* e = dict_get_slot(state->imports, name);
1750     if(c) return c;
1751     while(e) {
1752         if(!strcmp(e->key, name)) {
1753             c = (slotinfo_t*)e->data;
1754             if(c) return c;
1755         }
1756         e = e->next;
1757     }
1758
1759     /* try package.* imports */
1760     import_list_t*l = state->wildcard_imports;
1761     while(l) {
1762         //printf("does package %s contain a class %s?\n", l->import->package, name);
1763         c = registry_find(l->import->package, name);
1764         if(c) return c;
1765         l = l->next;
1766     }
1767
1768     /* try global package */
1769     c = registry_find("", name);
1770     if(c) return c;
1771   
1772     /* try local "filename" package */
1773     c = registry_find(internal_filename_package, name);
1774     if(c) return c;
1775
1776     return 0;
1777 }
1778 typedcode_t push_class(slotinfo_t*a)
1779 {
1780     typedcode_t x;
1781     x.c = 0;
1782     x.t = 0;
1783     if(a->access == ACCESS_PACKAGEINTERNAL &&
1784        strcmp(a->package, state->package) &&
1785        strcmp(a->package, internal_filename_package)
1786        ) {
1787        syntaxerror("Can't access internal %s %s in package '%s' from package '%s'",
1788             infotypename(a), a->name, a->package, state->package);
1789     }
1790
1791
1792     if(a->kind != INFOTYPE_CLASS) {
1793         MULTINAME(m, a);
1794         x.c = abc_findpropstrict2(x.c, &m);
1795         x.c = abc_getproperty2(x.c, &m);
1796         if(a->kind == INFOTYPE_METHOD) {
1797             methodinfo_t*f = (methodinfo_t*)a;
1798             x.t = TYPE_FUNCTION(f);
1799         } else {
1800             varinfo_t*v = (varinfo_t*)a;
1801             x.t = v->type;
1802         }
1803         return x;
1804     } else {
1805         if(state->cls && state->method == state->cls->static_init) {
1806             /* we're in the static initializer. 
1807                record the fact that we're using this class here */
1808             parsedclass_add_dependency(state->cls->dependencies, (classinfo_t*)a);
1809         }
1810         classinfo_t*c = (classinfo_t*)a;
1811         //if(c->slot) {
1812         if(0) { //Error #1026: Slot 1 exceeds slotCount=0 of global
1813             x.c = abc_getglobalscope(x.c);
1814             x.c = abc_getslot(x.c, c->slot);
1815         } else {
1816             MULTINAME(m, c);
1817             x.c = abc_getlex2(x.c, &m);
1818         }
1819         x.t = TYPE_CLASS(c);
1820     }
1821     return x;
1822 }
1823
1824
1825 char is_break_or_jump(code_t*c)
1826 {
1827     if(!c)
1828         return 0;
1829     if(c->opcode == OPCODE_JUMP ||
1830        c->opcode == OPCODE___BREAK__ ||
1831        c->opcode == OPCODE___CONTINUE__ ||
1832        c->opcode == OPCODE_THROW ||
1833        c->opcode == OPCODE_RETURNVOID ||
1834        c->opcode == OPCODE_RETURNVALUE) {
1835        return 1;
1836     }
1837     return 0;
1838 }
1839
1840 #define IS_FINALLY_TARGET(op) \
1841         ((op) == OPCODE___CONTINUE__ || \
1842          (op) == OPCODE___BREAK__ || \
1843          (op) == OPCODE_RETURNVOID || \
1844          (op) == OPCODE_RETURNVALUE || \
1845          (op) == OPCODE___RETHROW__)
1846
1847 static code_t* insert_finally_lookup(code_t*c, code_t*finally, int tempvar)
1848 {
1849 #define NEED_EXTRA_STACK_ARG
1850     code_t*finally_label = abc_nop(0);
1851     NEW(lookupswitch_t, l);
1852     //_lookupswitch
1853
1854     code_t*i = c;
1855     int count=0;
1856     while(i) {
1857         code_t*prev = i->prev;
1858         if(IS_FINALLY_TARGET(i->opcode)) {
1859            code_t*p = prev;
1860            char needvalue=0;
1861            if(i->opcode == OPCODE___RETHROW__ ||
1862               i->opcode == OPCODE_RETURNVALUE) {
1863                if(i->opcode == OPCODE___RETHROW__)
1864                  i->opcode = OPCODE_THROW;
1865                needvalue=1;
1866                p = abc_coerce_a(p);
1867                p = abc_setlocal(p, tempvar);
1868            }
1869            p = abc_pushbyte(p, count++);
1870            p = abc_jump(p, finally_label);
1871            code_t*target = p = abc_label(p);
1872 #ifdef NEED_EXTRA_STACK_ARG
1873            p = abc_pop(p);
1874 #endif
1875            if(needvalue) {
1876                p = abc_getlocal(p, tempvar);
1877            }
1878
1879            p->next = i;i->prev = p;
1880            list_append(l->targets, target);
1881         }
1882         i = prev;
1883     }
1884
1885     code_t*j,*f;
1886     c = abc_pushbyte(c, -1);
1887     c = code_append(c, finally_label);
1888     c = code_append(c, finally);
1889
1890 #ifdef NEED_EXTRA_STACK_ARG
1891     c = abc_dup(c);
1892 #endif
1893     c = abc_lookupswitch(c, l);
1894     c = l->def = abc_label(c);
1895 #ifdef NEED_EXTRA_STACK_ARG
1896     c = abc_pop(c);
1897 #endif
1898
1899     return c;
1900 }
1901
1902 static code_t* insert_finally_simple(code_t*c, code_t*finally, int tempvar)
1903 {
1904     code_t*i = c;
1905     while(i) {
1906         code_t*prev = i->prev;
1907         if(IS_FINALLY_TARGET(i->opcode)) {
1908            if(i->opcode == OPCODE___RETHROW__)
1909                 i->opcode = OPCODE_THROW;
1910            code_t*end = code_dup(finally);
1911            code_t*start = code_start(end);
1912            if(prev) prev->next = start;
1913            start->prev = prev;
1914            i->prev = end;
1915            end->next = i;
1916         }
1917         i = prev;
1918     }
1919     return code_append(c, finally);
1920 }
1921
1922 code_t* insert_finally(code_t*c, code_t*finally, int tempvar)
1923 {
1924     if(!finally)
1925         return c;
1926     code_t*i = c;
1927     char cantdup=0;
1928     int num_insertion_points=0;
1929     while(i) {
1930         if(IS_FINALLY_TARGET(i->opcode))
1931             num_insertion_points++;
1932         i = i->prev;
1933     }
1934     i = finally;
1935     int code_size=0;
1936     while(i) {
1937         code_size++;
1938         if(i->branch || i->opcode == OPCODE_LOOKUPSWITCH) {
1939             cantdup=1;
1940         }
1941         i = i->prev;
1942     }
1943     int simple_version_cost = (1+num_insertion_points)*code_size;
1944     int lookup_version_cost = 4*num_insertion_points + 5;
1945
1946     if(cantdup || simple_version_cost > lookup_version_cost) {
1947         //printf("(use lookup) simple=%d > lookup=%d\n", simple_version_cost, lookup_version_cost);
1948         return insert_finally_lookup(c, finally, tempvar);
1949     } else {
1950         //printf("(use simple) simple=%d < lookup=%d\n", simple_version_cost, lookup_version_cost);
1951         return insert_finally_simple(c, finally, tempvar);
1952     }
1953 }
1954
1955 #define PASS1 }} if(as3_pass == 1) {{
1956 #define PASS1END }} if(as3_pass == 2) {{
1957 #define PASS2 }} if(as3_pass == 2) {{
1958 #define PASS12 }} if(as3_pass == 1 || as3_pass == 2) {{
1959 #define PASS12END }} if(as3_pass == 2) {{
1960 #define PASS_ALWAYS }} {{
1961
1962 %}
1963
1964 %%
1965
1966 /* ------------ code blocks / statements ---------------- */
1967
1968 PROGRAM: MAYBE_PROGRAM_CODE_LIST
1969
1970 MAYBE_PROGRAM_CODE_LIST: | PROGRAM_CODE_LIST 
1971 PROGRAM_CODE_LIST: PROGRAM_CODE 
1972                  | PROGRAM_CODE_LIST PROGRAM_CODE
1973
1974 PROGRAM_CODE: PACKAGE_DECLARATION 
1975             | INTERFACE_DECLARATION 
1976             | CLASS_DECLARATION
1977             | FUNCTION_DECLARATION
1978             | SLOT_DECLARATION
1979             | PACKAGE_INITCODE
1980             | CONDITIONAL_COMPILATION '{' MAYBE_PROGRAM_CODE_LIST '}' {PASS_ALWAYS as3_pass=$1;}
1981             | ';'
1982
1983 MAYBE_INPACKAGE_CODE_LIST: | INPACKAGE_CODE_LIST
1984 INPACKAGE_CODE_LIST: INPACKAGE_CODE 
1985                    | INPACKAGE_CODE_LIST INPACKAGE_CODE
1986
1987 INPACKAGE_CODE: INTERFACE_DECLARATION 
1988               | CLASS_DECLARATION
1989               | FUNCTION_DECLARATION
1990               | SLOT_DECLARATION
1991               | PACKAGE_INITCODE
1992               | CONDITIONAL_COMPILATION '{' MAYBE_INPACKAGE_CODE_LIST '}' {PASS_ALWAYS as3_pass=$1;}
1993               | '[' EMBED_START E ']' {PASS_ALWAYS as3_pass=$2;PASS1 as3_warning("embed command ignored");}
1994               | ';'
1995
1996 MAYBECODE: CODE {$$=$1;}
1997 MAYBECODE: {$$=code_new();}
1998
1999 CODE: CODE CODEPIECE {
2000     $$=code_append($1,$2);
2001 }
2002 CODE: CODEPIECE {$$=$1;}
2003
2004 // code which may appear outside of methods
2005 CODE_STATEMENT: DEFAULT_NAMESPACE 
2006 CODE_STATEMENT: IMPORT 
2007 CODE_STATEMENT: FOR 
2008 CODE_STATEMENT: FOR_IN 
2009 CODE_STATEMENT: WHILE 
2010 CODE_STATEMENT: DO_WHILE 
2011 CODE_STATEMENT: SWITCH 
2012 CODE_STATEMENT: IF
2013 CODE_STATEMENT: WITH
2014 CODE_STATEMENT: TRY
2015 CODE_STATEMENT: VOIDEXPRESSION 
2016 CODE_STATEMENT: USE_NAMESPACE
2017 CODE_STATEMENT: NAMESPACE_DECLARATION
2018 CODE_STATEMENT: '{' CODE '}' {$$=$2;}
2019 CODE_STATEMENT: '{' '}' {$$=0;}
2020
2021 // code which may appear in methods (includes the above)
2022 CODEPIECE: ';' {$$=0;}
2023 CODEPIECE: CODE_STATEMENT
2024 CODEPIECE: VARIABLE_DECLARATION
2025 CODEPIECE: BREAK
2026 CODEPIECE: CONTINUE
2027 CODEPIECE: RETURN
2028 CODEPIECE: THROW
2029 CODEPIECE: CONDITIONAL_COMPILATION '{' CODE '}' {
2030     PASS_ALWAYS 
2031     if(as3_pass) {
2032         $$ = $3;
2033     } else {
2034         $$ = 0;
2035     }
2036     as3_pass=$1;
2037 }
2038
2039 //CODEBLOCK :  '{' CODE '}' {$$=$2;}
2040 //CODEBLOCK :  '{' '}'      {$$=0;}
2041 CODEBLOCK :  CODEPIECE ';'             {$$=$1;}
2042 CODEBLOCK :  CODEPIECE %prec below_semicolon {$$=$1;}
2043
2044 /* ------------ package init code ------------------- */
2045
2046 PACKAGE_INITCODE: CODE_STATEMENT {
2047     if($1) {
2048         if(!global->init) 
2049             global->init = abc_initscript(global->file);
2050         code_t**cc = &global->init->method->body->code;
2051         *cc = code_append(*cc, $1);
2052     }
2053 }
2054
2055 /* ------------ embed code ------------- */
2056
2057 EMBED_START: %prec above_function {
2058     PASS_ALWAYS
2059     $$ = as3_pass;
2060     as3_pass=0;
2061 }
2062
2063 /* ------------ conditional compilation ------------- */
2064
2065 CONDITIONAL_COMPILATION: T_IDENTIFIER "::" T_IDENTIFIER {
2066     PASS12
2067     $$=as3_pass;
2068     char*key = concat3($1,"::",$3);
2069     if(!definitions || !dict_contains(definitions, key)) {
2070         as3_pass=0;
2071     }
2072     free(key);
2073 }
2074
2075 /* ------------ variables --------------------------- */
2076
2077 %code {
2078     char is_subtype_of(classinfo_t*type, classinfo_t*supertype)
2079     {
2080         return 1; // FIXME
2081     }
2082     char do_init_variable(char*name)
2083     {
2084         if(!state->method->no_variable_scoping)
2085             return 0;
2086         if(!state->new_vars)
2087             return 1;
2088         return 1;
2089     }
2090 };
2091
2092 MAYBEEXPRESSION : '=' E {$$=$2;}
2093                 |       {$$=mkdummynode();}
2094
2095 VARIABLE_DECLARATION : "var" VARIABLE_LIST {$$=$2;}
2096 VARIABLE_DECLARATION : "const" VARIABLE_LIST {$$=$2;}
2097
2098 VARIABLE_LIST: ONE_VARIABLE                   {$$ = $1;}
2099 VARIABLE_LIST: VARIABLE_LIST ',' ONE_VARIABLE {$$ = code_append($1, $3);}
2100
2101 ONE_VARIABLE: T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION
2102 {
2103 PASS12
2104     if(variable_exists($1)) 
2105         syntaxerror("Variable %s already defined", $1);
2106 PASS1
2107     new_variable(state->method, $1, 0, 1, 0);
2108 PASS2
2109    
2110     char slot = 0;
2111     int index = 0;
2112     variable_t*v = 0;
2113     if(state->method->uses_slots) {
2114         v = find_slot(state->method, $1);
2115         if(v && !v->init) {
2116             // this variable is stored in a slot
2117             v->init = 1;
2118             v->type = $2;
2119             slot = 1;
2120         }
2121     }
2122     if(!v) {
2123         v = new_variable2(state->method, $1, $2, 1, 0);
2124     }
2125
2126     $$ = slot?abc_getscopeobject(0, 1):0;
2127     
2128     typedcode_t val = node_read($3);
2129     if(!is_subtype_of(val.t, $2)) {
2130         syntaxerror("Can't convert %s to %s", val.t->name, $2->name);
2131     }
2132     if($2) {
2133         if(val.c->prev || val.c->opcode != OPCODE_PUSHUNDEFINED) {
2134             $$ = code_append($$, val.c);
2135             $$ = converttype($$, val.t, $2);
2136         } else {
2137             code_free(val.c);
2138             $$ = defaultvalue($$, $2);
2139         }
2140     } else {
2141         if(val.c->prev || val.c->opcode != OPCODE_PUSHUNDEFINED) {
2142             $$ = code_append($$, val.c);
2143             $$ = abc_coerce_a($$);
2144         } else {
2145             // don't do anything
2146             code_free(val.c);
2147             code_free($$);
2148             $$ = 0;
2149             break;
2150         }
2151     }
2152     if(slot) {
2153         $$ = abc_setslot($$, v->index);
2154     } else {
2155         $$ = abc_setlocal($$, v->index);
2156         v->init = do_init_variable($1);
2157     }
2158 }
2159
2160 /* ------------ control flow ------------------------- */
2161
2162 IF_CODEBLOCK: {PASS12 new_state();} CODEBLOCK {
2163     $$ = var_block($2, state->vars);
2164     PASS12 old_state();
2165 }
2166 MAYBEELSE:  %prec below_else {$$ = code_new();}
2167 MAYBEELSE: "else" IF_CODEBLOCK {$$=$2;}
2168 //MAYBEELSE: ';' "else" CODEBLOCK {$$=$3;}
2169
2170 IF : "if" '(' EXPRESSION ')' IF_CODEBLOCK MAYBEELSE {
2171     $$ = code_new();
2172     $$ = code_append($$, $3.c);
2173     code_t*myjmp,*myif = $$ = abc_iffalse($$, 0);
2174    
2175     $$ = code_append($$, $5);
2176     if($6) {
2177         myjmp = $$ = abc_jump($$, 0);
2178     }
2179     myif->branch = $$ = abc_nop($$);
2180     if($6) {
2181         $$ = code_append($$, $6);
2182         myjmp->branch = $$ = abc_nop($$);
2183     }
2184 }
2185
2186 FOR_INIT : {$$=code_new();}
2187 FOR_INIT : VARIABLE_DECLARATION
2188 FOR_INIT : VOIDEXPRESSION
2189
2190 // TODO: why doesn't an %prec above_identifier resolve the r-r conflict here?
2191 //       (I don't see any easy way to revolve this conflict otherwise, as we
2192 //        can't touch VAR_READ without upsetting the precedence about "return")
2193 FOR_IN_INIT : "var" T_IDENTIFIER MAYBETYPE {
2194     PASS1 $$=$2;new_variable(state->method, $2,0,1,0);
2195     PASS2 $$=$2;new_variable(state->method, $2,$3,1,0);
2196 }
2197 FOR_IN_INIT : T_IDENTIFIER {
2198     PASS12
2199     $$=$1;
2200 }
2201
2202 FOR_START : T_FOR '(' {PASS12 new_state();$$.name=$1;$$.each=0;}
2203 FOR_START : T_FOR "each" '(' {PASS12 new_state();$$.name=$1;$$.each=1;}
2204
2205 FOR : FOR_START FOR_INIT ';' EXPRESSION ';' VOIDEXPRESSION ')' IF_CODEBLOCK {
2206     if($1.each) syntaxerror("invalid syntax: ; not allowed in for each statement");
2207     $$ = code_new();
2208     $$ = code_append($$, $2);
2209     code_t*loopstart = $$ = abc_label($$);
2210     $$ = code_append($$, $4.c);
2211     code_t*myif = $$ = abc_iffalse($$, 0);
2212     $$ = code_append($$, $8);
2213     code_t*cont = $$ = abc_nop($$);
2214     $$ = code_append($$, $6);
2215     $$ = abc_jump($$, loopstart);
2216     code_t*out = $$ = abc_nop($$);
2217     breakjumpsto($$, $1.name, out);
2218     continuejumpsto($$, $1.name, cont);
2219     myif->branch = out;
2220
2221     $$ = var_block($$, state->vars);
2222     PASS12 old_state();
2223 }
2224
2225 FOR_IN : FOR_START FOR_IN_INIT "in" EXPRESSION ')' IF_CODEBLOCK {
2226     node_t*n = resolve_identifier($2);
2227     typedcode_t w = node_write(n);
2228     
2229     int it = alloc_local();
2230     int array = alloc_local();
2231
2232     $$ = code_new();
2233     $$ = code_append($$, $4.c);
2234     $$ = abc_coerce_a($$);
2235     $$ = abc_setlocal($$, array);
2236     $$ = abc_pushbyte($$, 0);
2237     $$ = abc_setlocal($$, it);
2238
2239     code_t*loopstart = $$ = abc_label($$);
2240     
2241     $$ = abc_hasnext2($$, array, it);
2242     code_t*myif = $$ = abc_iffalse($$, 0);
2243     $$ = abc_getlocal($$, array);
2244     $$ = abc_getlocal($$, it);
2245     if(!$1.each)
2246         $$ = abc_nextname($$);
2247     else
2248         $$ = abc_nextvalue($$);
2249
2250     $$ = converttype($$, 0, w.t);
2251     $$ = code_append($$, w.c);
2252
2253     $$ = code_append($$, $6);
2254     $$ = abc_jump($$, loopstart);
2255     
2256     code_t*out = $$ = abc_nop($$);
2257     breakjumpsto($$, $1.name, out);
2258     continuejumpsto($$, $1.name, loopstart);
2259     
2260     myif->branch = out;
2261
2262     $$ = abc_kill($$, it);
2263     $$ = abc_kill($$, array);
2264
2265     $$ = var_block($$, state->vars);
2266     PASS12 old_state();
2267 }
2268
2269 WHILE : T_WHILE '(' EXPRESSION ')' IF_CODEBLOCK {
2270
2271     $$ = code_new();
2272
2273     code_t*myjmp = $$ = abc_jump($$, 0);
2274     code_t*loopstart = $$ = abc_label($$);
2275     $$ = code_append($$, $5);
2276     code_t*cont = $$ = abc_nop($$);
2277     myjmp->branch = cont;
2278     $$ = code_append($$, $3.c);
2279     $$ = abc_iftrue($$, loopstart);
2280     code_t*out = $$ = abc_nop($$);
2281     breakjumpsto($$, $1, out);
2282     continuejumpsto($$, $1, cont);
2283 }
2284
2285 DO_WHILE : T_DO IF_CODEBLOCK "while" '(' EXPRESSION ')' {
2286     $$ = code_new();
2287     code_t*loopstart = $$ = abc_label($$);
2288     $$ = code_append($$, $2);
2289     code_t*cont = $$ = abc_nop($$);
2290     $$ = code_append($$, $5.c);
2291     $$ = abc_iftrue($$, loopstart);
2292     code_t*out = $$ = abc_nop($$);
2293     breakjumpsto($$, $1, out);
2294     continuejumpsto($$, $1, cont);
2295 }
2296
2297 BREAK : "break" %prec prec_none {
2298     $$ = abc___break__(0, "");
2299 }
2300 BREAK : "break" T_IDENTIFIER {
2301     $$ = abc___break__(0, $2);
2302 }
2303 CONTINUE : "continue" %prec prec_none {
2304     $$ = abc___continue__(0, "");
2305 }
2306 CONTINUE : "continue" T_IDENTIFIER {
2307     $$ = abc___continue__(0, $2);
2308 }
2309
2310 MAYBE_CASE_LIST :           {$$=0;}
2311 MAYBE_CASE_LIST : CASE_LIST {$$=$1;}
2312 MAYBE_CASE_LIST : DEFAULT   {$$=$1;}
2313 MAYBE_CASE_LIST : CASE_LIST DEFAULT {$$=code_append($1,$2);}
2314 CASE_LIST: CASE             {$$=$1;}
2315 CASE_LIST: CASE_LIST CASE   {$$=code_append($$,$2);}
2316
2317 CASE: "case" E ':' MAYBECODE {
2318     $$ = abc_getlocal(0, state->switch_var);
2319     $$ = code_append($$, node_read($2).c);
2320     code_t*j = $$ = abc_ifne($$, 0);
2321     $$ = code_append($$, $4);
2322     if($$->opcode != OPCODE___BREAK__) {
2323         $$ = abc___fallthrough__($$, "");
2324     }
2325     code_t*e = $$ = abc_nop($$);
2326     j->branch = e;
2327 }
2328 DEFAULT: "default" ':' MAYBECODE {
2329     $$ = $3;
2330 }
2331 SWITCH : T_SWITCH '(' {PASS12 new_state();state->switch_var=alloc_local();} E ')' '{' MAYBE_CASE_LIST '}' {
2332     $$ = node_read($4).c;
2333     $$ = abc_setlocal($$, state->switch_var);
2334     $$ = code_append($$, $7);
2335
2336     code_t*out = $$ = abc_kill($$, state->switch_var);
2337     breakjumpsto($$, $1, out);
2338     
2339     code_t*c = $$,*lastblock=0;
2340     while(c) {
2341         if(c->opcode == OPCODE_IFNE) {
2342             if(!c->next) syntaxerror("internal error in fallthrough handling");
2343             lastblock=c->next;
2344         } else if(c->opcode == OPCODE___FALLTHROUGH__) {
2345             if(lastblock) {
2346                 c->opcode = OPCODE_JUMP;
2347                 c->branch = lastblock;
2348             } else {
2349                 /* fall through end of switch */
2350                 c->opcode = OPCODE_NOP;
2351             }
2352         }
2353         c=c->prev;
2354     }
2355    
2356     $$ = var_block($$, state->vars);
2357     PASS12 old_state();
2358 }
2359
2360 /* ------------ try / catch /finally ---------------- */
2361
2362 CATCH: "catch" '(' T_IDENTIFIER MAYBETYPE ')' {PASS12 new_state();
2363                                                       state->exception_name=$3;
2364                                                PASS1 new_variable(state->method, $3, 0, 0, 0);
2365                                                PASS2 new_variable(state->method, $3, $4, 0, 0);
2366                                               } 
2367         '{' MAYBECODE '}' {
2368     namespace_t name_ns = {ACCESS_PACKAGE, ""};
2369     multiname_t name = {QNAME, &name_ns, 0, $3};
2370     
2371     NEW(abc_exception_t, e)
2372     e->exc_type = sig2mname($4);
2373     e->var_name = multiname_clone(&name);
2374     $$ = e;
2375
2376     code_t*c = 0;
2377     int i = find_variable_safe(state, $3)->index;
2378     e->target = c = abc_nop(0);
2379     c = abc_setlocal(c, i);
2380     c = code_append(c, code_dup(state->method->scope_code));
2381     c = code_append(c, $8);
2382     c = abc_kill(c, i);
2383
2384     c = var_block(c, state->vars);
2385     PASS12 old_state();
2386 }
2387 FINALLY: "finally" '{' {PASS12 new_state();state->exception_name=0;} MAYBECODE '}' {
2388     $4 = var_block($4, state->vars);
2389     if(!$4) {
2390         $$=0;
2391     } else {
2392         NEW(abc_exception_t, e)
2393         e->exc_type = 0; //all exceptions
2394         e->var_name = 0; //no name
2395         e->target = 0;
2396         e->to = abc_nop(0);
2397         e->to = code_append(e->to, $4);
2398         $$ = e;
2399     }
2400     PASS12 old_state();
2401 }
2402
2403 CATCH_LIST: CATCH {$$.l=list_new();$$.finally=0;list_append($$.l,$1);}
2404 CATCH_LIST: CATCH_LIST CATCH {$$=$1;list_append($$.l,$2);}
2405 CATCH_FINALLY_LIST: CATCH_LIST {$$=$1;}
2406 CATCH_FINALLY_LIST: CATCH_LIST FINALLY {
2407     $$ = $1;
2408     $$.finally = 0;
2409     if($2) {
2410         list_append($$.l,$2);
2411         $$.finally = $2->to;$2->to=0;
2412     }
2413 }
2414 CATCH_FINALLY_LIST: FINALLY {
2415     $$.l=list_new();
2416     $$.finally = 0;
2417     if($1) {
2418         list_append($$.l,$1);
2419         $$.finally = $1->to;$1->to=0;
2420     }
2421 }
2422
2423 TRY : "try" '{' {PASS12 new_state();
2424                  state->method->has_exceptions=1;
2425                  state->method->late_binding=1;//for invariant scope_code
2426                 } MAYBECODE '}' CATCH_FINALLY_LIST {
2427     code_t*out = abc_nop(0);
2428
2429     code_t*start = abc_nop(0);
2430     $$ = code_append(start, $4);
2431     if(!is_break_or_jump($4)) {
2432         $$ = abc_jump($$, out);
2433     }
2434     code_t*end = $$ = abc_nop($$);
2435   
2436     int tmp;
2437     if($6.finally)
2438         tmp = alloc_local();
2439     
2440     abc_exception_list_t*l = $6.l;
2441     int count=0;
2442     while(l) {
2443         abc_exception_t*e = l->abc_exception;
2444         if(e->var_name) {
2445             $$ = code_append($$, e->target);
2446             $$ = abc_jump($$, out);
2447         } else {
2448             parserassert((ptroff_t)$6.finally);
2449             // finally block
2450             e->target = $$ = abc_nop($$);
2451             $$ = code_append($$, code_dup(state->method->scope_code));
2452             $$ = abc___rethrow__($$);
2453         }
2454         
2455         e->from = start;
2456         e->to = end;
2457
2458         l = l->next;
2459     }
2460     $$ = code_append($$, out);
2461
2462     $$ = insert_finally($$, $6.finally, tmp);
2463         
2464     list_concat(state->method->exceptions, $6.l);
2465    
2466     $$ = var_block($$, state->vars);
2467     PASS12 old_state();
2468 }
2469
2470 /* ------------ throw ------------------------------- */
2471
2472 THROW : "throw" EXPRESSION {
2473     $$=$2.c;
2474     $$=abc_throw($$);
2475 }
2476 THROW : "throw" %prec prec_none {
2477     if(!state->exception_name)
2478         syntaxerror("re-throw only possible within a catch block");
2479     variable_t*v = find_variable(state, state->exception_name);
2480     $$=code_new();
2481     $$=abc_getlocal($$, v->index);
2482     $$=abc_throw($$);
2483 }
2484
2485 /* ------------ with -------------------------------- */
2486
2487 WITH_HEAD : "with" '(' EXPRESSION ')' {
2488      new_state();
2489      if(state->method->has_exceptions) {
2490          int v = alloc_local();
2491          state->method->scope_code = abc_getlocal(state->method->scope_code, v);
2492          state->method->scope_code = abc_pushwith(state->method->scope_code);
2493          $$.number = v;
2494      }
2495      $$.cc = $3.c;
2496
2497 WITH : WITH_HEAD CODEBLOCK {
2498      /* remove getlocal;pushwith from scope code again */
2499      state->method->scope_code = code_cutlast(code_cutlast(state->method->scope_code));
2500
2501      $$ = $1.cc;
2502      if(state->method->has_exceptions) {
2503          $$ = abc_dup($$);
2504          $$ = abc_setlocal($$, $1.number);
2505      }
2506      $$ = abc_pushwith($$);
2507      $$ = code_append($$, $2);
2508      $$ = abc_popscope($$);
2509      old_state();
2510 }
2511
2512 /* ------------ packages and imports ---------------- */
2513
2514 X_IDENTIFIER: T_IDENTIFIER
2515             | "package" {PASS12 $$="package";}
2516             | "namespace" {PASS12 $$="namespace";}
2517             | "NaN" {PASS12 $$="NaN";}
2518             | T_NAMESPACE {PASS12 $$=$1;}
2519
2520 PACKAGE: PACKAGE '.' X_IDENTIFIER {PASS12 $$ = concat3($1,".",$3);free($1);$1=0;}
2521 PACKAGE: X_IDENTIFIER             {PASS12 $$=strdup($1);}
2522
2523 PACKAGE_DECLARATION : "package" PACKAGE '{' {PASS12 startpackage($2);free($2);$2=0;}
2524                                 MAYBE_INPACKAGE_CODE_LIST '}' {PASS12 endpackage();$$=0;}
2525 PACKAGE_DECLARATION : "package" '{' {PASS12 startpackage("");} 
2526                                 MAYBE_INPACKAGE_CODE_LIST '}' {PASS12 endpackage();$$=0;}
2527
2528 %code {
2529     static void state_has_imports()
2530     {
2531         state->wildcard_imports = list_clone(state->wildcard_imports);
2532         state->imports = dict_clone(state->imports);
2533         state->has_own_imports = 1;
2534     }
2535     static void import_toplevel(const char*package)
2536     {
2537         char* s = strdup(package);
2538         while(1) {
2539             dict_put(state->import_toplevel_packages, s, 0);
2540             char*x = strrchr(s, '.');
2541             if(!x)
2542                 break;
2543             *x = 0;
2544         }
2545         free(s);
2546     }
2547 };
2548
2549 IMPORT : "import" T_IDENTIFIER {
2550        PASS12
2551        slotinfo_t*s = registry_find(state->package, $2);
2552        if(!s && as3_pass==1) {as3_schedule_class(state->package, $2);}
2553        state_has_imports();
2554        dict_put(state->imports, state->package, $2);
2555        $$=0;
2556 }
2557 IMPORT : "import" PACKAGEANDCLASS {
2558        PASS12
2559        slotinfo_t*s = registry_find($2->package, $2->name);
2560        if(!s && as3_pass==1) {// || !(s->flags&FLAG_BUILTIN)) {
2561            as3_schedule_class($2->package, $2->name);
2562        }
2563        state_has_imports();
2564        dict_put(state->imports, $2->name, $2);
2565        import_toplevel($2->package);
2566        $$=0;
2567 }
2568 IMPORT : "import" PACKAGE '.' '*' {
2569        PASS12
2570        if(strncmp("flash.", $2, 6) && as3_pass==1) {
2571            as3_schedule_package($2);
2572        }
2573
2574        NEW(import_t,i);
2575        i->package = $2;
2576        state_has_imports();
2577        list_append(state->wildcard_imports, i);
2578        import_toplevel(i->package);
2579        $$=0;
2580 }
2581
2582 /* ------------ classes and interfaces (header) -------------- */
2583
2584 MAYBE_MODIFIERS : %prec above_function {PASS12 $$.flags=0;$$.ns=0;}
2585 MAYBE_MODIFIERS : MODIFIER_LIST        {PASS12 $$=$1;}
2586 MODIFIER_LIST : MODIFIER               {PASS12 $$=$1;}
2587 MODIFIER_LIST : MODIFIER_LIST MODIFIER {
2588     PASS12 
2589     $$.flags=$1.flags|$2.flags;
2590     if($1.ns && $2.ns) syntaxerror("only one namespace allowed in one declaration");
2591     $$.ns=$1.ns?$1.ns:$2.ns;
2592
2593 }
2594 MODIFIER : KW_PUBLIC {PASS12 $$.flags=FLAG_PUBLIC;$$.ns=0;}
2595          | KW_PRIVATE {PASS12 $$.flags=FLAG_PRIVATE;$$.ns=0;}
2596          | KW_PROTECTED {PASS12 $$.flags=FLAG_PROTECTED;$$.ns=0;}
2597          | KW_STATIC {PASS12 $$.flags=FLAG_STATIC;$$.ns=0;}
2598          | KW_DYNAMIC {PASS12 $$.flags=FLAG_DYNAMIC;$$.ns=0;}
2599          | KW_FINAL {PASS12 $$.flags=FLAG_FINAL;$$.ns=0;}
2600          | KW_OVERRIDE {PASS12 $$.flags=FLAG_OVERRIDE;$$.ns=0;}
2601          | KW_NATIVE {PASS12 $$.flags=FLAG_NATIVE;$$.ns=0;}
2602          | KW_INTERNAL {PASS12 $$.flags=FLAG_PACKAGEINTERNAL;$$.ns=0;}
2603          | T_NAMESPACE {PASS12 $$.flags=FLAG_NAMESPACE;
2604                                $$.ns=$1;
2605                        }
2606
2607 EXTENDS : {PASS12 $$=0;}
2608 EXTENDS : KW_EXTENDS CLASS_SPEC {PASS12 $$=$2;}
2609
2610 EXTENDS_LIST : {PASS12 $$=list_new();}
2611 EXTENDS_LIST : KW_EXTENDS CLASS_SPEC_LIST {PASS12 $$=$2;}
2612
2613 IMPLEMENTS_LIST : {PASS12 $$=list_new();}
2614 IMPLEMENTS_LIST : KW_IMPLEMENTS CLASS_SPEC_LIST {PASS12 $$=$2;}
2615
2616 CLASS_DECLARATION : MAYBE_MODIFIERS "class" T_IDENTIFIER 
2617                               EXTENDS IMPLEMENTS_LIST 
2618                               '{' {PASS12 startclass(&$1,$3,$4,$5);} 
2619                               MAYBE_CLASS_BODY 
2620                               '}' {PASS12 endclass();$$=0;}
2621
2622 INTERFACE_DECLARATION : MAYBE_MODIFIERS "interface" T_IDENTIFIER 
2623                               EXTENDS_LIST 
2624                               '{' {PASS12 $1.flags|=FLAG_INTERFACE;
2625                                           startclass(&$1,$3,0,$4);}
2626                               MAYBE_INTERFACE_BODY 
2627                               '}' {PASS12 endclass();$$=0;}
2628
2629 /* ------------ classes and interfaces (body) -------------- */
2630
2631 MAYBE_CLASS_BODY : 
2632 MAYBE_CLASS_BODY : CLASS_BODY
2633 CLASS_BODY : CLASS_BODY_ITEM
2634 CLASS_BODY : CLASS_BODY CLASS_BODY_ITEM
2635 CLASS_BODY_ITEM : ';'
2636 CLASS_BODY_ITEM : CONDITIONAL_COMPILATION '{' MAYBE_CLASS_BODY '}' {PASS_ALWAYS as3_pass=$1;}
2637 CLASS_BODY_ITEM : SLOT_DECLARATION
2638 CLASS_BODY_ITEM : FUNCTION_DECLARATION
2639 CLASS_BODY_ITEM : '[' EMBED_START E ']' {PASS_ALWAYS as3_pass=$2;PASS1 as3_warning("embed command ignored");}
2640
2641 CLASS_BODY_ITEM : CODE_STATEMENT {
2642     code_t*c = state->cls->static_init->header;
2643     c = code_append(c, $1);  
2644     state->cls->static_init->header = c;
2645 }
2646
2647 MAYBE_INTERFACE_BODY : 
2648 MAYBE_INTERFACE_BODY : INTERFACE_BODY
2649 INTERFACE_BODY : IDECLARATION
2650 INTERFACE_BODY : INTERFACE_BODY IDECLARATION
2651 IDECLARATION : ';'
2652 IDECLARATION : "var" T_IDENTIFIER {
2653     syntaxerror("variable declarations not allowed in interfaces");
2654 }
2655 IDECLARATION : MAYBE_MODIFIERS "function" GETSET T_IDENTIFIER '(' MAYBE_PARAM_LIST ')' MAYBETYPE {
2656     PASS12
2657     $1.flags |= FLAG_PUBLIC;
2658     if($1.flags&(FLAG_PRIVATE|FLAG_PACKAGEINTERNAL|FLAG_PROTECTED)) {
2659         syntaxerror("invalid method modifiers: interface methods always need to be public");
2660     }
2661     startfunction(&$1,$3,$4,&$6,$8);
2662     endfunction(&$1,$3,$4,&$6,$8, 0);
2663     list_deep_free($6.list);
2664 }
2665
2666 /* ------------ classes and interfaces (body, slots ) ------- */
2667
2668 %code {
2669     static int slotstate_varconst = 0;
2670     static modifiers_t*slotstate_flags = 0;
2671     static void setslotstate(modifiers_t* flags, int varconst)
2672     {
2673         slotstate_varconst = varconst;
2674         slotstate_flags = flags;
2675         if(state->cls) {
2676             if(flags) {
2677                 if(flags->flags&FLAG_STATIC) {
2678                     state->method = state->cls->static_init;
2679                 } else {
2680                     state->method = state->cls->init;
2681                 }
2682             } else {
2683                 // reset to "default" state (all in class code is static by default) */
2684                 state->method = state->cls->static_init;
2685             }
2686         } else {
2687             parserassert(state->method);
2688         }
2689     }
2690     static trait_t* add_abc_slot(modifiers_t* modifiers, const char*name, multiname_t*m, code_t***c)
2691     {
2692         int flags = modifiers->flags;
2693         namespace_t ns = modifiers2access(modifiers);
2694
2695         /* slot name */
2696         multiname_t mname = {QNAME, &ns, 0, name};
2697       
2698         trait_list_t**traits;
2699         code_t**code=0;
2700         if(!state->cls) {
2701             // global variable
2702             if(!global->init) global->init = abc_initscript(global->file);
2703             ns.name = state->package;
2704             traits = &global->init->traits;
2705             code = &global->init->method->body->code;
2706         } else if(flags&FLAG_STATIC) {
2707             // static variable
2708             traits = &state->cls->abc->static_traits;
2709             code = &state->cls->static_init->header;
2710         } else {
2711             // instance variable
2712             traits = &state->cls->abc->traits;
2713             code = &state->cls->init->header;
2714             
2715             if(ns.access == ACCESS_PROTECTED) {
2716                 ns.name = concat3(state->cls->info->package,":",state->cls->info->name);
2717             }
2718         }
2719         if(c)
2720             *c = code;
2721         if(m) 
2722             *m = *multiname_clone(&mname);
2723             
2724         return trait_new_member(traits, 0, multiname_clone(&mname), 0);
2725     }
2726 };
2727
2728 VARCONST: "var" | "const"
2729
2730 SLOT_DECLARATION: MAYBE_MODIFIERS VARCONST {PASS12 setslotstate(&$1,$2);} SLOT_LIST {PASS12 $$=$4;setslotstate(0, 0);}
2731
2732 SLOT_LIST: ONE_SLOT               {PASS12 $$=0;}
2733 SLOT_LIST: SLOT_LIST ',' ONE_SLOT {PASS12 $$=0;}
2734
2735 ONE_SLOT: T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION
2736 {
2737 PASS12
2738     int flags = slotstate_flags->flags;
2739     namespace_t ns = modifiers2access(slotstate_flags);
2740
2741     if(as3_pass == 1) {
2742
2743         varinfo_t* info = 0;
2744         if(state->cls) {
2745             memberinfo_t*i = registry_findmember(state->cls->info, ns.name, $1, 1, slotstate_flags->flags&FLAG_STATIC);
2746             if(i) {
2747                 check_override(i, flags);
2748             }
2749             info = varinfo_register_onclass(state->cls->info, ns.access, ns.name, $1, slotstate_flags->flags&FLAG_STATIC);
2750         } else {
2751             slotinfo_t*i = registry_find(state->package, $1);
2752             if(i) {
2753                 syntaxerror("package %s already contains '%s'", state->package, $1);
2754             }
2755             if(ns.name && ns.name[0]) {
2756                 syntaxerror("namespaces not allowed on package-level variables");
2757             }
2758             info = varinfo_register_global(ns.access, state->package, $1);
2759         }
2760
2761         info->type = $2;
2762         info->flags = flags;
2763         
2764         dict_put(global->token2info, (void*)(ptroff_t)as3_tokencount, info);
2765     }
2766
2767     if(as3_pass == 2) {
2768         varinfo_t*info = dict_lookup(global->token2info, (void*)(ptroff_t)as3_tokencount);
2769
2770         multiname_t mname;
2771         code_t**code;
2772         trait_t*t = add_abc_slot(slotstate_flags, $1, &mname, &code);
2773
2774         if($2) {
2775             MULTINAME(m, $2);
2776             t->type_name = multiname_clone(&m);
2777         }
2778         info->slot = t->slot_id;
2779         
2780         /* workaround for "VerifyError: Error #1053: Illegal override of ::test2 in C1" 
2781            FIXME: is there a way to use slots and still don't have conflicting overrides?
2782         */
2783         info->slot = t->slot_id = 0;
2784        
2785         constant_t cval = $3->type->eval($3);
2786         if(cval.type!=CONSTANT_UNKNOWN) {
2787             /* compile time constant */
2788             t->value = malloc(sizeof(constant_t));
2789             memcpy(t->value, &cval, sizeof(constant_t));
2790             info->value = constant_clone(t->value);
2791         } else {
2792             typedcode_t v = node_read($3);
2793             /* initalization code (if needed) */
2794             code_t*c = 0;
2795             if(v.c && !is_pushundefined(v.c)) {
2796                 c = abc_getlocal_0(c);
2797                 c = code_append(c, v.c);
2798                 c = converttype(c, v.t, $2);
2799                 if(!t->slot_id) {
2800                     c = abc_initproperty2(c, &mname);
2801                 } else {
2802                     c = abc_setslot(c, t->slot_id);
2803                 }
2804             }
2805             *code = code_append(*code, c);
2806         }
2807
2808         if(slotstate_varconst==KW_CONST) {
2809             t->kind= TRAIT_CONST;
2810             info->flags |= FLAG_CONST;
2811         }
2812     }
2813
2814     $$=0;
2815 }
2816
2817 /* ------------ constants -------------------------------------- */
2818
2819 MAYBECONSTANT: {$$=0;}
2820 MAYBECONSTANT: '=' E {
2821   $$ = malloc(sizeof(constant_t));
2822   *$$ = node_eval($2);
2823   if($$->type == CONSTANT_UNKNOWN) {
2824     syntaxerror("can't evaluate default parameter value (needs to be a compile-time constant)");
2825   }
2826 }
2827
2828 //CONSTANT : T_NAMESPACE {$$ = constant_new_namespace($1);}
2829 CONSTANT : T_INT {$$ = constant_new_int($1);}
2830 CONSTANT : T_UINT {
2831     $$ = constant_new_uint($1);
2832 }
2833 CONSTANT : T_FLOAT {$$ = constant_new_float($1);}
2834 CONSTANT : T_STRING {$$ = constant_new_string2($1.str,$1.len);free((char*)$1.str);}
2835 CONSTANT : "true" {$$ = constant_new_true($1);}
2836 CONSTANT : "false" {$$ = constant_new_false($1);}
2837 CONSTANT : "null" {$$ = constant_new_null($1);}
2838 CONSTANT : "undefined" {$$ = constant_new_undefined($1);}
2839 CONSTANT : KW_NAN {$$ = constant_new_float(__builtin_nan(""));}
2840
2841 /*CONSTANT : T_NAMESPACE {
2842     // TODO
2843     $$ = constant_new_namespace(namespace_new_namespace($1.url));
2844 }*/
2845
2846 /* ---------------------------xml ------------------------------ */
2847
2848 %code {
2849     static int xml_level = 0;
2850 };
2851
2852 XML: XMLNODE {
2853    multiname_t m = {QNAME, &stdns, 0, "XML"};
2854    typedcode_t v;
2855    v.c = 0;
2856    v.c = abc_getlex2(v.c, &m);
2857    v.c = code_append(v.c, node_read($1).c);
2858    v.c = abc_construct(v.c, 1);
2859    v.t = TYPE_XML;
2860    $$ = mkcodenode(v);
2861 }
2862
2863 OPEN : '<' {PASS_ALWAYS if(!xml_level++) tokenizer_begin_xml();}
2864 CLOSE : '>' {PASS_ALWAYS tokenizer_begin_xmltext();}
2865 CLOSE2 : {PASS_ALWAYS if(!--xml_level) tokenizer_end_xml(); else tokenizer_begin_xmltext();}
2866
2867 XMLEXPR1 : '{' E {PASS_ALWAYS tokenizer_begin_xmltext();} '}' {
2868     $$ = $2;
2869 }
2870 XMLEXPR2 : '{' E {PASS_ALWAYS tokenizer_begin_xml();} '}' {
2871     $$ = $2;
2872 }
2873 XMLTEXT : {$$=mkstringnode("");}
2874 XMLTEXT : XMLTEXT XMLEXPR1 {
2875     $$ = mkaddnode($1,$2);
2876 }
2877 XMLTEXT : XMLTEXT T_STRING {
2878     char* str = string_cstr(&$2);
2879     $$ = mkaddnode($1,mkstringnode(str));
2880     free(str);
2881 }
2882 XMLTEXT : XMLTEXT '>' {
2883     $$ = mkaddnode($1, mkstringnode(">"));
2884 }
2885 XML2 : XMLNODE XMLTEXT {
2886     $$ = mkaddnode($1,$2);
2887 }
2888 XML2 : XML2 XMLNODE XMLTEXT {
2889     $$ = mkaddnode($1, mkaddnode($2,$3));
2890 }
2891 XML_ID_OR_EXPR: T_IDENTIFIER {
2892     $$ = mkstringnode($1);
2893 }
2894 XML_ID_OR_EXPR: XMLEXPR2 {
2895     $$ = $1;
2896 }
2897
2898 MAYBE_XMLATTRIBUTES: {
2899     $$ = mkstringnode("");
2900 }
2901 MAYBE_XMLATTRIBUTES: XMLATTRIBUTES {
2902     $$ = mkaddnode(mkstringnode(" "),$1);
2903 }
2904
2905 XMLNODE : OPEN XML_ID_OR_EXPR MAYBE_XMLATTRIBUTES '/' CLOSE2 '>' {
2906     //$$ = allocprintf("<%s%s/>", $2, $3, $5, $8);
2907     $$ = mkaddnode(mkaddnode(mkaddnode(mkstringnode("<"),$2),$3),mkstringnode("/>"));
2908 }
2909 XMLNODE : OPEN XML_ID_OR_EXPR MAYBE_XMLATTRIBUTES CLOSE XMLTEXT '<' '/' XML_ID_OR_EXPR CLOSE2 '>' {
2910     //$$ = allocprintf("<%s%s>%s</%s>", $2, $3, $5, $8);
2911     $$ = mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(
2912          mkstringnode("<"),$2),$3),mkstringnode(">")),$5),mkstringnode("</")),$8),mkstringnode(">"));
2913 }
2914 XMLNODE : OPEN XML_ID_OR_EXPR MAYBE_XMLATTRIBUTES CLOSE XMLTEXT XML2 '<' '/' XML_ID_OR_EXPR CLOSE2 '>' {
2915     //$$ = allocprintf("<%s%s>%s%s</%s>", $2, $3, $5, $6, $9);
2916     $$ = mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(mkaddnode(
2917          mkstringnode("<"),$2),$3),mkstringnode(">")),$5),$6),mkstringnode("</")),$9),mkstringnode(">"));
2918 }
2919
2920 XMLATTRIBUTES: XMLATTRIBUTE {
2921     $$ = $1;
2922 }
2923 XMLATTRIBUTES: XMLATTRIBUTES XMLATTRIBUTE {
2924     $$ = mkaddnode($1, mkaddnode(mkstringnode(" "),$2));
2925 }
2926 XMLATTRIBUTE: XMLEXPR2 {
2927     $$ = $1;
2928 }
2929 XMLATTRIBUTE: XMLEXPR2 '=' T_STRING {
2930     char* str = string_cstr(&$3);
2931     $$ = mkaddnode($1, mkstringnode(concat2("=",str)));
2932     free(str);
2933 }
2934 XMLATTRIBUTE: XMLEXPR2 '=' XMLEXPR2 {
2935     $$ = mkaddnode($1, mkaddnode(mkstringnode("=\""), mkaddnode($3, mkstringnode("\""))));
2936 }
2937 XMLATTRIBUTE: T_IDENTIFIER '=' XMLEXPR2 {
2938     $$ = mkaddnode(mkaddnode(mkstringnode(concat2($1,"=\"")), $3), mkstringnode("\""));
2939 }
2940 XMLATTRIBUTE: T_IDENTIFIER '=' T_STRING {
2941     char* str = string_cstr(&$3);
2942     $$=mkstringnode(allocprintf("%s=%s", $1,str));
2943     free(str);
2944     free($1);free((char*)$3.str);
2945 }
2946
2947 /* ------------ classes and interfaces (body, functions) ------- */
2948
2949 // non-vararg version
2950 MAYBE_PARAM_LIST: {
2951     PASS12
2952     memset(&$$,0,sizeof($$));
2953 }
2954 MAYBE_PARAM_LIST: PARAM_LIST {
2955     PASS12
2956     $$=$1;
2957 }
2958
2959 // vararg version
2960 MAYBE_PARAM_LIST: "..." PARAM {
2961     PASS12
2962     memset(&$$,0,sizeof($$));
2963     $$.varargs=1;
2964     list_append($$.list, $2);
2965 }
2966 MAYBE_PARAM_LIST: PARAM_LIST ',' "..." PARAM {
2967     PASS12
2968     $$ =$1;
2969     $$.varargs=1;
2970     list_append($$.list, $4);
2971 }
2972
2973 // non empty
2974 PARAM_LIST: PARAM_LIST ',' PARAM {
2975     PASS12
2976     $$ = $1;
2977     list_append($$.list, $3);
2978 }
2979 PARAM_LIST: PARAM {
2980     PASS12
2981     memset(&$$,0,sizeof($$));
2982     list_append($$.list, $1);
2983 }
2984
2985 PARAM:  T_IDENTIFIER ':' TYPE MAYBECONSTANT {
2986      PASS12
2987      $$ = rfx_calloc(sizeof(param_t));
2988      $$->name=$1;
2989      $$->type = $3;
2990      PASS2
2991      $$->value = $4;
2992 }
2993 PARAM:  T_IDENTIFIER MAYBECONSTANT {
2994      PASS12
2995      $$ = rfx_calloc(sizeof(param_t));
2996      $$->name=$1;
2997      $$->type = TYPE_ANY;
2998      PASS2
2999      $$->value = $2;
3000 }
3001 GETSET : "get"
3002        | "set"
3003        | {PASS12 $$=0;}
3004
3005 FUNCTION_DECLARATION: MAYBE_MODIFIERS "function" GETSET T_IDENTIFIER '(' MAYBE_PARAM_LIST ')' 
3006                       MAYBETYPE '{' {PASS12 startfunction(&$1,$3,$4,&$6,$8);} MAYBECODE '}' 
3007 {
3008     PASS1 
3009     endfunction(&$1,$3,$4,&$6,0,0);
3010     PASS2
3011     if(!state->method->info) syntaxerror("internal error");
3012     
3013     code_t*c = method_header(state->method);
3014     c = wrap_function(c, 0, $11);
3015
3016     endfunction(&$1,$3,$4,&$6,$8,c);
3017     PASS12
3018     list_deep_free($6.list);
3019     $$=0;
3020 }
3021
3022 MAYBE_IDENTIFIER: T_IDENTIFIER
3023 MAYBE_IDENTIFIER: {PASS12 $$=0;}
3024 INNERFUNCTION: "function" MAYBE_IDENTIFIER '(' MAYBE_PARAM_LIST ')' MAYBETYPE 
3025                '{' {PASS12 innerfunction($2,&$4,$6);} MAYBECODE '}'
3026 {
3027     PASS1
3028     endfunction(0,0,$2,&$4,0,0);
3029     PASS2
3030     methodinfo_t*f = state->method->info;
3031     if(!f || !f->kind) syntaxerror("internal error");
3032     
3033     code_t*c = method_header(state->method);
3034     c = wrap_function(c, 0, $9);
3035
3036     int index = state->method->var_index;
3037     endfunction(0,0,$2,&$4,$6,c);
3038     
3039     $$.c = abc_getlocal(0, index);
3040     $$.t = TYPE_FUNCTION(f);
3041
3042     PASS12 list_deep_free($4.list);
3043 }
3044
3045
3046 /* ------------- package + class ids --------------- */
3047
3048 CLASS: X_IDENTIFIER {
3049     PASS1 NEW(unresolvedinfo_t,c);
3050           memset(c, 0, sizeof(*c));
3051           c->kind = INFOTYPE_UNRESOLVED;
3052           c->name = $1;
3053           c->package = get_package_from_name($1);
3054           if(!c->package) {
3055               c->nsset = get_current_imports();
3056               /* make the compiler look for this class in the current directory,
3057                  just in case: */
3058               as3_schedule_class_noerror(state->package, $1);
3059           }
3060           $$ = (classinfo_t*)c;
3061     PASS2
3062     slotinfo_t*s = find_class($1);
3063     if(!s) syntaxerror("Could not find class/method %s (current package: %s)\n", $1, state->package);
3064     $$ = (classinfo_t*)s;
3065 }
3066
3067 PACKAGEANDCLASS : PACKAGE '.' X_IDENTIFIER {
3068     PASS1 NEW(unresolvedinfo_t,c);
3069           memset(c, 0, sizeof(*c));
3070           c->kind = INFOTYPE_UNRESOLVED;
3071           c->package = $1;
3072           c->name = $3;
3073           $$ = (classinfo_t*)c;
3074     PASS2
3075     slotinfo_t*s = registry_find($1, $3);
3076     if(!s) syntaxerror("Couldn't find class/method %s.%s\n", $1, $3);
3077     free($1);$1=0;
3078     $$ = (classinfo_t*)s;
3079 }
3080
3081 CLASS_SPEC: PACKAGEANDCLASS
3082           | CLASS
3083
3084 CLASS_SPEC_LIST : CLASS_SPEC {PASS12 $$=list_new();list_append($$, $1);}
3085 CLASS_SPEC_LIST : CLASS_SPEC_LIST ',' CLASS_SPEC {PASS12 $$=$1;list_append($$,$3);}
3086
3087 TYPE : CLASS_SPEC {PASS12 $$=$1;}
3088      | '*'        {PASS12 $$=TYPE_ANY;}
3089      | "void"     {PASS12 $$=TYPE_VOID;}
3090     /*
3091      |  "String"  {$$=registry_getstringclass();}
3092      |  "int"     {$$=registry_getintclass();}
3093      |  "uint"    {$$=registry_getuintclass();}
3094      |  "Boolean" {$$=registry_getbooleanclass();}
3095      |  "Number"  {$$=registry_getnumberclass();}
3096     */
3097
3098 MAYBETYPE: ':' TYPE {PASS12 $$=$2;}
3099 MAYBETYPE:          {PASS12 $$=0;}
3100
3101 /* ----------function calls, delete, constructor calls ------ */
3102
3103 MAYBE_PARAM_VALUES :  %prec prec_none {$$.cc=0;$$.number=0;}
3104 MAYBE_PARAM_VALUES : '(' MAYBE_EXPRESSION_LIST ')' {$$=$2;}
3105
3106 MAYBE_EXPRESSION_LIST : {$$.cc=0;$$.number=0;}
3107 MAYBE_EXPRESSION_LIST : EXPRESSION_LIST
3108 MAYBE_EXPRESSION_LIST : EXPRESSION_LIST_AND_COMMA
3109
3110 EXPRESSION_LIST : NONCOMMAEXPRESSION             {$$.number=1;
3111                                                   $$.cc = $1.c;
3112                                                  }
3113
3114 EXPRESSION_LIST_AND_COMMA: EXPRESSION_LIST ',' {$$ = $1;}
3115 EXPRESSION_LIST : EXPRESSION_LIST_AND_COMMA NONCOMMAEXPRESSION {
3116                                                   $$.number= $1.number+1;
3117                                                   $$.cc = code_append($1.cc, $2.c);
3118                                                   }
3119                
3120 XX : %prec new2
3121 NEW : "new" E XX MAYBE_PARAM_VALUES {
3122     typedcode_t v = node_read($2);
3123     $$.c = v.c;
3124     if($$.c->opcode == OPCODE_COERCE_A) $$.c = code_cutlast($$.c);
3125     
3126     code_t*paramcode = $4.cc;
3127     if($$.c->opcode == OPCODE_GETPROPERTY) {
3128         multiname_t*name = $$.c->data[0];$$.c->data[0]=0;
3129         $$.c = code_cutlast($$.c);
3130         $$.c = code_append($$.c, paramcode);
3131         $$.c = abc_constructprop2($$.c, name, $4.number);
3132         multiname_destroy(name);
3133     } else if(is_getlocal($$.c)) {
3134         $$.c = code_append($$.c, paramcode);
3135         $$.c = abc_construct($$.c, $4.number);
3136     } else if(TYPE_IS_CLASS(v.t) && v.t->data) {
3137         code_free($$.c);
3138         classinfo_t*c = v.t->data;
3139         MULTINAME(m, c);
3140         $$.c = abc_findpropstrict2(0, &m);
3141         $$.c = code_append($$.c, paramcode);
3142         $$.c = abc_constructprop2($$.c, &m, $4.number);
3143     /*} else if($$.c->opcode == OPCODE_GETSLOT) {
3144         int slot = (int)(ptroff_t)$$.c->data[0];
3145         trait_t*t = traits_find_slotid(state->cls->abc->traits,slot);//FIXME
3146         multiname_t*name = t->name;
3147         $$.c = code_cutlast($$.c);
3148         $$.c = code_append($$.c, paramcode);
3149         $$.c = abc_constructprop2($$.c, name, $4.number);*/
3150     } else {
3151         $$.c = code_append($$.c, paramcode);
3152         $$.c = abc_construct($$.c, $4.number);
3153     }
3154    
3155     $$.t = TYPE_ANY;
3156     if(TYPE_IS_CLASS(v.t) && v.t->data) {
3157         $$.t = v.t->data;
3158     } else {
3159         $$.c = abc_coerce_a($$.c);
3160         $$.t = TYPE_ANY;
3161     }
3162 }
3163
3164 /* TODO: use abc_call (for calling local variables),
3165          abc_callstatic (for calling own methods) 
3166          call (for closures)
3167 */
3168 FUNCTIONCALL : E '(' MAYBE_EXPRESSION_LIST ')' {
3169    
3170     typedcode_t v = node_read($1);
3171     $$.c = v.c;
3172     if($$.c->opcode == OPCODE_COERCE_A) {
3173         $$.c = code_cutlast($$.c);
3174     }
3175     code_t*paramcode = $3.cc;
3176
3177     $$.t = TYPE_ANY;
3178     if($$.c->opcode == OPCODE_GETPROPERTY) {
3179         multiname_t*name = $$.c->data[0];$$.c->data[0]=0;
3180         $$.c = code_cutlast($$.c);
3181         $$.c = code_append($$.c, paramcode);
3182         $$.c = abc_callproperty2($$.c, name, $3.number);
3183         multiname_destroy(name);
3184 /*    } else if($$.c->opcode == OPCODE_GETSLOT && $$.c->prev->opcode != OPCODE_GETSCOPEOBJECT) {
3185         int slot = (int)(ptroff_t)$$.c->data[0];
3186         trait_t*t = traits_find_slotid(state->cls->abc->traits,slot);
3187         if(t->kind!=TRAIT_METHOD) {
3188             //ok: flash allows to assign closures to members.
3189         }
3190         multiname_t*name = t->name;
3191         $$.c = code_cutlast($$.c);
3192         $$.c = code_append($$.c, paramcode);
3193         //$$.c = abc_callmethod($$.c, t->method, len); //#1051 illegal early access binding
3194         $$.c = abc_callproperty2($$.c, name, $3.number);*/
3195     } else if($$.c->opcode == OPCODE_GETSUPER) {
3196         multiname_t*name = $$.c->data[0];$$.c->data[0]=0;
3197         $$.c = code_cutlast($$.c);
3198         $$.c = code_append($$.c, paramcode);
3199         $$.c = abc_callsuper2($$.c, name, $3.number);
3200         multiname_destroy(name);
3201     } else {
3202         $$.c = abc_getglobalscope($$.c);
3203         $$.c = code_append($$.c, paramcode);
3204         $$.c = abc_call($$.c, $3.number);
3205     }
3206    
3207     if(TYPE_IS_FUNCTION(v.t) && v.t->data) {
3208         $$.t = ((methodinfo_t*)(v.t->data))->return_type;
3209     } else if(TYPE_IS_CLASS(v.t) && v.t->data) {
3210         // calling a class is like a typecast
3211         $$.t = (classinfo_t*)v.t->data;
3212     } else {
3213         $$.t = TYPE_ANY;
3214         $$.c = abc_coerce_a($$.c);
3215     }
3216 }
3217
3218 FUNCTIONCALL : "super" '(' MAYBE_EXPRESSION_LIST ')' {
3219     if(!state->cls) syntaxerror("super() not allowed outside of a class");
3220     if(!state->method) syntaxerror("super() not allowed outside of a function");
3221     if(!state->method->is_constructor) syntaxerror("super() not allowed outside of a constructor");
3222
3223     $$.c = code_new();
3224     $$.c = abc_getlocal_0($$.c);
3225
3226     $$.c = code_append($$.c, $3.cc);
3227     /*
3228     this is dependent on the control path, check this somewhere else
3229     if(state->method->has_super)
3230         syntaxerror("constructor may call super() only once");
3231     */
3232     state->method->has_super = 1;
3233
3234     $$.c = abc_constructsuper($$.c, $3.number);
3235     $$.c = abc_pushundefined($$.c);
3236     $$.t = TYPE_ANY;
3237 }
3238
3239 DELETE: "delete" E {
3240     typedcode_t v = node_read($2);
3241     $$.c = v.c;
3242     if($$.c->opcode == OPCODE_COERCE_A) {
3243         $$.c = code_cutlast($$.c);
3244     }
3245     multiname_t*name = 0;
3246     if($$.c->opcode == OPCODE_GETPROPERTY) {
3247         $$.c->opcode = OPCODE_DELETEPROPERTY;
3248     } else if($$.c->opcode == OPCODE_GETSLOT) {
3249         int slot = (int)(ptroff_t)$$.c->data[0];
3250         multiname_t*name = traits_find_slotid(state->cls->abc->traits,slot)->name;
3251         $$.c = code_cutlast($$.c);
3252         $$.c = abc_deleteproperty2($$.c, name);
3253     } else {
3254         $$.c = abc_getlocal_0($$.c);
3255         MULTINAME_LATE(m, v.t?v.t->access:ACCESS_PACKAGE, "");
3256         $$.c = abc_deleteproperty2($$.c, &m);
3257     }
3258     $$.t = TYPE_BOOLEAN;
3259 }
3260
3261 RETURN: "return" %prec prec_none {
3262     $$ = abc_returnvoid(0);
3263 }
3264 RETURN: "return" EXPRESSION {
3265     $$ = $2.c;
3266     $$ = abc_returnvalue($$);
3267 }
3268
3269 // ----------------------- expression types -------------------------------------
3270
3271 NONCOMMAEXPRESSION : E %prec below_lt {
3272     $$ = node_read($1);
3273 }
3274 EXPRESSION : COMMA_EXPRESSION {
3275     $$ = node_read($1);
3276 }
3277 COMMA_EXPRESSION : E %prec below_lt {
3278     $$ = mkmultinode(&node_comma, $1);
3279 }
3280 COMMA_EXPRESSION : COMMA_EXPRESSION ',' E %prec below_lt {
3281     $$ = multinode_extend($1, $3);
3282 }
3283 VOIDEXPRESSION : E %prec below_minus { 
3284     $$ = node_exec($1); 
3285 }
3286 VOIDEXPRESSION : VOIDEXPRESSION ',' E %prec below_lt { 
3287     $$ = $1;
3288     $$ = code_append($$, node_exec($3)); 
3289 }
3290
3291 MAYBE_DICT_EXPRPAIR_LIST : {$$.cc=0;$$.number=0;}
3292 MAYBE_DICT_EXPRPAIR_LIST : DICT_EXPRPAIR_LIST {$$=$1;}
3293
3294 DICTLH: T_IDENTIFIER {$$=abc_pushstring(0,$1);}
3295 DICTLH: T_STRING     {$$=abc_pushstring2(0,&$1);}
3296 DICTLH: T_INT {syntaxerror("dictionary keys must be strings");}
3297 DICTLH: T_UINT {syntaxerror("dictionary keys must be strings");}
3298 DICTLH: T_FLOAT {syntaxerror("dictionary keys must be strings");}
3299
3300 DICT_EXPRPAIR_LIST : DICTLH ':' NONCOMMAEXPRESSION {
3301     $$.cc = 0;
3302     $$.cc = code_append($$.cc, $1);
3303     $$.cc = code_append($$.cc, $3.c);
3304     $$.number = 2;
3305 }
3306 DICT_EXPRPAIR_LIST : DICT_EXPRPAIR_LIST ',' DICTLH ':' NONCOMMAEXPRESSION {
3307     $$.cc = $1.cc;
3308     $$.number = $1.number+2;
3309     $$.cc = code_append($$.cc, $3);
3310     $$.cc = code_append($$.cc, $5.c);
3311 }
3312
3313 // ----------------------- expression evaluation -------------------------------------
3314
3315 E : INNERFUNCTION %prec prec_none {$$ = mkcodenode($1);}
3316 E : MEMBER %prec '.'              {$$ = mkcodenode($1);}
3317 E : NEW                           {$$ = mkcodenode($1);}
3318 E : DELETE                        {$$ = mkcodenode($1);}
3319 E : FUNCTIONCALL                  {$$ = mkcodenode($1);}
3320 E : VAR_READ %prec T_IDENTIFIER   {$$ = $1;}
3321
3322 E : CONSTANT { 
3323     $$ = mkconstnode($1);
3324 }
3325
3326 E : XML {
3327     $$ = $1;
3328 }
3329
3330 /* regexp */
3331 E : T_REGEXP {
3332     typedcode_t v;
3333     v.c = 0;
3334     multiname_t m = {QNAME, &stdns, 0, "RegExp"};
3335     if(!$1.options) {
3336         v.c = abc_getlex2(v.c, &m);
3337         v.c = abc_pushstring(v.c, $1.pattern);
3338         v.c = abc_construct(v.c, 1);
3339     } else {
3340         v.c = abc_getlex2(v.c, &m);
3341         v.c = abc_pushstring(v.c, $1.pattern);
3342         v.c = abc_pushstring(v.c, $1.options);
3343         v.c = abc_construct(v.c, 2);
3344     }
3345     v.t = TYPE_REGEXP;
3346     $$ = mkcodenode(v);
3347 }
3348
3349 E : KW_ARGUMENTS {
3350     PASS1
3351     state->method->need_arguments = 1;
3352     PASS2
3353     typedcode_t v;
3354     v.c = abc_getlocal(0, state->method->need_arguments);
3355     v.t = TYPE_ARRAY;
3356     $$ = mkcodenode(v);
3357 }
3358
3359 /* array */
3360 E : '[' MAYBE_EXPRESSION_LIST ']' {
3361     typedcode_t v;
3362     v.c = code_new();
3363     v.c = code_append(v.c, $2.cc);
3364     v.c = abc_newarray(v.c, $2.number);
3365     v.t = registry_getarrayclass();
3366     $$ = mkcodenode(v);
3367 }
3368
3369 /* dictionary */
3370 E : "{ (dictionary)" MAYBE_DICT_EXPRPAIR_LIST '}' {
3371     typedcode_t v;
3372     v.c = code_new();
3373     v.c = code_append(v.c, $2.cc);
3374     v.c = abc_newobject(v.c, $2.number/2);
3375     v.t = registry_getobjectclass();
3376     $$ =  mkcodenode(v);
3377 }
3378
3379 E : E '<' E {$$ = mknode2(&node_lt,$1,$3);}
3380 E : E '>' E {$$ = mknode2(&node_gt,$1,$3);}
3381 E : E "<=" E {$$ = mknode2(&node_le,$1,$3);}
3382 E : E ">=" E {$$ = mknode2(&node_ge,$1,$3);}
3383 E : E "==" E {$$ = mknode2(&node_eqeq,$1,$3);}
3384 E : E "===" E {$$ = mknode2(&node_eqeqeq,$1,$3);}
3385 E : E "!==" E {$$ = mknode2(&node_noteqeq,$1,$3);}
3386 E : E "!=" E {$$ = mknode2(&node_noteq,$1,$3);}
3387 E : E "||" E {$$ = mknode2(&node_oror,$1,$3);}
3388 E : E "&&" E {$$ = mknode2(&node_andand,$1,$3);}
3389 E : '!' E    {$$ = mknode1(&node_not, $2);}
3390 E : '~' E    {$$ = mknode1(&node_bitnot, $2);}
3391 E : E '&' E {$$ = mknode2(&node_bitand, $1, $3);}
3392 E : E '^' E {$$ = mknode2(&node_bitxor, $1, $3);}
3393 E : E '|' E {$$ = mknode2(&node_bitor, $1, $3);}
3394 E : E ">>" E {$$ = mknode2(&node_shr, $1, $3);}
3395 E : E ">>>" E {$$ = mknode2(&node_ushr, $1, $3);}
3396 E : E "<<" E {$$ = mknode2(&node_shl, $1, $3);}
3397 E : E '/' E {$$ = mknode2(&node_div, $1, $3);}
3398 E : E '%' E {$$ = mknode2(&node_mod, $1, $3);}
3399 E : E '+' E {$$ = mknode2(&node_plus, $1, $3);}
3400 E : E '-' E {$$ = mknode2(&node_minus, $1, $3);}
3401 E : E '*' E {$$ = mknode2(&node_multiply, $1, $3);}
3402 E : E "in" E {$$ = mknode2(&node_in, $1, $3);}
3403 E : E "as" E {$$ = mknode2(&node_as, $1, $3);}
3404 E : E "instanceof" E {$$ = mknode2(&node_instanceof, $1, $3);}
3405 E : E "is" E {$$ = mknode2(&node_is, $1, $3);}
3406 E : "typeof" E  {$$ = mknode1(&node_typeof, $2);}
3407 E : "void" E {$$ = mknode1(&node_void, $2);}
3408 E : "void" { $$ = mkconstnode(constant_new_undefined());}
3409 E : '(' COMMA_EXPRESSION ')' { $$=$2;}
3410 E : '-' E {$$ = mknode1(&node_neg, $2);}
3411 E : E '[' E ']' {$$ = mknode2(&node_arraylookup, $1,$3);}
3412 E : E "*=" E {$$ = mknode2(&node_muleq, $1, $3);}
3413 E : E "%=" E {$$ = mknode2(&node_modeq, $1, $3);}
3414 E : E "<<=" E {$$ = mknode2(&node_shleq, $1, $3);}
3415 E : E ">>=" E {$$ = mknode2(&node_shreq, $1, $3);}
3416 E : E ">>>=" E {$$ = mknode2(&node_ushreq, $1, $3);}
3417 E : E "/=" E { $$ = mknode2(&node_diveq, $1, $3);}
3418 E : E "|=" E { $$ = mknode2(&node_bitoreq, $1, $3);}
3419 E : E "^=" E { $$ = mknode2(&node_bitxoreq, $1, $3);}
3420 E : E "&=" E { $$ = mknode2(&node_bitandeq, $1, $3);}
3421 E : E "+=" E { $$ = mknode2(&node_pluseq, $1, $3);}
3422 E : E "-=" E { $$ = mknode2(&node_minuseq, $1, $3);}
3423 E : E '=' E { $$ = mknode2(&node_assign, $1, $3);}
3424 E : E '?' E ':' E %prec below_assignment { $$ = mknode3(&node_tenary, $1, $3, $5);}
3425
3426 E : E "++" { $$ = mknode1(&node_rplusplus, $1);}
3427 E : E "--" { $$ = mknode1(&node_rminusminus, $1);}
3428 E : "++" %prec plusplus_prefix E {$$ = mknode1(&node_lplusplus, $2); }
3429 E : "--" %prec minusminus_prefix E {$$ = mknode1(&node_lminusminus, $2); }
3430
3431 E : "super" '.' T_IDENTIFIER 
3432            { if(!state->cls->info)
3433                   syntaxerror("super keyword not allowed outside a class");
3434               classinfo_t*t = state->cls->info->superclass;
3435               if(!t) t = TYPE_OBJECT;
3436               memberinfo_t*f = findmember_nsset(t, $3, 1, 0);
3437               MEMBER_MULTINAME(m, f, $3);
3438               typedcode_t v;
3439               v.c = 0;
3440               v.c = abc_getlocal_0(v.c);
3441               v.c = abc_getsuper2(v.c, &m);
3442               v.t = slotinfo_gettype((slotinfo_t*)f);
3443               $$ = mkcodenode(v);
3444            }
3445
3446 E : '@' T_IDENTIFIER {
3447     typedcode_t v;
3448     multiname_t m = {MULTINAMEA, 0, &nopackage_namespace_set, $2};
3449     v.c = abc_getlex2(0, &m);
3450     v.t = TYPE_STRING;
3451     $$ = mkcodenode(v);
3452 }
3453
3454 E : E '.' '(' {PASS12 new_state();state->xmlfilter=1;} E ')' {
3455     PASS1 old_state();
3456     PASS2
3457     typedcode_t v = node_read($1);
3458     typedcode_t w = node_read($5);
3459     code_t*c = 0;
3460     int index = alloc_local();
3461     int result = alloc_local();
3462     int tmp = alloc_local();
3463     int xml = alloc_local();
3464     
3465     c = code_append(c, v.c);
3466     c = abc_checkfilter(c);
3467     c = abc_coerce_a(c); //hasnext2 converts to *
3468     c = abc_setlocal(c, xml);
3469     multiname_t m = {QNAME, &stdns, 0, "XMLList"};
3470     c = abc_getlex2(c, &m);
3471     c = abc_construct(c, 0);
3472     c = abc_setlocal(c, result);
3473     c = abc_pushbyte(c, 0);
3474     c = abc_setlocal(c, index);
3475     code_t*jmp = c = abc_jump(c, 0);
3476     code_t*loop = c = abc_label(c);
3477     c = abc_getlocal(c, xml);
3478     c = abc_getlocal(c, index);
3479     c = abc_nextvalue(c);
3480     c = abc_dup(c);
3481     c = abc_setlocal(c, tmp);
3482     c = abc_pushwith(c);
3483     c = code_append(c, w.c);
3484     c = abc_popscope(c);
3485     code_t*b = c = abc_iffalse(c, 0);
3486     c = abc_getlocal(c, result);
3487     c = abc_getlocal(c, index);
3488     c = abc_getlocal(c, tmp);
3489     multiname_t m2 = {MULTINAMEL, 0, &nopackage_namespace_set, 0};
3490     c = abc_setproperty2(c, &m2);
3491     c = b->branch = jmp->branch = abc_nop(c);
3492     c = abc_kill(c, tmp);
3493     c = abc_hasnext2(c, xml, index);
3494     c = abc_iftrue(c, loop);
3495     c = abc_getlocal(c, result);
3496     c = abc_kill(c, xml);
3497     c = abc_kill(c, result);
3498     c = abc_kill(c, index);
3499     
3500     c = var_block(c, state->vars);
3501     old_state();
3502     typedcode_t r;
3503     r.c = c;
3504     r.t = TYPE_XMLLIST;
3505     $$ = mkcodenode(r);
3506 }
3507
3508 ID_OR_NS : T_IDENTIFIER {$$=$1;}
3509 ID_OR_NS : '*' {$$="*";}
3510 ID_OR_NS : T_NAMESPACE {$$=(char*)$1;}
3511 SUBNODE: X_IDENTIFIER
3512        | '*' {$$="*";}
3513
3514 %code {
3515     node_t* resolve_identifier(const char*name);
3516     node_t* get_descendants(node_t*e,const char*ns,const char*subnode,char multi, char attr)
3517     {
3518         typedcode_t v = node_read(e);
3519         typedcode_t w;
3520
3521         multiname_t m = {0,0,0,subnode};
3522         namespace_t zero = {ZERONAMESPACE,"*"};
3523         if(!strcmp(ns,"*")) {
3524             m.ns = &zero;
3525             m.type = attr?QNAMEA:QNAME;
3526         } else {
3527             typedcode_t w = node_read(resolve_identifier(ns));
3528             if(!TYPE_IS_NAMESPACE(w.t)) {
3529                 as3_softwarning("%s might not be a namespace", ns);
3530             }
3531             v.c = code_append(v.c, w.c);
3532             v.c = converttype(v.c, w.t, TYPE_NAMESPACE);
3533             m.type = attr?RTQNAMEA:RTQNAME;
3534         }
3535
3536         if(!multi) {
3537             v.c = abc_getproperty2(v.c, &m);
3538         } else {
3539             v.c = abc_getdescendants2(v.c, &m);
3540         }
3541
3542         if(TYPE_IS_XML(v.t)) {
3543             v.t = TYPE_XMLLIST;
3544         } else {
3545             v.c = abc_coerce_a(v.c);
3546             v.t = TYPE_ANY;
3547         }
3548         return mkcodenode(v);
3549     }
3550 };
3551
3552 E : E '.' ID_OR_NS "::" SUBNODE {
3553     $$ = get_descendants($1, $3, $5, 0, 0);
3554 }
3555 E : E ".." SUBNODE {
3556     typedcode_t v = node_read($1);
3557     multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $3};
3558     v.c = abc_getdescendants2(v.c, &m);
3559     v.t = TYPE_XMLLIST;
3560     $$ = mkcodenode(v);
3561 }
3562 E : E ".." ID_OR_NS "::" SUBNODE {
3563     $$ = get_descendants($1, $3, $5, 1, 0);
3564 }
3565 E : E '.' '[' E ']' {
3566     typedcode_t v = node_read($1);
3567     typedcode_t w = node_read($4);
3568     multiname_t m = {MULTINAMEL, 0, &nopackage_namespace_set, 0};
3569     v.c = code_append(v.c, w.c);
3570     v.c = converttype(w.c, w.t, TYPE_STRING);
3571     v.c = abc_getproperty2(v.c, &m);
3572     v.t = TYPE_XMLLIST;
3573     $$ = mkcodenode(v);
3574 }
3575
3576 E : E '.' '@' SUBNODE {
3577     typedcode_t v = node_read($1);
3578     multiname_t m = {MULTINAMEA, 0, &nopackage_namespace_set, $4};
3579     v.c = abc_getproperty2(v.c, &m);
3580     v.t = TYPE_STRING;
3581     $$ = mkcodenode(v);
3582 }
3583
3584 E : E '.' '@' ID_OR_NS "::" SUBNODE {
3585     $$ = get_descendants($1, $4, $6, 0, 1);
3586 }
3587
3588 E : E ".." '@' SUBNODE {
3589     typedcode_t v = node_read($1);
3590     multiname_t m = {MULTINAMEA, 0, &nopackage_namespace_set, $4};
3591     v.c = abc_getdescendants2(v.c, &m);
3592     v.t = TYPE_STRING;
3593     $$ = mkcodenode(v);
3594 }
3595 E : E ".." '@' ID_OR_NS "::" SUBNODE {
3596     $$ = get_descendants($1, $4, $6, 1, 1);
3597 }
3598
3599 E : E '.' '@' '[' E ']' {
3600     typedcode_t v = node_read($1);
3601     typedcode_t w = node_read($5);
3602     multiname_t m = {MULTINAMELA, 0, &nopackage_namespace_set, 0};
3603     v.c = code_append(v.c, w.c);
3604     v.c = converttype(w.c, w.t, TYPE_STRING);
3605     v.c = abc_getproperty2(v.c, &m);
3606     v.t = TYPE_STRING;
3607     $$ = mkcodenode(v);
3608 }
3609 E : E ".." '@' '[' E ']' {
3610     typedcode_t v = node_read($1);
3611     typedcode_t w = node_read($5);
3612     multiname_t m = {MULTINAMELA, 0, &nopackage_namespace_set, 0};
3613     v.c = code_append(v.c, w.c);
3614     v.c = converttype(w.c, w.t, TYPE_STRING);
3615     v.c = abc_getdescendants2(v.c, &m);
3616     v.t = TYPE_STRING;
3617     $$ = mkcodenode(v);
3618 }
3619
3620 MEMBER : E '.' SUBNODE {
3621     typedcode_t v1 = node_read($1);
3622     $$.c = v1.c;
3623     classinfo_t*t = v1.t;
3624     char is_static = 0;
3625     if(TYPE_IS_CLASS(t) && t->data) {
3626         t = t->data;
3627         is_static = 1;
3628     }
3629     if(TYPE_IS_XML(t) && !findmember_nsset(t, $3, 1, is_static)) {
3630         multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $3};
3631         $$.c = abc_getproperty2($$.c, &m);
3632         $$.c = abc_coerce_a($$.c);
3633         $$.t = TYPE_XMLLIST;
3634     } else if(t) {
3635         if(t->subtype==INFOTYPE_UNRESOLVED) {
3636             syntaxerror("syntaxerror: trying to resolve property '%s' on incomplete object '%s'", $3, t->name);
3637         }
3638         memberinfo_t*f = findmember_nsset(t, $3, 1, is_static);
3639         char noslot = 0;
3640         if(f && !is_static != !(f->flags&FLAG_STATIC))
3641            noslot=1;
3642         if(f && f->slot && !noslot) {
3643             $$.c = abc_getslot($$.c, f->slot);
3644         } else {
3645             if(!f) {
3646                 if(!TYPE_IS_XMLLIST(t)) {
3647                     as3_softwarning("Access of undefined property '%s' in %s", $3, t->name);
3648                 }
3649             }
3650             MEMBER_MULTINAME(m, f, $3);
3651             $$.c = abc_getproperty2($$.c, &m);
3652         }
3653         /* determine type */
3654         $$.t = slotinfo_gettype((slotinfo_t*)f);
3655         if(!$$.t)
3656            $$.c = abc_coerce_a($$.c);
3657         
3658     } else if(v1.c && v1.c->opcode == OPCODE___PUSHPACKAGE__) {
3659         string_t*package = v1.c->data[0];
3660         char*package2 = concat3(package->str, ".", $3);
3661
3662         slotinfo_t*a = registry_find(package->str, $3);
3663         if(a) {
3664             $$ = push_class(a);
3665         } else if(dict_contains(state->import_toplevel_packages, package2) ||
3666                   registry_ispackage(package2)) {
3667             $$.c = v1.c;
3668             $$.c->data[0] = string_new4(package2);
3669             $$.t = 0;
3670         } else {
3671             syntaxerror("couldn't resolve %s", package2);
3672         }
3673     } else {
3674         /* when resolving a property on an unknown type, we do know the
3675            name of the property (and don't seem to need the package), but
3676            we need to make avm2 try out all access modes */
3677         as3_softwarning("Resolving %s on unknown type", $3);
3678         multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $3};
3679         $$.c = abc_getproperty2($$.c, &m);
3680         $$.c = abc_coerce_a($$.c);
3681         $$.t = TYPE_ANY;
3682     }
3683 }
3684
3685 %code {
3686     node_t* var_read(variable_t*v)
3687     {
3688         typedcode_t o;
3689         o.c = abc_getlocal(0, v->index);
3690         o.t = v->type;
3691         return mkcodenode(o);
3692     }
3693
3694     node_t* resolve_identifier(const char*name)
3695     {
3696         typedcode_t o;
3697         o.t = 0;
3698         o.c = 0;
3699
3700         slotinfo_t*a = 0;
3701         memberinfo_t*f = 0;
3702
3703         variable_t*v;
3704         /* look at variables */
3705         if((v = find_variable(state, name))) {
3706             // name is a local variable
3707             return var_read(v);
3708         }
3709         if((v = find_slot(state->method, name))) {
3710             o.c = abc_getscopeobject(o.c, 1);
3711             o.c = abc_getslot(o.c, v->index);
3712             o.t = v->type;
3713             return mkcodenode(o);
3714         }
3715
3716         int i_am_static = state->method->is_static;
3717
3718         if(!state->method->inner && !state->xmlfilter && state->cls)
3719         {
3720             /* look at current class' members */
3721             if((f = findmember_nsset(state->cls->info, name, 1, i_am_static)))
3722             {
3723                 // name is a member or attribute in this class
3724                 int var_is_static = (f->flags&FLAG_STATIC);
3725
3726                 if(f->kind == INFOTYPE_VAR && (f->flags&FLAG_CONST)) {
3727                     /* if the variable is a constant (and we know what is evaluates to), we
3728                        can just use the value itself */
3729                     varinfo_t*v = (varinfo_t*)f;
3730                     if(v->value) {
3731                         return mkconstnode(v->value);
3732                     }
3733                 }
3734                
3735                 if(var_is_static >= i_am_static) {
3736                     if(f->kind == INFOTYPE_METHOD) {
3737                         o.t = TYPE_FUNCTION(f);
3738                     } else {
3739                         o.t = f->type;
3740                     }
3741
3742                     if(var_is_static && !i_am_static) {
3743                     /* access to a static member from a non-static location.
3744                        do this via findpropstrict:
3745                        there doesn't seem to be any non-lookup way to access
3746                        static properties of a class */
3747                         state->method->late_binding = 1;
3748                         o.t = f->type;
3749                         namespace_t ns = {f->access, f->package};
3750                         multiname_t m = {QNAME, &ns, 0, name};
3751                         o.c = abc_findpropstrict2(o.c, &m);
3752                         o.c = abc_getproperty2(o.c, &m);
3753                         return mkcodenode(o);
3754                     } else if(f->slot>0) {
3755                         o.c = abc_getlocal_0(o.c);
3756                         o.c = abc_getslot(o.c, f->slot);
3757                         return mkcodenode(o);
3758                     } else {
3759                         MEMBER_MULTINAME(m, f, name);
3760                         o.c = abc_getlocal_0(o.c);
3761                         o.c = abc_getproperty2(o.c, &m);
3762                         return mkcodenode(o);
3763                     }
3764                 }
3765             } 
3766             /* special case: it's allowed to access non-static constants
3767                from a static context */
3768             if(i_am_static && (f=findmember_nsset(state->cls->info, name, 1, 0))) {
3769                 if(f->kind == INFOTYPE_VAR && (f->flags&FLAG_CONST)) {
3770                     varinfo_t*v = (varinfo_t*)f;
3771                     if(v->value) {
3772                         return mkconstnode(v->value);
3773                     }
3774                 }
3775             }
3776         }
3777         
3778         /* look at actual classes, in the current package and imported */
3779         if(!state->xmlfilter && (a = find_class(name))) {
3780             if(state->cls && state->cls->info == (classinfo_t*)a && i_am_static) {
3781                 o.c = abc_getlocal_0(0);
3782                 o.t = TYPE_CLASS((classinfo_t*)a);
3783             } else {
3784                 o = push_class(a);
3785             }
3786             return mkcodenode(o);
3787         }
3788
3789         /* look through package prefixes */
3790         if(!state->xmlfilter && 
3791            (dict_contains(state->import_toplevel_packages, name) || 
3792             registry_ispackage(name))) {
3793             o.c = abc___pushpackage__(o.c, (char*)name);
3794             o.t = 0;
3795             return mkcodenode(o); //?
3796         }
3797
3798         /* unknown object, let the avm2 resolve it */
3799         if(1) {
3800             if(!state->method->inner && !state->xmlfilter) {
3801                 /* we really should make inner functions aware of the class context */
3802                 as3_warning("Couldn't resolve '%s', doing late binding", name);
3803             }
3804             state->method->late_binding = 1;
3805                     
3806             multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, name};
3807
3808             o.t = 0;
3809             o.c = abc_findpropstrict2(o.c, &m);
3810             o.c = abc_getproperty2(o.c, &m);
3811             return mkcodenode(o);
3812         }
3813     }
3814 };
3815
3816 /* TODO: causes 16 r/r conflicts */
3817 VAR_READ : T_NAMESPACE {
3818     PASS2 
3819     $$ = resolve_identifier($1);
3820 }
3821
3822 VAR_READ : T_IDENTIFIER {
3823     PASS1
3824     /* Queue unresolved identifiers for checking against the parent
3825        function's variables.
3826        We consider everything which is not a local variable "unresolved".
3827        This encompasses class names, members of the surrounding class
3828        etc. which is *correct* because local variables of the parent function
3829        would shadow those.
3830        */
3831
3832     if(!find_variable(state, $1)) {
3833         unknown_variable($1);
3834         /* let the compiler know that it might want to check the current directory/package
3835            for this identifier- maybe there's a file $1.as defining $1. */
3836         as3_schedule_class_noerror(state->package, $1);
3837     }
3838    
3839     $$ = 0;
3840     PASS2
3841
3842     $$ = resolve_identifier($1);
3843 }
3844
3845 // ----------------- namespaces -------------------------------------------------
3846
3847 %code {
3848     void add_active_url(const char*url)
3849     {
3850         NEW(namespace_t,n);
3851         n->name = url;
3852         list_append(state->active_namespace_urls, n);
3853     }
3854 };
3855
3856 NAMESPACE_ID : "namespace" T_IDENTIFIER {
3857     PASS12
3858     NEW(namespace_decl_t,n);
3859     n->name = $2;
3860     n->url = $2;
3861     $$=n;
3862 }
3863 NAMESPACE_ID : "namespace" T_IDENTIFIER '=' T_IDENTIFIER {
3864     PASS12
3865     NEW(namespace_decl_t,n);
3866     n->name = $2;
3867     n->url = $4;
3868     $$=n;
3869 }
3870 NAMESPACE_ID : "namespace" T_IDENTIFIER '=' T_STRING {
3871     PASS12
3872     NEW(namespace_decl_t,n);
3873     n->name = $2;
3874     n->url = $4.str;
3875     $$=n;
3876 }
3877 NAMESPACE_DECLARATION : MAYBE_MODIFIERS NAMESPACE_ID {
3878     PASS12
3879     trie_put(active_namespaces, (unsigned char*)$2->name, (void*)$2->url);
3880
3881     namespace_t access = modifiers2access(&$1);
3882     varinfo_t* var = varinfo_register_global(access.access, state->package, $2->name);
3883     var->type = TYPE_NAMESPACE;
3884     namespace_t ns;
3885     ns.access = ACCESS_NAMESPACE;
3886     ns.name = $2->url;
3887     var->value = constant_new_namespace(&ns);
3888       
3889     if(as3_pass==2) {
3890         MULTINAME(m, TYPE_NAMESPACE);
3891         trait_t*t = add_abc_slot(&$1, $2->name, 0, 0);
3892         t->value = var->value;
3893         t->type_name = multiname_clone(&m);
3894     }
3895
3896     $$=0;
3897 }
3898
3899 DEFAULT_NAMESPACE : "default xml" "namespace" '=' E 
3900 {
3901     $$ = 0;
3902     $$ = code_append($$, node_read($4).c);
3903     $$ = abc_dxnslate($$);
3904 }
3905
3906 USE_NAMESPACE : "use" "namespace" CLASS_SPEC {
3907     PASS12
3908     const char*url = $3->name;
3909
3910     varinfo_t*s = (varinfo_t*)$3;
3911     if(s->kind == INFOTYPE_UNRESOLVED) {
3912         s = (varinfo_t*)registry_resolve((slotinfo_t*)s);
3913         if(!s)
3914             syntaxerror("Couldn't resolve namespace %s", $3->name);
3915     }
3916
3917     if(!s || s->kind != INFOTYPE_VAR)
3918         syntaxerror("%s.%s is not a public namespace (%d)", $3->package, $3->name, s?s->kind:-1);
3919     if(!s->value || !NS_TYPE(s->value->type))
3920         syntaxerror("%s.%s is not a namespace", $3->package, $3->name);
3921     url = s->value->ns->name;
3922
3923     trie_put(active_namespaces, (unsigned char*)$3->name, (void*)url);
3924     add_active_url(url);
3925     $$=0;
3926 }
3927