xref: /reactos/dll/win32/jscript/compile.c (revision d6d1efe7)
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 #include "parser.h"
25 
26 #include "wine/rbtree.h"
27 #include "wine/debug.h"
28 
29 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
30 WINE_DECLARE_DEBUG_CHANNEL(jscript_disas);
31 
32 typedef struct _statement_ctx_t {
33     unsigned stack_use;
34     BOOL using_scope;
35     BOOL using_except;
36 
37     unsigned break_label;
38     unsigned continue_label;
39 
40     const labelled_statement_t *labelled_stat;
41 
42     struct _statement_ctx_t *next;
43 } statement_ctx_t;
44 
45 typedef struct {
46     struct wine_rb_entry entry;
47     BSTR name;
48     int ref;
49 } function_local_t;
50 
51 typedef struct {
52     parser_ctx_t *parser;
53     bytecode_t *code;
54 
55     BOOL from_eval;
56 
57     unsigned code_off;
58     unsigned code_size;
59 
60     unsigned *labels;
61     unsigned labels_size;
62     unsigned labels_cnt;
63 
64     struct wine_rb_tree locals;
65     unsigned locals_cnt;
66 
67     statement_ctx_t *stat_ctx;
68     function_code_t *func;
69 
70     function_expression_t *func_head;
71     function_expression_t *func_tail;
72 
73     heap_pool_t heap;
74 } compiler_ctx_t;
75 
76 static const struct {
77     const char *op_str;
78     instr_arg_type_t arg1_type;
79     instr_arg_type_t arg2_type;
80 } instr_info[] = {
81 #define X(n,a,b,c) {#n,b,c},
82 OP_LIST
83 #undef X
84 };
85 
86 static void dump_instr_arg(instr_arg_type_t type, instr_arg_t *arg)
87 {
88     switch(type) {
89     case ARG_STR:
90         TRACE_(jscript_disas)("\t%s", debugstr_jsstr(arg->str));
91         break;
92     case ARG_BSTR:
93         TRACE_(jscript_disas)("\t%s", debugstr_wn(arg->bstr, SysStringLen(arg->bstr)));
94         break;
95     case ARG_INT:
96         TRACE_(jscript_disas)("\t%d", arg->uint);
97         break;
98     case ARG_UINT:
99     case ARG_ADDR:
100         TRACE_(jscript_disas)("\t%u", arg->uint);
101         break;
102     case ARG_FUNC:
103     case ARG_NONE:
104         break;
105     DEFAULT_UNREACHABLE;
106     }
107 }
108 
109 static void dump_code(compiler_ctx_t *ctx, unsigned off)
110 {
111     instr_t *instr;
112 
113     for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->code_off; instr++) {
114         TRACE_(jscript_disas)("%d:\t%s", (int)(instr-ctx->code->instrs), instr_info[instr->op].op_str);
115         if(instr_info[instr->op].arg1_type == ARG_DBL) {
116             TRACE_(jscript_disas)("\t%lf", instr->u.dbl);
117         }else {
118             dump_instr_arg(instr_info[instr->op].arg1_type, instr->u.arg);
119             dump_instr_arg(instr_info[instr->op].arg2_type, instr->u.arg+1);
120         }
121         TRACE_(jscript_disas)("\n");
122     }
123 }
124 
125 static HRESULT compile_expression(compiler_ctx_t*,expression_t*,BOOL);
126 static HRESULT compile_statement(compiler_ctx_t*,statement_ctx_t*,statement_t*);
127 
128 static inline void *compiler_alloc(bytecode_t *code, size_t size)
129 {
130     return heap_pool_alloc(&code->heap, size);
131 }
132 
133 static jsstr_t *compiler_alloc_string_len(compiler_ctx_t *ctx, const WCHAR *str, unsigned len)
134 {
135     jsstr_t *new_str;
136 
137     if(!ctx->code->str_pool_size) {
138         ctx->code->str_pool = heap_alloc(8 * sizeof(jsstr_t*));
139         if(!ctx->code->str_pool)
140             return NULL;
141         ctx->code->str_pool_size = 8;
142     }else if(ctx->code->str_pool_size == ctx->code->str_cnt) {
143         jsstr_t **new_pool;
144 
145         new_pool = heap_realloc(ctx->code->str_pool, ctx->code->str_pool_size*2*sizeof(jsstr_t*));
146         if(!new_pool)
147             return NULL;
148 
149         ctx->code->str_pool = new_pool;
150         ctx->code->str_pool_size *= 2;
151     }
152 
153     new_str = jsstr_alloc_len(str, len);
154     if(!new_str)
155         return NULL;
156 
157     ctx->code->str_pool[ctx->code->str_cnt++] = new_str;
158     return new_str;
159 }
160 
161 static jsstr_t *compiler_alloc_string(compiler_ctx_t *ctx, const WCHAR *str)
162 {
163     return compiler_alloc_string_len(ctx, str, strlenW(str));
164 }
165 
166 static BOOL ensure_bstr_slot(compiler_ctx_t *ctx)
167 {
168     if(!ctx->code->bstr_pool_size) {
169         ctx->code->bstr_pool = heap_alloc(8 * sizeof(BSTR));
170         if(!ctx->code->bstr_pool)
171             return FALSE;
172         ctx->code->bstr_pool_size = 8;
173     }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) {
174         BSTR *new_pool;
175 
176         new_pool = heap_realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR));
177         if(!new_pool)
178             return FALSE;
179 
180         ctx->code->bstr_pool = new_pool;
181         ctx->code->bstr_pool_size *= 2;
182     }
183 
184     return TRUE;
185 }
186 
187 static BSTR compiler_alloc_bstr(compiler_ctx_t *ctx, const WCHAR *str)
188 {
189     if(!ensure_bstr_slot(ctx))
190         return NULL;
191 
192     ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocString(str);
193     if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
194         return NULL;
195 
196     return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
197 }
198 
199 static BSTR compiler_alloc_bstr_len(compiler_ctx_t *ctx, const WCHAR *str, size_t len)
200 {
201     if(!ensure_bstr_slot(ctx))
202         return NULL;
203 
204     ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocStringLen(str, len);
205     if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
206         return NULL;
207 
208     return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
209 }
210 
211 static unsigned push_instr(compiler_ctx_t *ctx, jsop_t op)
212 {
213     assert(ctx->code_size >= ctx->code_off);
214 
215     if(ctx->code_size == ctx->code_off) {
216         instr_t *new_instrs;
217 
218         new_instrs = heap_realloc(ctx->code->instrs, ctx->code_size*2*sizeof(instr_t));
219         if(!new_instrs)
220             return 0;
221 
222         ctx->code->instrs = new_instrs;
223         ctx->code_size *= 2;
224     }
225 
226     ctx->code->instrs[ctx->code_off].op = op;
227     return ctx->code_off++;
228 }
229 
230 static inline instr_t *instr_ptr(compiler_ctx_t *ctx, unsigned off)
231 {
232     assert(off < ctx->code_off);
233     return ctx->code->instrs + off;
234 }
235 
236 static HRESULT push_instr_int(compiler_ctx_t *ctx, jsop_t op, LONG arg)
237 {
238     unsigned instr;
239 
240     instr = push_instr(ctx, op);
241     if(!instr)
242         return E_OUTOFMEMORY;
243 
244     instr_ptr(ctx, instr)->u.arg->lng = arg;
245     return S_OK;
246 }
247 
248 static HRESULT push_instr_str(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg)
249 {
250     unsigned instr;
251     jsstr_t *str;
252 
253     str = compiler_alloc_string(ctx, arg);
254     if(!str)
255         return E_OUTOFMEMORY;
256 
257     instr = push_instr(ctx, op);
258     if(!instr)
259         return E_OUTOFMEMORY;
260 
261     instr_ptr(ctx, instr)->u.arg->str = str;
262     return S_OK;
263 }
264 
265 static HRESULT push_instr_bstr(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg)
266 {
267     unsigned instr;
268     WCHAR *str;
269 
270     str = compiler_alloc_bstr(ctx, arg);
271     if(!str)
272         return E_OUTOFMEMORY;
273 
274     instr = push_instr(ctx, op);
275     if(!instr)
276         return E_OUTOFMEMORY;
277 
278     instr_ptr(ctx, instr)->u.arg->bstr = str;
279     return S_OK;
280 }
281 
282 static HRESULT push_instr_bstr_uint(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg1, unsigned arg2)
283 {
284     unsigned instr;
285     WCHAR *str;
286 
287     str = compiler_alloc_bstr(ctx, arg1);
288     if(!str)
289         return E_OUTOFMEMORY;
290 
291     instr = push_instr(ctx, op);
292     if(!instr)
293         return E_OUTOFMEMORY;
294 
295     instr_ptr(ctx, instr)->u.arg[0].bstr = str;
296     instr_ptr(ctx, instr)->u.arg[1].uint = arg2;
297     return S_OK;
298 }
299 
300 static HRESULT push_instr_uint_str(compiler_ctx_t *ctx, jsop_t op, unsigned arg1, const WCHAR *arg2)
301 {
302     unsigned instr;
303     jsstr_t *str;
304 
305     str = compiler_alloc_string(ctx, arg2);
306     if(!str)
307         return E_OUTOFMEMORY;
308 
309     instr = push_instr(ctx, op);
310     if(!instr)
311         return E_OUTOFMEMORY;
312 
313     instr_ptr(ctx, instr)->u.arg[0].uint = arg1;
314     instr_ptr(ctx, instr)->u.arg[1].str = str;
315     return S_OK;
316 }
317 
318 static HRESULT push_instr_double(compiler_ctx_t *ctx, jsop_t op, double arg)
319 {
320     unsigned instr;
321 
322     instr = push_instr(ctx, op);
323     if(!instr)
324         return E_OUTOFMEMORY;
325 
326     instr_ptr(ctx, instr)->u.dbl = arg;
327     return S_OK;
328 }
329 
330 static inline void set_arg_uint(compiler_ctx_t *ctx, unsigned instr, unsigned arg)
331 {
332     instr_ptr(ctx, instr)->u.arg->uint = arg;
333 }
334 
335 static HRESULT push_instr_uint(compiler_ctx_t *ctx, jsop_t op, unsigned arg)
336 {
337     unsigned instr;
338 
339     instr = push_instr(ctx, op);
340     if(!instr)
341         return E_OUTOFMEMORY;
342 
343     set_arg_uint(ctx, instr, arg);
344     return S_OK;
345 }
346 
347 static HRESULT compile_binary_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
348 {
349     HRESULT hres;
350 
351     hres = compile_expression(ctx, expr->expression1, TRUE);
352     if(FAILED(hres))
353         return hres;
354 
355     hres = compile_expression(ctx, expr->expression2, TRUE);
356     if(FAILED(hres))
357         return hres;
358 
359     return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
360 }
361 
362 static HRESULT compile_unary_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op)
363 {
364     HRESULT hres;
365 
366     hres = compile_expression(ctx, expr->expression, TRUE);
367     if(FAILED(hres))
368         return hres;
369 
370     return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
371 }
372 
373 /* ECMA-262 3rd Edition    11.2.1 */
374 static HRESULT compile_member_expression(compiler_ctx_t *ctx, member_expression_t *expr)
375 {
376     HRESULT hres;
377 
378     hres = compile_expression(ctx, expr->expression, TRUE);
379     if(FAILED(hres))
380         return hres;
381 
382     return push_instr_bstr(ctx, OP_member, expr->identifier);
383 }
384 
385 #define LABEL_FLAG 0x80000000
386 
387 static unsigned alloc_label(compiler_ctx_t *ctx)
388 {
389     if(!ctx->labels_size) {
390         ctx->labels = heap_alloc(8 * sizeof(*ctx->labels));
391         if(!ctx->labels)
392             return 0;
393         ctx->labels_size = 8;
394     }else if(ctx->labels_size == ctx->labels_cnt) {
395         unsigned *new_labels;
396 
397         new_labels = heap_realloc(ctx->labels, 2*ctx->labels_size*sizeof(*ctx->labels));
398         if(!new_labels)
399             return 0;
400 
401         ctx->labels = new_labels;
402         ctx->labels_size *= 2;
403     }
404 
405     return ctx->labels_cnt++ | LABEL_FLAG;
406 }
407 
408 static void label_set_addr(compiler_ctx_t *ctx, unsigned label)
409 {
410     assert(label & LABEL_FLAG);
411     ctx->labels[label & ~LABEL_FLAG] = ctx->code_off;
412 }
413 
414 static inline BOOL is_memberid_expr(expression_type_t type)
415 {
416     return type == EXPR_IDENT || type == EXPR_MEMBER || type == EXPR_ARRAY;
417 }
418 
419 static BOOL bind_local(compiler_ctx_t *ctx, const WCHAR *identifier, int *ret_ref)
420 {
421     statement_ctx_t *iter;
422     local_ref_t *ref;
423 
424     for(iter = ctx->stat_ctx; iter; iter = iter->next) {
425         if(iter->using_scope)
426             return FALSE;
427     }
428 
429     ref = lookup_local(ctx->func, identifier);
430     if(!ref)
431         return FALSE;
432 
433     *ret_ref = ref->ref;
434     return TRUE;
435 }
436 
437 static HRESULT emit_identifier_ref(compiler_ctx_t *ctx, const WCHAR *identifier, unsigned flags)
438 {
439     int local_ref;
440     if(bind_local(ctx, identifier, &local_ref))
441         return push_instr_int(ctx, OP_local_ref, local_ref);
442     return push_instr_bstr_uint(ctx, OP_identid, identifier, flags);
443 }
444 
445 static HRESULT emit_identifier(compiler_ctx_t *ctx, const WCHAR *identifier)
446 {
447     int local_ref;
448     if(bind_local(ctx, identifier, &local_ref))
449         return push_instr_int(ctx, OP_local, local_ref);
450     return push_instr_bstr(ctx, OP_ident, identifier);
451 }
452 
453 static HRESULT compile_memberid_expression(compiler_ctx_t *ctx, expression_t *expr, unsigned flags)
454 {
455     HRESULT hres = S_OK;
456 
457     switch(expr->type) {
458     case EXPR_IDENT: {
459         identifier_expression_t *ident_expr = (identifier_expression_t*)expr;
460 
461         hres = emit_identifier_ref(ctx, ident_expr->identifier, flags);
462         break;
463     }
464     case EXPR_ARRAY: {
465         binary_expression_t *array_expr = (binary_expression_t*)expr;
466 
467         hres = compile_expression(ctx, array_expr->expression1, TRUE);
468         if(FAILED(hres))
469             return hres;
470 
471         hres = compile_expression(ctx, array_expr->expression2, TRUE);
472         if(FAILED(hres))
473             return hres;
474 
475         hres = push_instr_uint(ctx, OP_memberid, flags);
476         break;
477     }
478     case EXPR_MEMBER: {
479         member_expression_t *member_expr = (member_expression_t*)expr;
480 
481         hres = compile_expression(ctx, member_expr->expression, TRUE);
482         if(FAILED(hres))
483             return hres;
484 
485         /* FIXME: Potential optimization */
486         hres = push_instr_str(ctx, OP_str, member_expr->identifier);
487         if(FAILED(hres))
488             return hres;
489 
490         hres = push_instr_uint(ctx, OP_memberid, flags);
491         break;
492     }
493     DEFAULT_UNREACHABLE;
494     }
495 
496     return hres;
497 }
498 
499 static HRESULT compile_increment_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op, int n)
500 {
501     HRESULT hres;
502 
503     if(!is_memberid_expr(expr->expression->type)) {
504         hres = compile_expression(ctx, expr->expression, TRUE);
505         if(FAILED(hres))
506             return hres;
507 
508         return push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
509     }
510 
511     hres = compile_memberid_expression(ctx, expr->expression, fdexNameEnsure);
512     if(FAILED(hres))
513         return hres;
514 
515     return push_instr_int(ctx, op, n);
516 }
517 
518 /* ECMA-262 3rd Edition    11.14 */
519 static HRESULT compile_comma_expression(compiler_ctx_t *ctx, binary_expression_t *expr, BOOL emit_ret)
520 {
521     HRESULT hres;
522 
523     hres = compile_expression(ctx, expr->expression1, FALSE);
524     if(FAILED(hres))
525         return hres;
526 
527     return compile_expression(ctx, expr->expression2, emit_ret);
528 }
529 
530 /* ECMA-262 3rd Edition    11.11 */
531 static HRESULT compile_logical_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
532 {
533     unsigned instr;
534     HRESULT hres;
535 
536     hres = compile_expression(ctx, expr->expression1, TRUE);
537     if(FAILED(hres))
538         return hres;
539 
540     instr = push_instr(ctx, op);
541     if(!instr)
542         return E_OUTOFMEMORY;
543 
544     hres = compile_expression(ctx, expr->expression2, TRUE);
545     if(FAILED(hres))
546         return hres;
547 
548     set_arg_uint(ctx, instr, ctx->code_off);
549     return S_OK;
550 }
551 
552 /* ECMA-262 3rd Edition    11.12 */
553 static HRESULT compile_conditional_expression(compiler_ctx_t *ctx, conditional_expression_t *expr)
554 {
555     unsigned jmp_false, jmp_end;
556     HRESULT hres;
557 
558     hres = compile_expression(ctx, expr->expression, TRUE);
559     if(FAILED(hres))
560         return hres;
561 
562     jmp_false = push_instr(ctx, OP_cnd_z);
563     if(!jmp_false)
564         return E_OUTOFMEMORY;
565 
566     hres = compile_expression(ctx, expr->true_expression, TRUE);
567     if(FAILED(hres))
568         return hres;
569 
570     jmp_end = push_instr(ctx, OP_jmp);
571     if(!jmp_end)
572         return E_OUTOFMEMORY;
573 
574     set_arg_uint(ctx, jmp_false, ctx->code_off);
575     hres = push_instr_uint(ctx, OP_pop, 1);
576     if(FAILED(hres))
577         return hres;
578 
579     hres = compile_expression(ctx, expr->false_expression, TRUE);
580     if(FAILED(hres))
581         return hres;
582 
583     set_arg_uint(ctx, jmp_end, ctx->code_off);
584     return S_OK;
585 }
586 
587 static HRESULT compile_new_expression(compiler_ctx_t *ctx, call_expression_t *expr)
588 {
589     unsigned arg_cnt = 0;
590     argument_t *arg;
591     HRESULT hres;
592 
593     hres = compile_expression(ctx, expr->expression, TRUE);
594     if(FAILED(hres))
595         return hres;
596 
597     for(arg = expr->argument_list; arg; arg = arg->next) {
598         hres = compile_expression(ctx, arg->expr, TRUE);
599         if(FAILED(hres))
600             return hres;
601         arg_cnt++;
602     }
603 
604     hres = push_instr_uint(ctx, OP_new, arg_cnt);
605     if(FAILED(hres))
606         return hres;
607 
608     hres = push_instr_uint(ctx, OP_pop, arg_cnt+1);
609     if(FAILED(hres))
610         return hres;
611 
612     return push_instr(ctx, OP_push_acc) ? S_OK : E_OUTOFMEMORY;
613 }
614 
615 static HRESULT compile_call_expression(compiler_ctx_t *ctx, call_expression_t *expr, BOOL emit_ret)
616 {
617     unsigned arg_cnt = 0, extra_args;
618     argument_t *arg;
619     unsigned instr;
620     jsop_t op;
621     HRESULT hres;
622 
623     if(is_memberid_expr(expr->expression->type)) {
624         op = OP_call_member;
625         extra_args = 2;
626         hres = compile_memberid_expression(ctx, expr->expression, 0);
627     }else {
628         op = OP_call;
629         extra_args = 1;
630         hres = compile_expression(ctx, expr->expression, TRUE);
631     }
632 
633     if(FAILED(hres))
634         return hres;
635 
636     for(arg = expr->argument_list; arg; arg = arg->next) {
637         hres = compile_expression(ctx, arg->expr, TRUE);
638         if(FAILED(hres))
639             return hres;
640         arg_cnt++;
641     }
642 
643     instr = push_instr(ctx, op);
644     if(!instr)
645         return E_OUTOFMEMORY;
646 
647     instr_ptr(ctx, instr)->u.arg[0].uint = arg_cnt;
648     instr_ptr(ctx, instr)->u.arg[1].lng = emit_ret;
649 
650     hres = push_instr_uint(ctx, OP_pop, arg_cnt + extra_args);
651     if(FAILED(hres))
652         return hres;
653 
654     return !emit_ret || push_instr(ctx, OP_push_acc) ? S_OK : E_OUTOFMEMORY;
655 }
656 
657 static HRESULT compile_delete_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
658 {
659     HRESULT hres;
660 
661     switch(expr->expression->type) {
662     case EXPR_ARRAY: {
663         binary_expression_t *array_expr = (binary_expression_t*)expr->expression;
664 
665         hres = compile_expression(ctx, array_expr->expression1, TRUE);
666         if(FAILED(hres))
667             return hres;
668 
669         hres = compile_expression(ctx, array_expr->expression2, TRUE);
670         if(FAILED(hres))
671             return hres;
672 
673         if(!push_instr(ctx, OP_delete))
674             return E_OUTOFMEMORY;
675         break;
676     }
677     case EXPR_MEMBER: {
678         member_expression_t *member_expr = (member_expression_t*)expr->expression;
679 
680         hres = compile_expression(ctx, member_expr->expression, TRUE);
681         if(FAILED(hres))
682             return hres;
683 
684         /* FIXME: Potential optimization */
685         hres = push_instr_str(ctx, OP_str, member_expr->identifier);
686         if(FAILED(hres))
687             return hres;
688 
689         if(!push_instr(ctx, OP_delete))
690             return E_OUTOFMEMORY;
691         break;
692     }
693     case EXPR_IDENT:
694         return push_instr_bstr(ctx, OP_delete_ident, ((identifier_expression_t*)expr->expression)->identifier);
695     default: {
696         static const WCHAR fixmeW[] = {'F','I','X','M','E',0};
697 
698         WARN("invalid delete, unimplemented exception message\n");
699 
700         hres = compile_expression(ctx, expr->expression, TRUE);
701         if(FAILED(hres))
702             return hres;
703 
704         return push_instr_uint_str(ctx, OP_throw_type, JS_E_INVALID_DELETE, fixmeW);
705     }
706     }
707 
708     return S_OK;
709 }
710 
711 static HRESULT compile_assign_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
712 {
713     BOOL use_throw_path = FALSE;
714     unsigned arg_cnt = 0;
715     HRESULT hres;
716 
717     if(expr->expression1->type == EXPR_CALL) {
718         call_expression_t *call_expr = (call_expression_t*)expr->expression1;
719         argument_t *arg;
720 
721         if(op != OP_LAST) {
722             FIXME("op %d not supported on parametrized assign expressions\n", op);
723             return E_NOTIMPL;
724         }
725 
726         if(is_memberid_expr(call_expr->expression->type) && call_expr->argument_list) {
727             hres = compile_memberid_expression(ctx, call_expr->expression, fdexNameEnsure);
728             if(FAILED(hres))
729                 return hres;
730 
731             for(arg = call_expr->argument_list; arg; arg = arg->next) {
732                 hres = compile_expression(ctx, arg->expr, TRUE);
733                 if(FAILED(hres))
734                     return hres;
735                 arg_cnt++;
736             }
737         }else {
738             use_throw_path = TRUE;
739         }
740     }else if(is_memberid_expr(expr->expression1->type)) {
741         hres = compile_memberid_expression(ctx, expr->expression1, fdexNameEnsure);
742         if(FAILED(hres))
743             return hres;
744     }else {
745         use_throw_path = TRUE;
746     }
747 
748     if(use_throw_path) {
749         /* Illegal assignment: evaluate and throw */
750         hres = compile_expression(ctx, expr->expression1, TRUE);
751         if(FAILED(hres))
752             return hres;
753 
754         hres = compile_expression(ctx, expr->expression2, TRUE);
755         if(FAILED(hres))
756             return hres;
757 
758         if(op != OP_LAST && !push_instr(ctx, op))
759             return E_OUTOFMEMORY;
760 
761         return push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
762     }
763 
764     if(op != OP_LAST && !push_instr(ctx, OP_refval))
765         return E_OUTOFMEMORY;
766 
767     hres = compile_expression(ctx, expr->expression2, TRUE);
768     if(FAILED(hres))
769         return hres;
770 
771     if(op != OP_LAST && !push_instr(ctx, op))
772         return E_OUTOFMEMORY;
773 
774     if(arg_cnt)
775         return push_instr_uint(ctx, OP_assign_call, arg_cnt);
776 
777     if(!push_instr(ctx, OP_assign))
778         return E_OUTOFMEMORY;
779 
780     return S_OK;
781 }
782 
783 static HRESULT compile_typeof_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
784 {
785     jsop_t op;
786     HRESULT hres;
787 
788     if(is_memberid_expr(expr->expression->type)) {
789         if(expr->expression->type == EXPR_IDENT)
790             return push_instr_bstr(ctx, OP_typeofident, ((identifier_expression_t*)expr->expression)->identifier);
791 
792         op = OP_typeofid;
793         hres = compile_memberid_expression(ctx, expr->expression, 0);
794     }else {
795         op = OP_typeof;
796         hres = compile_expression(ctx, expr->expression, TRUE);
797     }
798     if(FAILED(hres))
799         return hres;
800 
801     return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
802 }
803 
804 static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal)
805 {
806     switch(literal->type) {
807     case LT_BOOL:
808         return push_instr_int(ctx, OP_bool, literal->u.bval);
809     case LT_DOUBLE:
810         return push_instr_double(ctx, OP_double, literal->u.dval);
811     case LT_NULL:
812         return push_instr(ctx, OP_null) ? S_OK : E_OUTOFMEMORY;
813     case LT_STRING:
814         return push_instr_str(ctx, OP_str, literal->u.wstr);
815     case LT_REGEXP: {
816         unsigned instr;
817         jsstr_t *str;
818 
819         str = compiler_alloc_string_len(ctx, literal->u.regexp.str, literal->u.regexp.str_len);
820         if(!str)
821             return E_OUTOFMEMORY;
822 
823         instr = push_instr(ctx, OP_regexp);
824         if(!instr)
825             return E_OUTOFMEMORY;
826 
827         instr_ptr(ctx, instr)->u.arg[0].str = str;
828         instr_ptr(ctx, instr)->u.arg[1].uint = literal->u.regexp.flags;
829         return S_OK;
830     }
831     DEFAULT_UNREACHABLE;
832     }
833     return E_FAIL;
834 }
835 
836 static HRESULT literal_as_bstr(compiler_ctx_t *ctx, literal_t *literal, BSTR *str)
837 {
838     switch(literal->type) {
839     case LT_STRING:
840         *str = compiler_alloc_bstr(ctx, literal->u.wstr);
841         break;
842     case LT_DOUBLE: {
843         jsstr_t *jsstr;
844         HRESULT hres;
845 
846         hres = double_to_string(literal->u.dval, &jsstr);
847         if(FAILED(hres))
848             return hres;
849 
850         *str = compiler_alloc_bstr_len(ctx, NULL, jsstr_length(jsstr));
851         if(*str)
852             jsstr_flush(jsstr, *str);
853         jsstr_release(jsstr);
854         break;
855     }
856     DEFAULT_UNREACHABLE;
857     }
858 
859     return *str ? S_OK : E_OUTOFMEMORY;
860 }
861 
862 static HRESULT compile_array_literal(compiler_ctx_t *ctx, array_literal_expression_t *expr)
863 {
864     unsigned length = 0;
865     array_element_t *iter;
866     unsigned array_instr;
867     HRESULT hres;
868 
869     array_instr = push_instr(ctx, OP_carray);
870 
871     for(iter = expr->element_list; iter; iter = iter->next) {
872         length += iter->elision;
873 
874         hres = compile_expression(ctx, iter->expr, TRUE);
875         if(FAILED(hres))
876             return hres;
877 
878         hres = push_instr_uint(ctx, OP_carray_set, length);
879         if(FAILED(hres))
880             return hres;
881 
882         length++;
883     }
884 
885     instr_ptr(ctx, array_instr)->u.arg[0].uint = length + expr->length;
886     return S_OK;
887 }
888 
889 static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expression_t *expr)
890 {
891     property_definition_t *iter;
892     BSTR name;
893     HRESULT hres;
894 
895     if(!push_instr(ctx, OP_new_obj))
896         return E_OUTOFMEMORY;
897 
898     for(iter = expr->property_list; iter; iter = iter->next) {
899         hres = literal_as_bstr(ctx, iter->name, &name);
900         if(FAILED(hres))
901             return hres;
902 
903         hres = compile_expression(ctx, iter->value, TRUE);
904         if(FAILED(hres))
905             return hres;
906 
907         hres = push_instr_bstr_uint(ctx, OP_obj_prop, name, iter->type);
908         if(FAILED(hres))
909             return hres;
910     }
911 
912     return S_OK;
913 }
914 
915 static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr, BOOL emit_ret)
916 {
917     return emit_ret ? push_instr_uint(ctx, OP_func, expr->func_id) : S_OK;
918 }
919 
920 static HRESULT compile_expression(compiler_ctx_t *ctx, expression_t *expr, BOOL emit_ret)
921 {
922     HRESULT hres;
923 
924     switch(expr->type) {
925     case EXPR_ADD:
926         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add);
927         break;
928     case EXPR_AND:
929         hres = compile_logical_expression(ctx, (binary_expression_t*)expr, OP_cnd_z);
930         break;
931     case EXPR_ARRAY:
932         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_array);
933         break;
934     case EXPR_ARRAYLIT:
935         hres = compile_array_literal(ctx, (array_literal_expression_t*)expr);
936         break;
937     case EXPR_ASSIGN:
938         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_LAST);
939         break;
940     case EXPR_ASSIGNADD:
941         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_add);
942         break;
943     case EXPR_ASSIGNAND:
944         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_and);
945         break;
946     case EXPR_ASSIGNSUB:
947         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_sub);
948         break;
949     case EXPR_ASSIGNMUL:
950         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_mul);
951         break;
952     case EXPR_ASSIGNDIV:
953         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_div);
954         break;
955     case EXPR_ASSIGNMOD:
956         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_mod);
957         break;
958     case EXPR_ASSIGNOR:
959         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_or);
960         break;
961     case EXPR_ASSIGNLSHIFT:
962         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_lshift);
963         break;
964     case EXPR_ASSIGNRSHIFT:
965         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_rshift);
966         break;
967     case EXPR_ASSIGNRRSHIFT:
968         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_rshift2);
969         break;
970     case EXPR_ASSIGNXOR:
971         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_xor);
972         break;
973     case EXPR_BAND:
974         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_and);
975         break;
976     case EXPR_BITNEG:
977         hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_bneg);
978         break;
979     case EXPR_BOR:
980         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_or);
981         break;
982     case EXPR_CALL:
983         return compile_call_expression(ctx, (call_expression_t*)expr, emit_ret);
984     case EXPR_COMMA:
985         return compile_comma_expression(ctx, (binary_expression_t*)expr, emit_ret);
986     case EXPR_COND:
987         hres = compile_conditional_expression(ctx, (conditional_expression_t*)expr);
988         break;
989     case EXPR_DELETE:
990         hres = compile_delete_expression(ctx, (unary_expression_t*)expr);
991         break;
992     case EXPR_DIV:
993         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div);
994         break;
995     case EXPR_EQ:
996         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq);
997         break;
998     case EXPR_EQEQ:
999         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq2);
1000         break;
1001     case EXPR_FUNC:
1002         return compile_function_expression(ctx, (function_expression_t*)expr, emit_ret);
1003     case EXPR_GREATER:
1004         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gt);
1005         break;
1006     case EXPR_GREATEREQ:
1007         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gteq);
1008         break;
1009     case EXPR_IDENT:
1010         hres = emit_identifier(ctx, ((identifier_expression_t*)expr)->identifier);
1011         break;
1012     case EXPR_IN:
1013         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_in);
1014         break;
1015     case EXPR_INSTANCEOF:
1016         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_instanceof);
1017         break;
1018     case EXPR_LESS:
1019         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lt);
1020         break;
1021     case EXPR_LESSEQ:
1022         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lteq);
1023         break;
1024     case EXPR_LITERAL:
1025         hres = compile_literal(ctx, ((literal_expression_t*)expr)->literal);
1026         break;
1027     case EXPR_LOGNEG:
1028         hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg);
1029         break;
1030     case EXPR_LSHIFT:
1031         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lshift);
1032         break;
1033     case EXPR_MEMBER:
1034         hres = compile_member_expression(ctx, (member_expression_t*)expr);
1035         break;
1036     case EXPR_MINUS:
1037         hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_minus);
1038         break;
1039     case EXPR_MOD:
1040         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod);
1041         break;
1042     case EXPR_MUL:
1043         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul);
1044         break;
1045     case EXPR_NEW:
1046         hres = compile_new_expression(ctx, (call_expression_t*)expr);
1047         break;
1048     case EXPR_NOTEQ:
1049         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_neq);
1050         break;
1051     case EXPR_NOTEQEQ:
1052         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_neq2);
1053         break;
1054     case EXPR_OR:
1055         hres = compile_logical_expression(ctx, (binary_expression_t*)expr, OP_cnd_nz);
1056         break;
1057     case EXPR_PLUS:
1058         hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_tonum);
1059         break;
1060     case EXPR_POSTDEC:
1061         hres = compile_increment_expression(ctx, (unary_expression_t*)expr, OP_postinc, -1);
1062         break;
1063     case EXPR_POSTINC:
1064         hres = compile_increment_expression(ctx, (unary_expression_t*)expr, OP_postinc, 1);
1065         break;
1066     case EXPR_PREDEC:
1067         hres = compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, -1);
1068         break;
1069     case EXPR_PREINC:
1070         hres = compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, 1);
1071         break;
1072     case EXPR_PROPVAL:
1073         hres = compile_object_literal(ctx, (property_value_expression_t*)expr);
1074         break;
1075     case EXPR_RSHIFT:
1076         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_rshift);
1077         break;
1078     case EXPR_RRSHIFT:
1079         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_rshift2);
1080         break;
1081     case EXPR_SUB:
1082         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
1083         break;
1084     case EXPR_THIS:
1085         return !emit_ret || push_instr(ctx, OP_this) ? S_OK : E_OUTOFMEMORY;
1086     case EXPR_TYPEOF:
1087         hres = compile_typeof_expression(ctx, (unary_expression_t*)expr);
1088         break;
1089     case EXPR_VOID:
1090         hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_void);
1091         break;
1092     case EXPR_BXOR:
1093         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor);
1094         break;
1095     DEFAULT_UNREACHABLE;
1096     }
1097 
1098     if(FAILED(hres))
1099         return hres;
1100 
1101     return emit_ret ? S_OK : push_instr_uint(ctx, OP_pop, 1);
1102 }
1103 
1104 static inline BOOL is_loop_statement(statement_type_t type)
1105 {
1106     return type == STAT_FOR || type == STAT_FORIN || type == STAT_WHILE;
1107 }
1108 
1109 /* ECMA-262 3rd Edition    12.1 */
1110 static HRESULT compile_block_statement(compiler_ctx_t *ctx, statement_t *iter)
1111 {
1112     HRESULT hres;
1113 
1114     while(iter) {
1115         hres = compile_statement(ctx, NULL, iter);
1116         if(FAILED(hres))
1117             return hres;
1118 
1119         iter = iter->next;
1120     }
1121 
1122     return S_OK;
1123 }
1124 
1125 /* ECMA-262 3rd Edition    12.2 */
1126 static HRESULT compile_variable_list(compiler_ctx_t *ctx, variable_declaration_t *list)
1127 {
1128     variable_declaration_t *iter;
1129     HRESULT hres;
1130 
1131     assert(list != NULL);
1132 
1133     for(iter = list; iter; iter = iter->next) {
1134         if(!iter->expr)
1135             continue;
1136 
1137         hres = emit_identifier_ref(ctx, iter->identifier, 0);
1138         if(FAILED(hres))
1139             return hres;
1140 
1141         hres = compile_expression(ctx, iter->expr, TRUE);
1142         if(FAILED(hres))
1143             return hres;
1144 
1145         if(!push_instr(ctx, OP_assign))
1146             return E_OUTOFMEMORY;
1147 
1148         hres = push_instr_uint(ctx, OP_pop, 1);
1149         if(FAILED(hres))
1150             return hres;
1151     }
1152 
1153     return S_OK;
1154 }
1155 
1156 /* ECMA-262 3rd Edition    12.2 */
1157 static HRESULT compile_var_statement(compiler_ctx_t *ctx, var_statement_t *stat)
1158 {
1159     return compile_variable_list(ctx, stat->variable_list);
1160 }
1161 
1162 /* ECMA-262 3rd Edition    12.4 */
1163 static HRESULT compile_expression_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
1164 {
1165     HRESULT hres;
1166 
1167     hres = compile_expression(ctx, stat->expr, ctx->from_eval);
1168     if(FAILED(hres))
1169         return hres;
1170 
1171     return !ctx->from_eval || push_instr(ctx, OP_setret) ? S_OK : E_OUTOFMEMORY;
1172 }
1173 
1174 /* ECMA-262 3rd Edition    12.5 */
1175 static HRESULT compile_if_statement(compiler_ctx_t *ctx, if_statement_t *stat)
1176 {
1177     unsigned jmp_else;
1178     HRESULT hres;
1179 
1180     hres = compile_expression(ctx, stat->expr, TRUE);
1181     if(FAILED(hres))
1182         return hres;
1183 
1184     jmp_else = push_instr(ctx, OP_jmp_z);
1185     if(!jmp_else)
1186         return E_OUTOFMEMORY;
1187 
1188     hres = compile_statement(ctx, NULL, stat->if_stat);
1189     if(FAILED(hres))
1190         return hres;
1191 
1192     if(stat->else_stat) {
1193         unsigned jmp_end;
1194 
1195         jmp_end = push_instr(ctx, OP_jmp);
1196         if(!jmp_end)
1197             return E_OUTOFMEMORY;
1198 
1199         set_arg_uint(ctx, jmp_else, ctx->code_off);
1200 
1201         hres = compile_statement(ctx, NULL, stat->else_stat);
1202         if(FAILED(hres))
1203             return hres;
1204 
1205         set_arg_uint(ctx, jmp_end, ctx->code_off);
1206     }else {
1207         set_arg_uint(ctx, jmp_else, ctx->code_off);
1208     }
1209 
1210     return S_OK;
1211 }
1212 
1213 /* ECMA-262 3rd Edition    12.6.2 */
1214 static HRESULT compile_while_statement(compiler_ctx_t *ctx, while_statement_t *stat)
1215 {
1216     statement_ctx_t stat_ctx = {0, FALSE, FALSE};
1217     unsigned jmp_off;
1218     HRESULT hres;
1219 
1220     stat_ctx.break_label = alloc_label(ctx);
1221     if(!stat_ctx.break_label)
1222         return E_OUTOFMEMORY;
1223 
1224     stat_ctx.continue_label = alloc_label(ctx);
1225     if(!stat_ctx.continue_label)
1226         return E_OUTOFMEMORY;
1227 
1228     jmp_off = ctx->code_off;
1229 
1230     if(!stat->do_while) {
1231         label_set_addr(ctx, stat_ctx.continue_label);
1232         hres = compile_expression(ctx, stat->expr, TRUE);
1233         if(FAILED(hres))
1234             return hres;
1235 
1236         hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1237         if(FAILED(hres))
1238             return hres;
1239     }
1240 
1241     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1242     if(FAILED(hres))
1243         return hres;
1244 
1245     if(stat->do_while) {
1246         label_set_addr(ctx, stat_ctx.continue_label);
1247         hres = compile_expression(ctx, stat->expr, TRUE);
1248         if(FAILED(hres))
1249             return hres;
1250 
1251         hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1252         if(FAILED(hres))
1253             return hres;
1254     }
1255 
1256     hres = push_instr_uint(ctx, OP_jmp, jmp_off);
1257     if(FAILED(hres))
1258         return hres;
1259 
1260     label_set_addr(ctx, stat_ctx.break_label);
1261     return S_OK;
1262 }
1263 
1264 /* ECMA-262 3rd Edition    12.6.3 */
1265 static HRESULT compile_for_statement(compiler_ctx_t *ctx, for_statement_t *stat)
1266 {
1267     statement_ctx_t stat_ctx = {0, FALSE, FALSE};
1268     unsigned expr_off;
1269     HRESULT hres;
1270 
1271     if(stat->variable_list) {
1272         hres = compile_variable_list(ctx, stat->variable_list);
1273         if(FAILED(hres))
1274             return hres;
1275     }else if(stat->begin_expr) {
1276         hres = compile_expression(ctx, stat->begin_expr, FALSE);
1277         if(FAILED(hres))
1278             return hres;
1279     }
1280 
1281     stat_ctx.break_label = alloc_label(ctx);
1282     if(!stat_ctx.break_label)
1283         return E_OUTOFMEMORY;
1284 
1285     stat_ctx.continue_label = alloc_label(ctx);
1286     if(!stat_ctx.continue_label)
1287         return E_OUTOFMEMORY;
1288 
1289     expr_off = ctx->code_off;
1290 
1291     if(stat->expr) {
1292         hres = compile_expression(ctx, stat->expr, TRUE);
1293         if(FAILED(hres))
1294             return hres;
1295 
1296         hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1297         if(FAILED(hres))
1298             return hres;
1299     }
1300 
1301     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1302     if(FAILED(hres))
1303         return hres;
1304 
1305     label_set_addr(ctx, stat_ctx.continue_label);
1306 
1307     if(stat->end_expr) {
1308         hres = compile_expression(ctx, stat->end_expr, FALSE);
1309         if(FAILED(hres))
1310             return hres;
1311     }
1312 
1313     hres = push_instr_uint(ctx, OP_jmp, expr_off);
1314     if(FAILED(hres))
1315         return hres;
1316 
1317     label_set_addr(ctx, stat_ctx.break_label);
1318     return S_OK;
1319 }
1320 
1321 /* ECMA-262 3rd Edition    12.6.4 */
1322 static HRESULT compile_forin_statement(compiler_ctx_t *ctx, forin_statement_t *stat)
1323 {
1324     statement_ctx_t stat_ctx = {4, FALSE, FALSE};
1325     HRESULT hres;
1326 
1327     if(stat->variable) {
1328         hres = compile_variable_list(ctx, stat->variable);
1329         if(FAILED(hres))
1330             return hres;
1331     }
1332 
1333     stat_ctx.break_label = alloc_label(ctx);
1334     if(!stat_ctx.break_label)
1335         return E_OUTOFMEMORY;
1336 
1337     stat_ctx.continue_label = alloc_label(ctx);
1338     if(!stat_ctx.continue_label)
1339         return E_OUTOFMEMORY;
1340 
1341     hres = compile_expression(ctx, stat->in_expr, TRUE);
1342     if(FAILED(hres))
1343         return hres;
1344 
1345     if(stat->variable) {
1346         hres = emit_identifier_ref(ctx, stat->variable->identifier, fdexNameEnsure);
1347         if(FAILED(hres))
1348             return hres;
1349     }else if(is_memberid_expr(stat->expr->type)) {
1350         hres = compile_memberid_expression(ctx, stat->expr, fdexNameEnsure);
1351         if(FAILED(hres))
1352             return hres;
1353     }else {
1354         hres = push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
1355         if(FAILED(hres))
1356             return hres;
1357 
1358         /* FIXME: compile statement anyways when we depend on compiler to check errors */
1359         return S_OK;
1360     }
1361 
1362     hres = push_instr_int(ctx, OP_int, DISPID_STARTENUM);
1363     if(FAILED(hres))
1364         return hres;
1365 
1366     label_set_addr(ctx, stat_ctx.continue_label);
1367     hres = push_instr_uint(ctx, OP_forin, stat_ctx.break_label);
1368     if(FAILED(hres))
1369         return E_OUTOFMEMORY;
1370 
1371     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1372     if(FAILED(hres))
1373         return hres;
1374 
1375     hres = push_instr_uint(ctx, OP_jmp, stat_ctx.continue_label);
1376     if(FAILED(hres))
1377         return hres;
1378 
1379     label_set_addr(ctx, stat_ctx.break_label);
1380     return S_OK;
1381 }
1382 
1383 static HRESULT pop_to_stat(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx)
1384 {
1385     unsigned stack_pop = 0;
1386     statement_ctx_t *iter;
1387     HRESULT hres;
1388 
1389     for(iter = ctx->stat_ctx; iter != stat_ctx; iter = iter->next) {
1390         if(iter->using_scope && !push_instr(ctx, OP_pop_scope))
1391             return E_OUTOFMEMORY;
1392         if(iter->using_except) {
1393             if(stack_pop) {
1394                 hres = push_instr_uint(ctx, OP_pop, stack_pop);
1395                 if(FAILED(hres))
1396                     return hres;
1397                 stack_pop = 0;
1398             }
1399             hres = push_instr_uint(ctx, OP_pop_except, ctx->code_off+1);
1400             if(FAILED(hres))
1401                 return hres;
1402         }
1403         stack_pop += iter->stack_use;
1404     }
1405 
1406     if(stack_pop) {
1407         hres = push_instr_uint(ctx, OP_pop, stack_pop);
1408         if(FAILED(hres))
1409             return hres;
1410     }
1411 
1412     return S_OK;
1413 }
1414 
1415 /* ECMA-262 3rd Edition    12.7 */
1416 static HRESULT compile_continue_statement(compiler_ctx_t *ctx, branch_statement_t *stat)
1417 {
1418     statement_ctx_t *pop_ctx;
1419     HRESULT hres;
1420 
1421     if(stat->identifier) {
1422         statement_t *label_stat;
1423         statement_ctx_t *iter;
1424 
1425         pop_ctx = NULL;
1426 
1427         for(iter = ctx->stat_ctx; iter; iter = iter->next) {
1428             if(iter->continue_label)
1429                 pop_ctx = iter;
1430             if(iter->labelled_stat && !strcmpW(iter->labelled_stat->identifier, stat->identifier))
1431                 break;
1432         }
1433 
1434         if(!iter) {
1435             WARN("Label not found\n");
1436             return JS_E_LABEL_NOT_FOUND;
1437         }
1438 
1439         /* Labelled continue are allowed only on loops */
1440         for(label_stat = iter->labelled_stat->statement;
1441             label_stat->type == STAT_LABEL;
1442             label_stat = ((labelled_statement_t*)label_stat)->statement);
1443         if(!is_loop_statement(label_stat->type)) {
1444             WARN("Label is not a loop\n");
1445             return JS_E_INVALID_CONTINUE;
1446         }
1447 
1448         assert(pop_ctx != NULL);
1449     }else {
1450         for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
1451             if(pop_ctx->continue_label)
1452                 break;
1453         }
1454 
1455         if(!pop_ctx) {
1456             WARN("continue outside loop\n");
1457             return JS_E_INVALID_CONTINUE;
1458         }
1459     }
1460 
1461     hres = pop_to_stat(ctx, pop_ctx);
1462     if(FAILED(hres))
1463         return hres;
1464 
1465     return push_instr_uint(ctx, OP_jmp, pop_ctx->continue_label);
1466 }
1467 
1468 /* ECMA-262 3rd Edition    12.8 */
1469 static HRESULT compile_break_statement(compiler_ctx_t *ctx, branch_statement_t *stat)
1470 {
1471     statement_ctx_t *pop_ctx;
1472     HRESULT hres;
1473 
1474     if(stat->identifier) {
1475         for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
1476             if(pop_ctx->labelled_stat && !strcmpW(pop_ctx->labelled_stat->identifier, stat->identifier)) {
1477                 assert(pop_ctx->break_label);
1478                 break;
1479             }
1480         }
1481 
1482         if(!pop_ctx) {
1483             WARN("Label not found\n");
1484             return JS_E_LABEL_NOT_FOUND;
1485         }
1486     }else {
1487         for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
1488             if(pop_ctx->break_label && !pop_ctx->labelled_stat)
1489                 break;
1490         }
1491 
1492         if(!pop_ctx) {
1493             WARN("Break outside loop\n");
1494             return JS_E_INVALID_BREAK;
1495         }
1496     }
1497 
1498     hres = pop_to_stat(ctx, pop_ctx->next);
1499     if(FAILED(hres))
1500         return hres;
1501 
1502     return push_instr_uint(ctx, OP_jmp, pop_ctx->break_label);
1503 }
1504 
1505 /* ECMA-262 3rd Edition    12.9 */
1506 static HRESULT compile_return_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
1507 {
1508     HRESULT hres;
1509 
1510     if(ctx->from_eval) {
1511         WARN("misplaced return statement\n");
1512         return JS_E_MISPLACED_RETURN;
1513     }
1514 
1515     if(stat->expr) {
1516         hres = compile_expression(ctx, stat->expr, TRUE);
1517         if(FAILED(hres))
1518             return hres;
1519         if(!push_instr(ctx, OP_setret))
1520             return E_OUTOFMEMORY;
1521     }
1522 
1523     hres = pop_to_stat(ctx, NULL);
1524     if(FAILED(hres))
1525         return hres;
1526 
1527     return push_instr_uint(ctx, OP_ret, !stat->expr);
1528 }
1529 
1530 /* ECMA-262 3rd Edition    12.10 */
1531 static HRESULT compile_with_statement(compiler_ctx_t *ctx, with_statement_t *stat)
1532 {
1533     statement_ctx_t stat_ctx = {0, TRUE, FALSE};
1534     HRESULT hres;
1535 
1536     hres = compile_expression(ctx, stat->expr, TRUE);
1537     if(FAILED(hres))
1538         return hres;
1539 
1540     if(!push_instr(ctx, OP_push_scope))
1541         return E_OUTOFMEMORY;
1542 
1543     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1544     if(FAILED(hres))
1545         return hres;
1546 
1547     if(!push_instr(ctx, OP_pop_scope))
1548         return E_OUTOFMEMORY;
1549 
1550     return S_OK;
1551 }
1552 
1553 /* ECMA-262 3rd Edition    12.10 */
1554 static HRESULT compile_labelled_statement(compiler_ctx_t *ctx, labelled_statement_t *stat)
1555 {
1556     statement_ctx_t stat_ctx = {0, FALSE, FALSE, 0, 0, stat}, *iter;
1557     HRESULT hres;
1558 
1559     for(iter = ctx->stat_ctx; iter; iter = iter->next) {
1560         if(iter->labelled_stat && !strcmpW(iter->labelled_stat->identifier, stat->identifier)) {
1561             WARN("Label %s redefined\n", debugstr_w(stat->identifier));
1562             return JS_E_LABEL_REDEFINED;
1563         }
1564     }
1565 
1566     /* Labelled breaks are allowed for any labelled statements, not only loops (violating spec) */
1567     stat_ctx.break_label = alloc_label(ctx);
1568     if(!stat_ctx.break_label)
1569         return E_OUTOFMEMORY;
1570 
1571     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1572     if(FAILED(hres))
1573         return hres;
1574 
1575     label_set_addr(ctx, stat_ctx.break_label);
1576     return S_OK;
1577 }
1578 
1579 /* ECMA-262 3rd Edition    12.13 */
1580 static HRESULT compile_switch_statement(compiler_ctx_t *ctx, switch_statement_t *stat)
1581 {
1582     statement_ctx_t stat_ctx = {0, FALSE, FALSE};
1583     unsigned case_cnt = 0, *case_jmps, i, default_jmp;
1584     BOOL have_default = FALSE;
1585     statement_t *stat_iter;
1586     case_clausule_t *iter;
1587     HRESULT hres;
1588 
1589     hres = compile_expression(ctx, stat->expr, TRUE);
1590     if(FAILED(hres))
1591         return hres;
1592 
1593     stat_ctx.break_label = alloc_label(ctx);
1594     if(!stat_ctx.break_label)
1595         return E_OUTOFMEMORY;
1596 
1597     for(iter = stat->case_list; iter; iter = iter->next) {
1598         if(iter->expr)
1599             case_cnt++;
1600     }
1601 
1602     case_jmps = heap_alloc(case_cnt * sizeof(*case_jmps));
1603     if(!case_jmps)
1604         return E_OUTOFMEMORY;
1605 
1606     i = 0;
1607     for(iter = stat->case_list; iter; iter = iter->next) {
1608         if(!iter->expr) {
1609             have_default = TRUE;
1610             continue;
1611         }
1612 
1613         hres = compile_expression(ctx, iter->expr, TRUE);
1614         if(FAILED(hres))
1615             break;
1616 
1617         case_jmps[i] = push_instr(ctx, OP_case);
1618         if(!case_jmps[i]) {
1619             hres = E_OUTOFMEMORY;
1620             break;
1621         }
1622         i++;
1623     }
1624 
1625     if(SUCCEEDED(hres)) {
1626         hres = push_instr_uint(ctx, OP_pop, 1);
1627         if(SUCCEEDED(hres)) {
1628             default_jmp = push_instr(ctx, OP_jmp);
1629             if(!default_jmp)
1630                 hres = E_OUTOFMEMORY;
1631         }
1632     }
1633 
1634     if(FAILED(hres)) {
1635         heap_free(case_jmps);
1636         return hres;
1637     }
1638 
1639     i = 0;
1640     for(iter = stat->case_list; iter; iter = iter->next) {
1641         while(iter->next && iter->next->stat == iter->stat) {
1642             set_arg_uint(ctx, iter->expr ? case_jmps[i++] : default_jmp, ctx->code_off);
1643             iter = iter->next;
1644         }
1645 
1646         set_arg_uint(ctx, iter->expr ? case_jmps[i++] : default_jmp, ctx->code_off);
1647 
1648         for(stat_iter = iter->stat; stat_iter && (!iter->next || iter->next->stat != stat_iter);
1649             stat_iter = stat_iter->next) {
1650             hres = compile_statement(ctx, &stat_ctx, stat_iter);
1651             if(FAILED(hres))
1652                 break;
1653         }
1654         if(FAILED(hres))
1655             break;
1656     }
1657 
1658     heap_free(case_jmps);
1659     if(FAILED(hres))
1660         return hres;
1661     assert(i == case_cnt);
1662 
1663     if(!have_default) {
1664         hres = push_instr_uint(ctx, OP_jmp, stat_ctx.break_label);
1665         if(FAILED(hres))
1666             return hres;
1667         set_arg_uint(ctx, default_jmp, ctx->code_off);
1668     }
1669 
1670     label_set_addr(ctx, stat_ctx.break_label);
1671     return S_OK;
1672 }
1673 
1674 /* ECMA-262 3rd Edition    12.13 */
1675 static HRESULT compile_throw_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
1676 {
1677     HRESULT hres;
1678 
1679     hres = compile_expression(ctx, stat->expr, TRUE);
1680     if(FAILED(hres))
1681         return hres;
1682 
1683     return push_instr(ctx, OP_throw) ? S_OK : E_OUTOFMEMORY;
1684 }
1685 
1686 /* ECMA-262 3rd Edition    12.14 */
1687 static HRESULT compile_try_statement(compiler_ctx_t *ctx, try_statement_t *stat)
1688 {
1689     statement_ctx_t try_ctx = {0, FALSE, TRUE}, finally_ctx = {2, FALSE, FALSE};
1690     unsigned push_except, finally_off = 0, catch_off = 0, pop_except, catch_pop_except = 0;
1691     BSTR ident;
1692     HRESULT hres;
1693 
1694     push_except = push_instr(ctx, OP_push_except);
1695     if(!push_except)
1696         return E_OUTOFMEMORY;
1697 
1698     if(stat->catch_block) {
1699         ident = compiler_alloc_bstr(ctx, stat->catch_block->identifier);
1700         if(!ident)
1701             return E_OUTOFMEMORY;
1702     }else {
1703         ident = NULL;
1704     }
1705 
1706     hres = compile_statement(ctx, &try_ctx, stat->try_statement);
1707     if(FAILED(hres))
1708         return hres;
1709 
1710     pop_except = push_instr(ctx, OP_pop_except);
1711     if(!pop_except)
1712         return E_OUTOFMEMORY;
1713 
1714     if(stat->catch_block) {
1715         statement_ctx_t catch_ctx = {0, TRUE, stat->finally_statement != NULL};
1716 
1717         if(stat->finally_statement)
1718             catch_ctx.using_except = TRUE;
1719 
1720         catch_off = ctx->code_off;
1721 
1722         hres = push_instr_bstr(ctx, OP_enter_catch, ident);
1723         if(FAILED(hres))
1724             return hres;
1725 
1726         hres = compile_statement(ctx, &catch_ctx, stat->catch_block->statement);
1727         if(FAILED(hres))
1728             return hres;
1729 
1730         if(!push_instr(ctx, OP_pop_scope))
1731             return E_OUTOFMEMORY;
1732 
1733         if(stat->finally_statement) {
1734             catch_pop_except = push_instr(ctx, OP_pop_except);
1735             if(!catch_pop_except)
1736                 return E_OUTOFMEMORY;
1737         }
1738     }
1739 
1740     if(stat->finally_statement) {
1741         /*
1742          * finally block expects two elements on the stack, which may be:
1743          * - (true, return_addr) set by OP_pop_except, OP_end_finally jumps back to passed address
1744          * - (false, exception_value) set when unwinding an exception, which OP_end_finally rethrows
1745          */
1746         finally_off = ctx->code_off;
1747         hres = compile_statement(ctx, &finally_ctx, stat->finally_statement);
1748         if(FAILED(hres))
1749             return hres;
1750 
1751         if(!push_instr(ctx, OP_end_finally))
1752             return E_OUTOFMEMORY;
1753     }
1754 
1755     instr_ptr(ctx, pop_except)->u.arg[0].uint = ctx->code_off;
1756     if(catch_pop_except)
1757         instr_ptr(ctx, catch_pop_except)->u.arg[0].uint = ctx->code_off;
1758     instr_ptr(ctx, push_except)->u.arg[0].uint = catch_off;
1759     instr_ptr(ctx, push_except)->u.arg[1].uint = finally_off;
1760     return S_OK;
1761 }
1762 
1763 static HRESULT compile_statement(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx, statement_t *stat)
1764 {
1765     HRESULT hres;
1766 
1767     if(stat_ctx) {
1768         stat_ctx->next = ctx->stat_ctx;
1769         ctx->stat_ctx = stat_ctx;
1770     }
1771 
1772     switch(stat->type) {
1773     case STAT_BLOCK:
1774         hres = compile_block_statement(ctx, ((block_statement_t*)stat)->stat_list);
1775         break;
1776     case STAT_BREAK:
1777         hres = compile_break_statement(ctx, (branch_statement_t*)stat);
1778         break;
1779     case STAT_CONTINUE:
1780         hres = compile_continue_statement(ctx, (branch_statement_t*)stat);
1781         break;
1782     case STAT_EMPTY:
1783         /* nothing to do */
1784         hres = S_OK;
1785         break;
1786     case STAT_EXPR:
1787         hres = compile_expression_statement(ctx, (expression_statement_t*)stat);
1788         break;
1789     case STAT_FOR:
1790         hres = compile_for_statement(ctx, (for_statement_t*)stat);
1791         break;
1792     case STAT_FORIN:
1793         hres = compile_forin_statement(ctx, (forin_statement_t*)stat);
1794         break;
1795     case STAT_IF:
1796         hres = compile_if_statement(ctx, (if_statement_t*)stat);
1797         break;
1798     case STAT_LABEL:
1799         hres = compile_labelled_statement(ctx, (labelled_statement_t*)stat);
1800         break;
1801     case STAT_RETURN:
1802         hres = compile_return_statement(ctx, (expression_statement_t*)stat);
1803         break;
1804     case STAT_SWITCH:
1805         hres = compile_switch_statement(ctx, (switch_statement_t*)stat);
1806         break;
1807     case STAT_THROW:
1808         hres = compile_throw_statement(ctx, (expression_statement_t*)stat);
1809         break;
1810     case STAT_TRY:
1811         hres = compile_try_statement(ctx, (try_statement_t*)stat);
1812         break;
1813     case STAT_VAR:
1814         hres = compile_var_statement(ctx, (var_statement_t*)stat);
1815         break;
1816     case STAT_WHILE:
1817         hres = compile_while_statement(ctx, (while_statement_t*)stat);
1818         break;
1819     case STAT_WITH:
1820         hres = compile_with_statement(ctx, (with_statement_t*)stat);
1821         break;
1822     DEFAULT_UNREACHABLE;
1823     }
1824 
1825     if(stat_ctx) {
1826         assert(ctx->stat_ctx == stat_ctx);
1827         ctx->stat_ctx = stat_ctx->next;
1828     }
1829 
1830     return hres;
1831 }
1832 
1833 static int function_local_cmp(const void *key, const struct wine_rb_entry *entry)
1834 {
1835     function_local_t *local = WINE_RB_ENTRY_VALUE(entry, function_local_t, entry);
1836     return strcmpW(key, local->name);
1837 }
1838 
1839 static inline function_local_t *find_local(compiler_ctx_t *ctx, const WCHAR *name)
1840 {
1841     struct wine_rb_entry *entry = wine_rb_get(&ctx->locals, name);
1842     return entry ? WINE_RB_ENTRY_VALUE(entry, function_local_t, entry) : NULL;
1843 }
1844 
1845 static BOOL alloc_local(compiler_ctx_t *ctx, BSTR name, int ref)
1846 {
1847     function_local_t *local;
1848 
1849     local = heap_pool_alloc(&ctx->heap, sizeof(*local));
1850     if(!local)
1851         return FALSE;
1852 
1853     local->name = name;
1854     local->ref = ref;
1855     wine_rb_put(&ctx->locals, name, &local->entry);
1856     ctx->locals_cnt++;
1857     return TRUE;
1858 }
1859 
1860 static BOOL alloc_variable(compiler_ctx_t *ctx, const WCHAR *name)
1861 {
1862     BSTR ident;
1863 
1864     if(find_local(ctx, name))
1865         return TRUE;
1866 
1867     ident = compiler_alloc_bstr(ctx, name);
1868     if(!ident)
1869         return FALSE;
1870 
1871     return alloc_local(ctx, ident, ctx->func->var_cnt++);
1872 }
1873 
1874 static HRESULT visit_function_expression(compiler_ctx_t *ctx, function_expression_t *expr)
1875 {
1876     expr->func_id = ctx->func->func_cnt++;
1877     ctx->func_tail = ctx->func_tail ? (ctx->func_tail->next = expr) : (ctx->func_head = expr);
1878 
1879     return !expr->identifier || expr->event_target || alloc_variable(ctx, expr->identifier)
1880         ? S_OK : E_OUTOFMEMORY;
1881 }
1882 
1883 static HRESULT visit_expression(compiler_ctx_t *ctx, expression_t *expr)
1884 {
1885     HRESULT hres = S_OK;
1886 
1887     switch(expr->type) {
1888     case EXPR_ADD:
1889     case EXPR_AND:
1890     case EXPR_ARRAY:
1891     case EXPR_ASSIGN:
1892     case EXPR_ASSIGNADD:
1893     case EXPR_ASSIGNAND:
1894     case EXPR_ASSIGNSUB:
1895     case EXPR_ASSIGNMUL:
1896     case EXPR_ASSIGNDIV:
1897     case EXPR_ASSIGNMOD:
1898     case EXPR_ASSIGNOR:
1899     case EXPR_ASSIGNLSHIFT:
1900     case EXPR_ASSIGNRSHIFT:
1901     case EXPR_ASSIGNRRSHIFT:
1902     case EXPR_ASSIGNXOR:
1903     case EXPR_BAND:
1904     case EXPR_BOR:
1905     case EXPR_COMMA:
1906     case EXPR_DIV:
1907     case EXPR_EQ:
1908     case EXPR_EQEQ:
1909     case EXPR_GREATER:
1910     case EXPR_GREATEREQ:
1911     case EXPR_IN:
1912     case EXPR_INSTANCEOF:
1913     case EXPR_LESS:
1914     case EXPR_LESSEQ:
1915     case EXPR_LSHIFT:
1916     case EXPR_MOD:
1917     case EXPR_MUL:
1918     case EXPR_NOTEQ:
1919     case EXPR_NOTEQEQ:
1920     case EXPR_OR:
1921     case EXPR_RSHIFT:
1922     case EXPR_RRSHIFT:
1923     case EXPR_SUB:
1924     case EXPR_BXOR: {
1925         binary_expression_t *binary_expr = (binary_expression_t*)expr;
1926 
1927         hres = visit_expression(ctx, binary_expr->expression1);
1928         if(FAILED(hres))
1929             return hres;
1930 
1931         hres = visit_expression(ctx, binary_expr->expression2);
1932         break;
1933     }
1934     case EXPR_BITNEG:
1935     case EXPR_DELETE:
1936     case EXPR_LOGNEG:
1937     case EXPR_MINUS:
1938     case EXPR_PLUS:
1939     case EXPR_POSTDEC:
1940     case EXPR_POSTINC:
1941     case EXPR_PREDEC:
1942     case EXPR_PREINC:
1943     case EXPR_TYPEOF:
1944     case EXPR_VOID:
1945         hres = visit_expression(ctx, ((unary_expression_t*)expr)->expression);
1946         break;
1947     case EXPR_IDENT:
1948     case EXPR_LITERAL:
1949     case EXPR_THIS:
1950         break;
1951     case EXPR_ARRAYLIT: {
1952         array_literal_expression_t *array_expr = (array_literal_expression_t*)expr;
1953         array_element_t *iter;
1954 
1955         for(iter = array_expr->element_list; iter; iter = iter->next) {
1956             hres = visit_expression(ctx, iter->expr);
1957             if(FAILED(hres))
1958                 return hres;
1959         }
1960         break;
1961     }
1962     case EXPR_CALL:
1963     case EXPR_NEW: {
1964         call_expression_t *call_expr = (call_expression_t*)expr;
1965         argument_t *arg;
1966 
1967         hres = visit_expression(ctx, call_expr->expression);
1968         if(FAILED(hres))
1969             return hres;
1970 
1971         for(arg = call_expr->argument_list; arg; arg = arg->next) {
1972             hres = visit_expression(ctx, arg->expr);
1973             if(FAILED(hres))
1974                 return hres;
1975         }
1976         break;
1977     }
1978     case EXPR_COND: {
1979         conditional_expression_t *cond_expr = (conditional_expression_t*)expr;
1980 
1981         hres = visit_expression(ctx, cond_expr->expression);
1982         if(FAILED(hres))
1983             return hres;
1984 
1985         hres = visit_expression(ctx, cond_expr->true_expression);
1986         if(FAILED(hres))
1987             return hres;
1988 
1989         hres = visit_expression(ctx, cond_expr->false_expression);
1990         break;
1991     }
1992     case EXPR_FUNC:
1993         hres = visit_function_expression(ctx, (function_expression_t*)expr);
1994         break;
1995     case EXPR_MEMBER:
1996         hres = visit_expression(ctx, ((member_expression_t*)expr)->expression);
1997         break;
1998     case EXPR_PROPVAL: {
1999         property_definition_t *iter;
2000         for(iter = ((property_value_expression_t*)expr)->property_list; iter; iter = iter->next) {
2001             hres = visit_expression(ctx, iter->value);
2002             if(FAILED(hres))
2003                 return hres;
2004         }
2005         break;
2006     }
2007     DEFAULT_UNREACHABLE;
2008     }
2009 
2010     return hres;
2011 }
2012 
2013 static HRESULT visit_variable_list(compiler_ctx_t *ctx, variable_declaration_t *list)
2014 {
2015     variable_declaration_t *iter;
2016     HRESULT hres;
2017 
2018     for(iter = list; iter; iter = iter->next) {
2019         if(!alloc_variable(ctx, iter->identifier))
2020             return E_OUTOFMEMORY;
2021 
2022         if(iter->expr) {
2023             hres = visit_expression(ctx, iter->expr);
2024             if(FAILED(hres))
2025                 return hres;
2026         }
2027     }
2028 
2029     return S_OK;
2030 }
2031 
2032 static HRESULT visit_statement(compiler_ctx_t*,statement_t*);
2033 
2034 static HRESULT visit_block_statement(compiler_ctx_t *ctx, statement_t *iter)
2035 {
2036     HRESULT hres;
2037 
2038     while(iter) {
2039         hres = visit_statement(ctx, iter);
2040         if(FAILED(hres))
2041             return hres;
2042 
2043         iter = iter->next;
2044     }
2045 
2046     return S_OK;
2047 }
2048 
2049 static HRESULT visit_statement(compiler_ctx_t *ctx, statement_t *stat)
2050 {
2051     HRESULT hres = S_OK;
2052 
2053     switch(stat->type) {
2054     case STAT_BLOCK:
2055         hres = visit_block_statement(ctx, ((block_statement_t*)stat)->stat_list);
2056         break;
2057     case STAT_BREAK:
2058     case STAT_CONTINUE:
2059     case STAT_EMPTY:
2060         break;
2061     case STAT_EXPR:
2062     case STAT_RETURN:
2063     case STAT_THROW: {
2064         expression_statement_t *expr_stat = (expression_statement_t*)stat;
2065         if(expr_stat->expr)
2066             hres = visit_expression(ctx, expr_stat->expr);
2067         break;
2068     }
2069     case STAT_FOR: {
2070         for_statement_t *for_stat = (for_statement_t*)stat;
2071 
2072         if(for_stat->variable_list)
2073             hres = visit_variable_list(ctx, for_stat->variable_list);
2074         else if(for_stat->begin_expr)
2075             hres = visit_expression(ctx, for_stat->begin_expr);
2076         if(FAILED(hres))
2077             break;
2078 
2079         if(for_stat->expr) {
2080             hres = visit_expression(ctx, for_stat->expr);
2081             if(FAILED(hres))
2082                 break;
2083         }
2084 
2085         hres = visit_statement(ctx, for_stat->statement);
2086         if(FAILED(hres))
2087             break;
2088 
2089         if(for_stat->end_expr)
2090             hres = visit_expression(ctx, for_stat->end_expr);
2091         break;
2092     }
2093     case STAT_FORIN:  {
2094         forin_statement_t *forin_stat = (forin_statement_t*)stat;
2095 
2096         if(forin_stat->variable) {
2097             hres = visit_variable_list(ctx, forin_stat->variable);
2098             if(FAILED(hres))
2099                 break;
2100         }
2101 
2102         hres = visit_expression(ctx, forin_stat->in_expr);
2103         if(FAILED(hres))
2104             return hres;
2105 
2106         if(forin_stat->expr) {
2107             hres = visit_expression(ctx, forin_stat->expr);
2108             if(FAILED(hres))
2109                 return hres;
2110         }
2111 
2112         hres = visit_statement(ctx, forin_stat->statement);
2113         break;
2114     }
2115     case STAT_IF: {
2116         if_statement_t *if_stat = (if_statement_t*)stat;
2117 
2118         hres = visit_expression(ctx, if_stat->expr);
2119         if(FAILED(hres))
2120             return hres;
2121 
2122         hres = visit_statement(ctx, if_stat->if_stat);
2123         if(FAILED(hres))
2124             return hres;
2125 
2126         if(if_stat->else_stat)
2127             hres = visit_statement(ctx, if_stat->else_stat);
2128         break;
2129     }
2130     case STAT_LABEL:
2131         hres = visit_statement(ctx, ((labelled_statement_t*)stat)->statement);
2132         break;
2133     case STAT_SWITCH: {
2134         switch_statement_t *switch_stat = (switch_statement_t*)stat;
2135         statement_t *stat_iter;
2136         case_clausule_t *iter;
2137 
2138         hres = visit_expression(ctx, switch_stat->expr);
2139         if(FAILED(hres))
2140             return hres;
2141 
2142         for(iter = switch_stat->case_list; iter; iter = iter->next) {
2143             if(!iter->expr)
2144                 continue;
2145             hres = visit_expression(ctx, iter->expr);
2146             if(FAILED(hres))
2147                 return hres;
2148         }
2149 
2150         for(iter = switch_stat->case_list; iter; iter = iter->next) {
2151             while(iter->next && iter->next->stat == iter->stat)
2152                 iter = iter->next;
2153             for(stat_iter = iter->stat; stat_iter && (!iter->next || iter->next->stat != stat_iter);
2154                 stat_iter = stat_iter->next) {
2155                 hres = visit_statement(ctx, stat_iter);
2156                 if(FAILED(hres))
2157                     return hres;
2158             }
2159         }
2160         break;
2161     }
2162     case STAT_TRY: {
2163         try_statement_t *try_stat = (try_statement_t*)stat;
2164 
2165         hres = visit_statement(ctx, try_stat->try_statement);
2166         if(FAILED(hres))
2167             return hres;
2168 
2169         if(try_stat->catch_block) {
2170             hres = visit_statement(ctx, try_stat->catch_block->statement);
2171             if(FAILED(hres))
2172                 return hres;
2173         }
2174 
2175         if(try_stat->finally_statement)
2176             hres = visit_statement(ctx, try_stat->finally_statement);
2177         break;
2178     }
2179     case STAT_VAR:
2180         hres = visit_variable_list(ctx, ((var_statement_t*)stat)->variable_list);
2181         break;
2182     case STAT_WHILE: {
2183         while_statement_t *while_stat = (while_statement_t*)stat;
2184 
2185         hres = visit_expression(ctx, while_stat->expr);
2186         if(FAILED(hres))
2187             return hres;
2188 
2189         hres = visit_statement(ctx, while_stat->statement);
2190         break;
2191     }
2192     case STAT_WITH: {
2193         with_statement_t *with_stat = (with_statement_t*)stat;
2194 
2195         hres = visit_expression(ctx, with_stat->expr);
2196         if(FAILED(hres))
2197             return hres;
2198 
2199         hres = visit_statement(ctx, with_stat->statement);
2200         break;
2201     }
2202     DEFAULT_UNREACHABLE;
2203     }
2204 
2205     return hres;
2206 }
2207 
2208 static void resolve_labels(compiler_ctx_t *ctx, unsigned off)
2209 {
2210     instr_t *instr;
2211 
2212     for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->code_off; instr++) {
2213         if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->u.arg->uint & LABEL_FLAG)) {
2214             assert((instr->u.arg->uint & ~LABEL_FLAG) < ctx->labels_cnt);
2215             instr->u.arg->uint = ctx->labels[instr->u.arg->uint & ~LABEL_FLAG];
2216         }
2217         assert(instr_info[instr->op].arg2_type != ARG_ADDR);
2218     }
2219 
2220     ctx->labels_cnt = 0;
2221 }
2222 
2223 void release_bytecode(bytecode_t *code)
2224 {
2225     unsigned i;
2226 
2227     if(--code->ref)
2228         return;
2229 
2230     for(i=0; i < code->bstr_cnt; i++)
2231         SysFreeString(code->bstr_pool[i]);
2232     for(i=0; i < code->str_cnt; i++)
2233         jsstr_release(code->str_pool[i]);
2234 
2235     heap_free(code->source);
2236     heap_pool_free(&code->heap);
2237     heap_free(code->bstr_pool);
2238     heap_free(code->str_pool);
2239     heap_free(code->instrs);
2240     heap_free(code);
2241 }
2242 
2243 static HRESULT init_code(compiler_ctx_t *compiler, const WCHAR *source)
2244 {
2245     compiler->code = heap_alloc_zero(sizeof(bytecode_t));
2246     if(!compiler->code)
2247         return E_OUTOFMEMORY;
2248 
2249     compiler->code->ref = 1;
2250     heap_pool_init(&compiler->code->heap);
2251 
2252     compiler->code->source = heap_strdupW(source);
2253     if(!compiler->code->source) {
2254         release_bytecode(compiler->code);
2255         return E_OUTOFMEMORY;
2256     }
2257 
2258     compiler->code->instrs = heap_alloc(64 * sizeof(instr_t));
2259     if(!compiler->code->instrs) {
2260         release_bytecode(compiler->code);
2261         return E_OUTOFMEMORY;
2262     }
2263 
2264     compiler->code_size = 64;
2265     compiler->code_off = 1;
2266     return S_OK;
2267 }
2268 
2269 static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source, function_expression_t *func_expr,
2270         BOOL from_eval, function_code_t *func)
2271 {
2272     function_expression_t *iter;
2273     function_local_t *local;
2274     unsigned off, i;
2275     HRESULT hres;
2276 
2277     TRACE("\n");
2278 
2279     ctx->func_head = ctx->func_tail = NULL;
2280     ctx->from_eval = from_eval;
2281     ctx->func = func;
2282     ctx->locals_cnt = 0;
2283     wine_rb_init(&ctx->locals, function_local_cmp);
2284 
2285     if(func_expr) {
2286         parameter_t *param_iter;
2287 
2288         if(func_expr->identifier) {
2289             func->name = compiler_alloc_bstr(ctx, func_expr->identifier);
2290             if(!func->name)
2291                 return E_OUTOFMEMORY;
2292         }
2293 
2294         if(func_expr->event_target) {
2295             func->event_target = compiler_alloc_bstr(ctx, func_expr->event_target);
2296             if(!func->event_target)
2297                 return E_OUTOFMEMORY;
2298         }
2299 
2300         func->source = func_expr->src_str;
2301         func->source_len = func_expr->src_len;
2302 
2303         for(param_iter = func_expr->parameter_list; param_iter; param_iter = param_iter->next)
2304             func->param_cnt++;
2305 
2306         func->params = compiler_alloc(ctx->code, func->param_cnt * sizeof(*func->params));
2307         if(!func->params)
2308             return E_OUTOFMEMORY;
2309 
2310         for(param_iter = func_expr->parameter_list, i=0; param_iter; param_iter = param_iter->next, i++) {
2311             func->params[i] = compiler_alloc_bstr(ctx, param_iter->identifier);
2312             if(!func->params[i])
2313                 return E_OUTOFMEMORY;
2314         }
2315     }
2316 
2317     for(i = 0; i < func->param_cnt; i++) {
2318         if(!find_local(ctx, func->params[i]) && !alloc_local(ctx, func->params[i], -i-1))
2319             return E_OUTOFMEMORY;
2320     }
2321 
2322     hres = visit_block_statement(ctx, source->statement);
2323     if(FAILED(hres))
2324         return hres;
2325 
2326     func->locals = compiler_alloc(ctx->code, ctx->locals_cnt * sizeof(*func->locals));
2327     if(!func->locals)
2328         return E_OUTOFMEMORY;
2329     func->locals_cnt = ctx->locals_cnt;
2330 
2331     func->variables = compiler_alloc(ctx->code, func->var_cnt * sizeof(*func->variables));
2332     if(!func->variables)
2333         return E_OUTOFMEMORY;
2334 
2335     i = 0;
2336     WINE_RB_FOR_EACH_ENTRY(local, &ctx->locals, function_local_t, entry) {
2337         func->locals[i].name = local->name;
2338         func->locals[i].ref = local->ref;
2339         if(local->ref >= 0) {
2340             func->variables[local->ref].name = local->name;
2341             func->variables[local->ref].func_id = -1;
2342         }
2343         i++;
2344     }
2345     assert(i == ctx->locals_cnt);
2346 
2347     func->funcs = compiler_alloc(ctx->code, func->func_cnt * sizeof(*func->funcs));
2348     if(!func->funcs)
2349         return E_OUTOFMEMORY;
2350     memset(func->funcs, 0, func->func_cnt * sizeof(*func->funcs));
2351 
2352     off = ctx->code_off;
2353     hres = compile_block_statement(ctx, source->statement);
2354     if(FAILED(hres))
2355         return hres;
2356 
2357     resolve_labels(ctx, off);
2358 
2359     hres = push_instr_uint(ctx, OP_ret, !from_eval);
2360     if(FAILED(hres))
2361         return hres;
2362 
2363     if(TRACE_ON(jscript_disas))
2364         dump_code(ctx, off);
2365 
2366     func->instr_off = off;
2367 
2368     for(iter = ctx->func_head, i=0; iter; iter = iter->next, i++) {
2369         hres = compile_function(ctx, iter->source_elements, iter, FALSE, func->funcs+i);
2370         if(FAILED(hres))
2371             return hres;
2372 
2373         TRACE("[%d] func %s\n", i, debugstr_w(func->funcs[i].name));
2374         if(func->funcs[i].name && !func->funcs[i].event_target) {
2375             local_ref_t *local_ref = lookup_local(func, func->funcs[i].name);
2376             func->funcs[i].local_ref = local_ref->ref;
2377             TRACE("found ref %s %d for %s\n", debugstr_w(local_ref->name), local_ref->ref, debugstr_w(func->funcs[i].name));
2378             if(local_ref->ref >= 0)
2379                 func->variables[local_ref->ref].func_id = i;
2380         }
2381     }
2382 
2383     assert(i == func->func_cnt);
2384 
2385     return S_OK;
2386 }
2387 
2388 static HRESULT parse_arguments(compiler_ctx_t *ctx, const WCHAR *args, BSTR *arg_array, unsigned *args_size)
2389 {
2390     const WCHAR *ptr = args, *ptr2;
2391     unsigned arg_cnt = 0;
2392 
2393     while(isspaceW(*ptr))
2394         ptr++;
2395     if(!*ptr) {
2396         if(args_size)
2397             *args_size = 0;
2398         return S_OK;
2399     }
2400 
2401     while(1) {
2402         if(!isalphaW(*ptr) && *ptr != '_') {
2403             FIXME("expected alpha or '_': %s\n", debugstr_w(ptr));
2404             return E_FAIL;
2405         }
2406 
2407         ptr2 = ptr;
2408         while(isalnumW(*ptr) || *ptr == '_')
2409             ptr++;
2410 
2411         if(*ptr && *ptr != ',' && !isspaceW(*ptr)) {
2412             FIXME("unexpected har %s\n", debugstr_w(ptr));
2413             return E_FAIL;
2414         }
2415 
2416         if(arg_array) {
2417             arg_array[arg_cnt] = compiler_alloc_bstr_len(ctx, ptr2, ptr-ptr2);
2418             if(!arg_array[arg_cnt])
2419                 return E_OUTOFMEMORY;
2420         }
2421         arg_cnt++;
2422 
2423         while(isspaceW(*ptr))
2424             ptr++;
2425         if(!*ptr)
2426             break;
2427         if(*ptr != ',') {
2428             FIXME("expected ',': %s\n", debugstr_w(ptr));
2429             return E_FAIL;
2430         }
2431 
2432         ptr++;
2433         while(isspaceW(*ptr))
2434             ptr++;
2435     }
2436 
2437     if(args_size)
2438         *args_size = arg_cnt;
2439     return S_OK;
2440 }
2441 
2442 static HRESULT compile_arguments(compiler_ctx_t *ctx, const WCHAR *args)
2443 {
2444     HRESULT hres;
2445 
2446     hres = parse_arguments(ctx, args, NULL, &ctx->code->global_code.param_cnt);
2447     if(FAILED(hres))
2448         return hres;
2449 
2450     ctx->code->global_code.params = compiler_alloc(ctx->code,
2451             ctx->code->global_code.param_cnt * sizeof(*ctx->code->global_code.params));
2452     if(!ctx->code->global_code.params)
2453         return E_OUTOFMEMORY;
2454 
2455     return parse_arguments(ctx, args, ctx->code->global_code.params, NULL);
2456 }
2457 
2458 HRESULT compile_script(script_ctx_t *ctx, const WCHAR *code, const WCHAR *args, const WCHAR *delimiter,
2459         BOOL from_eval, BOOL use_decode, bytecode_t **ret)
2460 {
2461     compiler_ctx_t compiler = {0};
2462     HRESULT hres;
2463 
2464     hres = init_code(&compiler, code);
2465     if(FAILED(hres))
2466         return hres;
2467 
2468     if(args) {
2469         hres = compile_arguments(&compiler, args);
2470         if(FAILED(hres))
2471             return hres;
2472     }
2473 
2474     if(use_decode) {
2475         hres = decode_source(compiler.code->source);
2476         if(FAILED(hres)) {
2477             WARN("Decoding failed\n");
2478             return hres;
2479         }
2480     }
2481 
2482     hres = script_parse(ctx, compiler.code->source, delimiter, from_eval, &compiler.parser);
2483     if(FAILED(hres)) {
2484         release_bytecode(compiler.code);
2485         return hres;
2486     }
2487 
2488     heap_pool_init(&compiler.heap);
2489     hres = compile_function(&compiler, compiler.parser->source, NULL, from_eval, &compiler.code->global_code);
2490     heap_pool_free(&compiler.heap);
2491     parser_release(compiler.parser);
2492     if(FAILED(hres)) {
2493         release_bytecode(compiler.code);
2494         return hres;
2495     }
2496 
2497     *ret = compiler.code;
2498     return S_OK;
2499 }
2500