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