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