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