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