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