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