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