implemented overriding
[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
35 %}
36
37 //%glr-parser
38 //%expect-rr 1
39 %error-verbose
40
41 %union tokenunion {
42     enum yytokentype token;
43     int flags;
44
45     classinfo_t*classinfo;
46     classinfo_list_t*classinfo_list;
47
48     int number_int;
49     unsigned int number_uint;
50     double number_float;
51     code_t*code;
52     typedcode_t value;
53     typedcode_list_t*value_list;
54     param_t* param;
55     params_t params;
56     string_t str;
57     char*id;
58     constant_t*constant;
59 }
60
61
62 %token<id> T_IDENTIFIER
63 %token<str> T_STRING
64 %token<token> T_REGEXP
65 %token<token> T_EMPTY
66 %token<number_int> T_INT
67 %token<number_uint> T_UINT
68 %token<number_uint> T_BYTE
69 %token<number_uint> T_SHORT
70 %token<number_float> T_FLOAT
71
72 %token<id> T_FOR "for"
73 %token<id> T_WHILE "while"
74 %token<id> T_DO "do"
75 %token<id> T_SWITCH "switch"
76
77 %token<token> KW_IMPLEMENTS
78 %token<token> KW_NAMESPACE "namespace"
79 %token<token> KW_PACKAGE "package"
80 %token<token> KW_PROTECTED
81 %token<token> KW_PUBLIC
82 %token<token> KW_PRIVATE
83 %token<token> KW_USE "use"
84 %token<token> KW_INTERNAL
85 %token<token> KW_NEW "new"
86 %token<token> KW_NATIVE
87 %token<token> KW_FUNCTION "function"
88 %token<token> KW_UNDEFINED "undefined"
89 %token<token> KW_CONTINUE "continue"
90 %token<token> KW_CLASS "class"
91 %token<token> KW_CONST "const"
92 %token<token> KW_CATCH "catch"
93 %token<token> KW_CASE "case"
94 %token<token> KW_SET "set"
95 %token<token> KW_VOID "void"
96 %token<token> KW_STATIC
97 %token<token> KW_INSTANCEOF "instanceof"
98 %token<token> KW_IMPORT "import"
99 %token<token> KW_RETURN "return"
100 %token<token> KW_TYPEOF "typeof"
101 %token<token> KW_INTERFACE "interface"
102 %token<token> KW_NULL "null"
103 %token<token> KW_VAR "var"
104 %token<token> KW_DYNAMIC "dynamic"
105 %token<token> KW_OVERRIDE
106 %token<token> KW_FINAL
107 %token<token> KW_GET "get"
108 %token<token> KW_TRY "try"
109 %token<token> KW_SUPER "super"
110 %token<token> KW_EXTENDS
111 %token<token> KW_FALSE "false"
112 %token<token> KW_TRUE "true"
113 %token<token> KW_BOOLEAN "Boolean"
114 %token<token> KW_UINT "uint"
115 %token<token> KW_INT "int"
116 %token<token> KW_NUMBER "Number"
117 %token<token> KW_STRING "String"
118 %token<token> KW_DEFAULT "default"
119 %token<token> KW_DELETE "delete"
120 %token<token> KW_IF "if"
121 %token<token> KW_ELSE  "else"
122 %token<token> KW_BREAK   "break"
123 %token<token> KW_IS "is"
124 %token<token> KW_AS "as"
125
126 %token<token> T_EQEQ "=="
127 %token<token> T_EQEQEQ "==="
128 %token<token> T_NE "!="
129 %token<token> T_NEE "!=="
130 %token<token> T_LE "<="
131 %token<token> T_GE ">="
132 %token<token> T_DIVBY "/=" 
133 %token<token> T_MODBY "%="
134 %token<token> T_MULBY "*="
135 %token<token> T_PLUSBY "+=" 
136 %token<token> T_MINUSBY "-="
137 %token<token> T_SHRBY ">>="
138 %token<token> T_SHLBY "<<="
139 %token<token> T_USHRBY ">>>="
140 %token<token> T_OROR "||"
141 %token<token> T_ANDAND "&&"
142 %token<token> T_COLONCOLON "::"
143 %token<token> T_MINUSMINUS "--"
144 %token<token> T_PLUSPLUS "++"
145 %token<token> T_DOTDOT ".."
146 %token<token> T_DOTDOTDOT "..."
147 %token<token> T_SHL "<<"
148 %token<token> T_USHR ">>>"
149 %token<token> T_SHR ">>"
150
151 %type <id> X_IDENTIFIER PACKAGE
152 %type <token> VARCONST
153 %type <code> CODE
154 %type <code> CODEPIECE
155 %type <code> CODEBLOCK MAYBECODE MAYBE_CASE_LIST CASE_LIST DEFAULT CASE SWITCH
156 %type <token> PACKAGE_DECLARATION
157 %type <token> FUNCTION_DECLARATION
158 %type <code> VARIABLE_DECLARATION ONE_VARIABLE VARIABLE_LIST
159 %type <token> CLASS_DECLARATION
160 %type <token> NAMESPACE_DECLARATION
161 %type <token> INTERFACE_DECLARATION
162 %type <code> VOIDEXPRESSION
163 %type <value> EXPRESSION NONCOMMAEXPRESSION
164 %type <value> MAYBEEXPRESSION
165 %type <value> E DELETE
166 %type <value> CONSTANT
167 %type <code> FOR IF WHILE DO_WHILE MAYBEELSE BREAK RETURN CONTINUE
168 %type <token> USE_NAMESPACE
169 %type <code> FOR_INIT
170 %type <token> IMPORT
171 %type <classinfo> MAYBETYPE
172 %type <token> GETSET
173 %type <param> PARAM
174 %type <params> PARAM_LIST
175 %type <params> MAYBE_PARAM_LIST
176 %type <flags> MAYBE_MODIFIERS
177 %type <flags> MODIFIER_LIST
178 %type <constant> STATICCONSTANT MAYBESTATICCONSTANT
179 %type <classinfo_list> IMPLEMENTS_LIST
180 %type <classinfo> EXTENDS
181 %type <classinfo_list> EXTENDS_LIST
182 %type <classinfo> CLASS PACKAGEANDCLASS QNAME
183 %type <classinfo_list> QNAME_LIST
184 %type <classinfo> TYPE
185 %type <token> VAR
186 //%type <token> VARIABLE
187 %type <value> VAR_READ
188 %type <value> NEW
189 //%type <token> T_IDENTIFIER
190 %type <token> MODIFIER
191 %type <value> FUNCTIONCALL
192 %type <value_list> MAYBE_EXPRESSION_LIST EXPRESSION_LIST MAYBE_PARAM_VALUES MAYBE_EXPRPAIR_LIST EXPRPAIR_LIST
193
194 // precedence: from low to high
195
196 %left prec_none
197
198 %left below_semicolon
199 %left ';'
200 %left ','
201 %nonassoc below_assignment // for ?:, contrary to spec
202 %right '=' "*=" "/=" "%=" "+=" "-=" "<<=" ">>=" ">>>=" "&=" "^=" "|="
203 %right '?' ':'
204 %left "||"
205 %left "&&"
206 %nonassoc '|'
207 %nonassoc '^'
208 %nonassoc '&'
209 %nonassoc "==" "!=" "===" "!=="
210 %nonassoc "is" "as"
211 %nonassoc "<=" '<' ">=" '>' "instanceof" // TODO: support "a < b < c" syntax?
212 %left "<<" ">>" ">>>" 
213 %left below_minus
214 %left '-' '+'
215 %left '/' '*' '%'
216 %left plusplus_prefix minusminus_prefix '~' '!' "void" "delete" "typeof" //FIXME: *unary* + - should be here, too
217 %left "--" "++" 
218 %nonassoc below_curly
219 %left '[' ']' '{' "new" '.' ".." "::"
220 %nonassoc T_IDENTIFIER
221 %left below_else
222 %nonassoc "else"
223 %left '('
224
225 // needed for "return" precedence:
226 %nonassoc T_STRING T_REGEXP
227 %nonassoc T_INT T_UINT T_BYTE T_SHORT T_FLOAT
228 %nonassoc "false" "true" "null" "undefined" "super"
229
230
231      
232 %{
233
234 static int yyerror(char*s)
235 {
236    syntaxerror("%s", s); 
237 }
238 static char* concat3str(const char* t1, const char* t2, const char* t3)
239 {
240     int l1 = strlen(t1);
241     int l2 = strlen(t2);
242     int l3 = strlen(t3);
243     char*text = malloc(l1+l2+l3+1);
244     memcpy(text   , t1, l1);
245     memcpy(text+l1, t2, l2);
246     memcpy(text+l1+l2, t3, l3);
247     text[l1+l2+l3] = 0;
248     return text;
249 }
250
251 typedef struct _import {
252     char*package;
253 } import_t;
254
255 DECLARE_LIST(import);
256
257 typedef struct _classstate {
258     /* class data */
259     classinfo_t*info;
260     abc_class_t*abc;
261     code_t*init;
262     code_t*static_init;
263     char has_constructor;
264 } classstate_t;
265
266 typedef struct _methodstate {
267     /* method data */
268     memberinfo_t*info;
269     char late_binding;
270     /* code that needs to be executed at the start of
271        a method (like initializing local registers) */
272     code_t*initcode;
273     char is_constructor;
274     char has_super;
275 } methodstate_t;
276
277 typedef struct _state {
278     int level;
279
280     char*package;     
281     import_list_t*wildcard_imports;
282     dict_t*imports;
283     char has_own_imports;
284   
285     classstate_t*cls;   
286     methodstate_t*method;
287     
288     dict_t*vars;
289 } state_t;
290
291 typedef struct _global {
292     abc_file_t*file;
293     abc_script_t*init;
294
295     int variable_count;
296 } global_t;
297
298 static global_t*global = 0;
299 static state_t* state = 0;
300
301 DECLARE_LIST(state);
302
303 #define MULTINAME(m,x) \
304     multiname_t m;\
305     namespace_t m##_ns;\
306     registry_fill_multiname(&m, &m##_ns, x);
307                     
308 #define MEMBER_MULTINAME(m,f,n) \
309     multiname_t m;\
310     namespace_t m##_ns;\
311     if(f) { \
312         m##_ns.access = flags2access(f->flags); \
313         m##_ns.name = ""; \
314         m.type = QNAME; \
315         m.ns = &m##_ns; \
316         m.namespace_set = 0; \
317         m.name = f->name; \
318     } else { \
319         m.type = MULTINAME; \
320         m.ns =0; \
321         m.namespace_set = &nopackage_namespace_set; \
322         m.name = n; \
323     }
324
325 /* warning: list length of namespace set is undefined */
326 #define MULTINAME_LATE(m, access, package) \
327     namespace_t m##_ns = {access, package}; \
328     namespace_set_t m##_nsset; \
329     namespace_list_t m##_l;m##_l.next = 0; \
330     m##_nsset.namespaces = &m##_l; \
331     m##_nsset = m##_nsset; \
332     m##_l.namespace = &m##_ns; \
333     multiname_t m = {MULTINAMEL, 0, &m##_nsset, 0};
334
335 static namespace_t ns1 = {ACCESS_PRIVATE, ""};
336 static namespace_t ns2 = {ACCESS_PROTECTED, ""};
337 static namespace_t ns3 = {ACCESS_PACKAGEINTERNAL, ""};
338 static namespace_t ns4 = {ACCESS_PACKAGE, ""};
339 static namespace_list_t nl4 = {&ns4,0};
340 static namespace_list_t nl3 = {&ns3,&nl4};
341 static namespace_list_t nl2 = {&ns2,&nl3};
342 static namespace_list_t nl1 = {&ns1,&nl2};
343 static namespace_set_t nopackage_namespace_set = {&nl1};
344
345 static state_list_t*state_stack=0;
346     
347 static void init_globals()
348 {
349     global = rfx_calloc(sizeof(global_t));
350 }
351
352 static void new_state()
353 {
354     NEW(state_t, s);
355     NEW(state_list_t, sl);
356
357     state_t*oldstate = state;
358     if(state)
359         memcpy(s, state, sizeof(state_t)); //shallow copy
360     sl->next = state_stack;
361     sl->state = s;
362     if(!s->imports) {
363         s->imports = dict_new();
364     }
365     state_stack = sl;
366     state = s;
367     state->level++;
368     state->has_own_imports = 0;    
369     state->vars = dict_new();
370 }
371 static void state_has_imports()
372 {
373     state->wildcard_imports = list_clone(state->wildcard_imports);
374     state->imports = dict_clone(state->imports);
375     state->has_own_imports = 1;
376 }
377
378 static void old_state()
379 {
380     if(!state_stack || !state_stack->next)
381         syntaxerror("invalid nesting");
382     state_t*oldstate = state;
383     state_list_t*old = state_stack;
384     state_stack = state_stack->next;
385     free(old);
386     state = state_stack->state;
387     /*if(state->method->initcode) {
388         printf("residual initcode\n");
389         code_dump(state->method->initcode, 0, 0, "", stdout);
390     }*/
391     if(oldstate->has_own_imports) {
392         list_free(oldstate->wildcard_imports);
393         dict_destroy(oldstate->imports);oldstate->imports=0;
394     }
395 }
396 void initialize_state()
397 {
398     init_globals();
399     new_state();
400
401     global->file = abc_file_new();
402     global->file->flags &= ~ABCFILE_LAZY;
403     
404     global->init = abc_initscript(global->file, 0);
405     code_t*c = global->init->method->body->code;
406
407     c = abc_getlocal_0(c);
408     c = abc_pushscope(c);
409   
410     /* findpropstrict doesn't just return a scope object- it
411        also makes it "active" somehow. Push local_0 on the
412        scope stack and read it back with findpropstrict, it'll
413        contain properties like "trace". Trying to find the same
414        property on a "vanilla" local_0 yields only a "undefined" */
415     //c = abc_findpropstrict(c, "[package]::trace");
416     
417     /*c = abc_getlocal_0(c);
418     c = abc_findpropstrict(c, "[package]::trace");
419     c = abc_coerce_a(c);
420     c = abc_setlocal_1(c);
421
422     c = abc_pushbyte(c, 0);
423     c = abc_setlocal_2(c);
424    
425     code_t*xx = c = abc_label(c);
426     c = abc_findpropstrict(c, "[package]::trace");
427     c = abc_pushstring(c, "prop:");
428     c = abc_hasnext2(c, 1, 2);
429     c = abc_dup(c);
430     c = abc_setlocal_3(c);
431     c = abc_callpropvoid(c, "[package]::trace", 2);
432     c = abc_getlocal_3(c);
433     c = abc_kill(c, 3);
434     c = abc_iftrue(c,xx);*/
435
436     c = abc_findpropstrict(c, "[package]::trace");
437     c = abc_pushstring(c, "[entering global init function]");
438     c = abc_callpropvoid(c, "[package]::trace", 1);
439     
440     global->init->method->body->code = c;
441 }
442 void* finalize_state()
443 {
444     if(state->level!=1) {
445         syntaxerror("unexpected end of file");
446     }
447     abc_method_body_t*m = global->init->method->body;
448     //__ popscope(m);
449     
450     __ findpropstrict(m, "[package]::trace");
451     __ pushstring(m, "[leaving global init function]");
452     __ callpropvoid(m, "[package]::trace", 1);
453     __ returnvoid(m);
454     return global->file;
455 }
456
457
458 static void startpackage(char*name)
459 {
460     if(state->package) {
461         syntaxerror("Packages can not be nested."); 
462     } 
463     new_state();
464     /*printf("entering package \"%s\"\n", name);*/
465     state->package = name;
466 }
467 static void endpackage()
468 {
469     /*printf("leaving package \"%s\"\n", state->package);*/
470     old_state();
471 }
472
473 char*globalclass=0;
474 static void startclass(int flags, char*classname, classinfo_t*extends, classinfo_list_t*implements, char interface)
475 {
476     if(state->cls) {
477         syntaxerror("inner classes now allowed"); 
478     }
479     new_state();
480     state->cls = rfx_calloc(sizeof(classstate_t));
481
482     token_list_t*t=0;
483     classinfo_list_t*mlist=0;
484     /*printf("entering class %s\n", name);
485     printf("  modifiers: ");for(t=modifiers->tokens;t;t=t->next) printf("%s ", t->token);printf("\n");
486     if(extends) 
487         printf("  extends: %s.%s\n", extends->package, extends->name);
488     printf("  implements (%d): ", list_length(implements));
489     for(mlist=implements;mlist;mlist=mlist->next)  {
490         printf("%s ", mlist->classinfo?mlist->classinfo->name:0);
491     }
492     printf("\n");
493     */
494
495     if(flags&~(FLAG_INTERNAL|FLAG_PUBLIC|FLAG_FINAL|FLAG_DYNAMIC))
496         syntaxerror("invalid modifier(s)");
497
498     if((flags&(FLAG_PUBLIC|FLAG_INTERNAL)) == (FLAG_PUBLIC|FLAG_INTERNAL))
499         syntaxerror("public and internal not supported at the same time.");
500
501     /* create the class name, together with the proper attributes */
502     int access=0;
503     char*package=0;
504
505     if(!(flags&FLAG_PUBLIC) && !state->package) {
506         access = ACCESS_PRIVATE; package = current_filename;
507     } else if(!(flags&FLAG_PUBLIC) && state->package) {
508         access = ACCESS_PACKAGEINTERNAL; package = state->package;
509     } else if(state->package) {
510         access = ACCESS_PACKAGE; package = state->package;
511     } else {
512         syntaxerror("public classes only allowed inside a package");
513     }
514
515     if(registry_findclass(package, classname)) {
516         syntaxerror("Package \"%s\" already contains a class called \"%s\"", package, classname);
517     }
518    
519
520     /* build info struct */
521     int num_interfaces = (list_length(implements));
522     state->cls->info = classinfo_register(access, package, classname, num_interfaces);
523     state->cls->info->superclass = extends?extends:TYPE_OBJECT;
524     int pos = 0;
525     classinfo_list_t*l = implements;
526     for(l=implements;l;l=l->next) {
527         state->cls->info->interfaces[pos++] = l->classinfo;
528     }
529     
530     multiname_t*extends2 = sig2mname(extends);
531
532     MULTINAME(classname2,state->cls->info);
533
534     /*if(extends) {
535         state->cls_init = abc_getlocal_0(state->cls_init);
536         state->cls_init = abc_constructsuper(state->cls_init, 0);
537     }*/
538
539     state->cls->abc = abc_class_new(global->file, &classname2, extends2);
540     if(flags&FLAG_FINAL) abc_class_final(state->cls->abc);
541     if(!(flags&FLAG_DYNAMIC)) abc_class_sealed(state->cls->abc);
542     if(interface) {
543         state->cls->info->flags |= CLASS_INTERFACE;
544         abc_class_interface(state->cls->abc);
545     }
546
547     abc_class_protectedNS(state->cls->abc, classname);
548
549     for(mlist=implements;mlist;mlist=mlist->next) {
550         MULTINAME(m, mlist->classinfo);
551         abc_class_add_interface(state->cls->abc, &m);
552     }
553
554     /* now write the construction code for this class */
555     int slotindex = abc_initscript_addClassTrait(global->init, &classname2, state->cls->abc);
556
557     abc_method_body_t*m = global->init->method->body;
558     __ getglobalscope(m);
559     classinfo_t*s = extends;
560
561     int count=0;
562     
563     while(s) {
564         //TODO: take a look at the current scope stack, maybe 
565         //      we can re-use something
566         s = s->superclass;
567         if(!s) 
568         break;
569        
570         multiname_t*s2 = sig2mname(s);
571         __ getlex2(m, s2);
572         multiname_destroy(s2);
573
574         __ pushscope(m); count++;
575         m->code = m->code->prev->prev; // invert
576     }
577     /* continue appending after last op end */
578     while(m->code && m->code->next) m->code = m->code->next; 
579
580     /* TODO: if this is one of *our* classes, we can also 
581              do a getglobalscope/getslot <nr> (which references
582              the init function's slots) */
583     if(extends2) {
584         __ getlex2(m, extends2);
585         __ dup(m);
586         /* notice: we get a Verify Error #1107 if the top elemnt on the scope
587            stack is not the superclass */
588         __ pushscope(m);count++;
589     } else {
590         __ pushnull(m);
591         /* notice: we get a verify error #1107 if the top element on the scope 
592            stack is not the global object */
593         __ getlocal_0(m);
594         __ pushscope(m);count++;
595     }
596     __ newclass(m,state->cls->abc);
597     while(count--) {
598         __ popscope(m);
599     }
600     __ setslot(m, slotindex);
601
602     /* flash.display.MovieClip handling */
603     if(!globalclass && (flags&FLAG_PUBLIC) && classinfo_equals(registry_getMovieClip(),extends)) {
604         if(state->package && state->package[0]) {
605             globalclass = concat3str(state->package, ".", classname);
606         } else {
607             globalclass = strdup(classname);
608         }
609     }
610     multiname_destroy(extends2);
611 }
612
613 static code_t* wrap_function(code_t*c,code_t*initcode, code_t*body)
614 {
615     c = code_append(c, initcode);
616     c = code_append(c, body);
617     /* append return if necessary */
618     if(!c || c->opcode != OPCODE_RETURNVOID && 
619              c->opcode != OPCODE_RETURNVALUE) {
620         c = abc_returnvoid(c);
621     }
622     return c;
623 }
624
625 static void endclass()
626 {
627     if(!state->cls->has_constructor && !(state->cls->info->flags&CLASS_INTERFACE)) {
628         code_t*c = 0;
629         c = abc_getlocal_0(c);
630         c = abc_constructsuper(c, 0);
631         state->cls->init = code_append(state->cls->init, c);
632     }
633
634     if(state->cls->init) {
635         abc_method_t*m = abc_class_getconstructor(state->cls->abc, 0);
636         m->body->code = wrap_function(0, state->cls->init, m->body->code);
637     }
638     if(state->cls->static_init) {
639         abc_method_t*m = abc_class_getstaticconstructor(state->cls->abc, 0);
640         m->body->code = wrap_function(0, state->cls->static_init, m->body->code);
641     } else {
642         // handy for scope testing 
643         /*code_t*c = 0;
644         c = abc_pop(c);
645         c = abc_pop(c);
646         abc_class_getstaticconstructor(state->cls->abc,0)->body->code = c;*/
647     }
648
649     old_state();
650 }
651
652 typedef struct _variable {
653     int index;
654     classinfo_t*type;
655 } variable_t;
656
657 static int find_variable(char*name, classinfo_t**m)
658 {
659     state_list_t* s = state_stack;
660     while(s) {
661         variable_t*v = 0;
662         if(s->state->method)
663             v = dict_lookup(s->state->vars, name);
664         if(v) {
665             if(m) {
666                 *m = v->type;
667             }
668             return v->index;
669         }
670         s = s->next;
671     }
672     return -1;
673
674 static int find_variable_safe(char*name, classinfo_t**m)
675 {
676     int i = find_variable(name, m);
677     if(i<0)
678         syntaxerror("undefined variable: %s", name);
679     return i;
680 }
681 static char variable_exists(char*name) 
682 {
683     return dict_lookup(state->vars, name)!=0;
684 }
685 static int new_variable(char*name, classinfo_t*type)
686 {
687     NEW(variable_t, v);
688     v->index = global->variable_count;
689     v->type = type;
690     dict_put(state->vars, name, v);
691     return global->variable_count++;
692 }
693 #define TEMPVARNAME "__as3_temp__"
694 static int gettempvar()
695 {
696     int i = find_variable(TEMPVARNAME, 0);
697     if(i<0) {
698         i = new_variable(TEMPVARNAME, 0);
699     }
700     return i;
701 }
702
703 code_t* killvars(code_t*c) 
704 {
705     int t;
706     for(t=0;t<state->vars->hashsize;t++) {
707         dictentry_t*e =state->vars->slots[t];
708         while(e) {
709             variable_t*v = (variable_t*)e->data;
710             //do this always, otherwise register types don't match
711             //in the verifier when doing nested loops
712             //if(!TYPE_IS_BUILTIN_SIMPLE(type)) {
713             c = abc_kill(c, v->index);
714             e = e->next;
715         }
716     }
717     return c;
718 }
719
720 void check_code_for_break(code_t*c)
721 {
722     while(c) {
723         if(c->opcode == OPCODE___BREAK__) {
724             char*name = string_cstr(c->data[0]);
725             syntaxerror("Unresolved \"break %s\"", name);
726         }
727         if(c->opcode == OPCODE___CONTINUE__) {
728             char*name = string_cstr(c->data[0]);
729             syntaxerror("Unresolved \"continue %s\"", name);
730         }
731         c=c->prev;
732     }
733 }
734
735
736 static void check_constant_against_type(classinfo_t*t, constant_t*c)
737 {
738 #define xassert(b) if(!(b)) syntaxerror("Invalid default value %s for type '%s'", constant_tostring(c), t->name)
739    if(TYPE_IS_NUMBER(t)) {
740         xassert(c->type == CONSTANT_FLOAT
741              || c->type == CONSTANT_INT
742              || c->type == CONSTANT_UINT);
743    } else if(TYPE_IS_UINT(t)) {
744         xassert(c->type == CONSTANT_UINT ||
745                (c->type == CONSTANT_INT && c->i>0));
746    } else if(TYPE_IS_INT(t)) {
747         xassert(c->type == CONSTANT_INT);
748    } else if(TYPE_IS_BOOLEAN(t)) {
749         xassert(c->type == CONSTANT_TRUE
750              || c->type == CONSTANT_FALSE);
751    }
752 }
753
754 static memberinfo_t*registerfunction(enum yytokentype getset, int flags, char*name, params_t*params, classinfo_t*return_type, int slot)
755 {
756     memberinfo_t*minfo = 0;
757     if(getset != KW_GET && getset != KW_SET) {
758         if((minfo = registry_findmember(state->cls->info, name, 0))) {
759             if(minfo->parent == state->cls->info) {
760                 syntaxerror("class already contains a member/method called '%s'", name);
761             } else if(!minfo->parent) {
762                 syntaxerror("internal error: overriding method %s, which doesn't have parent", name);
763             } else {
764                 if(!(minfo->flags&(FLAG_STATIC|FLAG_PRIVATE)))
765                     syntaxerror("function %s already exists in superclass. Did you forget the 'override' keyword?");
766             }
767         }
768         minfo = memberinfo_register(state->cls->info, name, MEMBER_METHOD);
769         minfo->return_type = return_type;
770         // getslot on a member slot only returns "undefined", so no need
771         // to actually store these
772         //state->minfo->slot = state->method->abc->method->trait->slot_id;
773     } else {
774         int gs = getset==KW_GET?MEMBER_GET:MEMBER_SET;
775         classinfo_t*type=0;
776         if(getset == KW_GET)
777             type = return_type;
778         else if(params->list)
779             type = params->list->param->type;
780         // not sure wether to look into superclasses here, too
781         if((minfo=registry_findmember(state->cls->info, name, 0))) {
782             if(minfo->kind & ~(MEMBER_GET|MEMBER_SET))
783                 syntaxerror("class already contains a member or method called '%s'", name);
784             if(minfo->kind & gs)
785                 syntaxerror("getter/setter for '%s' already defined", name);
786             /* make a setter or getter into a getset */
787             minfo->kind |= gs;
788             if(!minfo->type) 
789                 minfo->type = type;
790             else
791                 if(type && minfo->type != type)
792                     syntaxerror("different type in getter and setter");
793         } else {
794             minfo = memberinfo_register(state->cls->info, name, gs);
795             minfo->type = type;
796         }
797         /* can't assign a slot as getter and setter might have different slots */
798         //minfo->slot = slot;
799     }
800     if(flags&FLAG_STATIC) minfo->flags |= FLAG_STATIC;
801     if(flags&FLAG_PUBLIC) minfo->flags |= FLAG_PUBLIC;
802     if(flags&FLAG_PRIVATE) minfo->flags |= FLAG_PRIVATE;
803     if(flags&FLAG_PROTECTED) minfo->flags |= FLAG_PROTECTED;
804     if(flags&FLAG_INTERNAL) minfo->flags |= FLAG_INTERNAL;
805     if(flags&FLAG_OVERRIDE) minfo->flags |= FLAG_OVERRIDE;
806     return minfo;
807 }
808
809 static int flags2access(int flags)
810 {
811     int access = 0;
812     if(flags&FLAG_PUBLIC)  {
813         if(access&(FLAG_PRIVATE|FLAG_PROTECTED|FLAG_INTERNAL)) syntaxerror("invalid combination of access levels");
814         access = ACCESS_PACKAGE;
815     } else if(flags&FLAG_PRIVATE) {
816         if(access&(FLAG_PUBLIC|FLAG_PROTECTED|FLAG_INTERNAL)) syntaxerror("invalid combination of access levels");
817         access = ACCESS_PRIVATE;
818     } else if(flags&FLAG_PROTECTED) {
819         if(access&(FLAG_PUBLIC|FLAG_PRIVATE|FLAG_INTERNAL)) syntaxerror("invalid combination of access levels");
820         access = ACCESS_PROTECTED;
821     } else {
822         access = ACCESS_PACKAGEINTERNAL;
823     }
824     return access;
825 }
826
827 static void startfunction(token_t*ns, int flags, enum yytokentype getset, char*name,
828                           params_t*params, classinfo_t*return_type)
829 {
830     if(state->method) {
831         syntaxerror("not able to start another method scope");
832     }
833     new_state();
834     state->method = rfx_calloc(sizeof(methodstate_t));
835     state->method->initcode = 0;
836     state->method->is_constructor = !strcmp(state->cls->info->name,name);
837     state->method->has_super = 0;
838     
839     state->cls->has_constructor |= state->method->is_constructor;
840
841     global->variable_count = 0;
842
843     /* state->vars is initialized by state_new */
844     if(new_variable((flags&FLAG_STATIC)?"class":"this", state->cls->info)!=0) syntaxerror("Internal error");
845     param_list_t*p=0;
846     for(p=params->list;p;p=p->next) {
847         new_variable(p->param->name, p->param->type);
848     }
849     if(state->method->is_constructor)
850         name = "__as3_constructor__";
851     state->method->info = registerfunction(getset, flags, name, params, return_type, 0);
852 }
853
854 static void endfunction(token_t*ns, int flags, enum yytokentype getset, char*name,
855                           params_t*params, classinfo_t*return_type, code_t*body)
856 {
857     namespace_t mname_ns = {flags2access(flags), ""};
858     multiname_t mname = {QNAME, &mname_ns, 0, name};
859
860     abc_method_t*f = 0;
861
862     multiname_t*type2 = sig2mname(return_type);
863     int slot = 0;
864     if(state->method->is_constructor) {
865         f = abc_class_getconstructor(state->cls->abc, type2);
866     } else {
867         if(flags&FLAG_STATIC)
868             f = abc_class_staticmethod(state->cls->abc, type2, &mname);
869         else
870             f = abc_class_method(state->cls->abc, type2, &mname);
871         slot = f->trait->slot_id;
872     }
873     //flash doesn't seem to allow us to access function slots
874     //state->method->info->slot = slot;
875
876     if(flags&FLAG_OVERRIDE) f->trait->attributes |= TRAIT_ATTR_OVERRIDE;
877     if(getset == KW_GET) f->trait->kind = TRAIT_GETTER;
878     if(getset == KW_SET) f->trait->kind = TRAIT_SETTER;
879     if(params->varargs) f->flags |= METHOD_NEED_REST;
880
881     char opt=0;
882     param_list_t*p=0;
883     for(p=params->list;p;p=p->next) {
884         if(params->varargs && !p->next) {
885             break; //varargs: omit last parameter in function signature
886         }
887         multiname_t*m = sig2mname(p->param->type);
888         list_append(f->parameters, m);
889         if(p->param->value) {
890             check_constant_against_type(p->param->type, p->param->value);
891             opt=1;list_append(f->optional_parameters, p->param->value);
892         } else if(opt) {
893             syntaxerror("non-optional parameter not allowed after optional parameters");
894         }
895     }
896     check_code_for_break(body);
897
898     if(f->body)
899         f->body->code = body;
900     else //interface
901         if(body)
902             syntaxerror("interface methods can't have a method body");
903         
904     old_state();
905 }
906
907
908
909 char is_subtype_of(classinfo_t*type, classinfo_t*supertype)
910 {
911     return 1; // FIXME
912 }
913
914 void breakjumpsto(code_t*c, char*name, code_t*jump) 
915 {
916     while(c) {
917         if(c->opcode == OPCODE___BREAK__) {
918             string_t*name2 = c->data[0];
919             if(!name2->len || !strncmp(name2->str, name, name2->len)) {
920                 c->opcode = OPCODE_JUMP;
921                 c->branch = jump;
922             }
923         }
924         c=c->prev;
925     }
926 }
927 void continuejumpsto(code_t*c, char*name, code_t*jump) 
928 {
929     while(c) {
930         if(c->opcode == OPCODE___CONTINUE__) {
931             string_t*name2 = c->data[0];
932             if(!name2->len || !strncmp(name2->str, name, name2->len)) {
933                 c->opcode = OPCODE_JUMP;
934                 c->branch = jump;
935             }
936         }
937         c = c->prev;
938     }
939 }
940
941 classinfo_t*join_types(classinfo_t*type1, classinfo_t*type2, char op)
942 {
943     if(!type1 || !type2) 
944         return registry_getanytype();
945     if(TYPE_IS_ANY(type1) || TYPE_IS_ANY(type2))
946         return registry_getanytype();
947     if(type1 == type2)
948         return type1;
949     return registry_getanytype();
950 }
951 code_t*converttype(code_t*c, classinfo_t*from, classinfo_t*to)
952 {
953     if(from==to)
954         return c;
955     if(!to) {
956         return abc_coerce_a(c);
957     }
958     MULTINAME(m, to);
959     if(!from) {
960         // cast an "any" type to a specific type. subject to
961         // runtime exceptions
962         return abc_coerce2(c, &m);
963     }
964     
965     if((TYPE_IS_NUMBER(from) || TYPE_IS_UINT(from) || TYPE_IS_INT(from)) &&
966        (TYPE_IS_NUMBER(to) || TYPE_IS_UINT(to) || TYPE_IS_INT(to))) {
967         // allow conversion between number types
968         return abc_coerce2(c, &m);
969     }
970     //printf("%s.%s\n", from.package, from.name);
971     //printf("%s.%s\n", to.package, to.name);
972
973     classinfo_t*supertype = from;
974     while(supertype) {
975         if(supertype == to) {
976              // target type is one of from's superclasses
977              return abc_coerce2(c, &m);
978         }
979         int t=0;
980         while(supertype->interfaces[t]) {
981             if(supertype->interfaces[t]==to) {
982                 // target type is one of from's interfaces
983                 return abc_coerce2(c, &m);
984             }
985             t++;
986         }
987         supertype = supertype->superclass;
988     }
989     if(TYPE_IS_FUNCTION(from) && TYPE_IS_FUNCTION(to))
990         return c;
991     if(TYPE_IS_CLASS(from) && TYPE_IS_CLASS(to))
992         return c;
993     syntaxerror("can't convert type %s to %s", from->name, to->name);
994 }
995
996 code_t*defaultvalue(code_t*c, classinfo_t*type)
997 {
998     if(TYPE_IS_INT(type)) {
999        c = abc_pushbyte(c, 0);
1000     } else if(TYPE_IS_UINT(type)) {
1001        c = abc_pushuint(c, 0);
1002     } else if(TYPE_IS_FLOAT(type)) {
1003        c = abc_pushnan(c);
1004     } else if(TYPE_IS_BOOLEAN(type)) {
1005        c = abc_pushfalse(c);
1006     } else {
1007        c = abc_pushnull(c);
1008     }
1009     return c;
1010 }
1011
1012 char is_pushundefined(code_t*c)
1013 {
1014     return (c && !c->prev && !c->next && c->opcode == OPCODE_PUSHUNDEFINED);
1015 }
1016
1017 void parserassert(int b)
1018 {
1019     if(!b) syntaxerror("internal error: assertion failed");
1020 }
1021
1022 static classinfo_t* find_class(char*name)
1023 {
1024     classinfo_t*c=0;
1025
1026     c = registry_findclass(state->package, name);
1027
1028     /* try explicit imports */
1029     dictentry_t* e = dict_get_slot(state->imports, name);
1030     while(e) {
1031         if(c)
1032             break;
1033         if(!strcmp(e->key, name)) {
1034             c = (classinfo_t*)e->data;
1035         }
1036         e = e->next;
1037     }
1038
1039     /* try package.* imports */
1040     import_list_t*l = state->wildcard_imports;
1041     while(l) {
1042         if(c)
1043             break;
1044         //printf("does package %s contain a class %s?\n", l->import->package, name);
1045         c = registry_findclass(l->import->package, name);
1046         l = l->next;
1047     }
1048
1049     /* try global package */
1050     if(!c) {
1051         c = registry_findclass("", name);
1052     }
1053     return c;
1054 }
1055
1056 static code_t* toreadwrite(code_t*in, code_t*middlepart, char justassign, char readbefore)
1057 {
1058     /* converts this:
1059
1060        [prefix code] [read instruction]
1061
1062        to this:
1063
1064        [prefix code] ([dup]) [read instruction] [middlepart] [setvar] [write instruction] [getvar]
1065     */
1066     
1067     if(in && in->opcode == OPCODE_COERCE_A) {
1068         in = code_cutlast(in);
1069     }
1070     if(in->next)
1071         syntaxerror("internal error");
1072
1073     /* chop off read instruction */
1074     code_t*prefix = in;
1075     code_t*r = in;
1076     if(r->prev) {
1077         prefix = r->prev;r->prev = 0;
1078         prefix->next=0;
1079     } else {
1080         prefix = 0;
1081     }
1082
1083     char use_temp_var = readbefore;
1084
1085     /* generate the write instruction, and maybe append a dup to the prefix code */
1086     code_t* write = abc_nop(0);
1087     if(r->opcode == OPCODE_GETPROPERTY) {
1088         write->opcode = OPCODE_SETPROPERTY;
1089         multiname_t*m = (multiname_t*)r->data[0];
1090         write->data[0] = multiname_clone(m);
1091         if(m->type == QNAME || m->type == MULTINAME) {
1092             if(!justassign) {
1093                 prefix = abc_dup(prefix); // we need the object, too
1094             }
1095             use_temp_var = 1;
1096         } else if(m->type == MULTINAMEL) {
1097             if(!justassign) {
1098                 /* dupping two values on the stack requires 5 operations and one register- 
1099                    couldn't adobe just have given us a dup2? */
1100                 int temp = gettempvar();
1101                 prefix = abc_setlocal(prefix, temp);
1102                 prefix = abc_dup(prefix);
1103                 prefix = abc_getlocal(prefix, temp);
1104                 prefix = abc_swap(prefix);
1105                 prefix = abc_getlocal(prefix, temp);
1106             }
1107             use_temp_var = 1;
1108         } else {
1109             syntaxerror("illegal lvalue: can't assign a value to this expression (not a qname/multiname)");
1110         }
1111     } else if(r->opcode == OPCODE_GETSLOT) {
1112         write->opcode = OPCODE_SETSLOT;
1113         write->data[0] = r->data[0];
1114         if(!justassign) {
1115             prefix = abc_dup(prefix); // we need the object, too
1116         }
1117         use_temp_var = 1;
1118     } else if(r->opcode == OPCODE_GETLOCAL) { 
1119         write->opcode = OPCODE_SETLOCAL;
1120         write->data[0] = r->data[0];
1121     } else if(r->opcode == OPCODE_GETLOCAL_0) { 
1122         write->opcode = OPCODE_SETLOCAL_0;
1123     } else if(r->opcode == OPCODE_GETLOCAL_1) { 
1124         write->opcode = OPCODE_SETLOCAL_1;
1125     } else if(r->opcode == OPCODE_GETLOCAL_2) { 
1126         write->opcode = OPCODE_SETLOCAL_2;
1127     } else if(r->opcode == OPCODE_GETLOCAL_3) { 
1128         write->opcode = OPCODE_SETLOCAL_3;
1129     } else {
1130         code_dump(r, 0, 0, "", stdout);
1131         syntaxerror("illegal lvalue: can't assign a value to this expression");
1132     }
1133     code_t* c = 0;
1134     
1135     int temp = -1;
1136     if(!justassign) {
1137         if(use_temp_var) {
1138             /* with getproperty/getslot, we have to be extra careful not
1139                to execute the read code twice, as it might have side-effects
1140                (e.g. if the property is in fact a setter/getter combination)
1141
1142                So read the value, modify it, and write it again,
1143                using prefix only once and making sure (by using a temporary
1144                register) that the return value is what we just wrote */
1145             temp = gettempvar();
1146             c = code_append(c, prefix);
1147             c = code_append(c, r);
1148             if(readbefore) {
1149                 c = abc_dup(c);
1150                 c = abc_setlocal(c, temp);
1151             }
1152             c = code_append(c, middlepart);
1153             if(!readbefore) {
1154                 c = abc_dup(c);
1155                 c = abc_setlocal(c, temp);
1156             }
1157             c = code_append(c, write);
1158             c = abc_getlocal(c, temp);
1159             c = abc_kill(c, temp);
1160         } else {
1161             /* if we're allowed to execute the read code twice *and*
1162                the middlepart doesn't modify the code, things are easier.
1163             */
1164             code_t* r2 = code_dup(r);
1165             //c = code_append(c, prefix);
1166             parserassert(!prefix);
1167             c = code_append(c, r);
1168             c = code_append(c, middlepart);
1169             c = code_append(c, write);
1170             c = code_append(c, r2);
1171         }
1172     } else {
1173         /* even smaller version: overwrite the value without reading
1174            it out first */
1175         if(!use_temp_var) {
1176             if(prefix) {
1177                 c = code_append(c, prefix);
1178                 c = abc_dup(c);
1179             }
1180             c = code_append(c, middlepart);
1181             c = code_append(c, write);
1182             c = code_append(c, r);
1183         } else {
1184             temp = gettempvar();
1185             if(prefix) {
1186                 c = code_append(c, prefix);
1187                 c = abc_dup(c);
1188             }
1189             c = code_append(c, middlepart);
1190             c = abc_dup(c);
1191             c = abc_setlocal(c, temp);
1192             c = code_append(c, write);
1193             c = abc_getlocal(c, temp);
1194         }
1195     }
1196
1197     return c;
1198 }
1199
1200 #define IS_INT(a) (TYPE_IS_INT((a).t) || TYPE_IS_UINT((a).t))
1201 #define BOTH_INT(a,b) (IS_INT(a) && IS_INT(b))
1202
1203 %}
1204
1205
1206 %%
1207
1208 /* ------------ code blocks / statements ---------------- */
1209
1210 PROGRAM: MAYBECODE {
1211     /* todo: do something with this code if we're outside a function */
1212     if($1)
1213         warning("ignored code");
1214 }
1215
1216 MAYBECODE: CODE {$$=$1;}
1217 MAYBECODE: {$$=code_new();}
1218
1219 CODE: CODE CODEPIECE {
1220     $$=code_append($1,$2);
1221 }
1222 CODE: CODEPIECE {
1223     $$=$1;
1224 }
1225
1226 CODEPIECE: PACKAGE_DECLARATION   {$$=code_new();/*enters a scope*/}
1227 CODEPIECE: CLASS_DECLARATION     {$$=code_new();/*enters a scope*/}
1228 CODEPIECE: FUNCTION_DECLARATION  {$$=code_new();/*enters a scope*/}
1229 CODEPIECE: INTERFACE_DECLARATION {$$=code_new();}
1230 CODEPIECE: IMPORT                {$$=code_new();/*adds imports to current scope*/}
1231 CODEPIECE: ';'                   {$$=code_new();}
1232 CODEPIECE: VARIABLE_DECLARATION  {$$=$1}
1233 CODEPIECE: VOIDEXPRESSION        {$$=$1}
1234 CODEPIECE: FOR                   {$$=$1}
1235 CODEPIECE: WHILE                 {$$=$1}
1236 CODEPIECE: DO_WHILE              {$$=$1}
1237 CODEPIECE: SWITCH                {$$=$1}
1238 CODEPIECE: BREAK                 {$$=$1}
1239 CODEPIECE: CONTINUE              {$$=$1}
1240 CODEPIECE: RETURN                {$$=$1}
1241 CODEPIECE: IF                    {$$=$1}
1242 CODEPIECE: NAMESPACE_DECLARATION {/*TODO*/$$=code_new();}
1243 CODEPIECE: USE_NAMESPACE         {/*TODO*/$$=code_new();}
1244
1245 CODEBLOCK :  '{' CODE '}' {$$=$2;}
1246 CODEBLOCK :  '{' '}'      {$$=0;}
1247 CODEBLOCK :  CODEPIECE ';'             {$$=$1;}
1248 CODEBLOCK :  CODEPIECE %prec below_semicolon {$$=$1;}
1249
1250 /* ------------ variables --------------------------- */
1251
1252 MAYBEEXPRESSION : '=' NONCOMMAEXPRESSION {$$=$2;}
1253                 |                {$$.c=abc_pushundefined(0);
1254                                   $$.t=TYPE_ANY;
1255                                  }
1256
1257 VAR : "const" | "var"
1258 VARIABLE_DECLARATION : VAR VARIABLE_LIST {$$=$2;}
1259
1260 VARIABLE_LIST: ONE_VARIABLE                   {$$ = $1;}
1261 VARIABLE_LIST: VARIABLE_LIST ',' ONE_VARIABLE {$$ = code_append($1, $3);}
1262
1263 ONE_VARIABLE: {} T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION
1264 {
1265     if(variable_exists($2))
1266         syntaxerror("Variable %s already defined", $2);
1267    
1268     if(!is_subtype_of($4.t, $3)) {
1269         syntaxerror("Can't convert %s to %s", $4.t->name, 
1270                                               $3->name);
1271     }
1272
1273     int index = new_variable($2, $3);
1274     
1275     if($3) {
1276         if($4.c->prev || $4.c->opcode != OPCODE_PUSHUNDEFINED) {
1277             $$ = $4.c;
1278             $$ = converttype($$, $4.t, $3);
1279             $$ = abc_setlocal($$, index);
1280         } else {
1281             $$ = defaultvalue(0, $3);
1282             $$ = abc_setlocal($$, index);
1283         }
1284
1285         /* if this is a typed variable:
1286            push default value for type on stack */
1287         if($3) {
1288             state->method->initcode = defaultvalue(state->method->initcode, $3);
1289             state->method->initcode = abc_setlocal(state->method->initcode, index);
1290         }
1291     } else {
1292         if($4.c->prev || $4.c->opcode != OPCODE_PUSHUNDEFINED) {
1293             $$ = $4.c;
1294             $$ = abc_coerce_a($$);
1295             $$ = abc_setlocal($$, index);
1296         } else {
1297             $$ = code_new();
1298         }
1299     }
1300     
1301     /* that's the default for a local register, anyway
1302         else {
1303         state->method->initcode = abc_pushundefined(state->method->initcode);
1304         state->method->initcode = abc_setlocal(state->method->initcode, index);
1305     }*/
1306     //printf("variable %s -> %d (%s)\n", $2->text, index, $4.t?$4.t->name:"");
1307 }
1308
1309 /* ------------ control flow ------------------------- */
1310
1311 MAYBEELSE:  %prec below_else {$$ = code_new();}
1312 MAYBEELSE: "else" CODEBLOCK {$$=$2;}
1313 //MAYBEELSE: ';' "else" CODEBLOCK {$$=$3;}
1314
1315 IF : "if" '(' {new_state();} EXPRESSION ')' CODEBLOCK MAYBEELSE {
1316     $$ = code_new();
1317     $$ = code_append($$, $4.c);
1318     code_t*myjmp,*myif = $$ = abc_iffalse($$, 0);
1319    
1320     $$ = code_append($$, $6);
1321     if($7) {
1322         myjmp = $$ = abc_jump($$, 0);
1323     }
1324     myif->branch = $$ = abc_nop($$);
1325     if($7) {
1326         $$ = code_append($$, $7);
1327         myjmp->branch = $$ = abc_nop($$);
1328     }
1329     
1330     $$ = killvars($$);old_state();
1331 }
1332
1333 FOR_INIT : {$$=code_new();}
1334 FOR_INIT : VARIABLE_DECLARATION
1335 FOR_INIT : VOIDEXPRESSION
1336
1337 FOR : T_FOR '(' {new_state();} FOR_INIT ';' EXPRESSION ';' VOIDEXPRESSION ')' CODEBLOCK {
1338     $$ = code_new();
1339     $$ = code_append($$, $4);
1340     code_t*loopstart = $$ = abc_label($$);
1341     $$ = code_append($$, $6.c);
1342     code_t*myif = $$ = abc_iffalse($$, 0);
1343     $$ = code_append($$, $10);
1344     code_t*cont = $$ = abc_nop($$);
1345     $$ = code_append($$, $8);
1346     $$ = abc_jump($$, loopstart);
1347     code_t*out = $$ = abc_nop($$);
1348     breakjumpsto($$, $1, out);
1349     continuejumpsto($$, $1, cont);
1350     myif->branch = out;
1351
1352     $$ = killvars($$);old_state();
1353 }
1354
1355 WHILE : T_WHILE '(' {new_state();} EXPRESSION ')' CODEBLOCK {
1356     $$ = code_new();
1357
1358     code_t*myjmp = $$ = abc_jump($$, 0);
1359     code_t*loopstart = $$ = abc_label($$);
1360     $$ = code_append($$, $6);
1361     code_t*cont = $$ = abc_nop($$);
1362     myjmp->branch = cont;
1363     $$ = code_append($$, $4.c);
1364     $$ = abc_iftrue($$, loopstart);
1365     code_t*out = $$ = abc_nop($$);
1366     breakjumpsto($$, $1, out);
1367     continuejumpsto($$, $1, cont);
1368
1369     $$ = killvars($$);
1370     old_state();
1371 }
1372
1373 DO_WHILE : T_DO {new_state();} CODEBLOCK "while" '(' EXPRESSION ')' {
1374     $$ = code_new();
1375     code_t*loopstart = $$ = abc_label($$);
1376     $$ = code_append($$, $3);
1377     code_t*cont = $$ = abc_nop($$);
1378     $$ = code_append($$, $6.c);
1379     $$ = abc_iftrue($$, loopstart);
1380     code_t*out = $$ = abc_nop($$);
1381     breakjumpsto($$, $1, out);
1382     continuejumpsto($$, $1, cont);
1383     $$ = killvars($$);
1384     old_state();
1385 }
1386
1387 BREAK : "break" %prec prec_none {
1388     $$ = abc___break__(0, "");
1389 }
1390 BREAK : "break" T_IDENTIFIER {
1391     $$ = abc___break__(0, $2);
1392 }
1393 CONTINUE : "continue" %prec prec_none {
1394     $$ = abc___continue__(0, "");
1395 }
1396 CONTINUE : "continue" T_IDENTIFIER {
1397     $$ = abc___continue__(0, $2);
1398 }
1399
1400 MAYBE_CASE_LIST :           {$$=0;}
1401 MAYBE_CASE_LIST : CASE_LIST {$$=$1;}
1402 MAYBE_CASE_LIST : DEFAULT   {$$=$1;}
1403 MAYBE_CASE_LIST : CASE_LIST DEFAULT {$$=code_append($1,$2);}
1404 CASE_LIST: CASE             {$$=$1}
1405 CASE_LIST: CASE_LIST CASE   {$$=code_append($$,$2);}
1406
1407 CASE: "case" E ':' MAYBECODE {
1408     $$ = abc_dup(0);
1409     $$ = code_append($$, $2.c);
1410     code_t*j = $$ = abc_ifne($$, 0);
1411     $$ = code_append($$, $4);
1412     if($$->opcode != OPCODE___BREAK__) {
1413         $$ = abc___fallthrough__($$, "");
1414     }
1415     code_t*e = $$ = abc_nop($$);
1416     j->branch = e;
1417 }
1418 DEFAULT: "default" ':' MAYBECODE {
1419     $$ = $3;
1420 }
1421 SWITCH : T_SWITCH '(' {new_state();} E ')' '{' MAYBE_CASE_LIST '}' {
1422     $$=$4.c;
1423     $$ = code_append($$, $7);
1424     code_t*out = $$ = abc_pop($$);
1425     breakjumpsto($$, $1, out);
1426     
1427     code_t*c = $$,*lastblock=0;
1428     while(c) {
1429         if(c->opcode == OPCODE_IFNE) {
1430             if(!c->next) syntaxerror("internal error in fallthrough handling");
1431             lastblock=c->next;
1432         } else if(c->opcode == OPCODE___FALLTHROUGH__) {
1433             if(lastblock) {
1434                 c->opcode = OPCODE_JUMP;
1435                 c->branch = lastblock;
1436             } else {
1437                 /* fall through end of switch */
1438                 c->opcode = OPCODE_NOP;
1439             }
1440         }
1441         c=c->prev;
1442     }
1443     old_state();
1444 }
1445
1446 /* ------------ packages and imports ---------------- */
1447
1448 X_IDENTIFIER: T_IDENTIFIER
1449             | "package" {$$="package";}
1450
1451 PACKAGE: PACKAGE '.' X_IDENTIFIER {$$ = concat3str($1,".",$3);}
1452 PACKAGE: X_IDENTIFIER             {$$=$1;}
1453
1454 PACKAGE_DECLARATION : "package" PACKAGE '{' {startpackage($2)} MAYBECODE '}' {endpackage()}
1455 PACKAGE_DECLARATION : "package" '{' {startpackage("")} MAYBECODE '}' {endpackage()}
1456
1457 IMPORT : "import" QNAME {
1458        classinfo_t*c = $2;
1459        if(!c) 
1460             syntaxerror("Couldn't import class\n");
1461        state_has_imports();
1462        dict_put(state->imports, c->name, c);
1463        $$=0;
1464 }
1465 IMPORT : "import" PACKAGE '.' '*' {
1466        NEW(import_t,i);
1467        i->package = $2;
1468        state_has_imports();
1469        list_append(state->wildcard_imports, i);
1470        $$=0;
1471 }
1472
1473 /* ------------ classes and interfaces (header) -------------- */
1474
1475 MAYBE_MODIFIERS : {$$=0;}
1476 MAYBE_MODIFIERS : MODIFIER_LIST {$$=$1}
1477 MODIFIER_LIST : MODIFIER               {$$=$1;}
1478 MODIFIER_LIST : MODIFIER_LIST MODIFIER {$$=$1|$2;}
1479
1480 MODIFIER : KW_PUBLIC {$$=FLAG_PUBLIC;}
1481          | KW_PRIVATE {$$=FLAG_PRIVATE;}
1482          | KW_PROTECTED {$$=FLAG_PROTECTED;}
1483          | KW_STATIC {$$=FLAG_STATIC;}
1484          | KW_DYNAMIC {$$=FLAG_DYNAMIC;}
1485          | KW_FINAL {$$=FLAG_FINAL;}
1486          | KW_OVERRIDE {$$=FLAG_OVERRIDE;}
1487          | KW_NATIVE {$$=FLAG_NATIVE;}
1488          | KW_INTERNAL {$$=FLAG_INTERNAL;}
1489
1490 EXTENDS : {$$=registry_getobjectclass();}
1491 EXTENDS : KW_EXTENDS QNAME {$$=$2;}
1492
1493 EXTENDS_LIST : {$$=list_new();}
1494 EXTENDS_LIST : KW_EXTENDS QNAME_LIST {$$=$2;}
1495
1496 IMPLEMENTS_LIST : {$$=list_new();}
1497 IMPLEMENTS_LIST : KW_IMPLEMENTS QNAME_LIST {$$=$2;}
1498
1499 CLASS_DECLARATION : MAYBE_MODIFIERS "class" T_IDENTIFIER 
1500                               EXTENDS IMPLEMENTS_LIST 
1501                               '{' {startclass($1,$3,$4,$5, 0);} 
1502                               MAYBE_DECLARATION_LIST 
1503                               '}' {endclass();}
1504
1505 INTERFACE_DECLARATION : MAYBE_MODIFIERS "interface" T_IDENTIFIER 
1506                               EXTENDS_LIST 
1507                               '{' {startclass($1,$3,0,$4,1);}
1508                               MAYBE_IDECLARATION_LIST 
1509                               '}' {endclass();}
1510
1511 /* ------------ classes and interfaces (body) -------------- */
1512
1513 MAYBE_DECLARATION_LIST : 
1514 MAYBE_DECLARATION_LIST : DECLARATION_LIST
1515 DECLARATION_LIST : DECLARATION
1516 DECLARATION_LIST : DECLARATION_LIST DECLARATION
1517 DECLARATION : ';'
1518 DECLARATION : SLOT_DECLARATION
1519 DECLARATION : FUNCTION_DECLARATION
1520
1521 MAYBE_IDECLARATION_LIST : 
1522 MAYBE_IDECLARATION_LIST : IDECLARATION_LIST
1523 IDECLARATION_LIST : IDECLARATION
1524 IDECLARATION_LIST : IDECLARATION_LIST IDECLARATION
1525 IDECLARATION : ';'
1526 IDECLARATION : "var" T_IDENTIFIER {
1527     syntaxerror("variable declarations not allowed in interfaces");
1528 }
1529 IDECLARATION : MAYBE_MODIFIERS "function" GETSET T_IDENTIFIER '(' MAYBE_PARAM_LIST ')' MAYBETYPE {
1530     $1 |= FLAG_PUBLIC;
1531     if($1&(FLAG_PRIVATE|FLAG_INTERNAL|FLAG_PROTECTED)) {
1532         syntaxerror("invalid method modifiers: interface methods always need to be public");
1533     }
1534     startfunction(0,$1,$3,$4,&$6,$8);
1535     endfunction(0,$1,$3,$4,&$6,$8, 0);
1536 }
1537
1538 /* ------------ classes and interfaces (body, slots ) ------- */
1539
1540 VARCONST: "var" | "const"
1541
1542 SLOT_DECLARATION: MAYBE_MODIFIERS VARCONST T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION {
1543     int flags = $1;
1544     memberinfo_t* info = memberinfo_register(state->cls->info, $3, MEMBER_SLOT);
1545     info->type = $4;
1546     info->flags = flags;
1547     trait_t*t=0;
1548
1549     namespace_t mname_ns = {flags2access(flags), ""};
1550     multiname_t mname = {QNAME, &mname_ns, 0, $3};
1551
1552     if(!(flags&FLAG_STATIC)) {
1553         if($4) {
1554             MULTINAME(m, $4);
1555             t=abc_class_slot(state->cls->abc, &mname, &m);
1556         } else {
1557             t=abc_class_slot(state->cls->abc, &mname, 0);
1558         }
1559         info->slot = t->slot_id;
1560     } else {
1561         if($4) {
1562             MULTINAME(m, $4);
1563             t=abc_class_staticslot(state->cls->abc, &mname, &m);
1564         } else {
1565             t=abc_class_staticslot(state->cls->abc, &mname, 0);
1566         }
1567         info->slot = t->slot_id;
1568     }
1569     if($5.c && !is_pushundefined($5.c)) {
1570         code_t*c = 0;
1571         c = abc_getlocal_0(c);
1572         c = code_append(c, $5.c);
1573         c = converttype(c, $5.t, $4);
1574         c = abc_setslot(c, t->slot_id);
1575         if(!(flags&FLAG_STATIC))
1576             state->cls->init = code_append(state->cls->init, c);
1577         else
1578             state->cls->static_init = code_append(state->cls->static_init, c);
1579     }
1580     if($2==KW_CONST) {
1581         t->kind= TRAIT_CONST;
1582     }
1583 }
1584
1585 /* ------------ constants -------------------------------------- */
1586
1587 MAYBESTATICCONSTANT: {$$=0;}
1588 MAYBESTATICCONSTANT: '=' STATICCONSTANT {$$=$2;}
1589
1590 STATICCONSTANT : T_BYTE {$$ = constant_new_int($1);}
1591 STATICCONSTANT : T_INT {$$ = constant_new_int($1);}
1592 STATICCONSTANT : T_UINT {$$ = constant_new_uint($1);}
1593 STATICCONSTANT : T_FLOAT {$$ = constant_new_float($1);}
1594 STATICCONSTANT : T_STRING {$$ = constant_new_string2($1.str,$1.len);}
1595 //STATICCONSTANT : T_NAMESPACE {$$ = constant_new_namespace($1);}
1596 STATICCONSTANT : "true" {$$ = constant_new_true($1);}
1597 STATICCONSTANT : "false" {$$ = constant_new_false($1);}
1598 STATICCONSTANT : "null" {$$ = constant_new_null($1);}
1599
1600 /* ------------ classes and interfaces (body, functions) ------- */
1601
1602 // non-vararg version
1603 MAYBE_PARAM_LIST: {
1604     memset(&$$,0,sizeof($$));
1605 }
1606 MAYBE_PARAM_LIST: PARAM_LIST {
1607     $$=$1;
1608 }
1609
1610 // vararg version
1611 MAYBE_PARAM_LIST: "..." PARAM {
1612     memset(&$$,0,sizeof($$));
1613     $$.varargs=1;
1614     list_append($$.list, $2);
1615 }
1616 MAYBE_PARAM_LIST: PARAM_LIST ',' "..." PARAM {
1617     $$ =$1;
1618     $$.varargs=1;
1619     list_append($$.list, $4);
1620 }
1621
1622 // non empty
1623 PARAM_LIST: PARAM_LIST ',' PARAM {
1624     $$ = $1;
1625     list_append($$.list, $3);
1626 }
1627 PARAM_LIST: PARAM {
1628     memset(&$$,0,sizeof($$));
1629     list_append($$.list, $1);
1630 }
1631
1632 PARAM:  T_IDENTIFIER ':' TYPE MAYBESTATICCONSTANT {
1633      $$ = malloc(sizeof(param_t));
1634      $$->name=$1;
1635      $$->type = $3;
1636      $$->value = $4;
1637 }
1638 PARAM:  T_IDENTIFIER MAYBESTATICCONSTANT {
1639      $$ = malloc(sizeof(param_t));
1640      $$->name=$1;
1641      $$->type = TYPE_ANY;
1642      $$->value = $2;
1643 }
1644 GETSET : "get" {$$=$1;}
1645        | "set" {$$=$1;}
1646        |       {$$=0;}
1647
1648 FUNCTION_DECLARATION: MAYBE_MODIFIERS "function" GETSET T_IDENTIFIER '(' MAYBE_PARAM_LIST ')' 
1649                       MAYBETYPE '{' {startfunction(0,$1,$3,$4,&$6,$8)} MAYBECODE '}' 
1650 {
1651     code_t*c = 0;
1652     if(state->method->late_binding) {
1653         c = abc_getlocal_0(c);
1654         c = abc_pushscope(c);
1655     }
1656     if(state->method->is_constructor && !state->method->has_super) {
1657         // call default constructor
1658         c = abc_getlocal_0(c);
1659         c = abc_constructsuper(c, 0);
1660     }
1661     c = wrap_function(c, state->method->initcode, $11);
1662     endfunction(0,$1,$3,$4,&$6,$8,c);
1663 }
1664
1665 /* ------------- package + class ids --------------- */
1666
1667 CLASS: T_IDENTIFIER {
1668
1669     /* try current package */
1670     $$ = find_class($1);
1671     if(!$$) syntaxerror("Could not find class %s\n", $1);
1672 }
1673
1674 PACKAGEANDCLASS : PACKAGE '.' T_IDENTIFIER {
1675     $$ = registry_findclass($1, $3);
1676     if(!$$) syntaxerror("Couldn't find class %s.%s\n", $1, $3);
1677 }
1678
1679 QNAME: PACKAGEANDCLASS
1680      | CLASS
1681
1682 QNAME_LIST : QNAME {$$=list_new();list_append($$, $1);}
1683 QNAME_LIST : QNAME_LIST ',' QNAME {$$=$1;list_append($$,$3);}
1684
1685 TYPE : QNAME      {$$=$1;}
1686      | '*'        {$$=registry_getanytype();}
1687      | "void"     {$$=registry_getanytype();}
1688     /*
1689      |  "String"  {$$=registry_getstringclass();}
1690      |  "int"     {$$=registry_getintclass();}
1691      |  "uint"    {$$=registry_getuintclass();}
1692      |  "Boolean" {$$=registry_getbooleanclass();}
1693      |  "Number"  {$$=registry_getnumberclass();}
1694     */
1695
1696 MAYBETYPE: ':' TYPE {$$=$2;}
1697 MAYBETYPE:          {$$=0;}
1698
1699 /* ----------function calls, delete, constructor calls ------ */
1700
1701 MAYBE_PARAM_VALUES :  %prec prec_none {$$=0;}
1702 MAYBE_PARAM_VALUES : '(' MAYBE_EXPRESSION_LIST ')' {$$=$2}
1703
1704 MAYBE_EXPRESSION_LIST : {$$=0;}
1705 MAYBE_EXPRESSION_LIST : EXPRESSION_LIST
1706 EXPRESSION_LIST : NONCOMMAEXPRESSION             {$$=list_new();
1707                                                   typedcode_t*t = malloc(sizeof(typedcode_t));
1708                                                   *t = $1;
1709                                                   list_append($$, t);}
1710 EXPRESSION_LIST : EXPRESSION_LIST ',' NONCOMMAEXPRESSION {$$=$1;
1711                                                   typedcode_t*t = malloc(sizeof(typedcode_t));
1712                                                   *t = $3;
1713                                                   list_append($$, t);}
1714
1715 NEW : "new" CLASS MAYBE_PARAM_VALUES {
1716     MULTINAME(m, $2);
1717     $$.c = code_new();
1718
1719     if($2->slot) {
1720         $$.c = abc_getglobalscope($$.c);
1721         $$.c = abc_getslot($$.c, $2->slot);
1722     } else {
1723         $$.c = abc_findpropstrict2($$.c, &m);
1724     }
1725
1726     typedcode_list_t*l = $3;
1727     int len = 0;
1728     while(l) {
1729         $$.c = code_append($$.c, l->typedcode->c); // push parameters on stack
1730         l = l->next;
1731         len ++;
1732     }
1733     if($2->slot)
1734         $$.c = abc_construct($$.c, len);
1735     else
1736         $$.c = abc_constructprop2($$.c, &m, len);
1737     $$.t = $2;
1738 }
1739
1740 /* TODO: use abc_call (for calling local variables),
1741          abc_callstatic (for calling own methods) 
1742          call (for closures)
1743 */
1744 FUNCTIONCALL : E '(' MAYBE_EXPRESSION_LIST ')' {
1745     typedcode_list_t*l = $3;
1746     int len = 0;
1747     code_t*paramcode = 0;
1748     while(l) {
1749         paramcode = code_append(paramcode, l->typedcode->c); // push parameters on stack
1750         l = l->next;
1751         len ++;
1752     }
1753        
1754     $$.c = $1.c;
1755     if($$.c->opcode == OPCODE_COERCE_A) {
1756         $$.c = code_cutlast($$.c);
1757     }
1758
1759     $$.t = TYPE_ANY;
1760     multiname_t*name = 0;
1761     if($$.c->opcode == OPCODE_GETPROPERTY) {
1762         name = multiname_clone($$.c->data[0]);
1763         $$.c = code_cutlast($$.c);
1764         $$.c = code_append($$.c, paramcode);
1765         $$.c = abc_callproperty2($$.c, name, len);
1766     } else if($$.c->opcode == OPCODE_GETSLOT) {
1767         int slot = (int)(ptroff_t)$$.c->data[0];
1768         trait_t*t = abc_class_find_slotid(state->cls->abc,slot);//FIXME
1769         if(t->kind!=TRAIT_METHOD) {
1770             //ok: flash allows to assign closures to members.
1771         }
1772         name = t->name;
1773         $$.c = code_cutlast($$.c);
1774         $$.c = code_append($$.c, paramcode);
1775         //$$.c = abc_callmethod($$.c, t->method, len); //#1051 illegal early access binding
1776         $$.c = abc_callproperty2($$.c, name, len);
1777     } else if($$.c->opcode == OPCODE_GETSUPER) {
1778         name = multiname_clone($$.c->data[0]);
1779         $$.c = code_cutlast($$.c);
1780         $$.c = code_append($$.c, paramcode);
1781         $$.c = abc_callsuper2($$.c, name, len);
1782     } else {
1783         $$.c = abc_getlocal_0($$.c);
1784         $$.c = code_append($$.c, paramcode);
1785         $$.c = abc_call($$.c, len);
1786     }
1787    
1788     memberinfo_t*f = 0;
1789    
1790     if(TYPE_IS_FUNCTION($1.t) && $1.t->function) {
1791         $$.t = $1.t->function->return_type;
1792     } else {
1793         $$.c = abc_coerce_a($$.c);
1794         $$.t = TYPE_ANY;
1795     }
1796 }
1797 FUNCTIONCALL : "super" '(' MAYBE_EXPRESSION_LIST ')' {
1798     if(!state->cls) syntaxerror("super() not allowed outside of a class");
1799     if(!state->method) syntaxerror("super() not allowed outside of a function");
1800     if(!state->method->is_constructor) syntaxerror("super() not allowed outside of a constructor");
1801
1802     $$.c = code_new();
1803     $$.c = abc_getlocal_0($$.c);
1804     typedcode_list_t*l = 0;
1805     int len = 0;
1806     for(l=$3;l;l=l->next) {
1807         $$.c = code_append($$.c, l->typedcode->c);len++;
1808     }
1809     /*
1810     this is dependent on the control path, check this somewhere else
1811     if(state->method->has_super)
1812         syntaxerror("constructor may call super() only once");
1813     */
1814     state->method->has_super = 1;
1815     $$.c = abc_constructsuper($$.c, len);
1816     $$.c = abc_pushundefined($$.c);
1817     $$.t = TYPE_ANY;
1818 }
1819
1820 DELETE: "delete" E {
1821     $$.c = $2.c;
1822     if($$.c->opcode == OPCODE_COERCE_A) {
1823         $$.c = code_cutlast($$.c);
1824     }
1825     multiname_t*name = 0;
1826     if($$.c->opcode == OPCODE_GETPROPERTY) {
1827         $$.c->opcode = OPCODE_DELETEPROPERTY;
1828     } else if($$.c->opcode == OPCODE_GETSLOT) {
1829         int slot = (int)(ptroff_t)$$.c->data[0];
1830         multiname_t*name = abc_class_find_slotid(state->cls->abc,slot)->name;
1831         $$.c = code_cutlast($$.c);
1832         $$.c = abc_deleteproperty2($$.c, name);
1833     } else {
1834         $$.c = abc_getlocal_0($$.c);
1835         MULTINAME_LATE(m, $2.t?$2.t->access:ACCESS_PACKAGE, "");
1836         $$.c = abc_deleteproperty2($$.c, &m);
1837     }
1838     $$.t = TYPE_BOOLEAN;
1839 }
1840
1841 RETURN: "return" %prec prec_none {
1842     $$ = abc_returnvoid(0);
1843 }
1844 RETURN: "return" EXPRESSION {
1845     $$ = $2.c;
1846     $$ = abc_returnvalue($$);
1847 }
1848
1849 // ----------------------- expression types -------------------------------------
1850
1851 NONCOMMAEXPRESSION : E        %prec below_minus {$$=$1;}
1852 EXPRESSION : E                %prec below_minus {$$ = $1;}
1853 EXPRESSION : EXPRESSION ',' E %prec below_minus {
1854     $$.c = $1.c;
1855     $$.c = cut_last_push($$.c);
1856     $$.c = code_append($$.c,$3.c);
1857     $$.t = $3.t;
1858 }
1859 VOIDEXPRESSION : EXPRESSION %prec below_minus {
1860     $$=cut_last_push($1.c);
1861 }
1862
1863 // ----------------------- expression evaluation -------------------------------------
1864
1865 E : CONSTANT
1866 E : VAR_READ %prec T_IDENTIFIER {$$ = $1;}
1867 E : NEW                         {$$ = $1;}
1868 E : DELETE                      {$$ = $1;}
1869 E : T_REGEXP                    {$$.c = abc_pushundefined(0); /* FIXME */
1870                                  $$.t = TYPE_ANY;
1871                                 }
1872
1873 CONSTANT : T_BYTE {$$.c = abc_pushbyte(0, $1);
1874                    //MULTINAME(m, registry_getintclass());
1875                    //$$.c = abc_coerce2($$.c, &m); // FIXME
1876                    $$.t = TYPE_INT;
1877                   }
1878 CONSTANT : T_SHORT {$$.c = abc_pushshort(0, $1);
1879                     $$.t = TYPE_INT;
1880                    }
1881 CONSTANT : T_INT {$$.c = abc_pushint(0, $1);
1882                   $$.t = TYPE_INT;
1883                  }
1884 CONSTANT : T_UINT {$$.c = abc_pushuint(0, $1);
1885                    $$.t = TYPE_UINT;
1886                   }
1887 CONSTANT : T_FLOAT {$$.c = abc_pushdouble(0, $1);
1888                     $$.t = TYPE_FLOAT;
1889                    }
1890 CONSTANT : T_STRING {$$.c = abc_pushstring2(0, &$1);
1891                      $$.t = TYPE_STRING;
1892                     }
1893 CONSTANT : "undefined" {$$.c = abc_pushundefined(0);
1894                     $$.t = TYPE_ANY;
1895                    }
1896 CONSTANT : "true" {$$.c = abc_pushtrue(0);
1897                     $$.t = TYPE_BOOLEAN;
1898                    }
1899 CONSTANT : "false" {$$.c = abc_pushfalse(0);
1900                      $$.t = TYPE_BOOLEAN;
1901                     }
1902 CONSTANT : "null" {$$.c = abc_pushnull(0);
1903                     $$.t = TYPE_NULL;
1904                    }
1905
1906 E : FUNCTIONCALL
1907 E : E '<' E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterequals($$.c);$$.c=abc_not($$.c);
1908              $$.t = TYPE_BOOLEAN;
1909             }
1910 E : E '>' E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterthan($$.c);
1911              $$.t = TYPE_BOOLEAN;
1912             }
1913 E : E "<=" E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterthan($$.c);$$.c=abc_not($$.c);
1914               $$.t = TYPE_BOOLEAN;
1915              }
1916 E : E ">=" E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterequals($$.c);
1917               $$.t = TYPE_BOOLEAN;
1918              }
1919 E : E "==" E {$$.c = code_append($1.c,$3.c);$$.c = abc_equals($$.c);
1920               $$.t = TYPE_BOOLEAN;
1921              }
1922 E : E "===" E {$$.c = code_append($1.c,$3.c);$$.c = abc_strictequals($$.c);
1923               $$.t = TYPE_BOOLEAN;
1924               }
1925 E : E "!==" E {$$.c = code_append($1.c,$3.c);$$.c = abc_strictequals($$.c);$$.c = abc_not($$.c);
1926               $$.t = TYPE_BOOLEAN;
1927              }
1928 E : E "!=" E {$$.c = code_append($1.c,$3.c);$$.c = abc_equals($$.c);$$.c = abc_not($$.c);
1929               $$.t = TYPE_BOOLEAN;
1930              }
1931
1932 E : E "||" E {$$.t = join_types($1.t, $3.t, 'O');
1933               $$.c = $1.c;
1934               $$.c = converttype($$.c, $1.t, $$.t);
1935               $$.c = abc_dup($$.c);
1936               code_t*jmp = $$.c = abc_iftrue($$.c, 0);
1937               $$.c = cut_last_push($$.c);
1938               $$.c = code_append($$.c,$3.c);
1939               $$.c = converttype($$.c, $3.t, $$.t);
1940               code_t*label = $$.c = abc_label($$.c);
1941               jmp->branch = label;
1942              }
1943 E : E "&&" E {
1944               $$.t = join_types($1.t, $3.t, 'A');
1945               /*printf("%08x:\n",$1.t);
1946               code_dump($1.c, 0, 0, "", stdout);
1947               printf("%08x:\n",$3.t);
1948               code_dump($3.c, 0, 0, "", stdout);
1949               printf("joining %08x and %08x to %08x\n", $1.t, $3.t, $$.t);*/
1950               $$.c = $1.c;
1951               $$.c = converttype($$.c, $1.t, $$.t);
1952               $$.c = abc_dup($$.c);
1953               code_t*jmp = $$.c = abc_iffalse($$.c, 0);
1954               $$.c = cut_last_push($$.c);
1955               $$.c = code_append($$.c,$3.c);
1956               $$.c = converttype($$.c, $3.t, $$.t);
1957               code_t*label = $$.c = abc_label($$.c);
1958               jmp->branch = label;              
1959              }
1960
1961 E : '!' E    {$$.c=$2.c;
1962               $$.c = abc_not($$.c);
1963               $$.t = TYPE_BOOLEAN;
1964              }
1965
1966 E : '~' E    {$$.c=$2.c;
1967               $$.c = abc_bitnot($$.c);
1968               $$.t = TYPE_INT;
1969              }
1970
1971 E : E '&' E {$$.c = code_append($1.c,$3.c);
1972              $$.c = abc_bitand($$.c);
1973              $$.t = TYPE_INT;
1974             }
1975
1976 E : E '^' E {$$.c = code_append($1.c,$3.c);
1977              $$.c = abc_bitxor($$.c);
1978              $$.t = TYPE_INT;
1979             }
1980
1981 E : E '|' E {$$.c = code_append($1.c,$3.c);
1982              $$.c = abc_bitor($$.c);
1983              $$.t = TYPE_INT;
1984             }
1985
1986 E : E '-' E {$$.c = code_append($1.c,$3.c);
1987              if(BOTH_INT($1,$3)) {
1988                 $$.c = abc_subtract_i($$.c);
1989                 $$.t = TYPE_INT;
1990              } else {
1991                 $$.c = abc_subtract($$.c);
1992                 $$.t = TYPE_NUMBER;
1993              }
1994             }
1995 E : E ">>" E {$$.c = code_append($1.c,$3.c);
1996              $$.c = abc_rshift($$.c);
1997              $$.t = TYPE_INT;
1998             }
1999 E : E ">>>" E {$$.c = code_append($1.c,$3.c);
2000              $$.c = abc_urshift($$.c);
2001              $$.t = TYPE_INT;
2002             }
2003 E : E "<<" E {$$.c = code_append($1.c,$3.c);
2004              $$.c = abc_lshift($$.c);
2005              $$.t = TYPE_INT;
2006             }
2007
2008 E : E '/' E {$$.c = code_append($1.c,$3.c);
2009              $$.c = abc_divide($$.c);
2010              $$.t = TYPE_NUMBER;
2011             }
2012 E : E '+' E {$$.c = code_append($1.c,$3.c);
2013              $$.c = abc_add($$.c);
2014              $$.t = TYPE_NUMBER;
2015             }
2016 E : E '%' E {$$.c = code_append($1.c,$3.c);
2017              $$.c = abc_modulo($$.c);
2018              $$.t = TYPE_NUMBER;
2019             }
2020 E : E '*' E {$$.c = code_append($1.c,$3.c);
2021              if(BOTH_INT($1,$3)) {
2022                 $$.c = abc_multiply_i($$.c);
2023                 $$.t = TYPE_INT;
2024              } else {
2025                 $$.c = abc_multiply($$.c);
2026                 $$.t = TYPE_NUMBER;
2027              }
2028             }
2029
2030 E : E "as" E {char use_astype=0; // flash player's astype works differently than astypelate
2031               if(use_astype && TYPE_IS_CLASS($3.t)) {
2032                 MULTINAME(m,$3.t->cls);
2033                 $$.c = abc_astype2($1.c, &m);
2034                 $$.t = $3.t->cls;
2035               } else {
2036                 $$.c = code_append($1.c, $3.c);
2037                 $$.c = abc_astypelate($$.c);
2038                 $$.t = TYPE_ANY;
2039               }
2040              }
2041
2042 E : E "instanceof" E 
2043              {$$.c = code_append($1.c, $3.c);
2044               $$.c = abc_instanceof($$.c);
2045               $$.t = TYPE_BOOLEAN;
2046              }
2047
2048 E : E "is" E {$$.c = code_append($1.c, $3.c);
2049               $$.c = abc_istypelate($$.c);
2050               $$.t = TYPE_BOOLEAN;
2051              }
2052
2053 E : "typeof" '(' E ')' {
2054               $$.c = $3.c;
2055               $$.c = abc_typeof($$.c);
2056               $$.t = TYPE_STRING;
2057              }
2058
2059 E : "void" E {
2060               $$.c = cut_last_push($2.c);
2061               $$.c = abc_pushundefined($$.c);
2062               $$.t = TYPE_ANY;
2063              }
2064
2065 E : "void" { $$.c = abc_pushundefined(0);
2066              $$.t = TYPE_ANY;
2067            }
2068
2069 E : '(' EXPRESSION ')' {$$=$2;} //allow commas in here, too
2070
2071 E : '-' E {
2072   $$=$2;
2073   if(IS_INT($2)) {
2074    $$.c=abc_negate_i($$.c);
2075    $$.t = TYPE_INT;
2076   } else {
2077    $$.c=abc_negate($$.c);
2078    $$.t = TYPE_NUMBER;
2079   }
2080 }
2081
2082 E : E '[' E ']' {
2083   $$.c = $1.c;
2084   $$.c = code_append($$.c, $3.c);
2085  
2086   MULTINAME_LATE(m, $1.t?$1.t->access:ACCESS_PACKAGE, "");
2087   $$.c = abc_getproperty2($$.c, &m);
2088   $$.t = 0; // array elements have unknown type
2089 }
2090
2091 E : '[' MAYBE_EXPRESSION_LIST ']' {
2092     $$.c = code_new();
2093     typedcode_list_t*l = 0;
2094     int len = 0;
2095     for(l=$2;l;l=l->next) {
2096         $$.c = code_append($$.c, l->typedcode->c);len++;
2097     }
2098     $$.c = abc_newarray($$.c, len);
2099     $$.t = registry_getarrayclass();
2100 }
2101
2102 MAYBE_EXPRPAIR_LIST : {$$=0;}
2103 MAYBE_EXPRPAIR_LIST : EXPRPAIR_LIST {$$=$1};
2104
2105 EXPRPAIR_LIST : NONCOMMAEXPRESSION ':' NONCOMMAEXPRESSION {
2106     typedcode_t*t1 = malloc(sizeof(typedcode_t));*t1 = $1;
2107     typedcode_t*t2 = malloc(sizeof(typedcode_t));*t2 = $3;
2108     $$ = 0;
2109     list_append($$, t1);
2110     list_append($$, t2);
2111 }
2112 EXPRPAIR_LIST : EXPRPAIR_LIST ',' NONCOMMAEXPRESSION ':' NONCOMMAEXPRESSION {
2113     $$=$1;
2114     typedcode_t*t1 = malloc(sizeof(typedcode_t));*t1 = $3;
2115     typedcode_t*t2 = malloc(sizeof(typedcode_t));*t2 = $5;
2116     list_append($$, t1);
2117     list_append($$, t2);
2118 }
2119 //MAYBECOMMA: ','
2120 //MAYBECOMMA:
2121
2122 E : '{' MAYBE_EXPRPAIR_LIST '}' {
2123     $$.c = code_new();
2124     typedcode_list_t*l = 0;
2125     int len = 0;
2126     for(l=$2;l;l=l->next) {
2127         $$.c = code_append($$.c, l->typedcode->c);len++;
2128     }
2129     $$.c = abc_newobject($$.c, len/2);
2130     $$.t = registry_getobjectclass();
2131 }
2132
2133 E : E "*=" E { 
2134                code_t*c = $3.c;
2135                if(BOTH_INT($1,$3)) {
2136                 c=abc_multiply_i(c);
2137                } else {
2138                 c=abc_multiply(c);
2139                }
2140                c=converttype(c, join_types($1.t, $3.t, '*'), $1.t);
2141                $$.c = toreadwrite($1.c, c, 0, 0);
2142                $$.t = $1.t;
2143               }
2144
2145 E : E "%=" E { 
2146                code_t*c = abc_modulo($3.c);
2147                c=converttype(c, join_types($1.t, $3.t, '%'), $1.t);
2148                $$.c = toreadwrite($1.c, c, 0, 0);
2149                $$.t = $1.t;
2150               }
2151 E : E "<<=" E { 
2152                code_t*c = abc_lshift($3.c);
2153                c=converttype(c, join_types($1.t, $3.t, '<'), $1.t);
2154                $$.c = toreadwrite($1.c, c, 0, 0);
2155                $$.t = $1.t;
2156               }
2157 E : E ">>=" E { 
2158                code_t*c = abc_rshift($3.c);
2159                c=converttype(c, join_types($1.t, $3.t, '>'), $1.t);
2160                $$.c = toreadwrite($1.c, c, 0, 0);
2161                $$.t = $1.t;
2162               }
2163 E : E ">>>=" E { 
2164                code_t*c = abc_urshift($3.c);
2165                c=converttype(c, join_types($1.t, $3.t, 'U'), $1.t);
2166                $$.c = toreadwrite($1.c, c, 0, 0);
2167                $$.t = $1.t;
2168               }
2169 E : E "/=" E { 
2170                code_t*c = abc_divide($3.c);
2171                c=converttype(c, join_types($1.t, $3.t, '/'), $1.t);
2172                $$.c = toreadwrite($1.c, c, 0, 0);
2173                $$.t = $1.t;
2174               }
2175 E : E "+=" E { 
2176                code_t*c = $3.c;
2177                if(TYPE_IS_INT($3.t) || TYPE_IS_UINT($3.t)) {
2178                 c=abc_add_i(c);
2179                } else {
2180                 c=abc_add(c);
2181                }
2182                c=converttype(c, join_types($1.t, $3.t, '+'), $1.t);
2183                
2184                $$.c = toreadwrite($1.c, c, 0, 0);
2185                $$.t = $1.t;
2186               }
2187 E : E "-=" E { code_t*c = $3.c; 
2188                if(TYPE_IS_INT($3.t) || TYPE_IS_UINT($3.t)) {
2189                 c=abc_subtract_i(c);
2190                } else {
2191                 c=abc_subtract(c);
2192                }
2193                c=converttype(c, join_types($1.t, $3.t, '-'), $1.t);
2194                
2195                $$.c = toreadwrite($1.c, c, 0, 0);
2196                $$.t = $1.t;
2197              }
2198 E : E '=' E { code_t*c = 0;
2199               c = code_append(c, $3.c);
2200               c = converttype(c, $3.t, $1.t);
2201               $$.c = toreadwrite($1.c, c, 1, 0);
2202               $$.t = $1.t;
2203             }
2204
2205 E : E '?' E ':' E %prec below_assignment { 
2206               $$.c = $1.c;
2207               code_t*j1 = $$.c = abc_iffalse($$.c, 0);
2208               $$.c = code_append($$.c, $3.c);
2209               code_t*j2 = $$.c = abc_jump($$.c, 0);
2210               $$.c = j1->branch = abc_label($$.c);
2211               $$.c = code_append($$.c, $5.c);
2212               $$.c = j2->branch = abc_label($$.c);
2213               $$.t = join_types($3.t,$5.t,'?');
2214             }
2215
2216 // TODO: use inclocal where appropriate
2217 E : E "++" { code_t*c = 0;
2218              classinfo_t*type = $1.t;
2219              if(TYPE_IS_INT(type) || TYPE_IS_UINT(type)) {
2220                  c=abc_increment_i(c);
2221                  type = TYPE_INT;
2222              } else {
2223                  c=abc_increment(c);
2224                  type = TYPE_NUMBER;
2225              }
2226              c=converttype(c, type, $1.t);
2227              $$.c = toreadwrite($1.c, c, 0, 1);
2228              $$.t = $1.t;
2229            }
2230 E : E "--" { code_t*c = 0;
2231              classinfo_t*type = $1.t;
2232              if(TYPE_IS_INT(type) || TYPE_IS_UINT(type)) {
2233                  c=abc_decrement_i(c);
2234                  type = TYPE_INT;
2235              } else {
2236                  c=abc_decrement(c);
2237                  type = TYPE_NUMBER;
2238              }
2239              c=converttype(c, type, $1.t);
2240              $$.c = toreadwrite($1.c, c, 0, 1);
2241              $$.t = $1.t;
2242             }
2243
2244 E : "++" %prec plusplus_prefix E { code_t*c = 0;
2245              classinfo_t*type = $2.t;
2246              if(TYPE_IS_INT(type) || TYPE_IS_UINT(type)) {
2247                  c=abc_increment_i(c);
2248                  type = TYPE_INT;
2249              } else {
2250                  c=abc_increment(c);
2251                  type = TYPE_NUMBER;
2252              }
2253              c=converttype(c, type, $2.t);
2254              $$.c = toreadwrite($2.c, c, 0, 0);
2255              $$.t = $2.t;
2256            }
2257
2258 E : "--" %prec minusminus_prefix E { code_t*c = 0;
2259              classinfo_t*type = $2.t;
2260              if(TYPE_IS_INT(type) || TYPE_IS_UINT(type)) {
2261                  c=abc_decrement_i(c);
2262                  type = TYPE_INT;
2263              } else {
2264                  c=abc_decrement(c);
2265                  type = TYPE_NUMBER;
2266              }
2267              c=converttype(c, type, $2.t);
2268              $$.c = toreadwrite($2.c, c, 0, 0);
2269              $$.t = $2.t;
2270            }
2271
2272 E : "super" '.' T_IDENTIFIER 
2273            { if(!state->cls->info)
2274                   syntaxerror("super keyword not allowed outside a class");
2275               classinfo_t*t = state->cls->info->superclass;
2276               if(!t) t = TYPE_OBJECT;
2277
2278               memberinfo_t*f = registry_findmember(t, $3, 1);
2279               namespace_t ns = {flags2access(f->flags), ""};
2280               MEMBER_MULTINAME(m, f, $3);
2281               $$.c = 0;
2282               $$.c = abc_getlocal_0($$.c);
2283               $$.c = abc_getsuper2($$.c, &m);
2284               $$.t = memberinfo_gettype(f);
2285            }
2286
2287 E : E '.' T_IDENTIFIER
2288             {$$.c = $1.c;
2289              classinfo_t*t = $1.t;
2290              char is_static = 0;
2291              if(TYPE_IS_CLASS(t) && t->cls) {
2292                  t = t->cls;
2293                  is_static = 1;
2294              }
2295              if(t) {
2296                  memberinfo_t*f = registry_findmember(t, $3, 1);
2297                  char noslot = 0;
2298                  if(f && !is_static != !(f->flags&FLAG_STATIC))
2299                     noslot=1;
2300                  if(f && f->slot && !noslot) {
2301                      $$.c = abc_getslot($$.c, f->slot);
2302                  } else {
2303                      MEMBER_MULTINAME(m, f, $3);
2304                      $$.c = abc_getproperty2($$.c, &m);
2305                  }
2306                  /* determine type */
2307                  $$.t = memberinfo_gettype(f);
2308                  if(!$$.t)
2309                     $$.c = abc_coerce_a($$.c);
2310              } else {
2311                  /* when resolving a property on an unknown type, we do know the
2312                     name of the property (and don't seem to need the package), but
2313                     we need to make avm2 try out all access modes */
2314                  multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $3};
2315                  $$.c = abc_getproperty2($$.c, &m);
2316                  $$.c = abc_coerce_a($$.c);
2317                  $$.t = registry_getanytype();
2318              }
2319             }
2320
2321 VAR_READ : T_IDENTIFIER {
2322     $$.t = 0;
2323     $$.c = 0;
2324     int i;
2325     classinfo_t*a = 0;
2326     memberinfo_t*f = 0;
2327
2328     /* look at variables */
2329     if((i = find_variable($1, &$$.t)) >= 0) {
2330         // $1 is a local variable
2331         $$.c = abc_getlocal($$.c, i);
2332
2333     /* look at current class' members */
2334     } else if((f = registry_findmember(state->cls->info, $1, 1))) {
2335         // $1 is a function in this class
2336         int var_is_static = (f->flags&FLAG_STATIC);
2337         int i_am_static = ((state->method && state->method->info)?(state->method->info->flags&FLAG_STATIC):FLAG_STATIC);
2338         if(var_is_static != i_am_static) {
2339             /* there doesn't seem to be any "static" way to access
2340                static properties of a class */
2341             state->method->late_binding = 1;
2342             $$.t = f->type;
2343             namespace_t ns = {flags2access(f->flags), ""};
2344             multiname_t m = {QNAME, &ns, 0, $1};
2345             $$.c = abc_findpropstrict2($$.c, &m);
2346             $$.c = abc_getproperty2($$.c, &m);
2347         } else {
2348             if(f->slot>0) {
2349                 $$.c = abc_getlocal_0($$.c);
2350                 $$.c = abc_getslot($$.c, f->slot);
2351             } else {
2352                 namespace_t ns = {flags2access(f->flags), ""};
2353                 multiname_t m = {QNAME, &ns, 0, $1};
2354                 $$.c = abc_getlocal_0($$.c);
2355                 $$.c = abc_getproperty2($$.c, &m);
2356             }
2357         }
2358         if(f->kind == MEMBER_METHOD) {
2359             $$.t = TYPE_FUNCTION(f);
2360         } else {
2361             $$.t = f->type;
2362         }
2363     
2364     /* look at actual classes, in the current package and imported */
2365     } else if((a = find_class($1))) {
2366         if(a->flags & FLAG_METHOD) {
2367             MULTINAME(m, a);
2368             $$.c = abc_findpropstrict2($$.c, &m);
2369             $$.c = abc_getproperty2($$.c, &m);
2370             $$.t = TYPE_FUNCTION(a->function);
2371         } else {
2372             if(a->slot) {
2373                 $$.c = abc_getglobalscope($$.c);
2374                 $$.c = abc_getslot($$.c, a->slot);
2375             } else {
2376                 MULTINAME(m, a);
2377                 $$.c = abc_getlex2($$.c, &m);
2378             }
2379             $$.t = TYPE_CLASS(a);
2380         }
2381
2382     /* unknown object, let the avm2 resolve it */
2383     } else {
2384         if(strcmp($1,"trace"))
2385             warning("Couldn't resolve '%s', doing late binding", $1);
2386         state->method->late_binding = 1;
2387                 
2388         multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $1};
2389
2390         $$.t = 0;
2391         $$.c = abc_findpropstrict2($$.c, &m);
2392         $$.c = abc_getproperty2($$.c, &m);
2393     }
2394 }
2395
2396 //TODO: 
2397 //VARIABLE : VARIABLE ".." T_IDENTIFIER // descendants
2398 //VARIABLE : VARIABLE "::" VARIABLE // namespace declaration
2399 //VARIABLE : VARIABLE "::" '[' EXPRESSION ']' // qualified expression
2400
2401 // ----------------- namespaces -------------------------------------------------
2402
2403 NAMESPACE_DECLARATION : MAYBE_MODIFIERS "namespace" T_IDENTIFIER {$$=$2;}
2404 NAMESPACE_DECLARATION : MAYBE_MODIFIERS "namespace" T_IDENTIFIER '=' T_IDENTIFIER {$$=$2;}
2405 NAMESPACE_DECLARATION : MAYBE_MODIFIERS "namespace" T_IDENTIFIER '=' T_STRING {$$=$2;}
2406
2407 USE_NAMESPACE : "use" "namespace" T_IDENTIFIER
2408