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