jscript: Get rid of stat_eval_table.
[wine] / dlls / jscript / compile.c
1 /*
2  * Copyright 2011 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include <math.h>
20 #include <assert.h>
21
22 #include "jscript.h"
23 #include "engine.h"
24
25 #include "wine/debug.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
28
29 typedef struct _statement_ctx_t {
30     unsigned stack_use;
31     BOOL using_scope;
32     BOOL using_except;
33
34     unsigned break_label;
35     unsigned continue_label;
36
37     struct _statement_ctx_t *next;
38 } statement_ctx_t;
39
40 struct _compiler_ctx_t {
41     parser_ctx_t *parser;
42     bytecode_t *code;
43
44     unsigned code_off;
45     unsigned code_size;
46
47     unsigned *labels;
48     unsigned labels_size;
49     unsigned labels_cnt;
50
51     statement_ctx_t *stat_ctx;
52 };
53
54 static const struct {
55     const char *op_str;
56     instr_arg_type_t arg1_type;
57     instr_arg_type_t arg2_type;
58 } instr_info[] = {
59 #define X(n,a,b,c) {#n,b,c},
60 OP_LIST
61 #undef X
62 };
63
64 static HRESULT compile_expression(compiler_ctx_t*,expression_t*);
65 static HRESULT compile_statement(compiler_ctx_t*,statement_ctx_t*,statement_t*);
66
67 static inline void *compiler_alloc(bytecode_t *code, size_t size)
68 {
69     return jsheap_alloc(&code->heap, size);
70 }
71
72 static WCHAR *compiler_alloc_string(bytecode_t *code, const WCHAR *str)
73 {
74     size_t size;
75     WCHAR *ret;
76
77     size = (strlenW(str)+1)*sizeof(WCHAR);
78     ret = compiler_alloc(code, size);
79     if(ret)
80         memcpy(ret, str, size);
81     return ret;
82 }
83
84 static BSTR compiler_alloc_bstr(compiler_ctx_t *ctx, const WCHAR *str)
85 {
86     if(!ctx->code->bstr_pool_size) {
87         ctx->code->bstr_pool = heap_alloc(8 * sizeof(BSTR));
88         if(!ctx->code->bstr_pool)
89             return NULL;
90         ctx->code->bstr_pool_size = 8;
91     }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) {
92         BSTR *new_pool;
93
94         new_pool = heap_realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR));
95         if(!new_pool)
96             return NULL;
97
98         ctx->code->bstr_pool = new_pool;
99         ctx->code->bstr_pool_size *= 2;
100     }
101
102     ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocString(str);
103     if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
104         return NULL;
105
106     return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
107 }
108
109 static unsigned push_instr(compiler_ctx_t *ctx, jsop_t op)
110 {
111     assert(ctx->code_size >= ctx->code_off);
112
113     if(!ctx->code_size) {
114         ctx->code->instrs = heap_alloc(64 * sizeof(instr_t));
115         if(!ctx->code->instrs)
116             return -1;
117         ctx->code_size = 64;
118     }else if(ctx->code_size == ctx->code_off) {
119         instr_t *new_instrs;
120
121         new_instrs = heap_realloc(ctx->code->instrs, ctx->code_size*2*sizeof(instr_t));
122         if(!new_instrs)
123             return -1;
124
125         ctx->code->instrs = new_instrs;
126         ctx->code_size *= 2;
127     }
128
129     ctx->code->instrs[ctx->code_off].op = op;
130     return ctx->code_off++;
131 }
132
133 static inline instr_t *instr_ptr(compiler_ctx_t *ctx, unsigned off)
134 {
135     assert(off < ctx->code_off);
136     return ctx->code->instrs + off;
137 }
138
139 static HRESULT push_instr_int(compiler_ctx_t *ctx, jsop_t op, LONG arg)
140 {
141     unsigned instr;
142
143     instr = push_instr(ctx, op);
144     if(instr == -1)
145         return E_OUTOFMEMORY;
146
147     instr_ptr(ctx, instr)->arg1.lng = arg;
148     return S_OK;
149 }
150
151 static HRESULT push_instr_str(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg)
152 {
153     unsigned instr;
154     WCHAR *str;
155
156     str = compiler_alloc_string(ctx->code, arg);
157     if(!str)
158         return E_OUTOFMEMORY;
159
160     instr = push_instr(ctx, op);
161     if(instr == -1)
162         return E_OUTOFMEMORY;
163
164     instr_ptr(ctx, instr)->arg1.str = str;
165     return S_OK;
166 }
167
168 static HRESULT push_instr_bstr(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg)
169 {
170     unsigned instr;
171     WCHAR *str;
172
173     str = compiler_alloc_bstr(ctx, arg);
174     if(!str)
175         return E_OUTOFMEMORY;
176
177     instr = push_instr(ctx, op);
178     if(instr == -1)
179         return E_OUTOFMEMORY;
180
181     instr_ptr(ctx, instr)->arg1.bstr = str;
182     return S_OK;
183 }
184
185 static HRESULT push_instr_bstr_uint(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg1, unsigned arg2)
186 {
187     unsigned instr;
188     WCHAR *str;
189
190     str = compiler_alloc_bstr(ctx, arg1);
191     if(!str)
192         return E_OUTOFMEMORY;
193
194     instr = push_instr(ctx, op);
195     if(instr == -1)
196         return E_OUTOFMEMORY;
197
198     instr_ptr(ctx, instr)->arg1.bstr = str;
199     instr_ptr(ctx, instr)->arg2.uint = arg2;
200     return S_OK;
201 }
202
203 static HRESULT push_instr_uint_str(compiler_ctx_t *ctx, jsop_t op, unsigned arg1, const WCHAR *arg2)
204 {
205     unsigned instr;
206     WCHAR *str;
207
208     str = compiler_alloc_string(ctx->code, arg2);
209     if(!str)
210         return E_OUTOFMEMORY;
211
212     instr = push_instr(ctx, op);
213     if(instr == -1)
214         return E_OUTOFMEMORY;
215
216     instr_ptr(ctx, instr)->arg1.uint = arg1;
217     instr_ptr(ctx, instr)->arg2.str = str;
218     return S_OK;
219 }
220
221 static HRESULT push_instr_double(compiler_ctx_t *ctx, jsop_t op, double arg)
222 {
223     unsigned instr;
224     DOUBLE *dbl;
225
226     dbl = compiler_alloc(ctx->code, sizeof(arg));
227     if(!dbl)
228         return E_OUTOFMEMORY;
229     *dbl = arg;
230
231     instr = push_instr(ctx, op);
232     if(instr == -1)
233         return E_OUTOFMEMORY;
234
235     instr_ptr(ctx, instr)->arg1.dbl = dbl;
236     return S_OK;
237 }
238
239 static HRESULT push_instr_uint(compiler_ctx_t *ctx, jsop_t op, unsigned arg)
240 {
241     unsigned instr;
242
243     instr = push_instr(ctx, op);
244     if(instr == -1)
245         return E_OUTOFMEMORY;
246
247     instr_ptr(ctx, instr)->arg1.uint = arg;
248     return S_OK;
249 }
250
251 static HRESULT compile_binary_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
252 {
253     HRESULT hres;
254
255     hres = compile_expression(ctx, expr->expression1);
256     if(FAILED(hres))
257         return hres;
258
259     hres = compile_expression(ctx, expr->expression2);
260     if(FAILED(hres))
261         return hres;
262
263     return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK;
264 }
265
266 static HRESULT compile_unary_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op)
267 {
268     HRESULT hres;
269
270     hres = compile_expression(ctx, expr->expression);
271     if(FAILED(hres))
272         return hres;
273
274     return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK;
275 }
276
277 /* ECMA-262 3rd Edition    11.2.1 */
278 static HRESULT compile_member_expression(compiler_ctx_t *ctx, member_expression_t *expr)
279 {
280     HRESULT hres;
281
282     hres = compile_expression(ctx, expr->expression);
283     if(FAILED(hres))
284         return hres;
285
286     return push_instr_bstr(ctx, OP_member, expr->identifier);
287 }
288
289 #define LABEL_FLAG 0x80000000
290
291 static unsigned alloc_label(compiler_ctx_t *ctx)
292 {
293     if(!ctx->labels_size) {
294         ctx->labels = heap_alloc(8 * sizeof(*ctx->labels));
295         if(!ctx->labels)
296             return -1;
297         ctx->labels_size = 8;
298     }else if(ctx->labels_size == ctx->labels_cnt) {
299         unsigned *new_labels;
300
301         new_labels = heap_realloc(ctx->labels, 2*ctx->labels_size*sizeof(*ctx->labels));
302         if(!new_labels)
303             return -1;
304
305         ctx->labels = new_labels;
306         ctx->labels_size *= 2;
307     }
308
309     return ctx->labels_cnt++ | LABEL_FLAG;
310 }
311
312 static void label_set_addr(compiler_ctx_t *ctx, unsigned label)
313 {
314     assert(label & LABEL_FLAG);
315     ctx->labels[label & ~LABEL_FLAG] = ctx->code_off;
316 }
317
318 static inline BOOL is_memberid_expr(expression_type_t type)
319 {
320     return type == EXPR_IDENT || type == EXPR_MEMBER || type == EXPR_ARRAY;
321 }
322
323 static HRESULT compile_memberid_expression(compiler_ctx_t *ctx, expression_t *expr, unsigned flags)
324 {
325     HRESULT hres = S_OK;
326
327     switch(expr->type) {
328     case EXPR_IDENT: {
329         identifier_expression_t *ident_expr = (identifier_expression_t*)expr;
330
331         hres = push_instr_bstr_uint(ctx, OP_identid, ident_expr->identifier, flags);
332         break;
333     }
334     case EXPR_ARRAY: {
335         binary_expression_t *array_expr = (binary_expression_t*)expr;
336
337         hres = compile_expression(ctx, array_expr->expression1);
338         if(FAILED(hres))
339             return hres;
340
341         hres = compile_expression(ctx, array_expr->expression2);
342         if(FAILED(hres))
343             return hres;
344
345         hres = push_instr_uint(ctx, OP_memberid, flags);
346         break;
347     }
348     case EXPR_MEMBER: {
349         member_expression_t *member_expr = (member_expression_t*)expr;
350
351         hres = compile_expression(ctx, member_expr->expression);
352         if(FAILED(hres))
353             return hres;
354
355         /* FIXME: Potential optimization */
356         hres = push_instr_str(ctx, OP_str, member_expr->identifier);
357         if(FAILED(hres))
358             return hres;
359
360         hres = push_instr_uint(ctx, OP_memberid, flags);
361         break;
362     }
363     default:
364         assert(0);
365     }
366
367     return hres;
368 }
369
370 static HRESULT compile_increment_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op, int n)
371 {
372     HRESULT hres;
373
374     if(!is_memberid_expr(expr->expression->type)) {
375         hres = compile_expression(ctx, expr->expression);
376         if(FAILED(hres))
377             return hres;
378
379         return push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
380     }
381
382     hres = compile_memberid_expression(ctx, expr->expression, fdexNameEnsure);
383     if(FAILED(hres))
384         return hres;
385
386     return push_instr_int(ctx, op, n);
387 }
388
389 /* ECMA-262 3rd Edition    11.14 */
390 static HRESULT compile_comma_expression(compiler_ctx_t *ctx, binary_expression_t *expr)
391 {
392     HRESULT hres;
393
394     hres = compile_expression(ctx, expr->expression1);
395     if(FAILED(hres))
396         return hres;
397
398     if(push_instr(ctx, OP_pop) == -1)
399         return E_OUTOFMEMORY;
400
401     return compile_expression(ctx, expr->expression2);
402 }
403
404 /* ECMA-262 3rd Edition    11.11 */
405 static HRESULT compile_logical_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
406 {
407     unsigned instr;
408     HRESULT hres;
409
410     hres = compile_expression(ctx, expr->expression1);
411     if(FAILED(hres))
412         return hres;
413
414     instr = push_instr(ctx, op);
415     if(instr == -1)
416         return E_OUTOFMEMORY;
417
418     hres = compile_expression(ctx, expr->expression2);
419     if(FAILED(hres))
420         return hres;
421
422     instr_ptr(ctx, instr)->arg1.uint = ctx->code_off;
423     return S_OK;
424 }
425
426 /* ECMA-262 3rd Edition    11.12 */
427 static HRESULT compile_conditional_expression(compiler_ctx_t *ctx, conditional_expression_t *expr)
428 {
429     unsigned jmp_false, jmp_end;
430     HRESULT hres;
431
432     hres = compile_expression(ctx, expr->expression);
433     if(FAILED(hres))
434         return hres;
435
436     jmp_false = push_instr(ctx, OP_cnd_z);
437     if(jmp_false == -1)
438         return E_OUTOFMEMORY;
439
440     hres = compile_expression(ctx, expr->true_expression);
441     if(FAILED(hres))
442         return hres;
443
444     jmp_end = push_instr(ctx, OP_jmp);
445     if(jmp_end == -1)
446         return E_OUTOFMEMORY;
447
448     instr_ptr(ctx, jmp_false)->arg1.uint = ctx->code_off;
449     if(push_instr(ctx, OP_pop) == -1)
450         return E_OUTOFMEMORY;
451
452     hres = compile_expression(ctx, expr->false_expression);
453     if(FAILED(hres))
454         return hres;
455
456     instr_ptr(ctx, jmp_end)->arg1.uint = ctx->code_off;
457     return S_OK;
458 }
459
460 static HRESULT compile_new_expression(compiler_ctx_t *ctx, call_expression_t *expr)
461 {
462     unsigned arg_cnt = 0;
463     argument_t *arg;
464     HRESULT hres;
465
466     hres = compile_expression(ctx, expr->expression);
467     if(FAILED(hres))
468         return hres;
469
470     for(arg = expr->argument_list; arg; arg = arg->next) {
471         hres = compile_expression(ctx, arg->expr);
472         if(FAILED(hres))
473             return hres;
474         arg_cnt++;
475     }
476
477     return push_instr_int(ctx, OP_new, arg_cnt);
478 }
479
480 static HRESULT compile_interp_fallback(compiler_ctx_t *ctx, statement_t *stat)
481 {
482     unsigned instr;
483
484     instr = push_instr(ctx, OP_tree);
485     if(instr == -1)
486         return E_OUTOFMEMORY;
487
488     instr_ptr(ctx, instr)->arg1.stat = stat;
489     return S_OK;
490 }
491
492 static HRESULT compile_call_expression(compiler_ctx_t *ctx, call_expression_t *expr, BOOL *no_ret)
493 {
494     unsigned arg_cnt = 0;
495     argument_t *arg;
496     unsigned instr;
497     jsop_t op;
498     HRESULT hres;
499
500     if(is_memberid_expr(expr->expression->type)) {
501         op = OP_call_member;
502         hres = compile_memberid_expression(ctx, expr->expression, 0);
503     }else {
504         op = OP_call;
505         hres = compile_expression(ctx, expr->expression);
506     }
507
508     if(FAILED(hres))
509         return hres;
510
511     for(arg = expr->argument_list; arg; arg = arg->next) {
512         hres = compile_expression(ctx, arg->expr);
513         if(FAILED(hres))
514             return hres;
515         arg_cnt++;
516     }
517
518     instr = push_instr(ctx, op);
519     if(instr == -1)
520         return E_OUTOFMEMORY;
521
522     instr_ptr(ctx, instr)->arg1.uint = arg_cnt;
523     instr_ptr(ctx, instr)->arg2.lng = no_ret == NULL;
524     if(no_ret)
525         *no_ret = TRUE;
526     return S_OK;
527 }
528
529 static HRESULT compile_delete_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
530 {
531     HRESULT hres;
532
533     switch(expr->expression->type) {
534     case EXPR_ARRAY: {
535         binary_expression_t *array_expr = (binary_expression_t*)expr->expression;
536
537         hres = compile_expression(ctx, array_expr->expression1);
538         if(FAILED(hres))
539             return hres;
540
541         hres = compile_expression(ctx, array_expr->expression2);
542         if(FAILED(hres))
543             return hres;
544
545         if(push_instr(ctx, OP_delete) == -1)
546             return E_OUTOFMEMORY;
547         break;
548     }
549     case EXPR_MEMBER: {
550         member_expression_t *member_expr = (member_expression_t*)expr->expression;
551
552         hres = compile_expression(ctx, member_expr->expression);
553         if(FAILED(hres))
554             return hres;
555
556         /* FIXME: Potential optimization */
557         hres = push_instr_str(ctx, OP_str, member_expr->identifier);
558         if(FAILED(hres))
559             return hres;
560
561         if(push_instr(ctx, OP_delete) == -1)
562             return E_OUTOFMEMORY;
563         break;
564     }
565     case EXPR_IDENT:
566         return push_instr_bstr(ctx, OP_delete_ident, ((identifier_expression_t*)expr->expression)->identifier);
567     default: {
568         const WCHAR fixmeW[] = {'F','I','X','M','E',0};
569
570         WARN("invalid delete, unimplemented exception message\n");
571
572         hres = compile_expression(ctx, expr->expression);
573         if(FAILED(hres))
574             return hres;
575
576         return push_instr_uint_str(ctx, OP_throw_type, JS_E_INVALID_DELETE, fixmeW);
577     }
578     }
579
580     return S_OK;
581 }
582
583 static HRESULT compile_assign_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
584 {
585     HRESULT hres;
586
587     if(!is_memberid_expr(expr->expression1->type)) {
588         hres = compile_expression(ctx, expr->expression1);
589         if(FAILED(hres))
590             return hres;
591
592         hres = compile_expression(ctx, expr->expression2);
593         if(FAILED(hres))
594             return hres;
595
596         if(op != OP_LAST && push_instr(ctx, op) == -1)
597             return E_OUTOFMEMORY;
598
599         return push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
600     }
601
602     hres = compile_memberid_expression(ctx, expr->expression1, fdexNameEnsure);
603     if(FAILED(hres))
604         return hres;
605
606     if(op != OP_LAST && push_instr(ctx, OP_refval) == -1)
607         return E_OUTOFMEMORY;
608
609     hres = compile_expression(ctx, expr->expression2);
610     if(FAILED(hres))
611         return hres;
612
613     if(op != OP_LAST && push_instr(ctx, op) == -1)
614         return E_OUTOFMEMORY;
615
616     if(push_instr(ctx, OP_assign) == -1)
617         return E_OUTOFMEMORY;
618
619     return S_OK;
620 }
621
622 static HRESULT compile_typeof_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
623 {
624     jsop_t op;
625     HRESULT hres;
626
627     if(is_memberid_expr(expr->expression->type)) {
628         if(expr->expression->type == EXPR_IDENT)
629             return push_instr_str(ctx, OP_typeofident, ((identifier_expression_t*)expr->expression)->identifier);
630
631         op = OP_typeofid;
632         hres = compile_memberid_expression(ctx, expr->expression, 0);
633     }else {
634         op = OP_typeof;
635         hres = compile_expression(ctx, expr->expression);
636     }
637     if(FAILED(hres))
638         return hres;
639
640     return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK;
641 }
642
643 static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal)
644 {
645     switch(literal->type) {
646     case LT_BOOL:
647         return push_instr_int(ctx, OP_bool, literal->u.bval);
648     case LT_DOUBLE:
649         return push_instr_double(ctx, OP_double, literal->u.dval);
650     case LT_INT:
651         return push_instr_int(ctx, OP_int, literal->u.lval);
652     case LT_NULL:
653         return push_instr(ctx, OP_null);
654     case LT_STRING:
655         return push_instr_str(ctx, OP_str, literal->u.wstr);
656     case LT_REGEXP: {
657         unsigned instr;
658         WCHAR *str;
659
660         str = compiler_alloc(ctx->code, (literal->u.regexp.str_len+1)*sizeof(WCHAR));
661         if(!str)
662             return E_OUTOFMEMORY;
663         memcpy(str, literal->u.regexp.str, literal->u.regexp.str_len*sizeof(WCHAR));
664         str[literal->u.regexp.str_len] = 0;
665
666         instr = push_instr(ctx, OP_regexp);
667         if(instr == -1)
668             return E_OUTOFMEMORY;
669
670         instr_ptr(ctx, instr)->arg1.str = str;
671         instr_ptr(ctx, instr)->arg2.lng = literal->u.regexp.flags;
672         return S_OK;
673     }
674     default:
675         assert(0);
676     }
677 }
678
679 static HRESULT literal_as_bstr(compiler_ctx_t *ctx, literal_t *literal, BSTR *str)
680 {
681     switch(literal->type) {
682     case LT_STRING:
683         *str = compiler_alloc_bstr(ctx, literal->u.wstr);
684         break;
685     case LT_INT:
686         *str = int_to_bstr(literal->u.lval);
687         break;
688     case LT_DOUBLE:
689         return double_to_bstr(literal->u.dval, str);
690     default:
691         assert(0);
692     }
693
694     return *str ? S_OK : E_OUTOFMEMORY;
695 }
696
697 static HRESULT compile_array_literal(compiler_ctx_t *ctx, array_literal_expression_t *expr)
698 {
699     unsigned i, elem_cnt = expr->length;
700     array_element_t *iter;
701     HRESULT hres;
702
703     for(iter = expr->element_list; iter; iter = iter->next) {
704         elem_cnt += iter->elision+1;
705
706         for(i=0; i < iter->elision; i++) {
707             if(push_instr(ctx, OP_undefined) == -1)
708                 return E_OUTOFMEMORY;
709         }
710
711         hres = compile_expression(ctx, iter->expr);
712         if(FAILED(hres))
713             return hres;
714     }
715
716     for(i=0; i < expr->length; i++) {
717         if(push_instr(ctx, OP_undefined) == -1)
718             return E_OUTOFMEMORY;
719     }
720
721     return push_instr_uint(ctx, OP_carray, elem_cnt);
722 }
723
724 static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expression_t *expr)
725 {
726     prop_val_t *iter;
727     unsigned instr;
728     BSTR name;
729     HRESULT hres;
730
731     if(push_instr(ctx, OP_new_obj) == -1)
732         return E_OUTOFMEMORY;
733
734     for(iter = expr->property_list; iter; iter = iter->next) {
735         hres = literal_as_bstr(ctx, iter->name, &name);
736         if(FAILED(hres))
737             return hres;
738
739         hres = compile_expression(ctx, iter->value);
740         if(FAILED(hres))
741             return hres;
742
743         instr = push_instr(ctx, OP_obj_prop);
744         if(instr == -1)
745             return E_OUTOFMEMORY;
746
747         instr_ptr(ctx, instr)->arg1.bstr = name;
748     }
749
750     return S_OK;
751 }
752
753 static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr)
754 {
755     unsigned instr;
756
757     /* FIXME: not exactly right */
758     if(expr->identifier)
759         return push_instr_bstr(ctx, OP_ident, expr->identifier);
760
761     instr = push_instr(ctx, OP_func);
762     if(instr == -1)
763         return E_OUTOFMEMORY;
764
765     instr_ptr(ctx, instr)->arg1.func = expr;
766     return S_OK;
767 }
768
769 static HRESULT compile_expression_noret(compiler_ctx_t *ctx, expression_t *expr, BOOL *no_ret)
770 {
771     switch(expr->type) {
772     case EXPR_ADD:
773         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add);
774     case EXPR_AND:
775         return compile_logical_expression(ctx, (binary_expression_t*)expr, OP_cnd_z);
776     case EXPR_ARRAY:
777         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_array);
778     case EXPR_ARRAYLIT:
779         return compile_array_literal(ctx, (array_literal_expression_t*)expr);
780     case EXPR_ASSIGN:
781         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_LAST);
782     case EXPR_ASSIGNADD:
783         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_add);
784     case EXPR_ASSIGNAND:
785         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_and);
786     case EXPR_ASSIGNSUB:
787         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_sub);
788     case EXPR_ASSIGNMUL:
789         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_mul);
790     case EXPR_ASSIGNDIV:
791         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_div);
792     case EXPR_ASSIGNMOD:
793         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_mod);
794     case EXPR_ASSIGNOR:
795         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_or);
796     case EXPR_ASSIGNLSHIFT:
797         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_lshift);
798     case EXPR_ASSIGNRSHIFT:
799         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_rshift);
800     case EXPR_ASSIGNRRSHIFT:
801         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_rshift2);
802     case EXPR_ASSIGNXOR:
803         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_xor);
804     case EXPR_BAND:
805         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_and);
806     case EXPR_BITNEG:
807         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_bneg);
808     case EXPR_BOR:
809         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_or);
810     case EXPR_CALL:
811         return compile_call_expression(ctx, (call_expression_t*)expr, no_ret);
812     case EXPR_COMMA:
813         return compile_comma_expression(ctx, (binary_expression_t*)expr);
814     case EXPR_COND:
815         return compile_conditional_expression(ctx, (conditional_expression_t*)expr);
816     case EXPR_DELETE:
817         return compile_delete_expression(ctx, (unary_expression_t*)expr);
818     case EXPR_DIV:
819         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div);
820     case EXPR_EQ:
821         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq);
822     case EXPR_EQEQ:
823         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq2);
824     case EXPR_FUNC:
825         return compile_function_expression(ctx, (function_expression_t*)expr);
826     case EXPR_GREATER:
827         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gt);
828     case EXPR_GREATEREQ:
829         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gteq);
830     case EXPR_IDENT:
831         return push_instr_bstr(ctx, OP_ident, ((identifier_expression_t*)expr)->identifier);
832     case EXPR_IN:
833         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_in);
834     case EXPR_INSTANCEOF:
835         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_instanceof);
836     case EXPR_LESS:
837         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lt);
838     case EXPR_LESSEQ:
839         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lteq);
840     case EXPR_LITERAL:
841         return compile_literal(ctx, ((literal_expression_t*)expr)->literal);
842     case EXPR_LOGNEG:
843         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg);
844     case EXPR_LSHIFT:
845         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lshift);
846     case EXPR_MEMBER:
847         return compile_member_expression(ctx, (member_expression_t*)expr);
848     case EXPR_MINUS:
849         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_minus);
850     case EXPR_MOD:
851         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod);
852     case EXPR_MUL:
853         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul);
854     case EXPR_NEW:
855         return compile_new_expression(ctx, (call_expression_t*)expr);
856     case EXPR_NOTEQ:
857         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_neq);
858     case EXPR_NOTEQEQ:
859         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_neq2);
860     case EXPR_OR:
861         return compile_logical_expression(ctx, (binary_expression_t*)expr, OP_cnd_nz);
862     case EXPR_PLUS:
863         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_tonum);
864     case EXPR_POSTDEC:
865         return compile_increment_expression(ctx, (unary_expression_t*)expr, OP_postinc, -1);
866     case EXPR_POSTINC:
867         return compile_increment_expression(ctx, (unary_expression_t*)expr, OP_postinc, 1);
868     case EXPR_PREDEC:
869         return compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, -1);
870     case EXPR_PREINC:
871         return compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, 1);
872     case EXPR_PROPVAL:
873         return compile_object_literal(ctx, (property_value_expression_t*)expr);
874     case EXPR_RSHIFT:
875         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_rshift);
876     case EXPR_RRSHIFT:
877         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_rshift2);
878     case EXPR_SUB:
879         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
880     case EXPR_THIS:
881         return push_instr(ctx, OP_this) == -1 ? E_OUTOFMEMORY : S_OK;
882     case EXPR_TYPEOF:
883         return compile_typeof_expression(ctx, (unary_expression_t*)expr);
884     case EXPR_VOID:
885         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_void);
886     case EXPR_BXOR:
887         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor);
888     default:
889         assert(0);
890     }
891
892     return S_OK;
893 }
894
895 static HRESULT compile_expression(compiler_ctx_t *ctx, expression_t *expr)
896 {
897     return compile_expression_noret(ctx, expr, NULL);
898 }
899
900 /* ECMA-262 3rd Edition    12.1 */
901 static HRESULT compile_block_statement(compiler_ctx_t *ctx, statement_t *iter)
902 {
903     HRESULT hres;
904
905     /* FIXME: do it only if needed */
906     if(!iter)
907         return push_instr(ctx, OP_undefined) == -1 ? E_OUTOFMEMORY : S_OK;
908
909     while(1) {
910         hres = compile_statement(ctx, NULL, iter);
911         if(FAILED(hres))
912             return hres;
913
914         iter = iter->next;
915         if(!iter)
916             break;
917
918         if(push_instr(ctx, OP_pop) == -1)
919             return E_OUTOFMEMORY;
920     }
921
922     return S_OK;
923 }
924
925 /* ECMA-262 3rd Edition    12.2 */
926 static HRESULT compile_variable_list(compiler_ctx_t *ctx, variable_declaration_t *list)
927 {
928     variable_declaration_t *iter;
929     HRESULT hres;
930
931     for(iter = list; iter; iter = iter->next) {
932         if(!iter->expr)
933             continue;
934
935         hres = compile_expression(ctx, iter->expr);
936         if(FAILED(hres))
937             return hres;
938
939         hres = push_instr_bstr(ctx, OP_var_set, iter->identifier);
940         if(FAILED(hres))
941             return hres;
942     }
943
944     return S_OK;
945 }
946
947 /* ECMA-262 3rd Edition    12.2 */
948 static HRESULT compile_var_statement(compiler_ctx_t *ctx, var_statement_t *stat)
949 {
950     HRESULT hres;
951
952     hres = compile_variable_list(ctx, stat->variable_list);
953     if(FAILED(hres))
954         return hres;
955
956     return push_instr(ctx, OP_undefined) == -1 ? E_OUTOFMEMORY : S_OK;
957 }
958
959 /* ECMA-262 3rd Edition    12.4 */
960 static HRESULT compile_expression_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
961 {
962     BOOL no_ret = FALSE;
963     HRESULT hres;
964
965     hres = compile_expression_noret(ctx, stat->expr, &no_ret);
966     if(FAILED(hres))
967         return hres;
968
969     /* FIXME: that's a big potential optimization */
970     if(no_ret && !push_instr(ctx, OP_undefined) == -1)
971         return E_OUTOFMEMORY;
972
973     return S_OK;
974 }
975
976 /* ECMA-262 3rd Edition    12.5 */
977 static HRESULT compile_if_statement(compiler_ctx_t *ctx, if_statement_t *stat)
978 {
979     unsigned jmp_else, jmp_end;
980     HRESULT hres;
981
982     hres = compile_expression(ctx, stat->expr);
983     if(FAILED(hres))
984         return hres;
985
986     jmp_else = push_instr(ctx, OP_jmp_z);
987     if(jmp_else == -1)
988         return E_OUTOFMEMORY;
989
990     hres = compile_statement(ctx, NULL, stat->if_stat);
991     if(FAILED(hres))
992         return hres;
993
994     jmp_end = push_instr(ctx, OP_jmp);
995     if(jmp_end == -1)
996         return E_OUTOFMEMORY;
997
998     instr_ptr(ctx, jmp_else)->arg1.uint = ctx->code_off;
999
1000     if(stat->else_stat) {
1001         hres = compile_statement(ctx, NULL, stat->else_stat);
1002         if(FAILED(hres))
1003             return hres;
1004     }else {
1005         /* FIXME: We could sometimes avoid it */
1006         if(push_instr(ctx, OP_undefined) == -1)
1007             return E_OUTOFMEMORY;
1008     }
1009
1010     instr_ptr(ctx, jmp_end)->arg1.uint = ctx->code_off;
1011     return S_OK;
1012 }
1013
1014 /* ECMA-262 3rd Edition    12.6.2 */
1015 static HRESULT compile_while_statement(compiler_ctx_t *ctx, while_statement_t *stat)
1016 {
1017     statement_ctx_t stat_ctx = {0, FALSE, FALSE};
1018     unsigned jmp_off;
1019     HRESULT hres;
1020
1021     stat_ctx.break_label = alloc_label(ctx);
1022     if(stat_ctx.break_label == -1)
1023         return E_OUTOFMEMORY;
1024
1025     stat_ctx.continue_label = alloc_label(ctx);
1026     if(stat_ctx.continue_label == -1)
1027         return E_OUTOFMEMORY;
1028
1029     if(!stat->do_while) {
1030         /* FIXME: avoid */
1031         if(push_instr(ctx, OP_undefined) == -1)
1032             return E_OUTOFMEMORY;
1033
1034         jmp_off = ctx->code_off;
1035         label_set_addr(ctx, stat_ctx.continue_label);
1036         hres = compile_expression(ctx, stat->expr);
1037         if(FAILED(hres))
1038             return hres;
1039
1040         hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1041         if(FAILED(hres))
1042             return hres;
1043
1044         if(push_instr(ctx, OP_pop) == -1)
1045             return E_OUTOFMEMORY;
1046     }else {
1047         jmp_off = ctx->code_off;
1048     }
1049
1050     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1051     if(FAILED(hres))
1052         return hres;
1053
1054     if(stat->do_while) {
1055         label_set_addr(ctx, stat_ctx.continue_label);
1056         hres = compile_expression(ctx, stat->expr);
1057         if(FAILED(hres))
1058             return hres;
1059
1060         hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1061         if(FAILED(hres))
1062             return hres;
1063
1064         if(push_instr(ctx, OP_pop) == -1)
1065             return E_OUTOFMEMORY;
1066     }
1067
1068     hres = push_instr_uint(ctx, OP_jmp, jmp_off);
1069     if(FAILED(hres))
1070         return hres;
1071
1072     label_set_addr(ctx, stat_ctx.break_label);
1073     return S_OK;
1074 }
1075
1076 /* ECMA-262 3rd Edition    12.6.3 */
1077 static HRESULT compile_for_statement(compiler_ctx_t *ctx, for_statement_t *stat)
1078 {
1079     statement_ctx_t stat_ctx = {0, FALSE, FALSE};
1080     unsigned expr_off;
1081     HRESULT hres;
1082
1083     if(stat->variable_list) {
1084         hres = compile_variable_list(ctx, stat->variable_list);
1085         if(FAILED(hres))
1086             return hres;
1087     }else if(stat->begin_expr) {
1088         BOOL no_ret = FALSE;
1089
1090         hres = compile_expression_noret(ctx, stat->begin_expr, &no_ret);
1091         if(FAILED(hres))
1092             return hres;
1093         if(!no_ret && push_instr(ctx, OP_pop) == -1)
1094             return E_OUTOFMEMORY;
1095     }
1096
1097     stat_ctx.break_label = alloc_label(ctx);
1098     if(stat_ctx.break_label == -1)
1099         return E_OUTOFMEMORY;
1100
1101     stat_ctx.continue_label = alloc_label(ctx);
1102     if(stat_ctx.continue_label == -1)
1103         return E_OUTOFMEMORY;
1104
1105     /* FIXME: avoid */
1106     if(push_instr(ctx, OP_undefined) == -1)
1107         return E_OUTOFMEMORY;
1108
1109     expr_off = ctx->code_off;
1110
1111     if(stat->expr) {
1112         hres = compile_expression(ctx, stat->expr);
1113         if(FAILED(hres))
1114             return hres;
1115
1116         hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1117         if(FAILED(hres))
1118             return hres;
1119     }
1120
1121     if(push_instr(ctx, OP_pop) == -1)
1122         return E_OUTOFMEMORY;
1123
1124     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1125     if(FAILED(hres))
1126         return hres;
1127
1128     label_set_addr(ctx, stat_ctx.continue_label);
1129
1130     if(stat->end_expr) {
1131         BOOL no_ret = FALSE;
1132
1133         hres = compile_expression_noret(ctx, stat->end_expr, &no_ret);
1134         if(FAILED(hres))
1135             return hres;
1136
1137         if(!no_ret && push_instr(ctx, OP_pop) == -1)
1138             return E_OUTOFMEMORY;
1139     }
1140
1141     hres = push_instr_uint(ctx, OP_jmp, expr_off);
1142     if(FAILED(hres))
1143         return hres;
1144
1145     label_set_addr(ctx, stat_ctx.break_label);
1146     return S_OK;
1147 }
1148
1149 /* ECMA-262 3rd Edition    12.6.4 */
1150 static HRESULT compile_forin_statement(compiler_ctx_t *ctx, forin_statement_t *stat)
1151 {
1152     statement_ctx_t stat_ctx = {4, FALSE, FALSE};
1153     HRESULT hres;
1154
1155     if(stat->variable) {
1156         hres = compile_variable_list(ctx, stat->variable);
1157         if(FAILED(hres))
1158             return hres;
1159     }
1160
1161     stat_ctx.break_label = alloc_label(ctx);
1162     if(stat_ctx.break_label == -1)
1163         return E_OUTOFMEMORY;
1164
1165     stat_ctx.continue_label = alloc_label(ctx);
1166     if(stat_ctx.continue_label == -1)
1167         return E_OUTOFMEMORY;
1168
1169     hres = compile_expression(ctx, stat->in_expr);
1170     if(FAILED(hres))
1171         return hres;
1172
1173     if(stat->variable) {
1174         hres = push_instr_bstr_uint(ctx, OP_identid, stat->variable->identifier, fdexNameEnsure);
1175         if(FAILED(hres))
1176             return hres;
1177     }else if(is_memberid_expr(stat->expr->type)) {
1178         hres = compile_memberid_expression(ctx, stat->expr, fdexNameEnsure);
1179         if(FAILED(hres))
1180             return hres;
1181     }else {
1182         hres = push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
1183         if(FAILED(hres))
1184             return hres;
1185
1186         /* FIXME: compile statement anyways when we depend on compiler to check errors */
1187         return S_OK;
1188     }
1189
1190     hres = push_instr_int(ctx, OP_int, DISPID_STARTENUM);
1191     if(FAILED(hres))
1192         return hres;
1193
1194     /* FIXME: avoid */
1195     if(push_instr(ctx, OP_undefined) == -1)
1196         return E_OUTOFMEMORY;
1197
1198     label_set_addr(ctx, stat_ctx.continue_label);
1199     hres = push_instr_uint(ctx, OP_forin, stat_ctx.break_label);
1200     if(FAILED(hres))
1201         return E_OUTOFMEMORY;
1202
1203     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1204     if(FAILED(hres))
1205         return hres;
1206
1207     hres = push_instr_uint(ctx, OP_jmp, stat_ctx.continue_label);
1208     if(FAILED(hres))
1209         return hres;
1210
1211     label_set_addr(ctx, stat_ctx.break_label);
1212     return S_OK;
1213 }
1214
1215 static HRESULT pop_to_stat(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx)
1216 {
1217     statement_ctx_t *iter = ctx->stat_ctx;
1218     unsigned stack_pop = 0;
1219
1220     while(1) {
1221         if(iter->using_scope && push_instr(ctx, OP_pop_scope) == -1)
1222             return E_OUTOFMEMORY;
1223         if(iter->using_except && push_instr(ctx, OP_pop_except) == -1)
1224             return E_OUTOFMEMORY;
1225         stack_pop += iter->stack_use;
1226         if(iter == stat_ctx)
1227             break;
1228         iter = iter->next;
1229     }
1230
1231     /* FIXME: optimize */
1232     while(stack_pop--) {
1233         if(push_instr(ctx, OP_pop) == -1)
1234             return E_OUTOFMEMORY;
1235     }
1236
1237     return S_OK;
1238 }
1239
1240 /* ECMA-262 3rd Edition    12.7 */
1241 static HRESULT compile_continue_statement(compiler_ctx_t *ctx, branch_statement_t *stat)
1242 {
1243     statement_ctx_t *pop_ctx;
1244     HRESULT hres;
1245
1246     for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
1247         if(pop_ctx->continue_label != -1)
1248             break;
1249     }
1250
1251     if(!pop_ctx || stat->identifier) {
1252         stat->stat.eval = continue_statement_eval;
1253         return compile_interp_fallback(ctx, &stat->stat);
1254     }
1255
1256     hres = pop_to_stat(ctx, pop_ctx);
1257     if(FAILED(hres))
1258         return hres;
1259
1260     if(push_instr(ctx, OP_undefined) == -1)
1261         return E_OUTOFMEMORY;
1262
1263     return push_instr_uint(ctx, OP_jmp, pop_ctx->continue_label);
1264 }
1265
1266 /* ECMA-262 3rd Edition    12.8 */
1267 static HRESULT compile_break_statement(compiler_ctx_t *ctx, branch_statement_t *stat)
1268 {
1269     statement_ctx_t *pop_ctx;
1270     HRESULT hres;
1271
1272     for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
1273         if(pop_ctx->break_label != -1)
1274             break;
1275     }
1276
1277     if(!pop_ctx || stat->identifier) {
1278         stat->stat.eval = break_statement_eval;
1279         return compile_interp_fallback(ctx, &stat->stat);
1280     }
1281
1282     hres = pop_to_stat(ctx, pop_ctx);
1283     if(FAILED(hres))
1284         return hres;
1285
1286     if(push_instr(ctx, OP_undefined) == -1)
1287         return E_OUTOFMEMORY;
1288
1289     return push_instr_uint(ctx, OP_jmp, pop_ctx->break_label);
1290 }
1291
1292 /* ECMA-262 3rd Edition    12.9 */
1293 static HRESULT compile_return_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
1294 {
1295     stat->stat.eval = return_statement_eval;
1296     return compile_interp_fallback(ctx, &stat->stat);
1297 }
1298
1299 /* ECMA-262 3rd Edition    12.10 */
1300 static HRESULT compile_with_statement(compiler_ctx_t *ctx, with_statement_t *stat)
1301 {
1302     statement_ctx_t stat_ctx = {0, TRUE, FALSE, -1, -1};
1303     HRESULT hres;
1304
1305     hres = compile_expression(ctx, stat->expr);
1306     if(FAILED(hres))
1307         return hres;
1308
1309     if(push_instr(ctx, OP_push_scope) == -1)
1310         return E_OUTOFMEMORY;
1311
1312     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1313     if(FAILED(hres))
1314         return hres;
1315
1316     if(push_instr(ctx, OP_pop_scope) == -1)
1317         return E_OUTOFMEMORY;
1318
1319     return S_OK;
1320 }
1321
1322 /* ECMA-262 3rd Edition    12.13 */
1323 static HRESULT compile_switch_statement(compiler_ctx_t *ctx, switch_statement_t *stat)
1324 {
1325     statement_ctx_t stat_ctx = {0, FALSE, FALSE, -1, -1};
1326     unsigned case_cnt = 0, *case_jmps, i, default_jmp;
1327     BOOL have_default = FALSE;
1328     statement_t *stat_iter;
1329     case_clausule_t *iter;
1330     HRESULT hres;
1331
1332     hres = compile_expression(ctx, stat->expr);
1333     if(FAILED(hres))
1334         return hres;
1335
1336     stat_ctx.break_label = alloc_label(ctx);
1337     if(stat_ctx.break_label == -1)
1338         return E_OUTOFMEMORY;
1339
1340     for(iter = stat->case_list; iter; iter = iter->next) {
1341         if(iter->expr)
1342             case_cnt++;
1343     }
1344
1345     case_jmps = heap_alloc(case_cnt * sizeof(*case_jmps));
1346     if(!case_jmps)
1347         return E_OUTOFMEMORY;
1348
1349     i = 0;
1350     for(iter = stat->case_list; iter; iter = iter->next) {
1351         if(!iter->expr) {
1352             have_default = TRUE;
1353             continue;
1354         }
1355
1356         hres = compile_expression(ctx, iter->expr);
1357         if(FAILED(hres))
1358             break;
1359
1360         case_jmps[i] = push_instr(ctx, OP_case);
1361         if(case_jmps[i] == -1) {
1362             hres = E_OUTOFMEMORY;
1363             break;
1364         }
1365         i++;
1366     }
1367
1368     if(SUCCEEDED(hres)) {
1369         if(push_instr(ctx, OP_pop) != -1) {
1370             default_jmp = push_instr(ctx, OP_jmp);
1371             if(default_jmp == -1)
1372                 hres = E_OUTOFMEMORY;
1373         }else {
1374             hres = E_OUTOFMEMORY;
1375         }
1376     }
1377
1378     if(FAILED(hres)) {
1379         heap_free(case_jmps);
1380         return hres;
1381     }
1382
1383     i = 0;
1384     for(iter = stat->case_list; iter; iter = iter->next) {
1385         while(iter->next && iter->next->stat == iter->stat) {
1386             instr_ptr(ctx, iter->expr ? case_jmps[i++] : default_jmp)->arg1.uint = ctx->code_off;
1387             iter = iter->next;
1388         }
1389
1390         instr_ptr(ctx, iter->expr ? case_jmps[i++] : default_jmp)->arg1.uint = ctx->code_off;
1391
1392         for(stat_iter = iter->stat; stat_iter && (!iter->next || iter->next->stat != stat_iter); stat_iter = stat_iter->next) {
1393             hres = compile_statement(ctx, &stat_ctx, stat_iter);
1394             if(FAILED(hres))
1395                 break;
1396
1397             if(stat_iter->next && push_instr(ctx, OP_pop) == -1) {
1398                 hres = E_OUTOFMEMORY;
1399                 break;
1400             }
1401         }
1402         if(FAILED(hres))
1403             break;
1404     }
1405
1406     heap_free(case_jmps);
1407     if(FAILED(hres))
1408         return hres;
1409     assert(i == case_cnt);
1410
1411     if(!have_default)
1412         instr_ptr(ctx, default_jmp)->arg1.uint = ctx->code_off;
1413
1414     label_set_addr(ctx, stat_ctx.break_label);
1415     return S_OK;
1416 }
1417
1418 /* ECMA-262 3rd Edition    12.13 */
1419 static HRESULT compile_throw_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
1420 {
1421     HRESULT hres;
1422
1423     hres = compile_expression(ctx, stat->expr);
1424     if(FAILED(hres))
1425         return hres;
1426
1427     return push_instr(ctx, OP_throw) == -1 ? E_OUTOFMEMORY : S_OK;
1428 }
1429
1430 /* ECMA-262 3rd Edition    12.14 */
1431 static HRESULT compile_try_statement(compiler_ctx_t *ctx, try_statement_t *stat)
1432 {
1433     statement_ctx_t try_ctx = {0, FALSE, TRUE, -1, -1}, catch_ctx = {0, TRUE, FALSE, -1, -1};
1434     statement_ctx_t finally_ctx = {2, FALSE, FALSE, -1, -1};
1435     unsigned push_except;
1436     BSTR ident;
1437     HRESULT hres;
1438
1439     push_except = push_instr(ctx, OP_push_except);
1440     if(push_except == -1)
1441         return E_OUTOFMEMORY;
1442
1443     if(stat->catch_block) {
1444         ident = compiler_alloc_bstr(ctx, stat->catch_block->identifier);
1445         if(!ident)
1446             return E_OUTOFMEMORY;
1447     }else {
1448         ident = NULL;
1449     }
1450
1451     instr_ptr(ctx, push_except)->arg2.bstr = ident;
1452
1453     if(!stat->catch_block)
1454         try_ctx.stack_use = 2;
1455
1456     hres = compile_statement(ctx, &try_ctx, stat->try_statement);
1457     if(FAILED(hres))
1458         return hres;
1459
1460     if(push_instr(ctx, OP_pop_except) == -1)
1461         return E_OUTOFMEMORY;
1462
1463     if(stat->catch_block) {
1464         unsigned jmp_finally;
1465
1466         jmp_finally = push_instr(ctx, OP_jmp);
1467         if(jmp_finally == -1)
1468             return E_OUTOFMEMORY;
1469
1470         instr_ptr(ctx, push_except)->arg1.uint = ctx->code_off;
1471
1472         hres = compile_statement(ctx, &catch_ctx, stat->catch_block->statement);
1473         if(FAILED(hres))
1474             return hres;
1475
1476         if(push_instr(ctx, OP_pop_scope) == -1)
1477             return E_OUTOFMEMORY;
1478
1479         instr_ptr(ctx, jmp_finally)->arg1.uint = ctx->code_off;
1480     }else {
1481         instr_ptr(ctx, push_except)->arg1.uint = ctx->code_off;
1482     }
1483
1484     if(stat->finally_statement) {
1485         /* FIXME: avoid */
1486         if(push_instr(ctx, OP_pop) == -1)
1487             return E_OUTOFMEMORY;
1488
1489         hres = compile_statement(ctx, stat->catch_block ? NULL : &finally_ctx, stat->finally_statement);
1490         if(FAILED(hres))
1491             return hres;
1492
1493         if(!stat->catch_block && push_instr(ctx, OP_end_finally) == -1)
1494             return E_OUTOFMEMORY;
1495     }
1496
1497     return S_OK;
1498 }
1499
1500 static HRESULT compile_statement(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx, statement_t *stat)
1501 {
1502     HRESULT hres;
1503
1504     if(stat_ctx) {
1505         stat_ctx->next = ctx->stat_ctx;
1506         ctx->stat_ctx = stat_ctx;
1507     }
1508
1509     switch(stat->type) {
1510     case STAT_BLOCK:
1511         hres = compile_block_statement(ctx, ((block_statement_t*)stat)->stat_list);
1512         break;
1513     case STAT_BREAK:
1514         hres = compile_break_statement(ctx, (branch_statement_t*)stat);
1515         break;
1516     case STAT_CONTINUE:
1517         hres = compile_continue_statement(ctx, (branch_statement_t*)stat);
1518         break;
1519     case STAT_EMPTY:
1520         hres = push_instr(ctx, OP_undefined) == -1 ? E_OUTOFMEMORY : S_OK; /* FIXME */
1521         break;
1522     case STAT_EXPR:
1523         hres = compile_expression_statement(ctx, (expression_statement_t*)stat);
1524         break;
1525     case STAT_FOR:
1526         hres = compile_for_statement(ctx, (for_statement_t*)stat);
1527         break;
1528     case STAT_FORIN:
1529         hres = compile_forin_statement(ctx, (forin_statement_t*)stat);
1530         break;
1531     case STAT_IF:
1532         hres = compile_if_statement(ctx, (if_statement_t*)stat);
1533         break;
1534     case STAT_LABEL:
1535         hres = push_instr(ctx, OP_label) == -1 ? E_OUTOFMEMORY : S_OK; /* FIXME */
1536         break;
1537     case STAT_RETURN:
1538         hres = compile_return_statement(ctx, (expression_statement_t*)stat);
1539         break;
1540     case STAT_SWITCH:
1541         hres = compile_switch_statement(ctx, (switch_statement_t*)stat);
1542         break;
1543     case STAT_THROW:
1544         hres = compile_throw_statement(ctx, (expression_statement_t*)stat);
1545         break;
1546     case STAT_TRY:
1547         hres = compile_try_statement(ctx, (try_statement_t*)stat);
1548         break;
1549     case STAT_VAR:
1550         hres = compile_var_statement(ctx, (var_statement_t*)stat);
1551         break;
1552     case STAT_WHILE:
1553         hres = compile_while_statement(ctx, (while_statement_t*)stat);
1554         break;
1555     case STAT_WITH:
1556         hres = compile_with_statement(ctx, (with_statement_t*)stat);
1557         break;
1558     default:
1559         hres = compile_interp_fallback(ctx, stat);
1560     }
1561
1562     if(stat_ctx) {
1563         assert(ctx->stat_ctx == stat_ctx);
1564         ctx->stat_ctx = stat_ctx->next;
1565     }
1566
1567     return hres;
1568 }
1569
1570 static void resolve_labels(compiler_ctx_t *ctx, unsigned off)
1571 {
1572     instr_t *instr;
1573
1574     for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->code_off; instr++) {
1575         if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->arg1.uint & LABEL_FLAG)) {
1576             assert((instr->arg1.uint & ~LABEL_FLAG) < ctx->labels_cnt);
1577             instr->arg1.uint = ctx->labels[instr->arg1.uint & ~LABEL_FLAG];
1578         }
1579         assert(instr_info[instr->op].arg2_type != ARG_ADDR);
1580     }
1581
1582     ctx->labels_cnt = 0;
1583 }
1584
1585 void release_bytecode(bytecode_t *code)
1586 {
1587     unsigned i;
1588
1589     for(i=0; i < code->bstr_cnt; i++)
1590         SysFreeString(code->bstr_pool[i]);
1591
1592     jsheap_free(&code->heap);
1593     heap_free(code->bstr_pool);
1594     heap_free(code->instrs);
1595     heap_free(code);
1596 }
1597
1598 void release_compiler(compiler_ctx_t *ctx)
1599 {
1600     heap_free(ctx);
1601 }
1602
1603 static HRESULT init_compiler(parser_ctx_t *parser)
1604 {
1605     if(!parser->code) {
1606         parser->code = heap_alloc_zero(sizeof(bytecode_t));
1607         if(!parser->code)
1608             return E_OUTOFMEMORY;
1609         jsheap_init(&parser->code->heap);
1610     }
1611
1612     if(!parser->compiler) {
1613         parser->compiler = heap_alloc_zero(sizeof(compiler_ctx_t));
1614         if(!parser->compiler)
1615             return E_OUTOFMEMORY;
1616
1617         parser->compiler->parser = parser;
1618         parser->compiler->code = parser->code;
1619     }
1620
1621     return S_OK;
1622 }
1623
1624 HRESULT compile_subscript(parser_ctx_t *parser, expression_t *expr, unsigned *ret_off)
1625 {
1626     HRESULT hres;
1627
1628     hres = init_compiler(parser);
1629     if(FAILED(hres))
1630         return hres;
1631
1632     *ret_off = parser->compiler->code_off;
1633     hres = compile_expression(parser->compiler, expr);
1634     if(FAILED(hres))
1635         return hres;
1636
1637     return push_instr(parser->compiler, OP_ret) == -1 ? E_OUTOFMEMORY : S_OK;
1638 }
1639
1640 HRESULT compile_subscript_stat(parser_ctx_t *parser, statement_t *stat, BOOL compile_block, unsigned *ret_off)
1641 {
1642     HRESULT hres;
1643
1644     TRACE("\n");
1645
1646     hres = init_compiler(parser);
1647     if(FAILED(hres))
1648         return hres;
1649
1650     *ret_off = parser->compiler->code_off;
1651     if(compile_block && stat->next)
1652         hres = compile_block_statement(parser->compiler, stat);
1653     else
1654         hres = compile_statement(parser->compiler, NULL, stat);
1655     if(FAILED(hres))
1656         return hres;
1657
1658     resolve_labels(parser->compiler, *ret_off);
1659
1660     return push_instr(parser->compiler, OP_ret) == -1 ? E_OUTOFMEMORY : S_OK;
1661 }