jscript: Use bytecode for block statement implementation.
[wine] / dlls / jscript / compile.c
1 /*
2  * Copyright 2011 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include <math.h>
20 #include <assert.h>
21
22 #include "jscript.h"
23 #include "engine.h"
24
25 #include "wine/debug.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
28
29 struct _compiler_ctx_t {
30     parser_ctx_t *parser;
31     bytecode_t *code;
32
33     unsigned code_off;
34     unsigned code_size;
35 };
36
37 static HRESULT compile_expression(compiler_ctx_t*,expression_t*);
38 static HRESULT compile_statement(compiler_ctx_t*,statement_t*);
39
40 static inline void *compiler_alloc(bytecode_t *code, size_t size)
41 {
42     return jsheap_alloc(&code->heap, size);
43 }
44
45 static WCHAR *compiler_alloc_string(bytecode_t *code, const WCHAR *str)
46 {
47     size_t size;
48     WCHAR *ret;
49
50     size = (strlenW(str)+1)*sizeof(WCHAR);
51     ret = compiler_alloc(code, size);
52     if(ret)
53         memcpy(ret, str, size);
54     return ret;
55 }
56
57 static BSTR compiler_alloc_bstr(compiler_ctx_t *ctx, const WCHAR *str)
58 {
59     if(!ctx->code->bstr_pool_size) {
60         ctx->code->bstr_pool = heap_alloc(8 * sizeof(BSTR));
61         if(!ctx->code->bstr_pool)
62             return NULL;
63         ctx->code->bstr_pool_size = 8;
64     }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) {
65         BSTR *new_pool;
66
67         new_pool = heap_realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR));
68         if(!new_pool)
69             return NULL;
70
71         ctx->code->bstr_pool = new_pool;
72         ctx->code->bstr_pool_size *= 2;
73     }
74
75     ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocString(str);
76     if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
77         return NULL;
78
79     return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
80 }
81
82 static unsigned push_instr(compiler_ctx_t *ctx, jsop_t op)
83 {
84     assert(ctx->code_size >= ctx->code_off);
85
86     if(!ctx->code_size) {
87         ctx->code->instrs = heap_alloc(64 * sizeof(instr_t));
88         if(!ctx->code->instrs)
89             return -1;
90         ctx->code_size = 64;
91     }else if(ctx->code_size == ctx->code_off) {
92         instr_t *new_instrs;
93
94         new_instrs = heap_realloc(ctx->code->instrs, ctx->code_size*2*sizeof(instr_t));
95         if(!new_instrs)
96             return -1;
97
98         ctx->code->instrs = new_instrs;
99         ctx->code_size *= 2;
100     }
101
102     ctx->code->instrs[ctx->code_off].op = op;
103     return ctx->code_off++;
104 }
105
106 static inline instr_t *instr_ptr(compiler_ctx_t *ctx, unsigned off)
107 {
108     assert(off < ctx->code_off);
109     return ctx->code->instrs + off;
110 }
111
112 static HRESULT push_instr_int(compiler_ctx_t *ctx, jsop_t op, LONG arg)
113 {
114     unsigned instr;
115
116     instr = push_instr(ctx, op);
117     if(instr == -1)
118         return E_OUTOFMEMORY;
119
120     instr_ptr(ctx, instr)->arg1.lng = arg;
121     return S_OK;
122 }
123
124 static HRESULT push_instr_str(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg)
125 {
126     unsigned instr;
127     WCHAR *str;
128
129     str = compiler_alloc_string(ctx->code, arg);
130     if(!str)
131         return E_OUTOFMEMORY;
132
133     instr = push_instr(ctx, op);
134     if(instr == -1)
135         return E_OUTOFMEMORY;
136
137     instr_ptr(ctx, instr)->arg1.str = str;
138     return S_OK;
139 }
140
141 static HRESULT push_instr_bstr(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg)
142 {
143     unsigned instr;
144     WCHAR *str;
145
146     str = compiler_alloc_bstr(ctx, arg);
147     if(!str)
148         return E_OUTOFMEMORY;
149
150     instr = push_instr(ctx, op);
151     if(instr == -1)
152         return E_OUTOFMEMORY;
153
154     instr_ptr(ctx, instr)->arg1.bstr = str;
155     return S_OK;
156 }
157
158 static HRESULT push_instr_bstr_uint(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg1, unsigned arg2)
159 {
160     unsigned instr;
161     WCHAR *str;
162
163     str = compiler_alloc_bstr(ctx, arg1);
164     if(!str)
165         return E_OUTOFMEMORY;
166
167     instr = push_instr(ctx, op);
168     if(instr == -1)
169         return E_OUTOFMEMORY;
170
171     instr_ptr(ctx, instr)->arg1.bstr = str;
172     instr_ptr(ctx, instr)->arg2.uint = arg2;
173     return S_OK;
174 }
175
176 static HRESULT push_instr_uint_str(compiler_ctx_t *ctx, jsop_t op, unsigned arg1, const WCHAR *arg2)
177 {
178     unsigned instr;
179     WCHAR *str;
180
181     str = compiler_alloc_string(ctx->code, arg2);
182     if(!str)
183         return E_OUTOFMEMORY;
184
185     instr = push_instr(ctx, op);
186     if(instr == -1)
187         return E_OUTOFMEMORY;
188
189     instr_ptr(ctx, instr)->arg1.uint = arg1;
190     instr_ptr(ctx, instr)->arg2.str = str;
191     return S_OK;
192 }
193
194 static HRESULT push_instr_double(compiler_ctx_t *ctx, jsop_t op, double arg)
195 {
196     unsigned instr;
197     DOUBLE *dbl;
198
199     dbl = compiler_alloc(ctx->code, sizeof(arg));
200     if(!dbl)
201         return E_OUTOFMEMORY;
202     *dbl = arg;
203
204     instr = push_instr(ctx, op);
205     if(instr == -1)
206         return E_OUTOFMEMORY;
207
208     instr_ptr(ctx, instr)->arg1.dbl = dbl;
209     return S_OK;
210 }
211
212 static HRESULT push_instr_uint(compiler_ctx_t *ctx, jsop_t op, unsigned arg)
213 {
214     unsigned instr;
215
216     instr = push_instr(ctx, op);
217     if(instr == -1)
218         return E_OUTOFMEMORY;
219
220     instr_ptr(ctx, instr)->arg1.uint = arg;
221     return S_OK;
222 }
223
224 static HRESULT compile_binary_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
225 {
226     HRESULT hres;
227
228     hres = compile_expression(ctx, expr->expression1);
229     if(FAILED(hres))
230         return hres;
231
232     hres = compile_expression(ctx, expr->expression2);
233     if(FAILED(hres))
234         return hres;
235
236     return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK;
237 }
238
239 static HRESULT compile_unary_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op)
240 {
241     HRESULT hres;
242
243     hres = compile_expression(ctx, expr->expression);
244     if(FAILED(hres))
245         return hres;
246
247     return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK;
248 }
249
250 /* ECMA-262 3rd Edition    11.2.1 */
251 static HRESULT compile_member_expression(compiler_ctx_t *ctx, member_expression_t *expr)
252 {
253     HRESULT hres;
254
255     hres = compile_expression(ctx, expr->expression);
256     if(FAILED(hres))
257         return hres;
258
259     return push_instr_bstr(ctx, OP_member, expr->identifier);
260 }
261
262 static inline BOOL is_memberid_expr(expression_type_t type)
263 {
264     return type == EXPR_IDENT || type == EXPR_MEMBER || type == EXPR_ARRAY;
265 }
266
267 static HRESULT compile_memberid_expression(compiler_ctx_t *ctx, expression_t *expr, unsigned flags)
268 {
269     HRESULT hres = S_OK;
270
271     switch(expr->type) {
272     case EXPR_IDENT: {
273         identifier_expression_t *ident_expr = (identifier_expression_t*)expr;
274
275         hres = push_instr_bstr_uint(ctx, OP_identid, ident_expr->identifier, flags);
276         break;
277     }
278     case EXPR_ARRAY: {
279         binary_expression_t *array_expr = (binary_expression_t*)expr;
280
281         hres = compile_expression(ctx, array_expr->expression1);
282         if(FAILED(hres))
283             return hres;
284
285         hres = compile_expression(ctx, array_expr->expression2);
286         if(FAILED(hres))
287             return hres;
288
289         hres = push_instr_uint(ctx, OP_memberid, flags);
290         break;
291     }
292     case EXPR_MEMBER: {
293         member_expression_t *member_expr = (member_expression_t*)expr;
294
295         hres = compile_expression(ctx, member_expr->expression);
296         if(FAILED(hres))
297             return hres;
298
299         /* FIXME: Potential optimization */
300         hres = push_instr_str(ctx, OP_str, member_expr->identifier);
301         if(FAILED(hres))
302             return hres;
303
304         hres = push_instr_uint(ctx, OP_memberid, flags);
305         break;
306     }
307     default:
308         assert(0);
309     }
310
311     return hres;
312 }
313
314 static HRESULT compile_increment_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op, int n)
315 {
316     HRESULT hres;
317
318     if(!is_memberid_expr(expr->expression->type)) {
319         hres = compile_expression(ctx, expr->expression);
320         if(FAILED(hres))
321             return hres;
322
323         return push_instr_uint(ctx, OP_throw, JS_E_ILLEGAL_ASSIGN);
324     }
325
326     hres = compile_memberid_expression(ctx, expr->expression, fdexNameEnsure);
327     if(FAILED(hres))
328         return hres;
329
330     return push_instr_int(ctx, op, n);
331 }
332
333 /* ECMA-262 3rd Edition    11.14 */
334 static HRESULT compile_comma_expression(compiler_ctx_t *ctx, binary_expression_t *expr)
335 {
336     HRESULT hres;
337
338     hres = compile_expression(ctx, expr->expression1);
339     if(FAILED(hres))
340         return hres;
341
342     if(push_instr(ctx, OP_pop) == -1)
343         return E_OUTOFMEMORY;
344
345     return compile_expression(ctx, expr->expression2);
346 }
347
348 /* ECMA-262 3rd Edition    11.11 */
349 static HRESULT compile_logical_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
350 {
351     unsigned instr;
352     HRESULT hres;
353
354     hres = compile_expression(ctx, expr->expression1);
355     if(FAILED(hres))
356         return hres;
357
358     instr = push_instr(ctx, op);
359     if(instr == -1)
360         return E_OUTOFMEMORY;
361
362     hres = compile_expression(ctx, expr->expression2);
363     if(FAILED(hres))
364         return hres;
365
366     instr_ptr(ctx, instr)->arg1.uint = ctx->code_off;
367     return S_OK;
368 }
369
370 /* ECMA-262 3rd Edition    11.12 */
371 static HRESULT compile_conditional_expression(compiler_ctx_t *ctx, conditional_expression_t *expr)
372 {
373     unsigned jmp_false, jmp_end;
374     HRESULT hres;
375
376     hres = compile_expression(ctx, expr->expression);
377     if(FAILED(hres))
378         return hres;
379
380     jmp_false = push_instr(ctx, OP_jmp_z);
381     if(jmp_false == -1)
382         return E_OUTOFMEMORY;
383
384     hres = compile_expression(ctx, expr->true_expression);
385     if(FAILED(hres))
386         return hres;
387
388     jmp_end = push_instr(ctx, OP_jmp);
389     if(jmp_end == -1)
390         return E_OUTOFMEMORY;
391
392     instr_ptr(ctx, jmp_false)->arg1.uint = ctx->code_off;
393     if(push_instr(ctx, OP_pop) == -1)
394         return E_OUTOFMEMORY;
395
396     hres = compile_expression(ctx, expr->false_expression);
397     if(FAILED(hres))
398         return hres;
399
400     instr_ptr(ctx, jmp_end)->arg1.uint = ctx->code_off;
401     return S_OK;
402 }
403
404 static HRESULT compile_new_expression(compiler_ctx_t *ctx, call_expression_t *expr)
405 {
406     unsigned arg_cnt = 0;
407     argument_t *arg;
408     HRESULT hres;
409
410     hres = compile_expression(ctx, expr->expression);
411     if(FAILED(hres))
412         return hres;
413
414     for(arg = expr->argument_list; arg; arg = arg->next) {
415         hres = compile_expression(ctx, arg->expr);
416         if(FAILED(hres))
417             return hres;
418         arg_cnt++;
419     }
420
421     return push_instr_int(ctx, OP_new, arg_cnt);
422 }
423
424 static HRESULT compile_interp_fallback(compiler_ctx_t *ctx, statement_t *stat)
425 {
426     unsigned instr;
427
428     instr = push_instr(ctx, OP_tree);
429     if(instr == -1)
430         return E_OUTOFMEMORY;
431
432     instr_ptr(ctx, instr)->arg1.stat = stat;
433     return S_OK;
434 }
435
436 static HRESULT compile_call_expression(compiler_ctx_t *ctx, call_expression_t *expr, BOOL *no_ret)
437 {
438     unsigned arg_cnt = 0;
439     argument_t *arg;
440     unsigned instr;
441     jsop_t op;
442     HRESULT hres;
443
444     if(is_memberid_expr(expr->expression->type)) {
445         op = OP_call_member;
446         hres = compile_memberid_expression(ctx, expr->expression, 0);
447     }else {
448         op = OP_call;
449         hres = compile_expression(ctx, expr->expression);
450     }
451
452     if(FAILED(hres))
453         return hres;
454
455     for(arg = expr->argument_list; arg; arg = arg->next) {
456         hres = compile_expression(ctx, arg->expr);
457         if(FAILED(hres))
458             return hres;
459         arg_cnt++;
460     }
461
462     instr = push_instr(ctx, op);
463     if(instr == -1)
464         return E_OUTOFMEMORY;
465
466     instr_ptr(ctx, instr)->arg1.uint = arg_cnt;
467     instr_ptr(ctx, instr)->arg2.lng = no_ret == NULL;
468     if(no_ret)
469         *no_ret = TRUE;
470     return S_OK;
471 }
472
473 static HRESULT compile_delete_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
474 {
475     HRESULT hres;
476
477     switch(expr->expression->type) {
478     case EXPR_ARRAY: {
479         binary_expression_t *array_expr = (binary_expression_t*)expr->expression;
480
481         hres = compile_expression(ctx, array_expr->expression1);
482         if(FAILED(hres))
483             return hres;
484
485         hres = compile_expression(ctx, array_expr->expression2);
486         if(FAILED(hres))
487             return hres;
488
489         if(push_instr(ctx, OP_delete) == -1)
490             return E_OUTOFMEMORY;
491         break;
492     }
493     case EXPR_MEMBER: {
494         member_expression_t *member_expr = (member_expression_t*)expr->expression;
495
496         hres = compile_expression(ctx, member_expr->expression);
497         if(FAILED(hres))
498             return hres;
499
500         /* FIXME: Potential optimization */
501         hres = push_instr_str(ctx, OP_str, member_expr->identifier);
502         if(FAILED(hres))
503             return hres;
504
505         if(push_instr(ctx, OP_delete) == -1)
506             return E_OUTOFMEMORY;
507         break;
508     }
509     case EXPR_IDENT:
510         return push_instr_bstr(ctx, OP_delete_ident, ((identifier_expression_t*)expr->expression)->identifier);
511     default: {
512         const WCHAR fixmeW[] = {'F','I','X','M','E',0};
513
514         WARN("invalid delete, unimplemented exception message\n");
515
516         hres = compile_expression(ctx, expr->expression);
517         if(FAILED(hres))
518             return hres;
519
520         return push_instr_uint_str(ctx, OP_throw_type, JS_E_INVALID_DELETE, fixmeW);
521     }
522     }
523
524     return S_OK;
525 }
526
527 static HRESULT compile_assign_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
528 {
529     HRESULT hres;
530
531     if(!is_memberid_expr(expr->expression1->type)) {
532         hres = compile_expression(ctx, expr->expression1);
533         if(FAILED(hres))
534             return hres;
535
536         hres = compile_expression(ctx, expr->expression2);
537         if(FAILED(hres))
538             return hres;
539
540         if(op != OP_LAST && push_instr(ctx, op) == -1)
541             return E_OUTOFMEMORY;
542
543         return push_instr_uint(ctx, OP_throw, JS_E_ILLEGAL_ASSIGN);
544     }
545
546     hres = compile_memberid_expression(ctx, expr->expression1, fdexNameEnsure);
547     if(FAILED(hres))
548         return hres;
549
550     if(op != OP_LAST && push_instr(ctx, OP_refval) == -1)
551         return E_OUTOFMEMORY;
552
553     hres = compile_expression(ctx, expr->expression2);
554     if(FAILED(hres))
555         return hres;
556
557     if(op != OP_LAST && push_instr(ctx, op) == -1)
558         return E_OUTOFMEMORY;
559
560     if(push_instr(ctx, OP_assign) == -1)
561         return E_OUTOFMEMORY;
562
563     return S_OK;
564 }
565
566 static HRESULT compile_typeof_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
567 {
568     jsop_t op;
569     HRESULT hres;
570
571     if(is_memberid_expr(expr->expression->type)) {
572         if(expr->expression->type == EXPR_IDENT)
573             return push_instr_str(ctx, OP_typeofident, ((identifier_expression_t*)expr->expression)->identifier);
574
575         op = OP_typeofid;
576         hres = compile_memberid_expression(ctx, expr->expression, 0);
577     }else {
578         op = OP_typeof;
579         hres = compile_expression(ctx, expr->expression);
580     }
581     if(FAILED(hres))
582         return hres;
583
584     return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK;
585 }
586
587 static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal)
588 {
589     switch(literal->type) {
590     case LT_BOOL:
591         return push_instr_int(ctx, OP_bool, literal->u.bval);
592     case LT_DOUBLE:
593         return push_instr_double(ctx, OP_double, literal->u.dval);
594     case LT_INT:
595         return push_instr_int(ctx, OP_int, literal->u.lval);
596     case LT_NULL:
597         return push_instr(ctx, OP_null);
598     case LT_STRING:
599         return push_instr_str(ctx, OP_str, literal->u.wstr);
600     case LT_REGEXP: {
601         unsigned instr;
602         WCHAR *str;
603
604         str = compiler_alloc(ctx->code, (literal->u.regexp.str_len+1)*sizeof(WCHAR));
605         if(!str)
606             return E_OUTOFMEMORY;
607         memcpy(str, literal->u.regexp.str, literal->u.regexp.str_len*sizeof(WCHAR));
608         str[literal->u.regexp.str_len] = 0;
609
610         instr = push_instr(ctx, OP_regexp);
611         if(instr == -1)
612             return E_OUTOFMEMORY;
613
614         instr_ptr(ctx, instr)->arg1.str = str;
615         instr_ptr(ctx, instr)->arg2.lng = literal->u.regexp.flags;
616         return S_OK;
617     }
618     default:
619         assert(0);
620     }
621 }
622
623 static HRESULT literal_as_bstr(compiler_ctx_t *ctx, literal_t *literal, BSTR *str)
624 {
625     switch(literal->type) {
626     case LT_STRING:
627         *str = compiler_alloc_bstr(ctx, literal->u.wstr);
628         break;
629     case LT_INT:
630         *str = int_to_bstr(literal->u.lval);
631         break;
632     case LT_DOUBLE:
633         return double_to_bstr(literal->u.dval, str);
634     default:
635         assert(0);
636     }
637
638     return *str ? S_OK : E_OUTOFMEMORY;
639 }
640
641 static HRESULT compile_array_literal(compiler_ctx_t *ctx, array_literal_expression_t *expr)
642 {
643     unsigned i, elem_cnt = expr->length;
644     array_element_t *iter;
645     HRESULT hres;
646
647     for(iter = expr->element_list; iter; iter = iter->next) {
648         elem_cnt += iter->elision+1;
649
650         for(i=0; i < iter->elision; i++) {
651             if(push_instr(ctx, OP_undefined) == -1)
652                 return E_OUTOFMEMORY;
653         }
654
655         hres = compile_expression(ctx, iter->expr);
656         if(FAILED(hres))
657             return hres;
658     }
659
660     for(i=0; i < expr->length; i++) {
661         if(push_instr(ctx, OP_undefined) == -1)
662             return E_OUTOFMEMORY;
663     }
664
665     return push_instr_uint(ctx, OP_carray, elem_cnt);
666 }
667
668 static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expression_t *expr)
669 {
670     prop_val_t *iter;
671     unsigned instr;
672     BSTR name;
673     HRESULT hres;
674
675     if(push_instr(ctx, OP_new_obj) == -1)
676         return E_OUTOFMEMORY;
677
678     for(iter = expr->property_list; iter; iter = iter->next) {
679         hres = literal_as_bstr(ctx, iter->name, &name);
680         if(FAILED(hres))
681             return hres;
682
683         hres = compile_expression(ctx, iter->value);
684         if(FAILED(hres))
685             return hres;
686
687         instr = push_instr(ctx, OP_obj_prop);
688         if(instr == -1)
689             return E_OUTOFMEMORY;
690
691         instr_ptr(ctx, instr)->arg1.bstr = name;
692     }
693
694     return S_OK;
695 }
696
697 static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr)
698 {
699     unsigned instr;
700
701     /* FIXME: not exactly right */
702     if(expr->identifier)
703         return push_instr_bstr(ctx, OP_ident, expr->identifier);
704
705     instr = push_instr(ctx, OP_func);
706     if(instr == -1)
707         return E_OUTOFMEMORY;
708
709     instr_ptr(ctx, instr)->arg1.func = expr;
710     return S_OK;
711 }
712
713 static HRESULT compile_expression_noret(compiler_ctx_t *ctx, expression_t *expr, BOOL *no_ret)
714 {
715     switch(expr->type) {
716     case EXPR_ADD:
717         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add);
718     case EXPR_AND:
719         return compile_logical_expression(ctx, (binary_expression_t*)expr, OP_jmp_z);
720     case EXPR_ARRAY:
721         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_array);
722     case EXPR_ARRAYLIT:
723         return compile_array_literal(ctx, (array_literal_expression_t*)expr);
724     case EXPR_ASSIGN:
725         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_LAST);
726     case EXPR_ASSIGNADD:
727         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_add);
728     case EXPR_ASSIGNAND:
729         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_and);
730     case EXPR_ASSIGNSUB:
731         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_sub);
732     case EXPR_ASSIGNMUL:
733         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_mul);
734     case EXPR_ASSIGNDIV:
735         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_div);
736     case EXPR_ASSIGNMOD:
737         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_mod);
738     case EXPR_ASSIGNOR:
739         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_or);
740     case EXPR_ASSIGNLSHIFT:
741         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_lshift);
742     case EXPR_ASSIGNRSHIFT:
743         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_rshift);
744     case EXPR_ASSIGNRRSHIFT:
745         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_rshift2);
746     case EXPR_ASSIGNXOR:
747         return compile_assign_expression(ctx, (binary_expression_t*)expr, OP_xor);
748     case EXPR_BAND:
749         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_and);
750     case EXPR_BITNEG:
751         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_bneg);
752     case EXPR_BOR:
753         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_or);
754     case EXPR_CALL:
755         return compile_call_expression(ctx, (call_expression_t*)expr, no_ret);
756     case EXPR_COMMA:
757         return compile_comma_expression(ctx, (binary_expression_t*)expr);
758     case EXPR_COND:
759         return compile_conditional_expression(ctx, (conditional_expression_t*)expr);
760     case EXPR_DELETE:
761         return compile_delete_expression(ctx, (unary_expression_t*)expr);
762     case EXPR_DIV:
763         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div);
764     case EXPR_EQ:
765         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq);
766     case EXPR_EQEQ:
767         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq2);
768     case EXPR_FUNC:
769         return compile_function_expression(ctx, (function_expression_t*)expr);
770     case EXPR_GREATER:
771         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gt);
772     case EXPR_GREATEREQ:
773         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gteq);
774     case EXPR_IDENT:
775         return push_instr_bstr(ctx, OP_ident, ((identifier_expression_t*)expr)->identifier);
776     case EXPR_IN:
777         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_in);
778     case EXPR_INSTANCEOF:
779         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_instanceof);
780     case EXPR_LESS:
781         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lt);
782     case EXPR_LESSEQ:
783         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lteq);
784     case EXPR_LITERAL:
785         return compile_literal(ctx, ((literal_expression_t*)expr)->literal);
786     case EXPR_LOGNEG:
787         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg);
788     case EXPR_LSHIFT:
789         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lshift);
790     case EXPR_MEMBER:
791         return compile_member_expression(ctx, (member_expression_t*)expr);
792     case EXPR_MINUS:
793         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_minus);
794     case EXPR_MOD:
795         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod);
796     case EXPR_MUL:
797         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul);
798     case EXPR_NEW:
799         return compile_new_expression(ctx, (call_expression_t*)expr);
800     case EXPR_NOTEQ:
801         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_neq);
802     case EXPR_NOTEQEQ:
803         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_neq2);
804     case EXPR_OR:
805         return compile_logical_expression(ctx, (binary_expression_t*)expr, OP_jmp_nz);
806     case EXPR_PLUS:
807         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_tonum);
808     case EXPR_POSTDEC:
809         return compile_increment_expression(ctx, (unary_expression_t*)expr, OP_postinc, -1);
810     case EXPR_POSTINC:
811         return compile_increment_expression(ctx, (unary_expression_t*)expr, OP_postinc, 1);
812     case EXPR_PREDEC:
813         return compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, -1);
814     case EXPR_PREINC:
815         return compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, 1);
816     case EXPR_PROPVAL:
817         return compile_object_literal(ctx, (property_value_expression_t*)expr);
818     case EXPR_RSHIFT:
819         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_rshift);
820     case EXPR_RRSHIFT:
821         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_rshift2);
822     case EXPR_SUB:
823         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
824     case EXPR_THIS:
825         return push_instr(ctx, OP_this) == -1 ? E_OUTOFMEMORY : S_OK;
826     case EXPR_TYPEOF:
827         return compile_typeof_expression(ctx, (unary_expression_t*)expr);
828     case EXPR_VOID:
829         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_void);
830     case EXPR_BXOR:
831         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor);
832     default:
833         assert(0);
834     }
835
836     return S_OK;
837 }
838
839 static HRESULT compile_expression(compiler_ctx_t *ctx, expression_t *expr)
840 {
841     return compile_expression_noret(ctx, expr, NULL);
842 }
843
844 static HRESULT compile_block_statement(compiler_ctx_t *ctx, statement_t *iter)
845 {
846     HRESULT hres;
847
848     /* FIXME: do it only if needed */
849     if(!iter)
850         return push_instr(ctx, OP_undefined) == -1 ? E_OUTOFMEMORY : S_OK;
851
852     while(1) {
853         hres = compile_statement(ctx, iter);
854         if(FAILED(hres))
855             return hres;
856
857         iter = iter->next;
858         if(!iter)
859             break;
860
861         if(push_instr(ctx, OP_pop) == -1)
862             return E_OUTOFMEMORY;
863     }
864
865     return S_OK;
866 }
867
868 static HRESULT compile_statement(compiler_ctx_t *ctx, statement_t *stat)
869 {
870     switch(stat->type) {
871     case STAT_BLOCK:
872         return compile_block_statement(ctx, ((block_statement_t*)stat)->stat_list);
873     default:
874         return compile_interp_fallback(ctx, stat);
875     }
876 }
877
878 void release_bytecode(bytecode_t *code)
879 {
880     unsigned i;
881
882     for(i=0; i < code->bstr_cnt; i++)
883         SysFreeString(code->bstr_pool[i]);
884
885     jsheap_free(&code->heap);
886     heap_free(code->bstr_pool);
887     heap_free(code->instrs);
888     heap_free(code);
889 }
890
891 void release_compiler(compiler_ctx_t *ctx)
892 {
893     heap_free(ctx);
894 }
895
896 static HRESULT init_compiler(parser_ctx_t *parser)
897 {
898     if(!parser->code) {
899         parser->code = heap_alloc_zero(sizeof(bytecode_t));
900         if(!parser->code)
901             return E_OUTOFMEMORY;
902         jsheap_init(&parser->code->heap);
903     }
904
905     if(!parser->compiler) {
906         parser->compiler = heap_alloc_zero(sizeof(compiler_ctx_t));
907         if(!parser->compiler)
908             return E_OUTOFMEMORY;
909
910         parser->compiler->parser = parser;
911         parser->compiler->code = parser->code;
912     }
913
914     return S_OK;
915 }
916
917 HRESULT compile_subscript(parser_ctx_t *parser, expression_t *expr, BOOL do_ret, unsigned *ret_off)
918 {
919     BOOL no_ret = FALSE;
920     HRESULT hres;
921
922     hres = init_compiler(parser);
923     if(FAILED(hres))
924         return hres;
925
926     *ret_off = parser->compiler->code_off;
927     hres = compile_expression_noret(parser->compiler, expr, do_ret ? NULL : &no_ret);
928     if(FAILED(hres))
929         return hres;
930
931     return push_instr(parser->compiler, OP_ret) == -1 ? E_OUTOFMEMORY : S_OK;
932 }
933
934 HRESULT compile_subscript_stat(parser_ctx_t *parser, statement_t *stat, unsigned *ret_off)
935 {
936     HRESULT hres;
937
938     TRACE("\n");
939
940     hres = init_compiler(parser);
941     if(FAILED(hres))
942         return hres;
943
944     *ret_off = parser->compiler->code_off;
945     hres = compile_statement(parser->compiler, stat);
946     if(FAILED(hres))
947         return hres;
948
949     return push_instr(parser->compiler, OP_ret) == -1 ? E_OUTOFMEMORY : S_OK;
950 }