xref: /reactos/dll/win32/jscript/compile.c (revision cc439606)
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_ret) ? 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_ret) ? 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         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     prop_val_t *iter;
892     unsigned instr;
893     BSTR name;
894     HRESULT hres;
895 
896     if(!push_instr(ctx, OP_new_obj))
897         return E_OUTOFMEMORY;
898 
899     for(iter = expr->property_list; iter; iter = iter->next) {
900         hres = literal_as_bstr(ctx, iter->name, &name);
901         if(FAILED(hres))
902             return hres;
903 
904         hres = compile_expression(ctx, iter->value, TRUE);
905         if(FAILED(hres))
906             return hres;
907 
908         instr = push_instr(ctx, OP_obj_prop);
909         if(!instr)
910             return E_OUTOFMEMORY;
911 
912         instr_ptr(ctx, instr)->u.arg->bstr = name;
913     }
914 
915     return S_OK;
916 }
917 
918 static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr, BOOL emit_ret)
919 {
920     return emit_ret ? push_instr_uint(ctx, OP_func, expr->func_id) : S_OK;
921 }
922 
923 static HRESULT compile_expression(compiler_ctx_t *ctx, expression_t *expr, BOOL emit_ret)
924 {
925     HRESULT hres;
926 
927     switch(expr->type) {
928     case EXPR_ADD:
929         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add);
930         break;
931     case EXPR_AND:
932         hres = compile_logical_expression(ctx, (binary_expression_t*)expr, OP_cnd_z);
933         break;
934     case EXPR_ARRAY:
935         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_array);
936         break;
937     case EXPR_ARRAYLIT:
938         hres = compile_array_literal(ctx, (array_literal_expression_t*)expr);
939         break;
940     case EXPR_ASSIGN:
941         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_LAST);
942         break;
943     case EXPR_ASSIGNADD:
944         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_add);
945         break;
946     case EXPR_ASSIGNAND:
947         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_and);
948         break;
949     case EXPR_ASSIGNSUB:
950         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_sub);
951         break;
952     case EXPR_ASSIGNMUL:
953         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_mul);
954         break;
955     case EXPR_ASSIGNDIV:
956         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_div);
957         break;
958     case EXPR_ASSIGNMOD:
959         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_mod);
960         break;
961     case EXPR_ASSIGNOR:
962         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_or);
963         break;
964     case EXPR_ASSIGNLSHIFT:
965         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_lshift);
966         break;
967     case EXPR_ASSIGNRSHIFT:
968         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_rshift);
969         break;
970     case EXPR_ASSIGNRRSHIFT:
971         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_rshift2);
972         break;
973     case EXPR_ASSIGNXOR:
974         hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_xor);
975         break;
976     case EXPR_BAND:
977         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_and);
978         break;
979     case EXPR_BITNEG:
980         hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_bneg);
981         break;
982     case EXPR_BOR:
983         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_or);
984         break;
985     case EXPR_CALL:
986         return compile_call_expression(ctx, (call_expression_t*)expr, emit_ret);
987     case EXPR_COMMA:
988         return compile_comma_expression(ctx, (binary_expression_t*)expr, emit_ret);
989     case EXPR_COND:
990         hres = compile_conditional_expression(ctx, (conditional_expression_t*)expr);
991         break;
992     case EXPR_DELETE:
993         hres = compile_delete_expression(ctx, (unary_expression_t*)expr);
994         break;
995     case EXPR_DIV:
996         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div);
997         break;
998     case EXPR_EQ:
999         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq);
1000         break;
1001     case EXPR_EQEQ:
1002         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq2);
1003         break;
1004     case EXPR_FUNC:
1005         return compile_function_expression(ctx, (function_expression_t*)expr, emit_ret);
1006     case EXPR_GREATER:
1007         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gt);
1008         break;
1009     case EXPR_GREATEREQ:
1010         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gteq);
1011         break;
1012     case EXPR_IDENT:
1013         hres = emit_identifier(ctx, ((identifier_expression_t*)expr)->identifier);
1014         break;
1015     case EXPR_IN:
1016         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_in);
1017         break;
1018     case EXPR_INSTANCEOF:
1019         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_instanceof);
1020         break;
1021     case EXPR_LESS:
1022         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lt);
1023         break;
1024     case EXPR_LESSEQ:
1025         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lteq);
1026         break;
1027     case EXPR_LITERAL:
1028         hres = compile_literal(ctx, ((literal_expression_t*)expr)->literal);
1029         break;
1030     case EXPR_LOGNEG:
1031         hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg);
1032         break;
1033     case EXPR_LSHIFT:
1034         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lshift);
1035         break;
1036     case EXPR_MEMBER:
1037         hres = compile_member_expression(ctx, (member_expression_t*)expr);
1038         break;
1039     case EXPR_MINUS:
1040         hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_minus);
1041         break;
1042     case EXPR_MOD:
1043         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod);
1044         break;
1045     case EXPR_MUL:
1046         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul);
1047         break;
1048     case EXPR_NEW:
1049         hres = compile_new_expression(ctx, (call_expression_t*)expr);
1050         break;
1051     case EXPR_NOTEQ:
1052         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_neq);
1053         break;
1054     case EXPR_NOTEQEQ:
1055         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_neq2);
1056         break;
1057     case EXPR_OR:
1058         hres = compile_logical_expression(ctx, (binary_expression_t*)expr, OP_cnd_nz);
1059         break;
1060     case EXPR_PLUS:
1061         hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_tonum);
1062         break;
1063     case EXPR_POSTDEC:
1064         hres = compile_increment_expression(ctx, (unary_expression_t*)expr, OP_postinc, -1);
1065         break;
1066     case EXPR_POSTINC:
1067         hres = compile_increment_expression(ctx, (unary_expression_t*)expr, OP_postinc, 1);
1068         break;
1069     case EXPR_PREDEC:
1070         hres = compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, -1);
1071         break;
1072     case EXPR_PREINC:
1073         hres = compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, 1);
1074         break;
1075     case EXPR_PROPVAL:
1076         hres = compile_object_literal(ctx, (property_value_expression_t*)expr);
1077         break;
1078     case EXPR_RSHIFT:
1079         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_rshift);
1080         break;
1081     case EXPR_RRSHIFT:
1082         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_rshift2);
1083         break;
1084     case EXPR_SUB:
1085         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
1086         break;
1087     case EXPR_THIS:
1088         return !emit_ret || push_instr(ctx, OP_this) ? S_OK : E_OUTOFMEMORY;
1089     case EXPR_TYPEOF:
1090         hres = compile_typeof_expression(ctx, (unary_expression_t*)expr);
1091         break;
1092     case EXPR_VOID:
1093         hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_void);
1094         break;
1095     case EXPR_BXOR:
1096         hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor);
1097         break;
1098     DEFAULT_UNREACHABLE;
1099     }
1100 
1101     if(FAILED(hres))
1102         return hres;
1103 
1104     return emit_ret ? S_OK : push_instr_uint(ctx, OP_pop, 1);
1105 }
1106 
1107 static inline BOOL is_loop_statement(statement_type_t type)
1108 {
1109     return type == STAT_FOR || type == STAT_FORIN || type == STAT_WHILE;
1110 }
1111 
1112 /* ECMA-262 3rd Edition    12.1 */
1113 static HRESULT compile_block_statement(compiler_ctx_t *ctx, statement_t *iter)
1114 {
1115     HRESULT hres;
1116 
1117     while(iter) {
1118         hres = compile_statement(ctx, NULL, iter);
1119         if(FAILED(hres))
1120             return hres;
1121 
1122         iter = iter->next;
1123     }
1124 
1125     return S_OK;
1126 }
1127 
1128 /* ECMA-262 3rd Edition    12.2 */
1129 static HRESULT compile_variable_list(compiler_ctx_t *ctx, variable_declaration_t *list)
1130 {
1131     variable_declaration_t *iter;
1132     HRESULT hres;
1133 
1134     assert(list != NULL);
1135 
1136     for(iter = list; iter; iter = iter->next) {
1137         if(!iter->expr)
1138             continue;
1139 
1140         hres = emit_identifier_ref(ctx, iter->identifier, 0);
1141         if(FAILED(hres))
1142             return hres;
1143 
1144         hres = compile_expression(ctx, iter->expr, TRUE);
1145         if(FAILED(hres))
1146             return hres;
1147 
1148         if(!push_instr(ctx, OP_assign))
1149             return E_OUTOFMEMORY;
1150 
1151         hres = push_instr_uint(ctx, OP_pop, 1);
1152         if(FAILED(hres))
1153             return hres;
1154     }
1155 
1156     return S_OK;
1157 }
1158 
1159 /* ECMA-262 3rd Edition    12.2 */
1160 static HRESULT compile_var_statement(compiler_ctx_t *ctx, var_statement_t *stat)
1161 {
1162     return compile_variable_list(ctx, stat->variable_list);
1163 }
1164 
1165 /* ECMA-262 3rd Edition    12.4 */
1166 static HRESULT compile_expression_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
1167 {
1168     HRESULT hres;
1169 
1170     hres = compile_expression(ctx, stat->expr, ctx->from_eval);
1171     if(FAILED(hres))
1172         return hres;
1173 
1174     return !ctx->from_eval || push_instr(ctx, OP_setret) ? S_OK : E_OUTOFMEMORY;
1175 }
1176 
1177 /* ECMA-262 3rd Edition    12.5 */
1178 static HRESULT compile_if_statement(compiler_ctx_t *ctx, if_statement_t *stat)
1179 {
1180     unsigned jmp_else;
1181     HRESULT hres;
1182 
1183     hres = compile_expression(ctx, stat->expr, TRUE);
1184     if(FAILED(hres))
1185         return hres;
1186 
1187     jmp_else = push_instr(ctx, OP_jmp_z);
1188     if(!jmp_else)
1189         return E_OUTOFMEMORY;
1190 
1191     hres = compile_statement(ctx, NULL, stat->if_stat);
1192     if(FAILED(hres))
1193         return hres;
1194 
1195     if(stat->else_stat) {
1196         unsigned jmp_end;
1197 
1198         jmp_end = push_instr(ctx, OP_jmp);
1199         if(!jmp_end)
1200             return E_OUTOFMEMORY;
1201 
1202         set_arg_uint(ctx, jmp_else, ctx->code_off);
1203 
1204         hres = compile_statement(ctx, NULL, stat->else_stat);
1205         if(FAILED(hres))
1206             return hres;
1207 
1208         set_arg_uint(ctx, jmp_end, ctx->code_off);
1209     }else {
1210         set_arg_uint(ctx, jmp_else, ctx->code_off);
1211     }
1212 
1213     return S_OK;
1214 }
1215 
1216 /* ECMA-262 3rd Edition    12.6.2 */
1217 static HRESULT compile_while_statement(compiler_ctx_t *ctx, while_statement_t *stat)
1218 {
1219     statement_ctx_t stat_ctx = {0, FALSE, FALSE};
1220     unsigned jmp_off;
1221     HRESULT hres;
1222 
1223     stat_ctx.break_label = alloc_label(ctx);
1224     if(!stat_ctx.break_label)
1225         return E_OUTOFMEMORY;
1226 
1227     stat_ctx.continue_label = alloc_label(ctx);
1228     if(!stat_ctx.continue_label)
1229         return E_OUTOFMEMORY;
1230 
1231     jmp_off = ctx->code_off;
1232 
1233     if(!stat->do_while) {
1234         label_set_addr(ctx, stat_ctx.continue_label);
1235         hres = compile_expression(ctx, stat->expr, TRUE);
1236         if(FAILED(hres))
1237             return hres;
1238 
1239         hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1240         if(FAILED(hres))
1241             return hres;
1242     }
1243 
1244     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1245     if(FAILED(hres))
1246         return hres;
1247 
1248     if(stat->do_while) {
1249         label_set_addr(ctx, stat_ctx.continue_label);
1250         hres = compile_expression(ctx, stat->expr, TRUE);
1251         if(FAILED(hres))
1252             return hres;
1253 
1254         hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1255         if(FAILED(hres))
1256             return hres;
1257     }
1258 
1259     hres = push_instr_uint(ctx, OP_jmp, jmp_off);
1260     if(FAILED(hres))
1261         return hres;
1262 
1263     label_set_addr(ctx, stat_ctx.break_label);
1264     return S_OK;
1265 }
1266 
1267 /* ECMA-262 3rd Edition    12.6.3 */
1268 static HRESULT compile_for_statement(compiler_ctx_t *ctx, for_statement_t *stat)
1269 {
1270     statement_ctx_t stat_ctx = {0, FALSE, FALSE};
1271     unsigned expr_off;
1272     HRESULT hres;
1273 
1274     if(stat->variable_list) {
1275         hres = compile_variable_list(ctx, stat->variable_list);
1276         if(FAILED(hres))
1277             return hres;
1278     }else if(stat->begin_expr) {
1279         hres = compile_expression(ctx, stat->begin_expr, FALSE);
1280         if(FAILED(hres))
1281             return hres;
1282     }
1283 
1284     stat_ctx.break_label = alloc_label(ctx);
1285     if(!stat_ctx.break_label)
1286         return E_OUTOFMEMORY;
1287 
1288     stat_ctx.continue_label = alloc_label(ctx);
1289     if(!stat_ctx.continue_label)
1290         return E_OUTOFMEMORY;
1291 
1292     expr_off = ctx->code_off;
1293 
1294     if(stat->expr) {
1295         hres = compile_expression(ctx, stat->expr, TRUE);
1296         if(FAILED(hres))
1297             return hres;
1298 
1299         hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1300         if(FAILED(hres))
1301             return hres;
1302     }
1303 
1304     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1305     if(FAILED(hres))
1306         return hres;
1307 
1308     label_set_addr(ctx, stat_ctx.continue_label);
1309 
1310     if(stat->end_expr) {
1311         hres = compile_expression(ctx, stat->end_expr, FALSE);
1312         if(FAILED(hres))
1313             return hres;
1314     }
1315 
1316     hres = push_instr_uint(ctx, OP_jmp, expr_off);
1317     if(FAILED(hres))
1318         return hres;
1319 
1320     label_set_addr(ctx, stat_ctx.break_label);
1321     return S_OK;
1322 }
1323 
1324 /* ECMA-262 3rd Edition    12.6.4 */
1325 static HRESULT compile_forin_statement(compiler_ctx_t *ctx, forin_statement_t *stat)
1326 {
1327     statement_ctx_t stat_ctx = {4, FALSE, FALSE};
1328     HRESULT hres;
1329 
1330     if(stat->variable) {
1331         hres = compile_variable_list(ctx, stat->variable);
1332         if(FAILED(hres))
1333             return hres;
1334     }
1335 
1336     stat_ctx.break_label = alloc_label(ctx);
1337     if(!stat_ctx.break_label)
1338         return E_OUTOFMEMORY;
1339 
1340     stat_ctx.continue_label = alloc_label(ctx);
1341     if(!stat_ctx.continue_label)
1342         return E_OUTOFMEMORY;
1343 
1344     hres = compile_expression(ctx, stat->in_expr, TRUE);
1345     if(FAILED(hres))
1346         return hres;
1347 
1348     if(stat->variable) {
1349         hres = emit_identifier_ref(ctx, stat->variable->identifier, fdexNameEnsure);
1350         if(FAILED(hres))
1351             return hres;
1352     }else if(is_memberid_expr(stat->expr->type)) {
1353         hres = compile_memberid_expression(ctx, stat->expr, fdexNameEnsure);
1354         if(FAILED(hres))
1355             return hres;
1356     }else {
1357         hres = push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
1358         if(FAILED(hres))
1359             return hres;
1360 
1361         /* FIXME: compile statement anyways when we depend on compiler to check errors */
1362         return S_OK;
1363     }
1364 
1365     hres = push_instr_int(ctx, OP_int, DISPID_STARTENUM);
1366     if(FAILED(hres))
1367         return hres;
1368 
1369     label_set_addr(ctx, stat_ctx.continue_label);
1370     hres = push_instr_uint(ctx, OP_forin, stat_ctx.break_label);
1371     if(FAILED(hres))
1372         return E_OUTOFMEMORY;
1373 
1374     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1375     if(FAILED(hres))
1376         return hres;
1377 
1378     hres = push_instr_uint(ctx, OP_jmp, stat_ctx.continue_label);
1379     if(FAILED(hres))
1380         return hres;
1381 
1382     label_set_addr(ctx, stat_ctx.break_label);
1383     return S_OK;
1384 }
1385 
1386 static HRESULT pop_to_stat(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx)
1387 {
1388     unsigned stack_pop = 0;
1389     statement_ctx_t *iter;
1390     HRESULT hres;
1391 
1392     for(iter = ctx->stat_ctx; iter != stat_ctx; iter = iter->next) {
1393         if(iter->using_scope && !push_instr(ctx, OP_pop_scope))
1394             return E_OUTOFMEMORY;
1395         if(iter->using_except) {
1396             if(stack_pop) {
1397                 hres = push_instr_uint(ctx, OP_pop, stack_pop);
1398                 if(FAILED(hres))
1399                     return hres;
1400                 stack_pop = 0;
1401             }
1402             hres = push_instr_uint(ctx, OP_pop_except, ctx->code_off+1);
1403             if(FAILED(hres))
1404                 return hres;
1405         }
1406         stack_pop += iter->stack_use;
1407     }
1408 
1409     if(stack_pop) {
1410         hres = push_instr_uint(ctx, OP_pop, stack_pop);
1411         if(FAILED(hres))
1412             return hres;
1413     }
1414 
1415     return S_OK;
1416 }
1417 
1418 /* ECMA-262 3rd Edition    12.7 */
1419 static HRESULT compile_continue_statement(compiler_ctx_t *ctx, branch_statement_t *stat)
1420 {
1421     statement_ctx_t *pop_ctx;
1422     HRESULT hres;
1423 
1424     if(stat->identifier) {
1425         statement_t *label_stat;
1426         statement_ctx_t *iter;
1427 
1428         pop_ctx = NULL;
1429 
1430         for(iter = ctx->stat_ctx; iter; iter = iter->next) {
1431             if(iter->continue_label)
1432                 pop_ctx = iter;
1433             if(iter->labelled_stat && !strcmpW(iter->labelled_stat->identifier, stat->identifier))
1434                 break;
1435         }
1436 
1437         if(!iter) {
1438             WARN("Label not found\n");
1439             return JS_E_LABEL_NOT_FOUND;
1440         }
1441 
1442         /* Labelled continue are allowed only on loops */
1443         for(label_stat = iter->labelled_stat->statement;
1444             label_stat->type == STAT_LABEL;
1445             label_stat = ((labelled_statement_t*)label_stat)->statement);
1446         if(!is_loop_statement(label_stat->type)) {
1447             WARN("Label is not a loop\n");
1448             return JS_E_INVALID_CONTINUE;
1449         }
1450 
1451         assert(pop_ctx != NULL);
1452     }else {
1453         for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
1454             if(pop_ctx->continue_label)
1455                 break;
1456         }
1457 
1458         if(!pop_ctx) {
1459             WARN("continue outside loop\n");
1460             return JS_E_INVALID_CONTINUE;
1461         }
1462     }
1463 
1464     hres = pop_to_stat(ctx, pop_ctx);
1465     if(FAILED(hres))
1466         return hres;
1467 
1468     return push_instr_uint(ctx, OP_jmp, pop_ctx->continue_label);
1469 }
1470 
1471 /* ECMA-262 3rd Edition    12.8 */
1472 static HRESULT compile_break_statement(compiler_ctx_t *ctx, branch_statement_t *stat)
1473 {
1474     statement_ctx_t *pop_ctx;
1475     HRESULT hres;
1476 
1477     if(stat->identifier) {
1478         for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
1479             if(pop_ctx->labelled_stat && !strcmpW(pop_ctx->labelled_stat->identifier, stat->identifier)) {
1480                 assert(pop_ctx->break_label);
1481                 break;
1482             }
1483         }
1484 
1485         if(!pop_ctx) {
1486             WARN("Label not found\n");
1487             return JS_E_LABEL_NOT_FOUND;
1488         }
1489     }else {
1490         for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
1491             if(pop_ctx->break_label && !pop_ctx->labelled_stat)
1492                 break;
1493         }
1494 
1495         if(!pop_ctx) {
1496             WARN("Break outside loop\n");
1497             return JS_E_INVALID_BREAK;
1498         }
1499     }
1500 
1501     hres = pop_to_stat(ctx, pop_ctx->next);
1502     if(FAILED(hres))
1503         return hres;
1504 
1505     return push_instr_uint(ctx, OP_jmp, pop_ctx->break_label);
1506 }
1507 
1508 /* ECMA-262 3rd Edition    12.9 */
1509 static HRESULT compile_return_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
1510 {
1511     HRESULT hres;
1512 
1513     if(ctx->from_eval) {
1514         WARN("misplaced return statement\n");
1515         return JS_E_MISPLACED_RETURN;
1516     }
1517 
1518     if(stat->expr) {
1519         hres = compile_expression(ctx, stat->expr, TRUE);
1520         if(FAILED(hres))
1521             return hres;
1522         if(!push_instr(ctx, OP_setret))
1523             return E_OUTOFMEMORY;
1524     }
1525 
1526     hres = pop_to_stat(ctx, NULL);
1527     if(FAILED(hres))
1528         return hres;
1529 
1530     return push_instr_uint(ctx, OP_ret, !stat->expr);
1531 }
1532 
1533 /* ECMA-262 3rd Edition    12.10 */
1534 static HRESULT compile_with_statement(compiler_ctx_t *ctx, with_statement_t *stat)
1535 {
1536     statement_ctx_t stat_ctx = {0, TRUE, FALSE};
1537     HRESULT hres;
1538 
1539     hres = compile_expression(ctx, stat->expr, TRUE);
1540     if(FAILED(hres))
1541         return hres;
1542 
1543     if(!push_instr(ctx, OP_push_scope))
1544         return E_OUTOFMEMORY;
1545 
1546     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1547     if(FAILED(hres))
1548         return hres;
1549 
1550     if(!push_instr(ctx, OP_pop_scope))
1551         return E_OUTOFMEMORY;
1552 
1553     return S_OK;
1554 }
1555 
1556 /* ECMA-262 3rd Edition    12.10 */
1557 static HRESULT compile_labelled_statement(compiler_ctx_t *ctx, labelled_statement_t *stat)
1558 {
1559     statement_ctx_t stat_ctx = {0, FALSE, FALSE, 0, 0, stat}, *iter;
1560     HRESULT hres;
1561 
1562     for(iter = ctx->stat_ctx; iter; iter = iter->next) {
1563         if(iter->labelled_stat && !strcmpW(iter->labelled_stat->identifier, stat->identifier)) {
1564             WARN("Label %s redefined\n", debugstr_w(stat->identifier));
1565             return JS_E_LABEL_REDEFINED;
1566         }
1567     }
1568 
1569     /* Labelled breaks are allowed for any labelled statements, not only loops (violating spec) */
1570     stat_ctx.break_label = alloc_label(ctx);
1571     if(!stat_ctx.break_label)
1572         return E_OUTOFMEMORY;
1573 
1574     hres = compile_statement(ctx, &stat_ctx, stat->statement);
1575     if(FAILED(hres))
1576         return hres;
1577 
1578     label_set_addr(ctx, stat_ctx.break_label);
1579     return S_OK;
1580 }
1581 
1582 /* ECMA-262 3rd Edition    12.13 */
1583 static HRESULT compile_switch_statement(compiler_ctx_t *ctx, switch_statement_t *stat)
1584 {
1585     statement_ctx_t stat_ctx = {0, FALSE, FALSE};
1586     unsigned case_cnt = 0, *case_jmps, i, default_jmp;
1587     BOOL have_default = FALSE;
1588     statement_t *stat_iter;
1589     case_clausule_t *iter;
1590     HRESULT hres;
1591 
1592     hres = compile_expression(ctx, stat->expr, TRUE);
1593     if(FAILED(hres))
1594         return hres;
1595 
1596     stat_ctx.break_label = alloc_label(ctx);
1597     if(!stat_ctx.break_label)
1598         return E_OUTOFMEMORY;
1599 
1600     for(iter = stat->case_list; iter; iter = iter->next) {
1601         if(iter->expr)
1602             case_cnt++;
1603     }
1604 
1605     case_jmps = heap_alloc(case_cnt * sizeof(*case_jmps));
1606     if(!case_jmps)
1607         return E_OUTOFMEMORY;
1608 
1609     i = 0;
1610     for(iter = stat->case_list; iter; iter = iter->next) {
1611         if(!iter->expr) {
1612             have_default = TRUE;
1613             continue;
1614         }
1615 
1616         hres = compile_expression(ctx, iter->expr, TRUE);
1617         if(FAILED(hres))
1618             break;
1619 
1620         case_jmps[i] = push_instr(ctx, OP_case);
1621         if(!case_jmps[i]) {
1622             hres = E_OUTOFMEMORY;
1623             break;
1624         }
1625         i++;
1626     }
1627 
1628     if(SUCCEEDED(hres)) {
1629         hres = push_instr_uint(ctx, OP_pop, 1);
1630         if(SUCCEEDED(hres)) {
1631             default_jmp = push_instr(ctx, OP_jmp);
1632             if(!default_jmp)
1633                 hres = E_OUTOFMEMORY;
1634         }
1635     }
1636 
1637     if(FAILED(hres)) {
1638         heap_free(case_jmps);
1639         return hres;
1640     }
1641 
1642     i = 0;
1643     for(iter = stat->case_list; iter; iter = iter->next) {
1644         while(iter->next && iter->next->stat == iter->stat) {
1645             set_arg_uint(ctx, iter->expr ? case_jmps[i++] : default_jmp, ctx->code_off);
1646             iter = iter->next;
1647         }
1648 
1649         set_arg_uint(ctx, iter->expr ? case_jmps[i++] : default_jmp, ctx->code_off);
1650 
1651         for(stat_iter = iter->stat; stat_iter && (!iter->next || iter->next->stat != stat_iter);
1652             stat_iter = stat_iter->next) {
1653             hres = compile_statement(ctx, &stat_ctx, stat_iter);
1654             if(FAILED(hres))
1655                 break;
1656         }
1657         if(FAILED(hres))
1658             break;
1659     }
1660 
1661     heap_free(case_jmps);
1662     if(FAILED(hres))
1663         return hres;
1664     assert(i == case_cnt);
1665 
1666     if(!have_default) {
1667         hres = push_instr_uint(ctx, OP_jmp, stat_ctx.break_label);
1668         if(FAILED(hres))
1669             return hres;
1670         set_arg_uint(ctx, default_jmp, ctx->code_off);
1671     }
1672 
1673     label_set_addr(ctx, stat_ctx.break_label);
1674     return S_OK;
1675 }
1676 
1677 /* ECMA-262 3rd Edition    12.13 */
1678 static HRESULT compile_throw_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
1679 {
1680     HRESULT hres;
1681 
1682     hres = compile_expression(ctx, stat->expr, TRUE);
1683     if(FAILED(hres))
1684         return hres;
1685 
1686     return push_instr(ctx, OP_throw) ? S_OK : E_OUTOFMEMORY;
1687 }
1688 
1689 /* ECMA-262 3rd Edition    12.14 */
1690 static HRESULT compile_try_statement(compiler_ctx_t *ctx, try_statement_t *stat)
1691 {
1692     statement_ctx_t try_ctx = {0, FALSE, TRUE}, finally_ctx = {2, FALSE, FALSE};
1693     unsigned push_except, finally_off = 0, catch_off = 0, pop_except, catch_pop_except = 0;
1694     BSTR ident;
1695     HRESULT hres;
1696 
1697     push_except = push_instr(ctx, OP_push_except);
1698     if(!push_except)
1699         return E_OUTOFMEMORY;
1700 
1701     if(stat->catch_block) {
1702         ident = compiler_alloc_bstr(ctx, stat->catch_block->identifier);
1703         if(!ident)
1704             return E_OUTOFMEMORY;
1705     }else {
1706         ident = NULL;
1707     }
1708 
1709     hres = compile_statement(ctx, &try_ctx, stat->try_statement);
1710     if(FAILED(hres))
1711         return hres;
1712 
1713     pop_except = push_instr(ctx, OP_pop_except);
1714     if(!pop_except)
1715         return E_OUTOFMEMORY;
1716 
1717     if(stat->catch_block) {
1718         statement_ctx_t catch_ctx = {0, TRUE, stat->finally_statement != NULL};
1719 
1720         if(stat->finally_statement)
1721             catch_ctx.using_except = TRUE;
1722 
1723         catch_off = ctx->code_off;
1724 
1725         hres = push_instr_bstr(ctx, OP_enter_catch, ident);
1726         if(FAILED(hres))
1727             return hres;
1728 
1729         hres = compile_statement(ctx, &catch_ctx, stat->catch_block->statement);
1730         if(FAILED(hres))
1731             return hres;
1732 
1733         if(!push_instr(ctx, OP_pop_scope))
1734             return E_OUTOFMEMORY;
1735 
1736         if(stat->finally_statement) {
1737             catch_pop_except = push_instr(ctx, OP_pop_except);
1738             if(!catch_pop_except)
1739                 return E_OUTOFMEMORY;
1740         }
1741     }
1742 
1743     if(stat->finally_statement) {
1744         /*
1745          * finally block expects two elements on the stack, which may be:
1746          * - (true, return_addr) set by OP_pop_except, OP_end_finally jumps back to passed address
1747          * - (false, exception_value) set when unwinding an exception, which OP_end_finally rethrows
1748          */
1749         finally_off = ctx->code_off;
1750         hres = compile_statement(ctx, &finally_ctx, stat->finally_statement);
1751         if(FAILED(hres))
1752             return hres;
1753 
1754         if(!push_instr(ctx, OP_end_finally))
1755             return E_OUTOFMEMORY;
1756     }
1757 
1758     instr_ptr(ctx, pop_except)->u.arg[0].uint = ctx->code_off;
1759     if(catch_pop_except)
1760         instr_ptr(ctx, catch_pop_except)->u.arg[0].uint = ctx->code_off;
1761     instr_ptr(ctx, push_except)->u.arg[0].uint = catch_off;
1762     instr_ptr(ctx, push_except)->u.arg[1].uint = finally_off;
1763     return S_OK;
1764 }
1765 
1766 static HRESULT compile_statement(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx, statement_t *stat)
1767 {
1768     HRESULT hres;
1769 
1770     if(stat_ctx) {
1771         stat_ctx->next = ctx->stat_ctx;
1772         ctx->stat_ctx = stat_ctx;
1773     }
1774 
1775     switch(stat->type) {
1776     case STAT_BLOCK:
1777         hres = compile_block_statement(ctx, ((block_statement_t*)stat)->stat_list);
1778         break;
1779     case STAT_BREAK:
1780         hres = compile_break_statement(ctx, (branch_statement_t*)stat);
1781         break;
1782     case STAT_CONTINUE:
1783         hres = compile_continue_statement(ctx, (branch_statement_t*)stat);
1784         break;
1785     case STAT_EMPTY:
1786         /* nothing to do */
1787         hres = S_OK;
1788         break;
1789     case STAT_EXPR:
1790         hres = compile_expression_statement(ctx, (expression_statement_t*)stat);
1791         break;
1792     case STAT_FOR:
1793         hres = compile_for_statement(ctx, (for_statement_t*)stat);
1794         break;
1795     case STAT_FORIN:
1796         hres = compile_forin_statement(ctx, (forin_statement_t*)stat);
1797         break;
1798     case STAT_IF:
1799         hres = compile_if_statement(ctx, (if_statement_t*)stat);
1800         break;
1801     case STAT_LABEL:
1802         hres = compile_labelled_statement(ctx, (labelled_statement_t*)stat);
1803         break;
1804     case STAT_RETURN:
1805         hres = compile_return_statement(ctx, (expression_statement_t*)stat);
1806         break;
1807     case STAT_SWITCH:
1808         hres = compile_switch_statement(ctx, (switch_statement_t*)stat);
1809         break;
1810     case STAT_THROW:
1811         hres = compile_throw_statement(ctx, (expression_statement_t*)stat);
1812         break;
1813     case STAT_TRY:
1814         hres = compile_try_statement(ctx, (try_statement_t*)stat);
1815         break;
1816     case STAT_VAR:
1817         hres = compile_var_statement(ctx, (var_statement_t*)stat);
1818         break;
1819     case STAT_WHILE:
1820         hres = compile_while_statement(ctx, (while_statement_t*)stat);
1821         break;
1822     case STAT_WITH:
1823         hres = compile_with_statement(ctx, (with_statement_t*)stat);
1824         break;
1825     DEFAULT_UNREACHABLE;
1826     }
1827 
1828     if(stat_ctx) {
1829         assert(ctx->stat_ctx == stat_ctx);
1830         ctx->stat_ctx = stat_ctx->next;
1831     }
1832 
1833     return hres;
1834 }
1835 
1836 static int function_local_cmp(const void *key, const struct wine_rb_entry *entry)
1837 {
1838     function_local_t *local = WINE_RB_ENTRY_VALUE(entry, function_local_t, entry);
1839     return strcmpW(key, local->name);
1840 }
1841 
1842 static inline function_local_t *find_local(compiler_ctx_t *ctx, const WCHAR *name)
1843 {
1844     struct wine_rb_entry *entry = wine_rb_get(&ctx->locals, name);
1845     return entry ? WINE_RB_ENTRY_VALUE(entry, function_local_t, entry) : NULL;
1846 }
1847 
1848 static BOOL alloc_local(compiler_ctx_t *ctx, BSTR name, int ref)
1849 {
1850     function_local_t *local;
1851 
1852     local = heap_pool_alloc(&ctx->heap, sizeof(*local));
1853     if(!local)
1854         return FALSE;
1855 
1856     local->name = name;
1857     local->ref = ref;
1858     wine_rb_put(&ctx->locals, name, &local->entry);
1859     ctx->locals_cnt++;
1860     return TRUE;
1861 }
1862 
1863 static BOOL alloc_variable(compiler_ctx_t *ctx, const WCHAR *name)
1864 {
1865     BSTR ident;
1866 
1867     if(find_local(ctx, name))
1868         return TRUE;
1869 
1870     ident = compiler_alloc_bstr(ctx, name);
1871     if(!ident)
1872         return FALSE;
1873 
1874     return alloc_local(ctx, ident, ctx->func->var_cnt++);
1875 }
1876 
1877 static HRESULT visit_function_expression(compiler_ctx_t *ctx, function_expression_t *expr)
1878 {
1879     expr->func_id = ctx->func->func_cnt++;
1880     ctx->func_tail = ctx->func_tail ? (ctx->func_tail->next = expr) : (ctx->func_head = expr);
1881 
1882     return !expr->identifier || expr->event_target || alloc_variable(ctx, expr->identifier)
1883         ? S_OK : E_OUTOFMEMORY;
1884 }
1885 
1886 static HRESULT visit_expression(compiler_ctx_t *ctx, expression_t *expr)
1887 {
1888     HRESULT hres = S_OK;
1889 
1890     switch(expr->type) {
1891     case EXPR_ADD:
1892     case EXPR_AND:
1893     case EXPR_ARRAY:
1894     case EXPR_ASSIGN:
1895     case EXPR_ASSIGNADD:
1896     case EXPR_ASSIGNAND:
1897     case EXPR_ASSIGNSUB:
1898     case EXPR_ASSIGNMUL:
1899     case EXPR_ASSIGNDIV:
1900     case EXPR_ASSIGNMOD:
1901     case EXPR_ASSIGNOR:
1902     case EXPR_ASSIGNLSHIFT:
1903     case EXPR_ASSIGNRSHIFT:
1904     case EXPR_ASSIGNRRSHIFT:
1905     case EXPR_ASSIGNXOR:
1906     case EXPR_BAND:
1907     case EXPR_BOR:
1908     case EXPR_COMMA:
1909     case EXPR_DIV:
1910     case EXPR_EQ:
1911     case EXPR_EQEQ:
1912     case EXPR_GREATER:
1913     case EXPR_GREATEREQ:
1914     case EXPR_IN:
1915     case EXPR_INSTANCEOF:
1916     case EXPR_LESS:
1917     case EXPR_LESSEQ:
1918     case EXPR_LSHIFT:
1919     case EXPR_MOD:
1920     case EXPR_MUL:
1921     case EXPR_NOTEQ:
1922     case EXPR_NOTEQEQ:
1923     case EXPR_OR:
1924     case EXPR_RSHIFT:
1925     case EXPR_RRSHIFT:
1926     case EXPR_SUB:
1927     case EXPR_BXOR: {
1928         binary_expression_t *binary_expr = (binary_expression_t*)expr;
1929 
1930         hres = visit_expression(ctx, binary_expr->expression1);
1931         if(FAILED(hres))
1932             return hres;
1933 
1934         hres = visit_expression(ctx, binary_expr->expression2);
1935         break;
1936     }
1937     case EXPR_BITNEG:
1938     case EXPR_DELETE:
1939     case EXPR_LOGNEG:
1940     case EXPR_MINUS:
1941     case EXPR_PLUS:
1942     case EXPR_POSTDEC:
1943     case EXPR_POSTINC:
1944     case EXPR_PREDEC:
1945     case EXPR_PREINC:
1946     case EXPR_TYPEOF:
1947     case EXPR_VOID:
1948         hres = visit_expression(ctx, ((unary_expression_t*)expr)->expression);
1949         break;
1950     case EXPR_IDENT:
1951     case EXPR_LITERAL:
1952     case EXPR_THIS:
1953         break;
1954     case EXPR_ARRAYLIT: {
1955         array_literal_expression_t *array_expr = (array_literal_expression_t*)expr;
1956         array_element_t *iter;
1957 
1958         for(iter = array_expr->element_list; iter; iter = iter->next) {
1959             hres = visit_expression(ctx, iter->expr);
1960             if(FAILED(hres))
1961                 return hres;
1962         }
1963         break;
1964     }
1965     case EXPR_CALL:
1966     case EXPR_NEW: {
1967         call_expression_t *call_expr = (call_expression_t*)expr;
1968         argument_t *arg;
1969 
1970         hres = visit_expression(ctx, call_expr->expression);
1971         if(FAILED(hres))
1972             return hres;
1973 
1974         for(arg = call_expr->argument_list; arg; arg = arg->next) {
1975             hres = visit_expression(ctx, arg->expr);
1976             if(FAILED(hres))
1977                 return hres;
1978         }
1979         break;
1980     }
1981     case EXPR_COND: {
1982         conditional_expression_t *cond_expr = (conditional_expression_t*)expr;
1983 
1984         hres = visit_expression(ctx, cond_expr->expression);
1985         if(FAILED(hres))
1986             return hres;
1987 
1988         hres = visit_expression(ctx, cond_expr->true_expression);
1989         if(FAILED(hres))
1990             return hres;
1991 
1992         hres = visit_expression(ctx, cond_expr->false_expression);
1993         break;
1994     }
1995     case EXPR_FUNC:
1996         hres = visit_function_expression(ctx, (function_expression_t*)expr);
1997         break;
1998     case EXPR_MEMBER:
1999         hres = visit_expression(ctx, ((member_expression_t*)expr)->expression);
2000         break;
2001     case EXPR_PROPVAL: {
2002         prop_val_t *iter;
2003         for(iter = ((property_value_expression_t*)expr)->property_list; iter; iter = iter->next) {
2004             hres = visit_expression(ctx, iter->value);
2005             if(FAILED(hres))
2006                 return hres;
2007         }
2008         break;
2009     }
2010     DEFAULT_UNREACHABLE;
2011     }
2012 
2013     return hres;
2014 }
2015 
2016 static HRESULT visit_variable_list(compiler_ctx_t *ctx, variable_declaration_t *list)
2017 {
2018     variable_declaration_t *iter;
2019     HRESULT hres;
2020 
2021     for(iter = list; iter; iter = iter->next) {
2022         if(!alloc_variable(ctx, iter->identifier))
2023             return E_OUTOFMEMORY;
2024 
2025         if(iter->expr) {
2026             hres = visit_expression(ctx, iter->expr);
2027             if(FAILED(hres))
2028                 return hres;
2029         }
2030     }
2031 
2032     return S_OK;
2033 }
2034 
2035 static HRESULT visit_statement(compiler_ctx_t*,statement_t*);
2036 
2037 static HRESULT visit_block_statement(compiler_ctx_t *ctx, statement_t *iter)
2038 {
2039     HRESULT hres;
2040 
2041     while(iter) {
2042         hres = visit_statement(ctx, iter);
2043         if(FAILED(hres))
2044             return hres;
2045 
2046         iter = iter->next;
2047     }
2048 
2049     return S_OK;
2050 }
2051 
2052 static HRESULT visit_statement(compiler_ctx_t *ctx, statement_t *stat)
2053 {
2054     HRESULT hres = S_OK;
2055 
2056     switch(stat->type) {
2057     case STAT_BLOCK:
2058         hres = visit_block_statement(ctx, ((block_statement_t*)stat)->stat_list);
2059         break;
2060     case STAT_BREAK:
2061     case STAT_CONTINUE:
2062     case STAT_EMPTY:
2063         break;
2064     case STAT_EXPR:
2065     case STAT_RETURN:
2066     case STAT_THROW: {
2067         expression_statement_t *expr_stat = (expression_statement_t*)stat;
2068         if(expr_stat->expr)
2069             hres = visit_expression(ctx, expr_stat->expr);
2070         break;
2071     }
2072     case STAT_FOR: {
2073         for_statement_t *for_stat = (for_statement_t*)stat;
2074 
2075         if(for_stat->variable_list)
2076             hres = visit_variable_list(ctx, for_stat->variable_list);
2077         else if(for_stat->begin_expr)
2078             hres = visit_expression(ctx, for_stat->begin_expr);
2079         if(FAILED(hres))
2080             break;
2081 
2082         if(for_stat->expr) {
2083             hres = visit_expression(ctx, for_stat->expr);
2084             if(FAILED(hres))
2085                 break;
2086         }
2087 
2088         hres = visit_statement(ctx, for_stat->statement);
2089         if(FAILED(hres))
2090             break;
2091 
2092         if(for_stat->end_expr)
2093             hres = visit_expression(ctx, for_stat->end_expr);
2094         break;
2095     }
2096     case STAT_FORIN:  {
2097         forin_statement_t *forin_stat = (forin_statement_t*)stat;
2098 
2099         if(forin_stat->variable) {
2100             hres = visit_variable_list(ctx, forin_stat->variable);
2101             if(FAILED(hres))
2102                 break;
2103         }
2104 
2105         hres = visit_expression(ctx, forin_stat->in_expr);
2106         if(FAILED(hres))
2107             return hres;
2108 
2109         if(forin_stat->expr) {
2110             hres = visit_expression(ctx, forin_stat->expr);
2111             if(FAILED(hres))
2112                 return hres;
2113         }
2114 
2115         hres = visit_statement(ctx, forin_stat->statement);
2116         break;
2117     }
2118     case STAT_IF: {
2119         if_statement_t *if_stat = (if_statement_t*)stat;
2120 
2121         hres = visit_expression(ctx, if_stat->expr);
2122         if(FAILED(hres))
2123             return hres;
2124 
2125         hres = visit_statement(ctx, if_stat->if_stat);
2126         if(FAILED(hres))
2127             return hres;
2128 
2129         if(if_stat->else_stat)
2130             hres = visit_statement(ctx, if_stat->else_stat);
2131         break;
2132     }
2133     case STAT_LABEL:
2134         hres = visit_statement(ctx, ((labelled_statement_t*)stat)->statement);
2135         break;
2136     case STAT_SWITCH: {
2137         switch_statement_t *switch_stat = (switch_statement_t*)stat;
2138         statement_t *stat_iter;
2139         case_clausule_t *iter;
2140 
2141         hres = visit_expression(ctx, switch_stat->expr);
2142         if(FAILED(hres))
2143             return hres;
2144 
2145         for(iter = switch_stat->case_list; iter; iter = iter->next) {
2146             if(!iter->expr)
2147                 continue;
2148             hres = visit_expression(ctx, iter->expr);
2149             if(FAILED(hres))
2150                 return hres;
2151         }
2152 
2153         for(iter = switch_stat->case_list; iter; iter = iter->next) {
2154             while(iter->next && iter->next->stat == iter->stat)
2155                 iter = iter->next;
2156             for(stat_iter = iter->stat; stat_iter && (!iter->next || iter->next->stat != stat_iter);
2157                 stat_iter = stat_iter->next) {
2158                 hres = visit_statement(ctx, stat_iter);
2159                 if(FAILED(hres))
2160                     return hres;
2161             }
2162         }
2163         break;
2164     }
2165     case STAT_TRY: {
2166         try_statement_t *try_stat = (try_statement_t*)stat;
2167 
2168         hres = visit_statement(ctx, try_stat->try_statement);
2169         if(FAILED(hres))
2170             return hres;
2171 
2172         if(try_stat->catch_block) {
2173             hres = visit_statement(ctx, try_stat->catch_block->statement);
2174             if(FAILED(hres))
2175                 return hres;
2176         }
2177 
2178         if(try_stat->finally_statement)
2179             hres = visit_statement(ctx, try_stat->finally_statement);
2180         break;
2181     }
2182     case STAT_VAR:
2183         hres = visit_variable_list(ctx, ((var_statement_t*)stat)->variable_list);
2184         break;
2185     case STAT_WHILE: {
2186         while_statement_t *while_stat = (while_statement_t*)stat;
2187 
2188         hres = visit_expression(ctx, while_stat->expr);
2189         if(FAILED(hres))
2190             return hres;
2191 
2192         hres = visit_statement(ctx, while_stat->statement);
2193         break;
2194     }
2195     case STAT_WITH: {
2196         with_statement_t *with_stat = (with_statement_t*)stat;
2197 
2198         hres = visit_expression(ctx, with_stat->expr);
2199         if(FAILED(hres))
2200             return hres;
2201 
2202         hres = visit_statement(ctx, with_stat->statement);
2203         break;
2204     }
2205     DEFAULT_UNREACHABLE;
2206     }
2207 
2208     return hres;
2209 }
2210 
2211 static void resolve_labels(compiler_ctx_t *ctx, unsigned off)
2212 {
2213     instr_t *instr;
2214 
2215     for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->code_off; instr++) {
2216         if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->u.arg->uint & LABEL_FLAG)) {
2217             assert((instr->u.arg->uint & ~LABEL_FLAG) < ctx->labels_cnt);
2218             instr->u.arg->uint = ctx->labels[instr->u.arg->uint & ~LABEL_FLAG];
2219         }
2220         assert(instr_info[instr->op].arg2_type != ARG_ADDR);
2221     }
2222 
2223     ctx->labels_cnt = 0;
2224 }
2225 
2226 void release_bytecode(bytecode_t *code)
2227 {
2228     unsigned i;
2229 
2230     if(--code->ref)
2231         return;
2232 
2233     for(i=0; i < code->bstr_cnt; i++)
2234         SysFreeString(code->bstr_pool[i]);
2235     for(i=0; i < code->str_cnt; i++)
2236         jsstr_release(code->str_pool[i]);
2237 
2238     heap_free(code->source);
2239     heap_pool_free(&code->heap);
2240     heap_free(code->bstr_pool);
2241     heap_free(code->str_pool);
2242     heap_free(code->instrs);
2243     heap_free(code);
2244 }
2245 
2246 static HRESULT init_code(compiler_ctx_t *compiler, const WCHAR *source)
2247 {
2248     compiler->code = heap_alloc_zero(sizeof(bytecode_t));
2249     if(!compiler->code)
2250         return E_OUTOFMEMORY;
2251 
2252     compiler->code->ref = 1;
2253     heap_pool_init(&compiler->code->heap);
2254 
2255     compiler->code->source = heap_strdupW(source);
2256     if(!compiler->code->source) {
2257         release_bytecode(compiler->code);
2258         return E_OUTOFMEMORY;
2259     }
2260 
2261     compiler->code->instrs = heap_alloc(64 * sizeof(instr_t));
2262     if(!compiler->code->instrs) {
2263         release_bytecode(compiler->code);
2264         return E_OUTOFMEMORY;
2265     }
2266 
2267     compiler->code_size = 64;
2268     compiler->code_off = 1;
2269     return S_OK;
2270 }
2271 
2272 static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source, function_expression_t *func_expr,
2273         BOOL from_eval, function_code_t *func)
2274 {
2275     function_expression_t *iter;
2276     function_local_t *local;
2277     unsigned off, i;
2278     HRESULT hres;
2279 
2280     TRACE("\n");
2281 
2282     ctx->func_head = ctx->func_tail = NULL;
2283     ctx->from_eval = from_eval;
2284     ctx->func = func;
2285     ctx->locals_cnt = 0;
2286     wine_rb_init(&ctx->locals, function_local_cmp);
2287 
2288     if(func_expr) {
2289         parameter_t *param_iter;
2290 
2291         if(func_expr->identifier) {
2292             func->name = compiler_alloc_bstr(ctx, func_expr->identifier);
2293             if(!func->name)
2294                 return E_OUTOFMEMORY;
2295         }
2296 
2297         if(func_expr->event_target) {
2298             func->event_target = compiler_alloc_bstr(ctx, func_expr->event_target);
2299             if(!func->event_target)
2300                 return E_OUTOFMEMORY;
2301         }
2302 
2303         func->source = func_expr->src_str;
2304         func->source_len = func_expr->src_len;
2305 
2306         for(param_iter = func_expr->parameter_list; param_iter; param_iter = param_iter->next)
2307             func->param_cnt++;
2308 
2309         func->params = compiler_alloc(ctx->code, func->param_cnt * sizeof(*func->params));
2310         if(!func->params)
2311             return E_OUTOFMEMORY;
2312 
2313         for(param_iter = func_expr->parameter_list, i=0; param_iter; param_iter = param_iter->next, i++) {
2314             func->params[i] = compiler_alloc_bstr(ctx, param_iter->identifier);
2315             if(!func->params[i])
2316                 return E_OUTOFMEMORY;
2317         }
2318     }
2319 
2320     for(i = 0; i < func->param_cnt; i++) {
2321         if(!find_local(ctx, func->params[i]) && !alloc_local(ctx, func->params[i], -i-1))
2322             return E_OUTOFMEMORY;
2323     }
2324 
2325     hres = visit_block_statement(ctx, source->statement);
2326     if(FAILED(hres))
2327         return hres;
2328 
2329     func->locals = compiler_alloc(ctx->code, ctx->locals_cnt * sizeof(*func->locals));
2330     if(!func->locals)
2331         return E_OUTOFMEMORY;
2332     func->locals_cnt = ctx->locals_cnt;
2333 
2334     func->variables = compiler_alloc(ctx->code, func->var_cnt * sizeof(*func->variables));
2335     if(!func->variables)
2336         return E_OUTOFMEMORY;
2337 
2338     i = 0;
2339     WINE_RB_FOR_EACH_ENTRY(local, &ctx->locals, function_local_t, entry) {
2340         func->locals[i].name = local->name;
2341         func->locals[i].ref = local->ref;
2342         if(local->ref >= 0) {
2343             func->variables[local->ref].name = local->name;
2344             func->variables[local->ref].func_id = -1;
2345         }
2346         i++;
2347     }
2348     assert(i == ctx->locals_cnt);
2349 
2350     func->funcs = compiler_alloc(ctx->code, func->func_cnt * sizeof(*func->funcs));
2351     if(!func->funcs)
2352         return E_OUTOFMEMORY;
2353     memset(func->funcs, 0, func->func_cnt * sizeof(*func->funcs));
2354 
2355     off = ctx->code_off;
2356     hres = compile_block_statement(ctx, source->statement);
2357     if(FAILED(hres))
2358         return hres;
2359 
2360     resolve_labels(ctx, off);
2361 
2362     hres = push_instr_uint(ctx, OP_ret, !from_eval);
2363     if(FAILED(hres))
2364         return hres;
2365 
2366     if(TRACE_ON(jscript_disas))
2367         dump_code(ctx, off);
2368 
2369     func->instr_off = off;
2370 
2371     for(iter = ctx->func_head, i=0; iter; iter = iter->next, i++) {
2372         hres = compile_function(ctx, iter->source_elements, iter, FALSE, func->funcs+i);
2373         if(FAILED(hres))
2374             return hres;
2375 
2376         TRACE("[%d] func %s\n", i, debugstr_w(func->funcs[i].name));
2377         if(func->funcs[i].name && !func->funcs[i].event_target) {
2378             local_ref_t *local_ref = lookup_local(func, func->funcs[i].name);
2379             func->funcs[i].local_ref = local_ref->ref;
2380             TRACE("found ref %s %d for %s\n", debugstr_w(local_ref->name), local_ref->ref, debugstr_w(func->funcs[i].name));
2381             if(local_ref->ref >= 0)
2382                 func->variables[local_ref->ref].func_id = i;
2383         }
2384     }
2385 
2386     assert(i == func->func_cnt);
2387 
2388     return S_OK;
2389 }
2390 
2391 static HRESULT parse_arguments(compiler_ctx_t *ctx, const WCHAR *args, BSTR *arg_array, unsigned *args_size)
2392 {
2393     const WCHAR *ptr = args, *ptr2;
2394     unsigned arg_cnt = 0;
2395 
2396     while(isspaceW(*ptr))
2397         ptr++;
2398     if(!*ptr) {
2399         if(args_size)
2400             *args_size = 0;
2401         return S_OK;
2402     }
2403 
2404     while(1) {
2405         if(!isalphaW(*ptr) && *ptr != '_') {
2406             FIXME("expected alpha or '_': %s\n", debugstr_w(ptr));
2407             return E_FAIL;
2408         }
2409 
2410         ptr2 = ptr;
2411         while(isalnumW(*ptr) || *ptr == '_')
2412             ptr++;
2413 
2414         if(*ptr && *ptr != ',' && !isspaceW(*ptr)) {
2415             FIXME("unexpected har %s\n", debugstr_w(ptr));
2416             return E_FAIL;
2417         }
2418 
2419         if(arg_array) {
2420             arg_array[arg_cnt] = compiler_alloc_bstr_len(ctx, ptr2, ptr-ptr2);
2421             if(!arg_array[arg_cnt])
2422                 return E_OUTOFMEMORY;
2423         }
2424         arg_cnt++;
2425 
2426         while(isspaceW(*ptr))
2427             ptr++;
2428         if(!*ptr)
2429             break;
2430         if(*ptr != ',') {
2431             FIXME("expected ',': %s\n", debugstr_w(ptr));
2432             return E_FAIL;
2433         }
2434 
2435         ptr++;
2436         while(isspaceW(*ptr))
2437             ptr++;
2438     }
2439 
2440     if(args_size)
2441         *args_size = arg_cnt;
2442     return S_OK;
2443 }
2444 
2445 static HRESULT compile_arguments(compiler_ctx_t *ctx, const WCHAR *args)
2446 {
2447     HRESULT hres;
2448 
2449     hres = parse_arguments(ctx, args, NULL, &ctx->code->global_code.param_cnt);
2450     if(FAILED(hres))
2451         return hres;
2452 
2453     ctx->code->global_code.params = compiler_alloc(ctx->code,
2454             ctx->code->global_code.param_cnt * sizeof(*ctx->code->global_code.params));
2455     if(!ctx->code->global_code.params)
2456         return E_OUTOFMEMORY;
2457 
2458     return parse_arguments(ctx, args, ctx->code->global_code.params, NULL);
2459 }
2460 
2461 HRESULT compile_script(script_ctx_t *ctx, const WCHAR *code, const WCHAR *args, const WCHAR *delimiter,
2462         BOOL from_eval, BOOL use_decode, bytecode_t **ret)
2463 {
2464     compiler_ctx_t compiler = {0};
2465     HRESULT hres;
2466 
2467     hres = init_code(&compiler, code);
2468     if(FAILED(hres))
2469         return hres;
2470 
2471     if(args) {
2472         hres = compile_arguments(&compiler, args);
2473         if(FAILED(hres))
2474             return hres;
2475     }
2476 
2477     if(use_decode) {
2478         hres = decode_source(compiler.code->source);
2479         if(FAILED(hres)) {
2480             WARN("Decoding failed\n");
2481             return hres;
2482         }
2483     }
2484 
2485     hres = script_parse(ctx, compiler.code->source, delimiter, from_eval, &compiler.parser);
2486     if(FAILED(hres)) {
2487         release_bytecode(compiler.code);
2488         return hres;
2489     }
2490 
2491     heap_pool_init(&compiler.heap);
2492     hres = compile_function(&compiler, compiler.parser->source, NULL, from_eval, &compiler.code->global_code);
2493     heap_pool_free(&compiler.heap);
2494     parser_release(compiler.parser);
2495     if(FAILED(hres)) {
2496         release_bytecode(compiler.code);
2497         return hres;
2498     }
2499 
2500     *ret = compiler.code;
2501     return S_OK;
2502 }
2503