xref: /reactos/dll/win32/jscript/compile.c (revision 53221834)
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 _compiler_ctx_t {
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 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, lstrlenW(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, jsstr_t *str)
249 {
250     unsigned instr;
251 
252     instr = push_instr(ctx, op);
253     if(!instr)
254         return E_OUTOFMEMORY;
255 
256     instr_ptr(ctx, instr)->u.arg->str = str;
257     return S_OK;
258 }
259 
260 static HRESULT push_instr_str_uint(compiler_ctx_t *ctx, jsop_t op, jsstr_t *str, unsigned arg2)
261 {
262     unsigned instr;
263 
264     instr = push_instr(ctx, op);
265     if(!instr)
266         return E_OUTOFMEMORY;
267 
268     instr_ptr(ctx, instr)->u.arg[0].str = str;
269     instr_ptr(ctx, instr)->u.arg[1].uint = arg2;
270     return S_OK;
271 }
272 
273 static HRESULT push_instr_bstr(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg)
274 {
275     unsigned instr;
276     WCHAR *str;
277 
278     str = compiler_alloc_bstr(ctx, arg);
279     if(!str)
280         return E_OUTOFMEMORY;
281 
282     instr = push_instr(ctx, op);
283     if(!instr)
284         return E_OUTOFMEMORY;
285 
286     instr_ptr(ctx, instr)->u.arg->bstr = str;
287     return S_OK;
288 }
289 
290 static HRESULT push_instr_bstr_uint(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg1, unsigned arg2)
291 {
292     unsigned instr;
293     WCHAR *str;
294 
295     str = compiler_alloc_bstr(ctx, arg1);
296     if(!str)
297         return E_OUTOFMEMORY;
298 
299     instr = push_instr(ctx, op);
300     if(!instr)
301         return E_OUTOFMEMORY;
302 
303     instr_ptr(ctx, instr)->u.arg[0].bstr = str;
304     instr_ptr(ctx, instr)->u.arg[1].uint = arg2;
305     return S_OK;
306 }
307 
308 static HRESULT push_instr_uint_str(compiler_ctx_t *ctx, jsop_t op, unsigned arg1, const WCHAR *arg2)
309 {
310     unsigned instr;
311     jsstr_t *str;
312 
313     str = compiler_alloc_string(ctx, arg2);
314     if(!str)
315         return E_OUTOFMEMORY;
316 
317     instr = push_instr(ctx, op);
318     if(!instr)
319         return E_OUTOFMEMORY;
320 
321     instr_ptr(ctx, instr)->u.arg[0].uint = arg1;
322     instr_ptr(ctx, instr)->u.arg[1].str = str;
323     return S_OK;
324 }
325 
326 static HRESULT push_instr_double(compiler_ctx_t *ctx, jsop_t op, double arg)
327 {
328     unsigned instr;
329 
330     instr = push_instr(ctx, op);
331     if(!instr)
332         return E_OUTOFMEMORY;
333 
334     instr_ptr(ctx, instr)->u.dbl = arg;
335     return S_OK;
336 }
337 
338 static inline void set_arg_uint(compiler_ctx_t *ctx, unsigned instr, unsigned arg)
339 {
340     instr_ptr(ctx, instr)->u.arg->uint = arg;
341 }
342 
343 static HRESULT push_instr_uint(compiler_ctx_t *ctx, jsop_t op, unsigned arg)
344 {
345     unsigned instr;
346 
347     instr = push_instr(ctx, op);
348     if(!instr)
349         return E_OUTOFMEMORY;
350 
351     set_arg_uint(ctx, instr, arg);
352     return S_OK;
353 }
354 
355 static HRESULT compile_binary_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
356 {
357     HRESULT hres;
358 
359     hres = compile_expression(ctx, expr->expression1, TRUE);
360     if(FAILED(hres))
361         return hres;
362 
363     hres = compile_expression(ctx, expr->expression2, TRUE);
364     if(FAILED(hres))
365         return hres;
366 
367     return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
368 }
369 
370 static HRESULT compile_unary_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op)
371 {
372     HRESULT hres;
373 
374     hres = compile_expression(ctx, expr->expression, TRUE);
375     if(FAILED(hres))
376         return hres;
377 
378     return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
379 }
380 
381 /* ECMA-262 3rd Edition    11.2.1 */
382 static HRESULT compile_member_expression(compiler_ctx_t *ctx, member_expression_t *expr)
383 {
384     HRESULT hres;
385 
386     hres = compile_expression(ctx, expr->expression, TRUE);
387     if(FAILED(hres))
388         return hres;
389 
390     return push_instr_bstr(ctx, OP_member, expr->identifier);
391 }
392 
393 #define LABEL_FLAG 0x80000000
394 
395 static unsigned alloc_label(compiler_ctx_t *ctx)
396 {
397     if(!ctx->labels_size) {
398         ctx->labels = heap_alloc(8 * sizeof(*ctx->labels));
399         if(!ctx->labels)
400             return 0;
401         ctx->labels_size = 8;
402     }else if(ctx->labels_size == ctx->labels_cnt) {
403         unsigned *new_labels;
404 
405         new_labels = heap_realloc(ctx->labels, 2*ctx->labels_size*sizeof(*ctx->labels));
406         if(!new_labels)
407             return 0;
408 
409         ctx->labels = new_labels;
410         ctx->labels_size *= 2;
411     }
412 
413     return ctx->labels_cnt++ | LABEL_FLAG;
414 }
415 
416 static void label_set_addr(compiler_ctx_t *ctx, unsigned label)
417 {
418     assert(label & LABEL_FLAG);
419     ctx->labels[label & ~LABEL_FLAG] = ctx->code_off;
420 }
421 
422 static inline BOOL is_memberid_expr(expression_type_t type)
423 {
424     return type == EXPR_IDENT || type == EXPR_MEMBER || type == EXPR_ARRAY;
425 }
426 
427 static BOOL bind_local(compiler_ctx_t *ctx, const WCHAR *identifier, int *ret_ref)
428 {
429     statement_ctx_t *iter;
430     local_ref_t *ref;
431 
432     for(iter = ctx->stat_ctx; iter; iter = iter->next) {
433         if(iter->using_scope)
434             return FALSE;
435     }
436 
437     ref = lookup_local(ctx->func, identifier);
438     if(!ref)
439         return FALSE;
440 
441     *ret_ref = ref->ref;
442     return TRUE;
443 }
444 
445 static HRESULT emit_identifier_ref(compiler_ctx_t *ctx, const WCHAR *identifier, unsigned flags)
446 {
447     int local_ref;
448     if(bind_local(ctx, identifier, &local_ref))
449         return push_instr_int(ctx, OP_local_ref, local_ref);
450     return push_instr_bstr_uint(ctx, OP_identid, identifier, flags);
451 }
452 
453 static HRESULT emit_identifier(compiler_ctx_t *ctx, const WCHAR *identifier)
454 {
455     int local_ref;
456     if(bind_local(ctx, identifier, &local_ref))
457         return push_instr_int(ctx, OP_local, local_ref);
458     return push_instr_bstr(ctx, OP_ident, identifier);
459 }
460 
461 static HRESULT compile_memberid_expression(compiler_ctx_t *ctx, expression_t *expr, unsigned flags)
462 {
463     HRESULT hres = S_OK;
464 
465     switch(expr->type) {
466     case EXPR_IDENT: {
467         identifier_expression_t *ident_expr = (identifier_expression_t*)expr;
468 
469         hres = emit_identifier_ref(ctx, ident_expr->identifier, flags);
470         break;
471     }
472     case EXPR_ARRAY: {
473         binary_expression_t *array_expr = (binary_expression_t*)expr;
474 
475         hres = compile_expression(ctx, array_expr->expression1, TRUE);
476         if(FAILED(hres))
477             return hres;
478 
479         hres = compile_expression(ctx, array_expr->expression2, TRUE);
480         if(FAILED(hres))
481             return hres;
482 
483         hres = push_instr_uint(ctx, OP_memberid, flags);
484         break;
485     }
486     case EXPR_MEMBER: {
487         member_expression_t *member_expr = (member_expression_t*)expr;
488         jsstr_t *jsstr;
489 
490         hres = compile_expression(ctx, member_expr->expression, TRUE);
491         if(FAILED(hres))
492             return hres;
493 
494         /* FIXME: Potential optimization */
495         jsstr = compiler_alloc_string(ctx, member_expr->identifier);
496         if(!jsstr)
497             return E_OUTOFMEMORY;
498 
499         hres = push_instr_str(ctx, OP_str, jsstr);
500         if(FAILED(hres))
501             return hres;
502 
503         hres = push_instr_uint(ctx, OP_memberid, flags);
504         break;
505     }
506     DEFAULT_UNREACHABLE;
507     }
508 
509     return hres;
510 }
511 
512 static HRESULT compile_increment_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op, int n)
513 {
514     HRESULT hres;
515 
516     if(!is_memberid_expr(expr->expression->type)) {
517         hres = compile_expression(ctx, expr->expression, TRUE);
518         if(FAILED(hres))
519             return hres;
520 
521         return push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
522     }
523 
524     hres = compile_memberid_expression(ctx, expr->expression, fdexNameEnsure);
525     if(FAILED(hres))
526         return hres;
527 
528     return push_instr_int(ctx, op, n);
529 }
530 
531 /* ECMA-262 3rd Edition    11.14 */
532 static HRESULT compile_comma_expression(compiler_ctx_t *ctx, binary_expression_t *expr, BOOL emit_ret)
533 {
534     HRESULT hres;
535 
536     hres = compile_expression(ctx, expr->expression1, FALSE);
537     if(FAILED(hres))
538         return hres;
539 
540     return compile_expression(ctx, expr->expression2, emit_ret);
541 }
542 
543 /* ECMA-262 3rd Edition    11.11 */
544 static HRESULT compile_logical_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
545 {
546     unsigned instr;
547     HRESULT hres;
548 
549     hres = compile_expression(ctx, expr->expression1, TRUE);
550     if(FAILED(hres))
551         return hres;
552 
553     instr = push_instr(ctx, op);
554     if(!instr)
555         return E_OUTOFMEMORY;
556 
557     hres = compile_expression(ctx, expr->expression2, TRUE);
558     if(FAILED(hres))
559         return hres;
560 
561     set_arg_uint(ctx, instr, ctx->code_off);
562     return S_OK;
563 }
564 
565 /* ECMA-262 3rd Edition    11.12 */
566 static HRESULT compile_conditional_expression(compiler_ctx_t *ctx, conditional_expression_t *expr)
567 {
568     unsigned jmp_false, jmp_end;
569     HRESULT hres;
570 
571     hres = compile_expression(ctx, expr->expression, TRUE);
572     if(FAILED(hres))
573         return hres;
574 
575     jmp_false = push_instr(ctx, OP_cnd_z);
576     if(!jmp_false)
577         return E_OUTOFMEMORY;
578 
579     hres = compile_expression(ctx, expr->true_expression, TRUE);
580     if(FAILED(hres))
581         return hres;
582 
583     jmp_end = push_instr(ctx, OP_jmp);
584     if(!jmp_end)
585         return E_OUTOFMEMORY;
586 
587     set_arg_uint(ctx, jmp_false, ctx->code_off);
588     hres = push_instr_uint(ctx, OP_pop, 1);
589     if(FAILED(hres))
590         return hres;
591 
592     hres = compile_expression(ctx, expr->false_expression, TRUE);
593     if(FAILED(hres))
594         return hres;
595 
596     set_arg_uint(ctx, jmp_end, ctx->code_off);
597     return S_OK;
598 }
599 
600 static HRESULT compile_new_expression(compiler_ctx_t *ctx, call_expression_t *expr)
601 {
602     unsigned arg_cnt = 0;
603     argument_t *arg;
604     HRESULT hres;
605 
606     hres = compile_expression(ctx, expr->expression, TRUE);
607     if(FAILED(hres))
608         return hres;
609 
610     for(arg = expr->argument_list; arg; arg = arg->next) {
611         hres = compile_expression(ctx, arg->expr, TRUE);
612         if(FAILED(hres))
613             return hres;
614         arg_cnt++;
615     }
616 
617     hres = push_instr_uint(ctx, OP_new, arg_cnt);
618     if(FAILED(hres))
619         return hres;
620 
621     hres = push_instr_uint(ctx, OP_pop, arg_cnt+1);
622     if(FAILED(hres))
623         return hres;
624 
625     return push_instr(ctx, OP_push_acc) ? S_OK : E_OUTOFMEMORY;
626 }
627 
628 static HRESULT compile_call_expression(compiler_ctx_t *ctx, call_expression_t *expr, BOOL emit_ret)
629 {
630     unsigned arg_cnt = 0, extra_args;
631     argument_t *arg;
632     unsigned instr;
633     jsop_t op;
634     HRESULT hres;
635 
636     if(is_memberid_expr(expr->expression->type)) {
637         op = OP_call_member;
638         extra_args = 2;
639         hres = compile_memberid_expression(ctx, expr->expression, 0);
640     }else {
641         op = OP_call;
642         extra_args = 1;
643         hres = compile_expression(ctx, expr->expression, TRUE);
644     }
645 
646     if(FAILED(hres))
647         return hres;
648 
649     for(arg = expr->argument_list; arg; arg = arg->next) {
650         hres = compile_expression(ctx, arg->expr, TRUE);
651         if(FAILED(hres))
652             return hres;
653         arg_cnt++;
654     }
655 
656     instr = push_instr(ctx, op);
657     if(!instr)
658         return E_OUTOFMEMORY;
659 
660     instr_ptr(ctx, instr)->u.arg[0].uint = arg_cnt;
661     instr_ptr(ctx, instr)->u.arg[1].lng = emit_ret;
662 
663     hres = push_instr_uint(ctx, OP_pop, arg_cnt + extra_args);
664     if(FAILED(hres))
665         return hres;
666 
667     return !emit_ret || push_instr(ctx, OP_push_acc) ? S_OK : E_OUTOFMEMORY;
668 }
669 
670 static HRESULT compile_delete_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
671 {
672     HRESULT hres;
673 
674     switch(expr->expression->type) {
675     case EXPR_ARRAY: {
676         binary_expression_t *array_expr = (binary_expression_t*)expr->expression;
677 
678         hres = compile_expression(ctx, array_expr->expression1, TRUE);
679         if(FAILED(hres))
680             return hres;
681 
682         hres = compile_expression(ctx, array_expr->expression2, TRUE);
683         if(FAILED(hres))
684             return hres;
685 
686         if(!push_instr(ctx, OP_delete))
687             return E_OUTOFMEMORY;
688         break;
689     }
690     case EXPR_MEMBER: {
691         member_expression_t *member_expr = (member_expression_t*)expr->expression;
692         jsstr_t *jsstr;
693 
694         hres = compile_expression(ctx, member_expr->expression, TRUE);
695         if(FAILED(hres))
696             return hres;
697 
698         /* FIXME: Potential optimization */
699         jsstr = compiler_alloc_string(ctx, member_expr->identifier);
700         if(!jsstr)
701             return E_OUTOFMEMORY;
702 
703         hres = push_instr_str(ctx, OP_str, jsstr);
704         if(FAILED(hres))
705             return hres;
706 
707         if(!push_instr(ctx, OP_delete))
708             return E_OUTOFMEMORY;
709         break;
710     }
711     case EXPR_IDENT:
712         return push_instr_bstr(ctx, OP_delete_ident, ((identifier_expression_t*)expr->expression)->identifier);
713     default: {
714         static const WCHAR fixmeW[] = {'F','I','X','M','E',0};
715 
716         WARN("invalid delete, unimplemented exception message\n");
717 
718         hres = compile_expression(ctx, expr->expression, TRUE);
719         if(FAILED(hres))
720             return hres;
721 
722         return push_instr_uint_str(ctx, OP_throw_type, JS_E_INVALID_DELETE, fixmeW);
723     }
724     }
725 
726     return S_OK;
727 }
728 
729 static HRESULT compile_assign_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
730 {
731     BOOL use_throw_path = FALSE;
732     unsigned arg_cnt = 0;
733     HRESULT hres;
734 
735     if(expr->expression1->type == EXPR_CALL) {
736         call_expression_t *call_expr = (call_expression_t*)expr->expression1;
737         argument_t *arg;
738 
739         if(is_memberid_expr(call_expr->expression->type) && call_expr->argument_list) {
740             hres = compile_memberid_expression(ctx, call_expr->expression, fdexNameEnsure);
741             if(FAILED(hres))
742                 return hres;
743 
744             for(arg = call_expr->argument_list; arg; arg = arg->next) {
745                 hres = compile_expression(ctx, arg->expr, TRUE);
746                 if(FAILED(hres))
747                     return hres;
748                 arg_cnt++;
749             }
750 
751             if(op != OP_LAST) {
752                 unsigned instr;
753 
754                 /* We need to call the functions twice: to get the value and to set it.
755                  * JavaScript interpreted functions may to modify value on the stack,
756                  * but assignment calls are allowed only on external functions, so we
757                  * may reuse the stack here. */
758                 instr = push_instr(ctx, OP_call_member);
759                 if(!instr)
760                     return E_OUTOFMEMORY;
761                 instr_ptr(ctx, instr)->u.arg[0].uint = arg_cnt;
762                 instr_ptr(ctx, instr)->u.arg[1].lng = 1;
763 
764                 if(!push_instr(ctx, OP_push_acc))
765                     return E_OUTOFMEMORY;
766             }
767         }else {
768             use_throw_path = TRUE;
769         }
770     }else if(is_memberid_expr(expr->expression1->type)) {
771         hres = compile_memberid_expression(ctx, expr->expression1, fdexNameEnsure);
772         if(FAILED(hres))
773             return hres;
774         if(op != OP_LAST && !push_instr(ctx, OP_refval))
775             return E_OUTOFMEMORY;
776     }else {
777         use_throw_path = TRUE;
778     }
779 
780     if(use_throw_path) {
781         /* Illegal assignment: evaluate and throw */
782         hres = compile_expression(ctx, expr->expression1, TRUE);
783         if(FAILED(hres))
784             return hres;
785 
786         hres = compile_expression(ctx, expr->expression2, TRUE);
787         if(FAILED(hres))
788             return hres;
789 
790         if(op != OP_LAST && !push_instr(ctx, op))
791             return E_OUTOFMEMORY;
792 
793         return push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
794     }
795 
796     hres = compile_expression(ctx, expr->expression2, TRUE);
797     if(FAILED(hres))
798         return hres;
799 
800     if(op != OP_LAST && !push_instr(ctx, op))
801         return E_OUTOFMEMORY;
802 
803     if(arg_cnt)
804         return push_instr_uint(ctx, OP_assign_call, arg_cnt);
805 
806     if(!push_instr(ctx, OP_assign))
807         return E_OUTOFMEMORY;
808 
809     return S_OK;
810 }
811 
812 static HRESULT compile_typeof_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
813 {
814     jsop_t op;
815     HRESULT hres;
816 
817     if(is_memberid_expr(expr->expression->type)) {
818         if(expr->expression->type == EXPR_IDENT)
819             return push_instr_bstr(ctx, OP_typeofident, ((identifier_expression_t*)expr->expression)->identifier);
820 
821         op = OP_typeofid;
822         hres = compile_memberid_expression(ctx, expr->expression, 0);
823     }else {
824         op = OP_typeof;
825         hres = compile_expression(ctx, expr->expression, TRUE);
826     }
827     if(FAILED(hres))
828         return hres;
829 
830     return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
831 }
832 
833 static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal)
834 {
835     switch(literal->type) {
836     case LT_BOOL:
837         return push_instr_int(ctx, OP_bool, literal->u.bval);
838     case LT_DOUBLE:
839         return push_instr_double(ctx, OP_double, literal->u.dval);
840     case LT_NULL:
841         return push_instr(ctx, OP_null) ? S_OK : E_OUTOFMEMORY;
842     case LT_STRING:
843         return push_instr_str(ctx, OP_str, literal->u.str);
844     case LT_REGEXP:
845         return push_instr_str_uint(ctx, OP_regexp, literal->u.regexp.str, literal->u.regexp.flags);
846     DEFAULT_UNREACHABLE;
847     }
848     return E_FAIL;
849 }
850 
851 static HRESULT literal_as_string(compiler_ctx_t *ctx, literal_t *literal, jsstr_t **str)
852 {
853     switch(literal->type) {
854     case LT_STRING:
855         *str = literal->u.str;
856         break;
857     case LT_DOUBLE:
858         return double_to_string(literal->u.dval, str);
859     DEFAULT_UNREACHABLE;
860     }
861 
862     return *str ? S_OK : E_OUTOFMEMORY;
863 }
864 
865 static HRESULT compile_array_literal(compiler_ctx_t *ctx, array_literal_expression_t *expr)
866 {
867     unsigned length = 0;
868     array_element_t *iter;
869     unsigned array_instr;
870     HRESULT hres;
871 
872     array_instr = push_instr(ctx, OP_carray);
873 
874     for(iter = expr->element_list; iter; iter = iter->next) {
875         length += iter->elision;
876 
877         hres = compile_expression(ctx, iter->expr, TRUE);
878         if(FAILED(hres))
879             return hres;
880 
881         hres = push_instr_uint(ctx, OP_carray_set, length);
882         if(FAILED(hres))
883             return hres;
884 
885         length++;
886     }
887 
888     instr_ptr(ctx, array_instr)->u.arg[0].uint = length + expr->length;
889     return S_OK;
890 }
891 
892 static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expression_t *expr)
893 {
894     property_definition_t *iter;
895     jsstr_t *name;
896     HRESULT hres;
897 
898     if(!push_instr(ctx, OP_new_obj))
899         return E_OUTOFMEMORY;
900 
901     for(iter = expr->property_list; iter; iter = iter->next) {
902         hres = literal_as_string(ctx, iter->name, &name);
903         if(FAILED(hres))
904             return hres;
905 
906         hres = compile_expression(ctx, iter->value, TRUE);
907         if(FAILED(hres))
908             return hres;
909 
910         hres = push_instr_str_uint(ctx, OP_obj_prop, name, iter->type);
911         if(FAILED(hres))
912             return hres;
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 && !wcscmp(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 && !wcscmp(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 && !wcscmp(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 wcscmp(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         property_definition_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(iswspace(*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(!iswalpha(*ptr) && *ptr != '_') {
2406             FIXME("expected alpha or '_': %s\n", debugstr_w(ptr));
2407             return E_FAIL;
2408         }
2409 
2410         ptr2 = ptr;
2411         while(iswalnum(*ptr) || *ptr == '_')
2412             ptr++;
2413 
2414         if(*ptr && *ptr != ',' && !iswspace(*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(iswspace(*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(iswspace(*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, 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