jscript: Always use bytecode for for statement.
[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 off_backup, jmp_off;
1019     HRESULT hres;
1020
1021     off_backup = ctx->code_off;
1022
1023     stat_ctx.break_label = alloc_label(ctx);
1024     if(stat_ctx.break_label == -1)
1025         return E_OUTOFMEMORY;
1026
1027     stat_ctx.continue_label = alloc_label(ctx);
1028     if(stat_ctx.continue_label == -1)
1029         return E_OUTOFMEMORY;
1030
1031     if(!stat->do_while) {
1032         /* FIXME: avoid */
1033         if(push_instr(ctx, OP_undefined) == -1)
1034             return E_OUTOFMEMORY;
1035
1036         jmp_off = ctx->code_off;
1037         label_set_addr(ctx, stat_ctx.continue_label);
1038         hres = compile_expression(ctx, stat->expr);
1039         if(FAILED(hres))
1040             return hres;
1041
1042         hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1043         if(FAILED(hres))
1044             return hres;
1045
1046         if(push_instr(ctx, OP_pop) == -1)
1047             return E_OUTOFMEMORY;
1048     }else {
1049         jmp_off = ctx->code_off;
1050     }
1051
1052     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1053     if(hres == E_NOTIMPL) {
1054         ctx->code_off = off_backup;
1055         stat->stat.eval = while_statement_eval;
1056         return compile_interp_fallback(ctx, &stat->stat);
1057     }
1058     if(FAILED(hres))
1059         return hres;
1060
1061     if(stat->do_while) {
1062         label_set_addr(ctx, stat_ctx.continue_label);
1063         hres = compile_expression(ctx, stat->expr);
1064         if(FAILED(hres))
1065             return hres;
1066
1067         hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1068         if(FAILED(hres))
1069             return hres;
1070
1071         if(push_instr(ctx, OP_pop) == -1)
1072             return E_OUTOFMEMORY;
1073     }
1074
1075     hres = push_instr_uint(ctx, OP_jmp, jmp_off);
1076     if(FAILED(hres))
1077         return hres;
1078
1079     label_set_addr(ctx, stat_ctx.break_label);
1080     return S_OK;
1081 }
1082
1083 /* ECMA-262 3rd Edition    12.6.3 */
1084 static HRESULT compile_for_statement(compiler_ctx_t *ctx, for_statement_t *stat)
1085 {
1086     statement_ctx_t stat_ctx = {0, FALSE, FALSE};
1087     unsigned expr_off;
1088     HRESULT hres;
1089
1090     if(stat->variable_list) {
1091         hres = compile_variable_list(ctx, stat->variable_list);
1092         if(FAILED(hres))
1093             return hres;
1094     }else if(stat->begin_expr) {
1095         BOOL no_ret = FALSE;
1096
1097         hres = compile_expression_noret(ctx, stat->begin_expr, &no_ret);
1098         if(FAILED(hres))
1099             return hres;
1100         if(!no_ret && push_instr(ctx, OP_pop) == -1)
1101             return E_OUTOFMEMORY;
1102     }
1103
1104     stat_ctx.break_label = alloc_label(ctx);
1105     if(stat_ctx.break_label == -1)
1106         return E_OUTOFMEMORY;
1107
1108     stat_ctx.continue_label = alloc_label(ctx);
1109     if(stat_ctx.continue_label == -1)
1110         return E_OUTOFMEMORY;
1111
1112     /* FIXME: avoid */
1113     if(push_instr(ctx, OP_undefined) == -1)
1114         return E_OUTOFMEMORY;
1115
1116     expr_off = ctx->code_off;
1117
1118     if(stat->expr) {
1119         hres = compile_expression(ctx, stat->expr);
1120         if(FAILED(hres))
1121             return hres;
1122
1123         hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1124         if(FAILED(hres))
1125             return hres;
1126     }
1127
1128     if(push_instr(ctx, OP_pop) == -1)
1129         return E_OUTOFMEMORY;
1130
1131     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1132     if(FAILED(hres))
1133         return hres;
1134
1135     label_set_addr(ctx, stat_ctx.continue_label);
1136
1137     if(stat->end_expr) {
1138         BOOL no_ret = FALSE;
1139
1140         hres = compile_expression_noret(ctx, stat->end_expr, &no_ret);
1141         if(FAILED(hres))
1142             return hres;
1143
1144         if(!no_ret && push_instr(ctx, OP_pop) == -1)
1145             return E_OUTOFMEMORY;
1146     }
1147
1148     hres = push_instr_uint(ctx, OP_jmp, expr_off);
1149     if(FAILED(hres))
1150         return hres;
1151
1152     label_set_addr(ctx, stat_ctx.break_label);
1153     return S_OK;
1154 }
1155
1156 /* ECMA-262 3rd Edition    12.6.4 */
1157 static HRESULT compile_forin_statement(compiler_ctx_t *ctx, forin_statement_t *stat)
1158 {
1159     statement_ctx_t stat_ctx = {4, FALSE, FALSE};
1160     HRESULT hres;
1161
1162     if(stat->variable) {
1163         hres = compile_variable_list(ctx, stat->variable);
1164         if(FAILED(hres))
1165             return hres;
1166     }
1167
1168     stat_ctx.break_label = alloc_label(ctx);
1169     if(stat_ctx.break_label == -1)
1170         return E_OUTOFMEMORY;
1171
1172     stat_ctx.continue_label = alloc_label(ctx);
1173     if(stat_ctx.continue_label == -1)
1174         return E_OUTOFMEMORY;
1175
1176     hres = compile_expression(ctx, stat->in_expr);
1177     if(FAILED(hres))
1178         return hres;
1179
1180     if(stat->variable) {
1181         hres = push_instr_bstr_uint(ctx, OP_identid, stat->variable->identifier, fdexNameEnsure);
1182         if(FAILED(hres))
1183             return hres;
1184     }else if(is_memberid_expr(stat->expr->type)) {
1185         hres = compile_memberid_expression(ctx, stat->expr, fdexNameEnsure);
1186         if(FAILED(hres))
1187             return hres;
1188     }else {
1189         hres = push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
1190         if(FAILED(hres))
1191             return hres;
1192
1193         /* FIXME: compile statement anyways when we depend on compiler to check errors */
1194         return S_OK;
1195     }
1196
1197     hres = push_instr_int(ctx, OP_int, DISPID_STARTENUM);
1198     if(FAILED(hres))
1199         return hres;
1200
1201     /* FIXME: avoid */
1202     if(push_instr(ctx, OP_undefined) == -1)
1203         return E_OUTOFMEMORY;
1204
1205     label_set_addr(ctx, stat_ctx.continue_label);
1206     hres = push_instr_uint(ctx, OP_forin, stat_ctx.break_label);
1207     if(FAILED(hres))
1208         return E_OUTOFMEMORY;
1209
1210     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1211     if(FAILED(hres))
1212         return hres;
1213
1214     hres = push_instr_uint(ctx, OP_jmp, stat_ctx.continue_label);
1215     if(FAILED(hres))
1216         return hres;
1217
1218     label_set_addr(ctx, stat_ctx.break_label);
1219     return S_OK;
1220 }
1221
1222 static HRESULT pop_to_stat(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx)
1223 {
1224     statement_ctx_t *iter = ctx->stat_ctx;
1225     unsigned stack_pop = 0;
1226
1227     while(1) {
1228         if(iter->using_scope && push_instr(ctx, OP_pop_scope) == -1)
1229             return E_OUTOFMEMORY;
1230         if(iter->using_except && push_instr(ctx, OP_pop_except) == -1)
1231             return E_OUTOFMEMORY;
1232         stack_pop += iter->stack_use;
1233         if(iter == stat_ctx)
1234             break;
1235         iter = iter->next;
1236     }
1237
1238     /* FIXME: optimize */
1239     while(stack_pop--) {
1240         if(push_instr(ctx, OP_pop) == -1)
1241             return E_OUTOFMEMORY;
1242     }
1243
1244     return S_OK;
1245 }
1246
1247 /* ECMA-262 3rd Edition    12.7 */
1248 static HRESULT compile_continue_statement(compiler_ctx_t *ctx, branch_statement_t *stat)
1249 {
1250     statement_ctx_t *pop_ctx;
1251     HRESULT hres;
1252
1253     for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
1254         if(pop_ctx->continue_label != -1)
1255             break;
1256     }
1257
1258     if(!pop_ctx || stat->identifier) {
1259         stat->stat.eval = continue_statement_eval;
1260         return compile_interp_fallback(ctx, &stat->stat);
1261     }
1262
1263     hres = pop_to_stat(ctx, pop_ctx);
1264     if(FAILED(hres))
1265         return hres;
1266
1267     if(push_instr(ctx, OP_undefined) == -1)
1268         return E_OUTOFMEMORY;
1269
1270     return push_instr_uint(ctx, OP_jmp, pop_ctx->continue_label);
1271 }
1272
1273 /* ECMA-262 3rd Edition    12.8 */
1274 static HRESULT compile_break_statement(compiler_ctx_t *ctx, branch_statement_t *stat)
1275 {
1276     statement_ctx_t *pop_ctx;
1277     HRESULT hres;
1278
1279     for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
1280         if(pop_ctx->break_label != -1)
1281             break;
1282     }
1283
1284     if(!pop_ctx || stat->identifier) {
1285         stat->stat.eval = break_statement_eval;
1286         return compile_interp_fallback(ctx, &stat->stat);
1287     }
1288
1289     hres = pop_to_stat(ctx, pop_ctx);
1290     if(FAILED(hres))
1291         return hres;
1292
1293     if(push_instr(ctx, OP_undefined) == -1)
1294         return E_OUTOFMEMORY;
1295
1296     return push_instr_uint(ctx, OP_jmp, pop_ctx->break_label);
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     unsigned off_backup;
1331     HRESULT hres;
1332
1333     off_backup = ctx->code_off;
1334
1335     hres = compile_expression(ctx, stat->expr);
1336     if(FAILED(hres))
1337         return hres;
1338
1339     stat_ctx.break_label = alloc_label(ctx);
1340     if(stat_ctx.break_label == -1)
1341         return E_OUTOFMEMORY;
1342
1343     for(iter = stat->case_list; iter; iter = iter->next) {
1344         if(iter->expr)
1345             case_cnt++;
1346     }
1347
1348     case_jmps = heap_alloc(case_cnt * sizeof(*case_jmps));
1349     if(!case_jmps)
1350         return E_OUTOFMEMORY;
1351
1352     i = 0;
1353     for(iter = stat->case_list; iter; iter = iter->next) {
1354         if(!iter->expr) {
1355             have_default = TRUE;
1356             continue;
1357         }
1358
1359         hres = compile_expression(ctx, iter->expr);
1360         if(FAILED(hres))
1361             break;
1362
1363         case_jmps[i] = push_instr(ctx, OP_case);
1364         if(case_jmps[i] == -1) {
1365             hres = E_OUTOFMEMORY;
1366             break;
1367         }
1368         i++;
1369     }
1370
1371     if(SUCCEEDED(hres)) {
1372         if(push_instr(ctx, OP_pop) != -1) {
1373             default_jmp = push_instr(ctx, OP_jmp);
1374             if(default_jmp == -1)
1375                 hres = E_OUTOFMEMORY;
1376         }else {
1377             hres = E_OUTOFMEMORY;
1378         }
1379     }
1380
1381     if(FAILED(hres)) {
1382         heap_free(case_jmps);
1383         return hres;
1384     }
1385
1386     i = 0;
1387     for(iter = stat->case_list; iter; iter = iter->next) {
1388         while(iter->next && iter->next->stat == iter->stat) {
1389             instr_ptr(ctx, iter->expr ? case_jmps[i++] : default_jmp)->arg1.uint = ctx->code_off;
1390             iter = iter->next;
1391         }
1392
1393         instr_ptr(ctx, iter->expr ? case_jmps[i++] : default_jmp)->arg1.uint = ctx->code_off;
1394
1395         for(stat_iter = iter->stat; stat_iter && (!iter->next || iter->next->stat != stat_iter); stat_iter = stat_iter->next) {
1396             hres = compile_statement(ctx, &stat_ctx, stat_iter);
1397             if(hres == E_NOTIMPL) {
1398                 ctx->code_off = off_backup;
1399                 stat->stat.eval = switch_statement_eval;
1400                 return compile_interp_fallback(ctx, &stat->stat);
1401             }
1402             if(FAILED(hres))
1403                 break;
1404
1405             if(stat_iter->next && push_instr(ctx, OP_pop) == -1) {
1406                 hres = E_OUTOFMEMORY;
1407                 break;
1408             }
1409         }
1410         if(FAILED(hres))
1411             break;
1412     }
1413
1414     heap_free(case_jmps);
1415     if(FAILED(hres))
1416         return hres;
1417     assert(i == case_cnt);
1418
1419     if(!have_default)
1420         instr_ptr(ctx, default_jmp)->arg1.uint = ctx->code_off;
1421
1422     label_set_addr(ctx, stat_ctx.break_label);
1423     return S_OK;
1424 }
1425
1426 /* ECMA-262 3rd Edition    12.13 */
1427 static HRESULT compile_throw_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
1428 {
1429     HRESULT hres;
1430
1431     hres = compile_expression(ctx, stat->expr);
1432     if(FAILED(hres))
1433         return hres;
1434
1435     return push_instr(ctx, OP_throw) == -1 ? E_OUTOFMEMORY : S_OK;
1436 }
1437
1438 /* ECMA-262 3rd Edition    12.14 */
1439 static HRESULT compile_try_statement(compiler_ctx_t *ctx, try_statement_t *stat)
1440 {
1441     statement_ctx_t try_ctx = {0, FALSE, TRUE, -1, -1}, catch_ctx = {0, TRUE, FALSE, -1, -1};
1442     statement_ctx_t finally_ctx = {2, FALSE, FALSE, -1, -1};
1443     unsigned off_backup, push_except;
1444     BSTR ident;
1445     HRESULT hres;
1446
1447     off_backup = ctx->code_off;
1448
1449     push_except = push_instr(ctx, OP_push_except);
1450     if(push_except == -1)
1451         return E_OUTOFMEMORY;
1452
1453     if(stat->catch_block) {
1454         ident = compiler_alloc_bstr(ctx, stat->catch_block->identifier);
1455         if(!ident)
1456             return E_OUTOFMEMORY;
1457     }else {
1458         ident = NULL;
1459     }
1460
1461     instr_ptr(ctx, push_except)->arg2.bstr = ident;
1462
1463     if(!stat->catch_block)
1464         try_ctx.stack_use = 2;
1465
1466     hres = compile_statement(ctx, &try_ctx, stat->try_statement);
1467     if(hres == E_NOTIMPL) {
1468         ctx->code_off = off_backup;
1469         stat->stat.eval = try_statement_eval;
1470         return compile_interp_fallback(ctx, &stat->stat);
1471     }
1472     if(FAILED(hres))
1473         return hres;
1474
1475     if(push_instr(ctx, OP_pop_except) == -1)
1476         return E_OUTOFMEMORY;
1477
1478     if(stat->catch_block) {
1479         unsigned jmp_finally;
1480
1481         jmp_finally = push_instr(ctx, OP_jmp);
1482         if(jmp_finally == -1)
1483             return E_OUTOFMEMORY;
1484
1485         instr_ptr(ctx, push_except)->arg1.uint = ctx->code_off;
1486
1487         hres = compile_statement(ctx, &catch_ctx, stat->catch_block->statement);
1488         if(hres == E_NOTIMPL) {
1489             ctx->code_off = off_backup;
1490             stat->stat.eval = try_statement_eval;
1491             return compile_interp_fallback(ctx, &stat->stat);
1492         }
1493         if(FAILED(hres))
1494             return hres;
1495
1496         if(push_instr(ctx, OP_pop_scope) == -1)
1497             return E_OUTOFMEMORY;
1498
1499         instr_ptr(ctx, jmp_finally)->arg1.uint = ctx->code_off;
1500     }else {
1501         instr_ptr(ctx, push_except)->arg1.uint = ctx->code_off;
1502     }
1503
1504     if(stat->finally_statement) {
1505         /* FIXME: avoid */
1506         if(push_instr(ctx, OP_pop) == -1)
1507             return E_OUTOFMEMORY;
1508
1509         hres = compile_statement(ctx, stat->catch_block ? NULL : &finally_ctx, stat->finally_statement);
1510         if(hres == E_NOTIMPL) {
1511             ctx->code_off = off_backup;
1512             stat->stat.eval = try_statement_eval;
1513             return compile_interp_fallback(ctx, &stat->stat);
1514         }
1515         if(FAILED(hres))
1516             return hres;
1517
1518         if(!stat->catch_block && push_instr(ctx, OP_end_finally) == -1)
1519             return E_OUTOFMEMORY;
1520     }
1521
1522     return S_OK;
1523 }
1524
1525 static HRESULT compile_statement(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx, statement_t *stat)
1526 {
1527     HRESULT hres;
1528
1529     if(stat_ctx) {
1530         stat_ctx->next = ctx->stat_ctx;
1531         ctx->stat_ctx = stat_ctx;
1532     }
1533
1534     switch(stat->type) {
1535     case STAT_BLOCK:
1536         hres = compile_block_statement(ctx, ((block_statement_t*)stat)->stat_list);
1537         break;
1538     case STAT_BREAK:
1539         hres = compile_break_statement(ctx, (branch_statement_t*)stat);
1540         break;
1541     case STAT_CONTINUE:
1542         hres = compile_continue_statement(ctx, (branch_statement_t*)stat);
1543         break;
1544     case STAT_EMPTY:
1545         hres = push_instr(ctx, OP_undefined) == -1 ? E_OUTOFMEMORY : S_OK; /* FIXME */
1546         break;
1547     case STAT_EXPR:
1548         hres = compile_expression_statement(ctx, (expression_statement_t*)stat);
1549         break;
1550     case STAT_FOR:
1551         hres = compile_for_statement(ctx, (for_statement_t*)stat);
1552         break;
1553     case STAT_FORIN:
1554         hres = compile_forin_statement(ctx, (forin_statement_t*)stat);
1555         break;
1556     case STAT_IF:
1557         hres = compile_if_statement(ctx, (if_statement_t*)stat);
1558         break;
1559     case STAT_LABEL:
1560         hres = push_instr(ctx, OP_label) == -1 ? E_OUTOFMEMORY : S_OK; /* FIXME */
1561         break;
1562     case STAT_SWITCH:
1563         hres = compile_switch_statement(ctx, (switch_statement_t*)stat);
1564         break;
1565     case STAT_THROW:
1566         hres = compile_throw_statement(ctx, (expression_statement_t*)stat);
1567         break;
1568     case STAT_TRY:
1569         hres = compile_try_statement(ctx, (try_statement_t*)stat);
1570         break;
1571     case STAT_VAR:
1572         hres = compile_var_statement(ctx, (var_statement_t*)stat);
1573         break;
1574     case STAT_WHILE:
1575         hres = compile_while_statement(ctx, (while_statement_t*)stat);
1576         break;
1577     case STAT_WITH:
1578         hres = compile_with_statement(ctx, (with_statement_t*)stat);
1579         break;
1580     default:
1581         hres = compile_interp_fallback(ctx, stat);
1582     }
1583
1584     if(stat_ctx) {
1585         assert(ctx->stat_ctx == stat_ctx);
1586         ctx->stat_ctx = stat_ctx->next;
1587     }
1588
1589     return hres;
1590 }
1591
1592 static void resolve_labels(compiler_ctx_t *ctx, unsigned off)
1593 {
1594     instr_t *instr;
1595
1596     for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->code_off; instr++) {
1597         if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->arg1.uint & LABEL_FLAG)) {
1598             assert((instr->arg1.uint & ~LABEL_FLAG) < ctx->labels_cnt);
1599             instr->arg1.uint = ctx->labels[instr->arg1.uint & ~LABEL_FLAG];
1600         }
1601         assert(instr_info[instr->op].arg2_type != ARG_ADDR);
1602     }
1603
1604     ctx->labels_cnt = 0;
1605 }
1606
1607 void release_bytecode(bytecode_t *code)
1608 {
1609     unsigned i;
1610
1611     for(i=0; i < code->bstr_cnt; i++)
1612         SysFreeString(code->bstr_pool[i]);
1613
1614     jsheap_free(&code->heap);
1615     heap_free(code->bstr_pool);
1616     heap_free(code->instrs);
1617     heap_free(code);
1618 }
1619
1620 void release_compiler(compiler_ctx_t *ctx)
1621 {
1622     heap_free(ctx);
1623 }
1624
1625 static HRESULT init_compiler(parser_ctx_t *parser)
1626 {
1627     if(!parser->code) {
1628         parser->code = heap_alloc_zero(sizeof(bytecode_t));
1629         if(!parser->code)
1630             return E_OUTOFMEMORY;
1631         jsheap_init(&parser->code->heap);
1632     }
1633
1634     if(!parser->compiler) {
1635         parser->compiler = heap_alloc_zero(sizeof(compiler_ctx_t));
1636         if(!parser->compiler)
1637             return E_OUTOFMEMORY;
1638
1639         parser->compiler->parser = parser;
1640         parser->compiler->code = parser->code;
1641     }
1642
1643     return S_OK;
1644 }
1645
1646 HRESULT compile_subscript(parser_ctx_t *parser, expression_t *expr, unsigned *ret_off)
1647 {
1648     HRESULT hres;
1649
1650     hres = init_compiler(parser);
1651     if(FAILED(hres))
1652         return hres;
1653
1654     *ret_off = parser->compiler->code_off;
1655     hres = compile_expression(parser->compiler, expr);
1656     if(FAILED(hres))
1657         return hres;
1658
1659     return push_instr(parser->compiler, OP_ret) == -1 ? E_OUTOFMEMORY : S_OK;
1660 }
1661
1662 HRESULT compile_subscript_stat(parser_ctx_t *parser, statement_t *stat, BOOL compile_block, unsigned *ret_off)
1663 {
1664     HRESULT hres;
1665
1666     TRACE("\n");
1667
1668     hres = init_compiler(parser);
1669     if(FAILED(hres))
1670         return hres;
1671
1672     *ret_off = parser->compiler->code_off;
1673     if(compile_block && stat->next)
1674         hres = compile_block_statement(parser->compiler, stat);
1675     else
1676         hres = compile_statement(parser->compiler, NULL, stat);
1677     if(FAILED(hres))
1678         return hres;
1679
1680     resolve_labels(parser->compiler, *ret_off);
1681
1682     return push_instr(parser->compiler, OP_ret) == -1 ? E_OUTOFMEMORY : S_OK;
1683 }