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