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