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