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