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