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