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