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