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