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