ReactOS 0.4.17-dev-357-ga8f14ff
compile.c
Go to the documentation of this file.
1/*
2 * Copyright 2011 Jacek Caban for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include <math.h>
20#include <assert.h>
21
22#include "jscript.h"
23#include "engine.h"
24#include "parser.h"
25
26#include "wine/rbtree.h"
27#include "wine/debug.h"
28
31
32typedef struct _statement_ctx_t {
33 unsigned stack_use;
36
37 unsigned break_label;
39
41
42 unsigned int scope_index;
47
48typedef struct {
51 int ref;
53
54typedef struct _compiler_ctx_t {
57
59
60 unsigned code_off;
61 unsigned code_size;
62
63 unsigned *labels;
64 unsigned labels_size;
65 unsigned labels_cnt;
66
67 struct
68 {
70 unsigned int locals_cnt;
71 unsigned int *ref_index;
72 }
76
79
80 unsigned loc;
81
85
88
89static const struct {
90 const char *op_str;
93} instr_info[] = {
94#define X(n,a,b,c) {#n,b,c},
96#undef X
97};
98
100{
101 switch(type) {
102 case ARG_STR:
103 TRACE_(jscript_disas)("\t%s", debugstr_jsstr(arg->str));
104 break;
105 case ARG_BSTR:
106 TRACE_(jscript_disas)("\t%s", debugstr_wn(arg->bstr, SysStringLen(arg->bstr)));
107 break;
108 case ARG_INT:
109 TRACE_(jscript_disas)("\t%d", arg->uint);
110 break;
111 case ARG_UINT:
112 case ARG_ADDR:
113 TRACE_(jscript_disas)("\t%u", arg->uint);
114 break;
115 case ARG_FUNC:
116 case ARG_NONE:
117 break;
119 }
120}
121
122static void dump_code(compiler_ctx_t *ctx, unsigned off)
123{
124 instr_t *instr;
125
126 for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->code_off; instr++) {
127 TRACE_(jscript_disas)("%d:\t%s", (int)(instr-ctx->code->instrs), instr_info[instr->op].op_str);
128 if(instr_info[instr->op].arg1_type == ARG_DBL) {
129 TRACE_(jscript_disas)("\t%lf", instr->u.dbl);
130 }else {
131 dump_instr_arg(instr_info[instr->op].arg1_type, instr->u.arg);
132 dump_instr_arg(instr_info[instr->op].arg2_type, instr->u.arg+1);
133 }
134 TRACE_(jscript_disas)("\n");
135 }
136}
137
140
141static int function_local_cmp(const void *key, const struct wine_rb_entry *entry)
142{
144 return wcscmp(key, local->name);
145}
146
147static BOOL alloc_local_scope(compiler_ctx_t *ctx, unsigned int *scope_index)
148{
149 unsigned int scope, new_size;
150 void *new_alloc;
151
152 scope = ctx->local_scope_count++;
153 if (scope == ctx->local_scope_size)
154 {
155 new_size = max(1, ctx->local_scope_size * 2);
156 if (!(new_alloc = realloc(ctx->local_scopes, new_size * sizeof(*ctx->local_scopes))))
157 return FALSE;
158 ctx->local_scopes = new_alloc;
159 ctx->local_scope_size = new_size;
160 }
161
162 ctx->local_scopes[scope].locals_cnt = 0;
163 ctx->local_scopes[scope].ref_index = scope_index;
164 wine_rb_init(&ctx->local_scopes[scope].locals, function_local_cmp);
165 *scope_index = scope;
166
167 return TRUE;
168}
169
170static void remove_local_scope(compiler_ctx_t *ctx, unsigned int scope_index)
171{
172 unsigned int i;
173
174 assert(scope_index < ctx->local_scope_count);
175 --ctx->local_scope_count;
176 assert(scope_index == *ctx->local_scopes[scope_index].ref_index);
177 *ctx->local_scopes[scope_index].ref_index = 0;
178 memmove(&ctx->local_scopes[scope_index], &ctx->local_scopes[scope_index + 1],
179 sizeof(*ctx->local_scopes) * (ctx->local_scope_count - scope_index));
180 for (i = scope_index; i < ctx->local_scope_count; ++i)
181 --*ctx->local_scopes[i].ref_index;
182}
183
184static inline void *compiler_alloc(bytecode_t *code, size_t size)
185{
186 return heap_pool_alloc(&code->heap, size);
187}
188
190{
191 jsstr_t *new_str;
192
193 if(!ctx->code->str_pool_size) {
194 ctx->code->str_pool = malloc(8 * sizeof(jsstr_t*));
195 if(!ctx->code->str_pool)
196 return NULL;
197 ctx->code->str_pool_size = 8;
198 }else if(ctx->code->str_pool_size == ctx->code->str_cnt) {
199 jsstr_t **new_pool;
200
201 new_pool = realloc(ctx->code->str_pool, ctx->code->str_pool_size*2*sizeof(jsstr_t*));
202 if(!new_pool)
203 return NULL;
204
205 ctx->code->str_pool = new_pool;
206 ctx->code->str_pool_size *= 2;
207 }
208
209 new_str = jsstr_alloc_len(str, len);
210 if(!new_str)
211 return NULL;
212
213 ctx->code->str_pool[ctx->code->str_cnt++] = new_str;
214 return new_str;
215}
216
218{
220}
221
223{
224 if(!ctx->code->bstr_pool_size) {
225 ctx->code->bstr_pool = malloc(8 * sizeof(BSTR));
226 if(!ctx->code->bstr_pool)
227 return FALSE;
228 ctx->code->bstr_pool_size = 8;
229 }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) {
230 BSTR *new_pool;
231
232 new_pool = realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR));
233 if(!new_pool)
234 return FALSE;
235
236 ctx->code->bstr_pool = new_pool;
237 ctx->code->bstr_pool_size *= 2;
238 }
239
240 return TRUE;
241}
242
244{
246 return NULL;
247
248 ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocString(str);
249 if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
250 return NULL;
251
252 return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
253}
254
256{
258 return NULL;
259
260 ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocStringLen(str, len);
261 if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
262 return NULL;
263
264 return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
265}
266
268{
269 ctx->loc = loc;
270}
271
273{
274 assert(ctx->code_size >= ctx->code_off);
275
276 if(ctx->code_size == ctx->code_off) {
277 instr_t *new_instrs;
278
279 new_instrs = realloc(ctx->code->instrs, ctx->code_size*2*sizeof(instr_t));
280 if(!new_instrs)
281 return 0;
282
283 ctx->code->instrs = new_instrs;
284 ctx->code_size *= 2;
285 }
286
287 ctx->code->instrs[ctx->code_off].op = op;
288 ctx->code->instrs[ctx->code_off].loc = ctx->loc;
289 return ctx->code_off++;
290}
291
292static inline instr_t *instr_ptr(compiler_ctx_t *ctx, unsigned off)
293{
294 assert(off < ctx->code_off);
295 return ctx->code->instrs + off;
296}
297
299{
300 unsigned instr;
301
302 instr = push_instr(ctx, op);
303 if(!instr)
304 return E_OUTOFMEMORY;
305
306 instr_ptr(ctx, instr)->u.arg->lng = arg;
307 return S_OK;
308}
309
311{
312 unsigned instr;
313
314 instr = push_instr(ctx, op);
315 if(!instr)
316 return E_OUTOFMEMORY;
317
318 instr_ptr(ctx, instr)->u.arg->str = str;
319 return S_OK;
320}
321
323{
324 unsigned instr;
325
326 instr = push_instr(ctx, op);
327 if(!instr)
328 return E_OUTOFMEMORY;
329
330 instr_ptr(ctx, instr)->u.arg[0].str = str;
331 instr_ptr(ctx, instr)->u.arg[1].uint = arg2;
332 return S_OK;
333}
334
336{
337 unsigned instr;
338 WCHAR *str;
339
341 if(!str)
342 return E_OUTOFMEMORY;
343
344 instr = push_instr(ctx, op);
345 if(!instr)
346 return E_OUTOFMEMORY;
347
348 instr_ptr(ctx, instr)->u.arg->bstr = str;
349 return S_OK;
350}
351
353{
354 unsigned instr;
355 WCHAR *str;
356
358 if(!str)
359 return E_OUTOFMEMORY;
360
361 instr = push_instr(ctx, op);
362 if(!instr)
363 return E_OUTOFMEMORY;
364
365 instr_ptr(ctx, instr)->u.arg[0].bstr = str;
366 instr_ptr(ctx, instr)->u.arg[1].uint = arg2;
367 return S_OK;
368}
369
371{
372 unsigned instr;
373 jsstr_t *str;
374
376 if(!str)
377 return E_OUTOFMEMORY;
378
379 instr = push_instr(ctx, op);
380 if(!instr)
381 return E_OUTOFMEMORY;
382
383 instr_ptr(ctx, instr)->u.arg[0].uint = arg1;
384 instr_ptr(ctx, instr)->u.arg[1].str = str;
385 return S_OK;
386}
387
389{
390 unsigned instr;
391
392 instr = push_instr(ctx, op);
393 if(!instr)
394 return E_OUTOFMEMORY;
395
396 instr_ptr(ctx, instr)->u.dbl = arg;
397 return S_OK;
398}
399
400static inline void set_arg_uint(compiler_ctx_t *ctx, unsigned instr, unsigned arg)
401{
402 instr_ptr(ctx, instr)->u.arg->uint = arg;
403}
404
406{
407 unsigned instr;
408
409 instr = push_instr(ctx, op);
410 if(!instr)
411 return E_OUTOFMEMORY;
412
413 set_arg_uint(ctx, instr, arg);
414 return S_OK;
415}
416
418{
420
421 hres = compile_expression(ctx, expr->expression1, TRUE);
422 if(FAILED(hres))
423 return hres;
424
425 hres = compile_expression(ctx, expr->expression2, TRUE);
426 if(FAILED(hres))
427 return hres;
428
429 return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
430}
431
433{
435
436 hres = compile_expression(ctx, expr->expression, TRUE);
437 if(FAILED(hres))
438 return hres;
439
440 return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
441}
442
443/* ECMA-262 3rd Edition 11.2.1 */
445{
447
448 hres = compile_expression(ctx, expr->expression, TRUE);
449 if(FAILED(hres))
450 return hres;
451
452 return push_instr_bstr(ctx, OP_member, expr->identifier);
453}
454
455#define LABEL_FLAG 0x80000000
456
458{
459 if(!ctx->labels_size) {
460 ctx->labels = malloc(8 * sizeof(*ctx->labels));
461 if(!ctx->labels)
462 return 0;
463 ctx->labels_size = 8;
464 }else if(ctx->labels_size == ctx->labels_cnt) {
465 unsigned *new_labels;
466
467 new_labels = realloc(ctx->labels, 2*ctx->labels_size*sizeof(*ctx->labels));
468 if(!new_labels)
469 return 0;
470
471 ctx->labels = new_labels;
472 ctx->labels_size *= 2;
473 }
474
475 return ctx->labels_cnt++ | LABEL_FLAG;
476}
477
478static void label_set_addr(compiler_ctx_t *ctx, unsigned label)
479{
481 ctx->labels[label & ~LABEL_FLAG] = ctx->code_off;
482}
483
485{
486 return type == EXPR_IDENT || type == EXPR_MEMBER || type == EXPR_ARRAY;
487}
488
489static BOOL bind_local(compiler_ctx_t *ctx, const WCHAR *identifier, int *ret_ref)
490{
491 statement_ctx_t *iter;
493
494 for(iter = ctx->stat_ctx; iter; iter = iter->next) {
495 if(iter->using_scope)
496 {
497 if (!iter->block_scope)
498 return FALSE;
499
500 if ((ref = lookup_local(ctx->func, identifier, iter->scope_index)))
501 {
502 *ret_ref = ref->ref;
503 return TRUE;
504 }
505 }
506 }
507
508 ref = lookup_local(ctx->func, identifier, 0);
509 if(!ref)
510 return FALSE;
511
512 *ret_ref = ref->ref;
513 return TRUE;
514}
515
516static HRESULT emit_identifier_ref(compiler_ctx_t *ctx, const WCHAR *identifier, unsigned flags)
517{
518 int local_ref;
519 if(bind_local(ctx, identifier, &local_ref))
520 return push_instr_int(ctx, OP_local_ref, local_ref);
521 return push_instr_bstr_uint(ctx, OP_identid, identifier, flags);
522}
523
524static HRESULT emit_identifier(compiler_ctx_t *ctx, const WCHAR *identifier)
525{
526 int local_ref;
527 if(bind_local(ctx, identifier, &local_ref))
528 return push_instr_int(ctx, OP_local, local_ref);
529 return push_instr_bstr(ctx, OP_ident, identifier);
530}
531
533{
535
536 if(expr->type == EXPR_ARRAY) {
538
539 hres = compile_expression(ctx, array_expr->expression1, TRUE);
540 if(FAILED(hres))
541 return hres;
542
543 hres = compile_expression(ctx, array_expr->expression2, TRUE);
544 if(FAILED(hres))
545 return hres;
546
547 if(!push_instr(ctx, OP_to_string))
548 return E_OUTOFMEMORY;
549 }else {
551 jsstr_t *jsstr;
552
554
555 hres = compile_expression(ctx, member_expr->expression, TRUE);
556 if(FAILED(hres))
557 return hres;
558
559 jsstr = compiler_alloc_string(ctx, member_expr->identifier);
560 if(!jsstr)
561 return E_OUTOFMEMORY;
562
563 hres = push_instr_str(ctx, OP_str, jsstr);
564 if(FAILED(hres))
565 return hres;
566 }
567
568 return S_OK;
569}
570
572{
573 if (stat_ctx)
574 {
575 stat_ctx->next = ctx->stat_ctx;
576 ctx->stat_ctx = stat_ctx;
577 }
578}
579
581{
582 if (stat_ctx)
583 {
584 assert(ctx->stat_ctx == stat_ctx);
585 ctx->stat_ctx = stat_ctx->next;
586 }
587}
588
590{
592
593 if(expr->type == EXPR_IDENT) {
595 return emit_identifier_ref(ctx, ident_expr->identifier, flags);
596 }
597
599 if(FAILED(hres))
600 return hres;
601
602 return push_instr_uint(ctx, OP_memberid, flags);
603}
604
606{
608
609 if(!is_memberid_expr(expr->expression->type)) {
610 hres = compile_expression(ctx, expr->expression, TRUE);
611 if(FAILED(hres))
612 return hres;
613
614 return push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
615 }
616
617 hres = compile_memberid_expression(ctx, expr->expression, fdexNameEnsure);
618 if(FAILED(hres))
619 return hres;
620
621 return push_instr_int(ctx, op, n);
622}
623
624/* ECMA-262 3rd Edition 11.14 */
626{
628
629 hres = compile_expression(ctx, expr->expression1, FALSE);
630 if(FAILED(hres))
631 return hres;
632
633 return compile_expression(ctx, expr->expression2, emit_ret);
634}
635
636/* ECMA-262 3rd Edition 11.11 */
638{
639 unsigned instr;
641
642 hres = compile_expression(ctx, expr->expression1, TRUE);
643 if(FAILED(hres))
644 return hres;
645
646 instr = push_instr(ctx, op);
647 if(!instr)
648 return E_OUTOFMEMORY;
649
650 hres = compile_expression(ctx, expr->expression2, TRUE);
651 if(FAILED(hres))
652 return hres;
653
654 set_arg_uint(ctx, instr, ctx->code_off);
655 return S_OK;
656}
657
658/* ECMA-262 3rd Edition 11.12 */
660{
661 unsigned jmp_false, jmp_end;
663
664 hres = compile_expression(ctx, expr->expression, TRUE);
665 if(FAILED(hres))
666 return hres;
667
668 jmp_false = push_instr(ctx, OP_cnd_z);
669 if(!jmp_false)
670 return E_OUTOFMEMORY;
671
672 hres = compile_expression(ctx, expr->true_expression, TRUE);
673 if(FAILED(hres))
674 return hres;
675
676 jmp_end = push_instr(ctx, OP_jmp);
677 if(!jmp_end)
678 return E_OUTOFMEMORY;
679
680 set_arg_uint(ctx, jmp_false, ctx->code_off);
681 hres = push_instr_uint(ctx, OP_pop, 1);
682 if(FAILED(hres))
683 return hres;
684
685 hres = compile_expression(ctx, expr->false_expression, TRUE);
686 if(FAILED(hres))
687 return hres;
688
689 set_arg_uint(ctx, jmp_end, ctx->code_off);
690 return S_OK;
691}
692
694{
695 unsigned arg_cnt = 0;
698
699 hres = compile_expression(ctx, expr->expression, TRUE);
700 if(FAILED(hres))
701 return hres;
702
703 for(arg = expr->argument_list; arg; arg = arg->next) {
705 if(FAILED(hres))
706 return hres;
707 arg_cnt++;
708 }
709
710 hres = push_instr_uint(ctx, OP_new, arg_cnt);
711 if(FAILED(hres))
712 return hres;
713
714 hres = push_instr_uint(ctx, OP_pop, arg_cnt+1);
715 if(FAILED(hres))
716 return hres;
717
718 return push_instr(ctx, OP_push_acc) ? S_OK : E_OUTOFMEMORY;
719}
720
722{
723 unsigned arg_cnt = 0, extra_args = 0;
724 HRESULT hres = S_OK;
726 unsigned instr;
727 jsop_t op;
728
729 if(is_memberid_expr(expr->expression->type)) {
730 if(expr->expression->type == EXPR_IDENT && !wcscmp(((identifier_expression_t*)expr->expression)->identifier, L"eval"))
731 op = OP_call_eval;
732 else {
733 op = OP_call_member;
734 extra_args = 2;
735 hres = compile_memberid_expression(ctx, expr->expression, 0);
736 }
737 }else {
738 op = OP_call;
739 extra_args = 1;
740 hres = compile_expression(ctx, expr->expression, TRUE);
741 }
742
743 if(FAILED(hres))
744 return hres;
745
746 for(arg = expr->argument_list; arg; arg = arg->next) {
748 if(FAILED(hres))
749 return hres;
750 arg_cnt++;
751 }
752
753 instr = push_instr(ctx, op);
754 if(!instr)
755 return E_OUTOFMEMORY;
756
757 instr_ptr(ctx, instr)->u.arg[0].uint = arg_cnt;
758 instr_ptr(ctx, instr)->u.arg[1].lng = emit_ret;
759
760 hres = push_instr_uint(ctx, OP_pop, arg_cnt + extra_args);
761 if(FAILED(hres))
762 return hres;
763
764 return !emit_ret || push_instr(ctx, OP_push_acc) ? S_OK : E_OUTOFMEMORY;
765}
766
768{
770
771 switch(expr->expression->type) {
772 case EXPR_ARRAY: {
773 binary_expression_t *array_expr = (binary_expression_t*)expr->expression;
774
775 hres = compile_expression(ctx, array_expr->expression1, TRUE);
776 if(FAILED(hres))
777 return hres;
778
779 hres = compile_expression(ctx, array_expr->expression2, TRUE);
780 if(FAILED(hres))
781 return hres;
782
783 if(!push_instr(ctx, OP_delete))
784 return E_OUTOFMEMORY;
785 break;
786 }
787 case EXPR_MEMBER: {
788 member_expression_t *member_expr = (member_expression_t*)expr->expression;
789 jsstr_t *jsstr;
790
791 hres = compile_expression(ctx, member_expr->expression, TRUE);
792 if(FAILED(hres))
793 return hres;
794
795 /* FIXME: Potential optimization */
796 jsstr = compiler_alloc_string(ctx, member_expr->identifier);
797 if(!jsstr)
798 return E_OUTOFMEMORY;
799
800 hres = push_instr_str(ctx, OP_str, jsstr);
801 if(FAILED(hres))
802 return hres;
803
804 if(!push_instr(ctx, OP_delete))
805 return E_OUTOFMEMORY;
806 break;
807 }
808 case EXPR_IDENT:
809 return push_instr_bstr(ctx, OP_delete_ident, ((identifier_expression_t*)expr->expression)->identifier);
810 default: {
811 WARN("invalid delete, unimplemented exception message\n");
812
813 hres = compile_expression(ctx, expr->expression, TRUE);
814 if(FAILED(hres))
815 return hres;
816
817 return push_instr_uint_str(ctx, OP_throw_type, JS_E_INVALID_DELETE, L"FIXME");
818 }
819 }
820
821 return S_OK;
822}
823
825{
826 jsop_t assign_op = OP_throw_ref;
827 unsigned arg_cnt = 0;
829
830 if(expr->expression1->type == EXPR_CALL) {
831 call_expression_t *call_expr = (call_expression_t*)expr->expression1;
833
834 if(is_memberid_expr(call_expr->expression->type) && call_expr->argument_list) {
835 hres = compile_memberid_expression(ctx, call_expr->expression, fdexNameEnsure);
836 if(FAILED(hres))
837 return hres;
838
839 for(arg = call_expr->argument_list; arg; arg = arg->next) {
841 if(FAILED(hres))
842 return hres;
843 arg_cnt++;
844 }
845
846 if(op != OP_LAST) {
847 unsigned instr;
848
849 /* We need to call the functions twice: to get the value and to set it.
850 * JavaScript interpreted functions may to modify value on the stack,
851 * but assignment calls are allowed only on external functions, so we
852 * may reuse the stack here. */
853 instr = push_instr(ctx, OP_call_member);
854 if(!instr)
855 return E_OUTOFMEMORY;
856 instr_ptr(ctx, instr)->u.arg[0].uint = arg_cnt;
857 instr_ptr(ctx, instr)->u.arg[1].lng = 1;
858
859 if(!push_instr(ctx, OP_push_acc))
860 return E_OUTOFMEMORY;
861 }
862 assign_op = OP_assign_call;
863 }
864 }else if(is_memberid_expr(expr->expression1->type)) {
865 if(op != OP_LAST || expr->expression1->type == EXPR_IDENT) {
866 hres = compile_memberid_expression(ctx, expr->expression1, fdexNameEnsure);
867 if(FAILED(hres))
868 return hres;
869 if(op != OP_LAST && !push_instr(ctx, OP_refval))
870 return E_OUTOFMEMORY;
871 assign_op = OP_assign;
872 }else {
873 hres = emit_member_expression(ctx, expr->expression1);
874 if(FAILED(hres))
875 return hres;
876 assign_op = OP_set_member;
877 }
878 }
879
880 if(assign_op == OP_throw_ref) {
881 /* Illegal assignment: evaluate and throw */
882 hres = compile_expression(ctx, expr->expression1, TRUE);
883 if(FAILED(hres))
884 return hres;
886 }
887
888 hres = compile_expression(ctx, expr->expression2, TRUE);
889 if(FAILED(hres))
890 return hres;
891
892 if(op != OP_LAST && !push_instr(ctx, op))
893 return E_OUTOFMEMORY;
894
895 return push_instr_uint(ctx, assign_op, arg_cnt);
896}
897
899{
900 jsop_t op;
902
903 if(is_memberid_expr(expr->expression->type)) {
904 if(expr->expression->type == EXPR_IDENT)
905 return push_instr_bstr(ctx, OP_typeofident, ((identifier_expression_t*)expr->expression)->identifier);
906
907 op = OP_typeofid;
908 hres = compile_memberid_expression(ctx, expr->expression, 0);
909 }else {
910 op = OP_typeof;
911 hres = compile_expression(ctx, expr->expression, TRUE);
912 }
913 if(FAILED(hres))
914 return hres;
915
916 return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
917}
918
920{
921 switch(literal->type) {
922 case LT_BOOL:
923 return push_instr_int(ctx, OP_bool, literal->u.bval);
924 case LT_DOUBLE:
925 return push_instr_double(ctx, OP_double, literal->u.dval);
926 case LT_NULL:
927 return push_instr(ctx, OP_null) ? S_OK : E_OUTOFMEMORY;
928 case LT_STRING:
929 return push_instr_str(ctx, OP_str, literal->u.str);
930 case LT_REGEXP:
931 return push_instr_str_uint(ctx, OP_regexp, literal->u.regexp.str, literal->u.regexp.flags);
933 }
934 return E_FAIL;
935}
936
938{
939 switch(literal->type) {
940 case LT_STRING:
941 *str = literal->u.str;
942 break;
943 case LT_DOUBLE:
944 return double_to_string(literal->u.dval, str);
946 }
947
948 return *str ? S_OK : E_OUTOFMEMORY;
949}
950
952{
953 unsigned length = 0;
954 array_element_t *iter;
955 unsigned array_instr;
957
958 array_instr = push_instr(ctx, OP_carray);
959
960 for(iter = expr->element_list; iter; iter = iter->next) {
961 length += iter->elision;
962
964 if(FAILED(hres))
965 return hres;
966
967 hres = push_instr_uint(ctx, OP_carray_set, length);
968 if(FAILED(hres))
969 return hres;
970
971 length++;
972 }
973
974 instr_ptr(ctx, array_instr)->u.arg[0].uint = length + expr->length;
975 return S_OK;
976}
977
979{
981 jsstr_t *name;
983
984 if(!push_instr(ctx, OP_new_obj))
985 return E_OUTOFMEMORY;
986
987 for(iter = expr->property_list; iter; iter = iter->next) {
988 hres = literal_as_string(ctx, iter->name, &name);
989 if(FAILED(hres))
990 return hres;
991
993 if(FAILED(hres))
994 return hres;
995
996 hres = push_instr_str_uint(ctx, OP_obj_prop, name, iter->type);
997 if(FAILED(hres))
998 return hres;
999 }
1000
1001 return S_OK;
1002}
1003
1005{
1006 statement_ctx_t *stat_ctx;
1007
1008 assert(ctx->current_function_expr);
1009
1010 for(stat_ctx = ctx->stat_ctx; stat_ctx; stat_ctx = stat_ctx->next)
1011 {
1012 if(stat_ctx->block_scope)
1013 break;
1014 }
1015 ctx->current_function_expr->scope_index = stat_ctx ? stat_ctx->scope_index : 0;
1016 ctx->current_function_expr = ctx->current_function_expr->next;
1017
1018 return emit_ret ? push_instr_uint(ctx, OP_func, expr->func_id) : S_OK;
1019}
1020
1022{
1023 HRESULT hres;
1024
1025 switch(expr->type) {
1026 case EXPR_ADD:
1028 break;
1029 case EXPR_AND:
1031 break;
1032 case EXPR_ARRAY:
1034 break;
1035 case EXPR_ARRAYLIT:
1037 break;
1038 case EXPR_ASSIGN:
1040 break;
1041 case EXPR_ASSIGNADD:
1043 break;
1044 case EXPR_ASSIGNAND:
1046 break;
1047 case EXPR_ASSIGNSUB:
1049 break;
1050 case EXPR_ASSIGNMUL:
1052 break;
1053 case EXPR_ASSIGNDIV:
1055 break;
1056 case EXPR_ASSIGNMOD:
1058 break;
1059 case EXPR_ASSIGNOR:
1061 break;
1062 case EXPR_ASSIGNLSHIFT:
1064 break;
1065 case EXPR_ASSIGNRSHIFT:
1067 break;
1068 case EXPR_ASSIGNRRSHIFT:
1070 break;
1071 case EXPR_ASSIGNXOR:
1073 break;
1074 case EXPR_BAND:
1076 break;
1077 case EXPR_BITNEG:
1079 break;
1080 case EXPR_BOR:
1082 break;
1083 case EXPR_CALL:
1085 case EXPR_COMMA:
1087 case EXPR_COND:
1089 break;
1090 case EXPR_DELETE:
1092 break;
1093 case EXPR_DIV:
1095 break;
1096 case EXPR_EQ:
1098 break;
1099 case EXPR_EQEQ:
1101 break;
1102 case EXPR_FUNC:
1104 case EXPR_GREATER:
1106 break;
1107 case EXPR_GREATEREQ:
1109 break;
1110 case EXPR_IDENT:
1112 break;
1113 case EXPR_IN:
1115 break;
1116 case EXPR_INSTANCEOF:
1118 break;
1119 case EXPR_LESS:
1121 break;
1122 case EXPR_LESSEQ:
1124 break;
1125 case EXPR_LITERAL:
1127 break;
1128 case EXPR_LOGNEG:
1130 break;
1131 case EXPR_LSHIFT:
1133 break;
1134 case EXPR_MEMBER:
1136 break;
1137 case EXPR_MINUS:
1139 break;
1140 case EXPR_MOD:
1142 break;
1143 case EXPR_MUL:
1145 break;
1146 case EXPR_NEW:
1148 break;
1149 case EXPR_NOTEQ:
1151 break;
1152 case EXPR_NOTEQEQ:
1154 break;
1155 case EXPR_OR:
1157 break;
1158 case EXPR_PLUS:
1160 break;
1161 case EXPR_POSTDEC:
1163 break;
1164 case EXPR_POSTINC:
1166 break;
1167 case EXPR_PREDEC:
1169 break;
1170 case EXPR_PREINC:
1172 break;
1173 case EXPR_PROPVAL:
1175 break;
1176 case EXPR_RSHIFT:
1178 break;
1179 case EXPR_RRSHIFT:
1181 break;
1182 case EXPR_SUB:
1184 break;
1185 case EXPR_THIS:
1186 return !emit_ret || push_instr(ctx, OP_this) ? S_OK : E_OUTOFMEMORY;
1187 case EXPR_TYPEOF:
1189 break;
1190 case EXPR_VOID:
1192 break;
1193 case EXPR_BXOR:
1195 break;
1197 }
1198
1199 if(FAILED(hres))
1200 return hres;
1201
1202 return emit_ret ? S_OK : push_instr_uint(ctx, OP_pop, 1);
1203}
1204
1206{
1207 return type == STAT_FOR || type == STAT_FORIN || type == STAT_WHILE;
1208}
1209
1210/* ECMA-262 3rd Edition 12.1 */
1212{
1213 statement_ctx_t stat_ctx = {0, TRUE};
1214 BOOL needs_scope;
1215 HRESULT hres;
1216
1217 needs_scope = block && block->scope_index;
1218 if (needs_scope)
1219 {
1220 if(FAILED(hres = push_instr_uint(ctx, OP_push_block_scope, block->scope_index)))
1221 return hres;
1222
1223 stat_ctx.scope_index = block->scope_index;
1224 stat_ctx.block_scope = TRUE;
1225 }
1226
1227 while(iter) {
1228 hres = compile_statement(ctx, needs_scope ? &stat_ctx : NULL, iter);
1229 if(FAILED(hres))
1230 return hres;
1231
1232 iter = iter->next;
1233 }
1234
1235 if(needs_scope && !push_instr(ctx, OP_pop_scope))
1236 return E_OUTOFMEMORY;
1237
1238 return S_OK;
1239}
1240
1241/* ECMA-262 3rd Edition 12.2 */
1243{
1245 HRESULT hres;
1246
1247 assert(list != NULL);
1248
1249 for(iter = list; iter; iter = iter->next) {
1250 if(!iter->expr)
1251 continue;
1252
1253 if (iter->constant)
1254 FIXME("Constant variables are not supported.\n");
1255
1257 if(FAILED(hres))
1258 return hres;
1259
1260 hres = compile_expression(ctx, iter->expr, TRUE);
1261 if(FAILED(hres))
1262 return hres;
1263
1264 if(!push_instr(ctx, OP_assign))
1265 return E_OUTOFMEMORY;
1266
1267 hres = push_instr_uint(ctx, OP_pop, 1);
1268 if(FAILED(hres))
1269 return hres;
1270 }
1271
1272 return S_OK;
1273}
1274
1275/* ECMA-262 3rd Edition 12.2 */
1277{
1278 return compile_variable_list(ctx, stat->variable_list);
1279}
1280
1281/* ECMA-262 3rd Edition 12.4 */
1283{
1284 HRESULT hres;
1285
1286 hres = compile_expression(ctx, stat->expr, ctx->from_eval);
1287 if(FAILED(hres))
1288 return hres;
1289
1290 return !ctx->from_eval || push_instr(ctx, OP_setret) ? S_OK : E_OUTOFMEMORY;
1291}
1292
1293/* ECMA-262 3rd Edition 12.5 */
1295{
1296 unsigned jmp_else;
1297 HRESULT hres;
1298
1299 hres = compile_expression(ctx, stat->expr, TRUE);
1300 if(FAILED(hres))
1301 return hres;
1302
1303 jmp_else = push_instr(ctx, OP_jmp_z);
1304 if(!jmp_else)
1305 return E_OUTOFMEMORY;
1306
1307 hres = compile_statement(ctx, NULL, stat->if_stat);
1308 if(FAILED(hres))
1309 return hres;
1310
1311 if(stat->else_stat) {
1312 unsigned jmp_end;
1313
1314 jmp_end = push_instr(ctx, OP_jmp);
1315 if(!jmp_end)
1316 return E_OUTOFMEMORY;
1317
1318 set_arg_uint(ctx, jmp_else, ctx->code_off);
1319
1320 hres = compile_statement(ctx, NULL, stat->else_stat);
1321 if(FAILED(hres))
1322 return hres;
1323
1324 set_arg_uint(ctx, jmp_end, ctx->code_off);
1325 }else {
1326 set_arg_uint(ctx, jmp_else, ctx->code_off);
1327 }
1328
1329 return S_OK;
1330}
1331
1332/* ECMA-262 3rd Edition 12.6.2 */
1334{
1335 statement_ctx_t stat_ctx = {0, FALSE, FALSE};
1336 unsigned jmp_off;
1337 HRESULT hres;
1338
1339 stat_ctx.break_label = alloc_label(ctx);
1340 if(!stat_ctx.break_label)
1341 return E_OUTOFMEMORY;
1342
1343 stat_ctx.continue_label = alloc_label(ctx);
1344 if(!stat_ctx.continue_label)
1345 return E_OUTOFMEMORY;
1346
1347 jmp_off = ctx->code_off;
1348
1349 if(!stat->do_while) {
1351 hres = compile_expression(ctx, stat->expr, TRUE);
1352 if(FAILED(hres))
1353 return hres;
1354
1355 hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1356 if(FAILED(hres))
1357 return hres;
1358 }
1359
1360 hres = compile_statement(ctx, &stat_ctx, stat->statement);
1361 if(FAILED(hres))
1362 return hres;
1363
1364 set_compiler_loc(ctx, stat->stat.loc);
1365 if(stat->do_while) {
1367 hres = compile_expression(ctx, stat->expr, TRUE);
1368 if(FAILED(hres))
1369 return hres;
1370
1371 hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1372 if(FAILED(hres))
1373 return hres;
1374 }
1375
1376 hres = push_instr_uint(ctx, OP_jmp, jmp_off);
1377 if(FAILED(hres))
1378 return hres;
1379
1380 label_set_addr(ctx, stat_ctx.break_label);
1381 return S_OK;
1382}
1383
1384/* ECMA-262 10th Edition 13.7.4 */
1386{
1387 statement_ctx_t stat_ctx = {0, FALSE, FALSE};
1388 statement_ctx_t scope_stat_ctx = {0, TRUE};
1389 unsigned expr_off;
1390 HRESULT hres;
1391
1392 if (stat->scope_index)
1393 {
1394 if(FAILED(hres = push_instr_uint(ctx, OP_push_block_scope, stat->scope_index)))
1395 return hres;
1396
1397 scope_stat_ctx.scope_index = stat->scope_index;
1398 scope_stat_ctx.block_scope = TRUE;
1399 push_compiler_statement_ctx(ctx, &scope_stat_ctx);
1400 }
1401
1402 if(stat->variable_list) {
1403 hres = compile_variable_list(ctx, stat->variable_list);
1404 if(FAILED(hres))
1405 goto done;
1406 }else if(stat->begin_expr) {
1407 hres = compile_expression(ctx, stat->begin_expr, FALSE);
1408 if(FAILED(hres))
1409 goto done;
1410 }
1411
1412 stat_ctx.break_label = alloc_label(ctx);
1413 if(!stat_ctx.break_label)
1414 {
1416 goto done;
1417 }
1418
1419 stat_ctx.continue_label = alloc_label(ctx);
1420 if(!stat_ctx.continue_label)
1421 {
1423 goto done;
1424 }
1425 expr_off = ctx->code_off;
1426
1427 if(stat->expr) {
1428 set_compiler_loc(ctx, stat->expr_loc);
1429 hres = compile_expression(ctx, stat->expr, TRUE);
1430 if(FAILED(hres))
1431 goto done;
1432
1433 hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
1434 if(FAILED(hres))
1435 goto done;
1436 }
1437
1438 hres = compile_statement(ctx, &stat_ctx, stat->statement);
1439 if(FAILED(hres))
1440 goto done;
1441
1443
1444 if(stat->end_expr) {
1445 set_compiler_loc(ctx, stat->end_loc);
1446 hres = compile_expression(ctx, stat->end_expr, FALSE);
1447 if(FAILED(hres))
1448 goto done;
1449 }
1450
1451 hres = push_instr_uint(ctx, OP_jmp, expr_off);
1452 if(FAILED(hres))
1453 goto done;
1454
1455 label_set_addr(ctx, stat_ctx.break_label);
1456 hres = S_OK;
1457done:
1458 if (stat->scope_index)
1459 {
1460 pop_compiler_statement_ctx(ctx, &scope_stat_ctx);
1461 if(SUCCEEDED(hres) && !push_instr(ctx, OP_pop_scope))
1462 return E_OUTOFMEMORY;
1463 }
1464 return hres;
1465}
1466
1467/* ECMA-262 3rd Edition 12.6.4 */
1469{
1470 statement_ctx_t stat_ctx = {4, FALSE, FALSE};
1471 HRESULT hres;
1472
1473 if(stat->variable) {
1474 hres = compile_variable_list(ctx, stat->variable);
1475 if(FAILED(hres))
1476 return hres;
1477 }
1478
1479 stat_ctx.break_label = alloc_label(ctx);
1480 if(!stat_ctx.break_label)
1481 return E_OUTOFMEMORY;
1482
1483 stat_ctx.continue_label = alloc_label(ctx);
1484 if(!stat_ctx.continue_label)
1485 return E_OUTOFMEMORY;
1486
1487 hres = compile_expression(ctx, stat->in_expr, TRUE);
1488 if(FAILED(hres))
1489 return hres;
1490
1491 if(stat->variable) {
1492 hres = emit_identifier_ref(ctx, stat->variable->identifier, fdexNameEnsure);
1493 if(FAILED(hres))
1494 return hres;
1495 }else if(is_memberid_expr(stat->expr->type)) {
1496 hres = compile_memberid_expression(ctx, stat->expr, fdexNameEnsure);
1497 if(FAILED(hres))
1498 return hres;
1499 }else {
1500 hres = push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
1501 if(FAILED(hres))
1502 return hres;
1503
1504 /* FIXME: compile statement anyways when we depend on compiler to check errors */
1505 return S_OK;
1506 }
1507
1508 hres = push_instr_int(ctx, OP_int, DISPID_STARTENUM);
1509 if(FAILED(hres))
1510 return hres;
1511
1513 hres = push_instr_uint(ctx, OP_forin, stat_ctx.break_label);
1514 if(FAILED(hres))
1515 return E_OUTOFMEMORY;
1516
1517 hres = compile_statement(ctx, &stat_ctx, stat->statement);
1518 if(FAILED(hres))
1519 return hres;
1520
1521 hres = push_instr_uint(ctx, OP_jmp, stat_ctx.continue_label);
1522 if(FAILED(hres))
1523 return hres;
1524
1525 label_set_addr(ctx, stat_ctx.break_label);
1526 return S_OK;
1527}
1528
1530{
1531 unsigned stack_pop = 0;
1532 statement_ctx_t *iter;
1533 HRESULT hres;
1534
1535 for(iter = ctx->stat_ctx; iter != stat_ctx; iter = iter->next) {
1536 if(iter->using_scope && !push_instr(ctx, OP_pop_scope))
1537 return E_OUTOFMEMORY;
1538 if(iter->using_except) {
1539 if(stack_pop) {
1540 hres = push_instr_uint(ctx, OP_pop, stack_pop);
1541 if(FAILED(hres))
1542 return hres;
1543 stack_pop = 0;
1544 }
1545 hres = push_instr_uint(ctx, OP_pop_except, ctx->code_off+1);
1546 if(FAILED(hres))
1547 return hres;
1548 }
1549 stack_pop += iter->stack_use;
1550 }
1551
1552 if(stack_pop) {
1553 hres = push_instr_uint(ctx, OP_pop, stack_pop);
1554 if(FAILED(hres))
1555 return hres;
1556 }
1557
1558 return S_OK;
1559}
1560
1561/* ECMA-262 3rd Edition 12.7 */
1563{
1564 statement_ctx_t *pop_ctx;
1565 HRESULT hres;
1566
1567 if(stat->identifier) {
1568 statement_t *label_stat;
1569 statement_ctx_t *iter;
1570
1571 pop_ctx = NULL;
1572
1573 for(iter = ctx->stat_ctx; iter; iter = iter->next) {
1574 if(iter->continue_label)
1575 pop_ctx = iter;
1576 if(iter->labelled_stat && !wcscmp(iter->labelled_stat->identifier, stat->identifier))
1577 break;
1578 }
1579
1580 if(!iter) {
1581 WARN("Label not found\n");
1582 return JS_E_LABEL_NOT_FOUND;
1583 }
1584
1585 /* Labelled continue are allowed only on loops */
1586 for(label_stat = iter->labelled_stat->statement;
1587 label_stat->type == STAT_LABEL;
1588 label_stat = ((labelled_statement_t*)label_stat)->statement);
1589 if(!is_loop_statement(label_stat->type)) {
1590 WARN("Label is not a loop\n");
1591 return JS_E_INVALID_CONTINUE;
1592 }
1593
1594 assert(pop_ctx != NULL);
1595 }else {
1596 for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
1597 if(pop_ctx->continue_label)
1598 break;
1599 }
1600
1601 if(!pop_ctx) {
1602 WARN("continue outside loop\n");
1603 return JS_E_INVALID_CONTINUE;
1604 }
1605 }
1606
1607 hres = pop_to_stat(ctx, pop_ctx);
1608 if(FAILED(hres))
1609 return hres;
1610
1611 return push_instr_uint(ctx, OP_jmp, pop_ctx->continue_label);
1612}
1613
1614/* ECMA-262 3rd Edition 12.8 */
1616{
1617 statement_ctx_t *pop_ctx;
1618 HRESULT hres;
1619
1620 if(stat->identifier) {
1621 for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
1622 if(pop_ctx->labelled_stat && !wcscmp(pop_ctx->labelled_stat->identifier, stat->identifier)) {
1623 assert(pop_ctx->break_label);
1624 break;
1625 }
1626 }
1627
1628 if(!pop_ctx) {
1629 WARN("Label not found\n");
1630 return JS_E_LABEL_NOT_FOUND;
1631 }
1632 }else {
1633 for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
1634 if(pop_ctx->break_label && !pop_ctx->labelled_stat)
1635 break;
1636 }
1637
1638 if(!pop_ctx) {
1639 WARN("Break outside loop\n");
1640 return JS_E_INVALID_BREAK;
1641 }
1642 }
1643
1644 hres = pop_to_stat(ctx, pop_ctx->next);
1645 if(FAILED(hres))
1646 return hres;
1647
1648 return push_instr_uint(ctx, OP_jmp, pop_ctx->break_label);
1649}
1650
1651/* ECMA-262 3rd Edition 12.9 */
1653{
1654 HRESULT hres;
1655
1656 if(ctx->from_eval) {
1657 WARN("misplaced return statement\n");
1658 return JS_E_MISPLACED_RETURN;
1659 }
1660
1661 if(stat->expr) {
1662 hres = compile_expression(ctx, stat->expr, TRUE);
1663 if(FAILED(hres))
1664 return hres;
1665 if(!push_instr(ctx, OP_setret))
1666 return E_OUTOFMEMORY;
1667 }
1668
1670 if(FAILED(hres))
1671 return hres;
1672
1673 return push_instr_uint(ctx, OP_ret, !stat->expr);
1674}
1675
1676/* ECMA-262 3rd Edition 12.10 */
1678{
1679 statement_ctx_t stat_ctx = {0, TRUE, FALSE};
1680 HRESULT hres;
1681
1682 hres = compile_expression(ctx, stat->expr, TRUE);
1683 if(FAILED(hres))
1684 return hres;
1685
1686 if(!push_instr(ctx, OP_push_with_scope))
1687 return E_OUTOFMEMORY;
1688
1689 hres = compile_statement(ctx, &stat_ctx, stat->statement);
1690 if(FAILED(hres))
1691 return hres;
1692
1693 if(!push_instr(ctx, OP_pop_scope))
1694 return E_OUTOFMEMORY;
1695
1696 return S_OK;
1697}
1698
1699/* ECMA-262 3rd Edition 12.10 */
1701{
1702 statement_ctx_t stat_ctx = {0, FALSE, FALSE, 0, 0, stat}, *iter;
1703 HRESULT hres;
1704
1705 for(iter = ctx->stat_ctx; iter; iter = iter->next) {
1706 if(iter->labelled_stat && !wcscmp(iter->labelled_stat->identifier, stat->identifier)) {
1707 WARN("Label %s redefined\n", debugstr_w(stat->identifier));
1708 return JS_E_LABEL_REDEFINED;
1709 }
1710 }
1711
1712 /* Labelled breaks are allowed for any labelled statements, not only loops (violating spec) */
1713 stat_ctx.break_label = alloc_label(ctx);
1714 if(!stat_ctx.break_label)
1715 return E_OUTOFMEMORY;
1716
1717 hres = compile_statement(ctx, &stat_ctx, stat->statement);
1718 if(FAILED(hres))
1719 return hres;
1720
1721 label_set_addr(ctx, stat_ctx.break_label);
1722 return S_OK;
1723}
1724
1725/* ECMA-262 3rd Edition 12.13 */
1727{
1728 statement_ctx_t stat_ctx = {0, FALSE, FALSE};
1729 unsigned case_cnt = 0, *case_jmps, i, default_jmp;
1730 BOOL have_default = FALSE;
1731 statement_t *stat_iter;
1732 case_clausule_t *iter;
1733 HRESULT hres;
1734
1735 hres = compile_expression(ctx, stat->expr, TRUE);
1736 if(FAILED(hres))
1737 return hres;
1738
1739 stat_ctx.break_label = alloc_label(ctx);
1740 if(!stat_ctx.break_label)
1741 return E_OUTOFMEMORY;
1742
1743 for(iter = stat->case_list; iter; iter = iter->next) {
1744 if(iter->expr)
1745 case_cnt++;
1746 }
1747
1748 case_jmps = malloc(case_cnt * sizeof(*case_jmps));
1749 if(!case_jmps)
1750 return E_OUTOFMEMORY;
1751
1752 i = 0;
1753 for(iter = stat->case_list; iter; iter = iter->next) {
1754 if(!iter->expr) {
1755 have_default = TRUE;
1756 continue;
1757 }
1758
1759 set_compiler_loc(ctx, iter->loc);
1760 hres = compile_expression(ctx, iter->expr, TRUE);
1761 if(FAILED(hres))
1762 break;
1763
1764 case_jmps[i] = push_instr(ctx, OP_case);
1765 if(!case_jmps[i]) {
1767 break;
1768 }
1769 i++;
1770 }
1771
1772 if(SUCCEEDED(hres)) {
1773 hres = push_instr_uint(ctx, OP_pop, 1);
1774 if(SUCCEEDED(hres)) {
1775 default_jmp = push_instr(ctx, OP_jmp);
1776 if(!default_jmp)
1778 }
1779 }
1780
1781 if(FAILED(hres)) {
1782 free(case_jmps);
1783 return hres;
1784 }
1785
1786 i = 0;
1787 for(iter = stat->case_list; iter; iter = iter->next) {
1788 while(iter->next && iter->next->stat == iter->stat) {
1789 set_arg_uint(ctx, iter->expr ? case_jmps[i++] : default_jmp, ctx->code_off);
1790 iter = iter->next;
1791 }
1792
1793 set_arg_uint(ctx, iter->expr ? case_jmps[i++] : default_jmp, ctx->code_off);
1794
1795 for(stat_iter = iter->stat; stat_iter && (!iter->next || iter->next->stat != stat_iter);
1796 stat_iter = stat_iter->next) {
1797 hres = compile_statement(ctx, &stat_ctx, stat_iter);
1798 if(FAILED(hres))
1799 break;
1800 }
1801 if(FAILED(hres))
1802 break;
1803 }
1804
1805 free(case_jmps);
1806 if(FAILED(hres))
1807 return hres;
1808 assert(i == case_cnt);
1809
1810 if(!have_default) {
1811 hres = push_instr_uint(ctx, OP_jmp, stat_ctx.break_label);
1812 if(FAILED(hres))
1813 return hres;
1814 set_arg_uint(ctx, default_jmp, ctx->code_off);
1815 }
1816
1817 label_set_addr(ctx, stat_ctx.break_label);
1818 return S_OK;
1819}
1820
1821/* ECMA-262 3rd Edition 12.13 */
1823{
1824 HRESULT hres;
1825
1826 hres = compile_expression(ctx, stat->expr, TRUE);
1827 if(FAILED(hres))
1828 return hres;
1829
1830 return push_instr(ctx, OP_throw) ? S_OK : E_OUTOFMEMORY;
1831}
1832
1833/* ECMA-262 3rd Edition 12.14 */
1835{
1836 statement_ctx_t try_ctx = {0, FALSE, TRUE}, finally_ctx = {2, FALSE, FALSE};
1837 unsigned push_except, finally_off = 0, catch_off = 0, pop_except, catch_pop_except = 0;
1838 BSTR ident;
1839 HRESULT hres;
1840
1841 push_except = push_instr(ctx, OP_push_except);
1842 if(!push_except)
1843 return E_OUTOFMEMORY;
1844
1845 if(stat->catch_block) {
1846 ident = compiler_alloc_bstr(ctx, stat->catch_block->identifier);
1847 if(!ident)
1848 return E_OUTOFMEMORY;
1849 }else {
1850 ident = NULL;
1851 }
1852
1853 hres = compile_statement(ctx, &try_ctx, stat->try_statement);
1854 if(FAILED(hres))
1855 return hres;
1856
1857 pop_except = push_instr(ctx, OP_pop_except);
1858 if(!pop_except)
1859 return E_OUTOFMEMORY;
1860
1861 if(stat->catch_block) {
1862 statement_ctx_t catch_ctx = {0, TRUE, stat->finally_statement != NULL};
1863
1864 if(stat->finally_statement)
1865 catch_ctx.using_except = TRUE;
1866
1867 catch_off = ctx->code_off;
1868
1869 hres = push_instr_bstr(ctx, OP_enter_catch, ident);
1870 if(FAILED(hres))
1871 return hres;
1872
1873 hres = compile_statement(ctx, &catch_ctx, stat->catch_block->statement);
1874 if(FAILED(hres))
1875 return hres;
1876
1877 if(!push_instr(ctx, OP_pop_scope))
1878 return E_OUTOFMEMORY;
1879
1880 if(stat->finally_statement) {
1881 catch_pop_except = push_instr(ctx, OP_pop_except);
1882 if(!catch_pop_except)
1883 return E_OUTOFMEMORY;
1884 }
1885 }
1886
1887 if(stat->finally_statement) {
1888 /*
1889 * finally block expects two elements on the stack, which may be:
1890 * - (true, return_addr) set by OP_pop_except, OP_end_finally jumps back to passed address
1891 * - (false, exception_value) set when unwinding an exception, which OP_end_finally rethrows
1892 */
1893 finally_off = ctx->code_off;
1894 hres = compile_statement(ctx, &finally_ctx, stat->finally_statement);
1895 if(FAILED(hres))
1896 return hres;
1897
1898 set_compiler_loc(ctx, stat->finally_loc);
1899 if(!push_instr(ctx, OP_end_finally))
1900 return E_OUTOFMEMORY;
1901 }
1902
1903 instr_ptr(ctx, pop_except)->u.arg[0].uint = ctx->code_off;
1904 if(catch_pop_except)
1905 instr_ptr(ctx, catch_pop_except)->u.arg[0].uint = ctx->code_off;
1906 instr_ptr(ctx, push_except)->u.arg[0].uint = catch_off;
1907 instr_ptr(ctx, push_except)->u.arg[1].uint = finally_off;
1908 return S_OK;
1909}
1910
1912{
1913 HRESULT hres;
1914
1916
1917 set_compiler_loc(ctx, stat->loc);
1918
1919 switch(stat->type) {
1920 case STAT_BLOCK:
1922 break;
1923 case STAT_BREAK:
1925 break;
1926 case STAT_CONTINUE:
1928 break;
1929 case STAT_EMPTY:
1930 /* nothing to do */
1931 hres = S_OK;
1932 break;
1933 case STAT_EXPR:
1935 break;
1936 case STAT_FOR:
1938 break;
1939 case STAT_FORIN:
1941 break;
1942 case STAT_IF:
1944 break;
1945 case STAT_LABEL:
1947 break;
1948 case STAT_RETURN:
1950 break;
1951 case STAT_SWITCH:
1953 break;
1954 case STAT_THROW:
1956 break;
1957 case STAT_TRY:
1959 break;
1960 case STAT_VAR:
1962 break;
1963 case STAT_WHILE:
1965 break;
1966 case STAT_WITH:
1968 break;
1970 }
1971
1973
1974 return hres;
1975}
1976
1977static inline function_local_t *find_local(compiler_ctx_t *ctx, const WCHAR *name, unsigned int scope)
1978{
1979 struct wine_rb_entry *entry = wine_rb_get(&ctx->local_scopes[scope].locals, name);
1981}
1982
1983static BOOL alloc_local(compiler_ctx_t *ctx, BSTR name, int ref, unsigned int scope)
1984{
1986
1987 local = heap_pool_alloc(&ctx->heap, sizeof(*local));
1988 if(!local)
1989 return FALSE;
1990
1991 local->name = name;
1992 local->ref = ref;
1993 wine_rb_put(&ctx->local_scopes[scope].locals, name, &local->entry);
1994 ctx->local_scopes[scope].locals_cnt++;
1995 return TRUE;
1996}
1997
1998static BOOL alloc_variable(compiler_ctx_t *ctx, const WCHAR *name, unsigned int scope)
1999{
2000 BSTR ident;
2001
2002 if(find_local(ctx, name, scope))
2003 return TRUE;
2004
2006 if(!ident)
2007 return FALSE;
2008
2009 return alloc_local(ctx, ident, ctx->func->var_cnt++, scope);
2010}
2011
2013{
2014 statement_ctx_t *stat_ctx;
2015
2016 expr->func_id = ctx->func->func_cnt++;
2017 ctx->func_tail = ctx->func_tail ? (ctx->func_tail->next = expr) : (ctx->func_head = expr);
2018
2019 if(!expr->identifier || expr->event_target)
2020 return S_OK;
2021
2022 for (stat_ctx = ctx->stat_ctx; stat_ctx; stat_ctx = stat_ctx->next)
2023 {
2024 if (stat_ctx->block_scope)
2025 {
2026 stat_ctx->scope_has_functions = TRUE;
2027 break;
2028 }
2029 }
2030
2031 if(!expr->is_statement && ctx->parser->script->version >= SCRIPTLANGUAGEVERSION_ES5)
2032 return S_OK;
2033
2034 return alloc_variable(ctx, expr->identifier, stat_ctx ? stat_ctx->scope_index : 0) ? S_OK : E_OUTOFMEMORY;
2035}
2036
2038{
2039 HRESULT hres = S_OK;
2040
2041 switch(expr->type) {
2042 case EXPR_ADD:
2043 case EXPR_AND:
2044 case EXPR_ARRAY:
2045 case EXPR_ASSIGN:
2046 case EXPR_ASSIGNADD:
2047 case EXPR_ASSIGNAND:
2048 case EXPR_ASSIGNSUB:
2049 case EXPR_ASSIGNMUL:
2050 case EXPR_ASSIGNDIV:
2051 case EXPR_ASSIGNMOD:
2052 case EXPR_ASSIGNOR:
2053 case EXPR_ASSIGNLSHIFT:
2054 case EXPR_ASSIGNRSHIFT:
2055 case EXPR_ASSIGNRRSHIFT:
2056 case EXPR_ASSIGNXOR:
2057 case EXPR_BAND:
2058 case EXPR_BOR:
2059 case EXPR_COMMA:
2060 case EXPR_DIV:
2061 case EXPR_EQ:
2062 case EXPR_EQEQ:
2063 case EXPR_GREATER:
2064 case EXPR_GREATEREQ:
2065 case EXPR_IN:
2066 case EXPR_INSTANCEOF:
2067 case EXPR_LESS:
2068 case EXPR_LESSEQ:
2069 case EXPR_LSHIFT:
2070 case EXPR_MOD:
2071 case EXPR_MUL:
2072 case EXPR_NOTEQ:
2073 case EXPR_NOTEQEQ:
2074 case EXPR_OR:
2075 case EXPR_RSHIFT:
2076 case EXPR_RRSHIFT:
2077 case EXPR_SUB:
2078 case EXPR_BXOR: {
2080
2081 hres = visit_expression(ctx, binary_expr->expression1);
2082 if(FAILED(hres))
2083 return hres;
2084
2085 hres = visit_expression(ctx, binary_expr->expression2);
2086 break;
2087 }
2088 case EXPR_BITNEG:
2089 case EXPR_DELETE:
2090 case EXPR_LOGNEG:
2091 case EXPR_MINUS:
2092 case EXPR_PLUS:
2093 case EXPR_POSTDEC:
2094 case EXPR_POSTINC:
2095 case EXPR_PREDEC:
2096 case EXPR_PREINC:
2097 case EXPR_TYPEOF:
2098 case EXPR_VOID:
2099 hres = visit_expression(ctx, ((unary_expression_t*)expr)->expression);
2100 break;
2101 case EXPR_IDENT:
2102 case EXPR_LITERAL:
2103 case EXPR_THIS:
2104 break;
2105 case EXPR_ARRAYLIT: {
2107 array_element_t *iter;
2108
2109 for(iter = array_expr->element_list; iter; iter = iter->next) {
2110 hres = visit_expression(ctx, iter->expr);
2111 if(FAILED(hres))
2112 return hres;
2113 }
2114 break;
2115 }
2116 case EXPR_CALL:
2117 case EXPR_NEW: {
2119 argument_t *arg;
2120
2121 hres = visit_expression(ctx, call_expr->expression);
2122 if(FAILED(hres))
2123 return hres;
2124
2125 for(arg = call_expr->argument_list; arg; arg = arg->next) {
2126 hres = visit_expression(ctx, arg->expr);
2127 if(FAILED(hres))
2128 return hres;
2129 }
2130 break;
2131 }
2132 case EXPR_COND: {
2134
2135 hres = visit_expression(ctx, cond_expr->expression);
2136 if(FAILED(hres))
2137 return hres;
2138
2140 if(FAILED(hres))
2141 return hres;
2142
2144 break;
2145 }
2146 case EXPR_FUNC:
2148 break;
2149 case EXPR_MEMBER:
2150 hres = visit_expression(ctx, ((member_expression_t*)expr)->expression);
2151 break;
2152 case EXPR_PROPVAL: {
2154 for(iter = ((property_value_expression_t*)expr)->property_list; iter; iter = iter->next) {
2155 hres = visit_expression(ctx, iter->value);
2156 if(FAILED(hres))
2157 return hres;
2158 }
2159 break;
2160 }
2162 }
2163
2164 return hres;
2165}
2166
2168{
2170 statement_ctx_t *stat_ctx;
2171 HRESULT hres;
2172
2173 for(iter = list; iter; iter = iter->next) {
2174 for (stat_ctx = ctx->stat_ctx; stat_ctx; stat_ctx = stat_ctx->next)
2175 {
2176 if (stat_ctx->block_scope)
2177 break;
2178 }
2179
2180 if(!alloc_variable(ctx, iter->identifier, iter->block_scope && stat_ctx ? stat_ctx->scope_index : 0))
2181 return E_OUTOFMEMORY;
2182
2183 if(iter->expr) {
2184 hres = visit_expression(ctx, iter->expr);
2185 if(FAILED(hres))
2186 return hres;
2187 }
2188 }
2189
2190 return S_OK;
2191}
2192
2194
2196{
2197 statement_ctx_t stat_ctx = {0, TRUE};
2198 BOOL needs_scope;
2199 HRESULT hres;
2200
2201 needs_scope = block && ctx->parser->script->version >= SCRIPTLANGUAGEVERSION_ES5;
2202 if (needs_scope)
2203 {
2204 if (!alloc_local_scope(ctx, &block->scope_index))
2205 return E_OUTOFMEMORY;
2206
2207 stat_ctx.scope_index = block->scope_index;
2208 stat_ctx.block_scope = TRUE;
2209 }
2210
2211 while(iter) {
2212 hres = visit_statement(ctx, needs_scope ? &stat_ctx : NULL, iter);
2213 if(FAILED(hres))
2214 return hres;
2215
2216 iter = iter->next;
2217 }
2218
2219 if (needs_scope && !(ctx->local_scopes[stat_ctx.scope_index].locals_cnt || stat_ctx.scope_has_functions))
2220 remove_local_scope(ctx, block->scope_index);
2221
2222 return S_OK;
2223}
2224
2226{
2227 HRESULT hres = S_OK;
2228
2230
2231 switch(stat->type) {
2232 case STAT_BLOCK:
2234 break;
2235 case STAT_BREAK:
2236 case STAT_CONTINUE:
2237 case STAT_EMPTY:
2238 break;
2239 case STAT_EXPR: {
2241 if(expr_stat->expr) {
2242 if(expr_stat->expr->type == EXPR_FUNC)
2243 ((function_expression_t*)expr_stat->expr)->is_statement = TRUE;
2244 hres = visit_expression(ctx, expr_stat->expr);
2245 }
2246 break;
2247 }
2248 case STAT_RETURN:
2249 case STAT_THROW: {
2251 if(expr_stat->expr)
2252 hres = visit_expression(ctx, expr_stat->expr);
2253 break;
2254 }
2255 case STAT_FOR: {
2256 statement_ctx_t stat_ctx_data = {0, TRUE}, *stat_ctx = NULL;
2257 for_statement_t *for_stat = (for_statement_t*)stat;
2258
2259 if(for_stat->variable_list)
2260 {
2262
2263 for(var = for_stat->variable_list; var; var = var->next)
2264 {
2265 if (var->block_scope)
2266 {
2267 stat_ctx = &stat_ctx_data;
2268 break;
2269 }
2270 }
2271
2272 if (stat_ctx)
2273 {
2274 if (!alloc_local_scope(ctx, &for_stat->scope_index))
2275 {
2277 break;
2278 }
2279 stat_ctx->scope_index = for_stat->scope_index;
2280 stat_ctx->block_scope = TRUE;
2282 }
2284 }
2285 else if(for_stat->begin_expr)
2286 hres = visit_expression(ctx, for_stat->begin_expr);
2287 if(FAILED(hres))
2288 {
2290 break;
2291 }
2292
2293 if(for_stat->expr) {
2294 hres = visit_expression(ctx, for_stat->expr);
2295 if(FAILED(hres))
2296 {
2298 break;
2299 }
2300 }
2301
2302 hres = visit_statement(ctx, NULL, for_stat->statement);
2303 if(FAILED(hres))
2304 {
2306 break;
2307 }
2308 if(for_stat->end_expr)
2309 hres = visit_expression(ctx, for_stat->end_expr);
2311 break;
2312 }
2313 case STAT_FORIN: {
2315
2316 if(forin_stat->variable) {
2317 hres = visit_variable_list(ctx, forin_stat->variable);
2318 if(FAILED(hres))
2319 break;
2320 }
2321
2322 hres = visit_expression(ctx, forin_stat->in_expr);
2323 if(FAILED(hres))
2324 return hres;
2325
2326 if(forin_stat->expr) {
2327 hres = visit_expression(ctx, forin_stat->expr);
2328 if(FAILED(hres))
2329 return hres;
2330 }
2331
2332 hres = visit_statement(ctx, NULL, forin_stat->statement);
2333 break;
2334 }
2335 case STAT_IF: {
2336 if_statement_t *if_stat = (if_statement_t*)stat;
2337
2338 hres = visit_expression(ctx, if_stat->expr);
2339 if(FAILED(hres))
2340 return hres;
2341
2342 hres = visit_statement(ctx, NULL, if_stat->if_stat);
2343 if(FAILED(hres))
2344 return hres;
2345
2346 if(if_stat->else_stat)
2347 hres = visit_statement(ctx, NULL, if_stat->else_stat);
2348 break;
2349 }
2350 case STAT_LABEL:
2352 break;
2353 case STAT_SWITCH: {
2355 statement_t *stat_iter;
2356 case_clausule_t *iter;
2357
2358 hres = visit_expression(ctx, switch_stat->expr);
2359 if(FAILED(hres))
2360 return hres;
2361
2362 for(iter = switch_stat->case_list; iter; iter = iter->next) {
2363 if(!iter->expr)
2364 continue;
2365 hres = visit_expression(ctx, iter->expr);
2366 if(FAILED(hres))
2367 return hres;
2368 }
2369
2370 for(iter = switch_stat->case_list; iter; iter = iter->next) {
2371 while(iter->next && iter->next->stat == iter->stat)
2372 iter = iter->next;
2373 for(stat_iter = iter->stat; stat_iter && (!iter->next || iter->next->stat != stat_iter);
2374 stat_iter = stat_iter->next) {
2375 hres = visit_statement(ctx, NULL, stat_iter);
2376 if(FAILED(hres))
2377 return hres;
2378 }
2379 }
2380 break;
2381 }
2382 case STAT_TRY: {
2383 try_statement_t *try_stat = (try_statement_t*)stat;
2384
2385 hres = visit_statement(ctx, NULL, try_stat->try_statement);
2386 if(FAILED(hres))
2387 return hres;
2388
2389 if(try_stat->catch_block) {
2391 if(FAILED(hres))
2392 return hres;
2393 }
2394
2395 if(try_stat->finally_statement)
2397 break;
2398 }
2399 case STAT_VAR:
2400 hres = visit_variable_list(ctx, ((var_statement_t*)stat)->variable_list);
2401 break;
2402 case STAT_WHILE: {
2404
2405 hres = visit_expression(ctx, while_stat->expr);
2406 if(FAILED(hres))
2407 return hres;
2408
2409 hres = visit_statement(ctx, NULL, while_stat->statement);
2410 break;
2411 }
2412 case STAT_WITH: {
2413 with_statement_t *with_stat = (with_statement_t*)stat;
2414
2415 hres = visit_expression(ctx, with_stat->expr);
2416 if(FAILED(hres))
2417 return hres;
2418
2419 hres = visit_statement(ctx, NULL, with_stat->statement);
2420 break;
2421 }
2423 }
2424
2426
2427 return hres;
2428}
2429
2430static void resolve_labels(compiler_ctx_t *ctx, unsigned off)
2431{
2432 instr_t *instr;
2433
2434 for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->code_off; instr++) {
2435 if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->u.arg->uint & LABEL_FLAG)) {
2436 assert((instr->u.arg->uint & ~LABEL_FLAG) < ctx->labels_cnt);
2437 instr->u.arg->uint = ctx->labels[instr->u.arg->uint & ~LABEL_FLAG];
2438 }
2439 assert(instr_info[instr->op].arg2_type != ARG_ADDR);
2440 }
2441
2442 ctx->labels_cnt = 0;
2443}
2444
2445unsigned get_location_line(bytecode_t *code, unsigned loc, unsigned *char_pos)
2446{
2447 unsigned line = code->start_line;
2448 const WCHAR *nl, *p;
2449
2450 for(nl = p = code->source; p < code->source + loc; p++) {
2451 if(*p != '\n') continue;
2452 line++;
2453 nl = p + 1;
2454 }
2455 *char_pos = loc - (nl - code->source);
2456 return line;
2457}
2458
2460{
2461 unsigned i;
2462
2463 if(--code->ref)
2464 return;
2465
2466 for(i=0; i < code->bstr_cnt; i++)
2467 SysFreeString(code->bstr_pool[i]);
2468 for(i=0; i < code->str_cnt; i++)
2469 jsstr_release(code->str_pool[i]);
2470
2471 if(code->named_item)
2472 release_named_item(code->named_item);
2473 free(code->source);
2474 heap_pool_free(&code->heap);
2475 free(code->bstr_pool);
2476 free(code->str_pool);
2477 free(code->instrs);
2478 free(code);
2479}
2480
2481static HRESULT init_code(compiler_ctx_t *compiler, const WCHAR *source, UINT64 source_context, unsigned start_line)
2482{
2483 size_t len = source ? lstrlenW(source) : 0;
2484
2485 if(len > INT32_MAX)
2486 return E_OUTOFMEMORY;
2487
2488 compiler->code = calloc(1, sizeof(bytecode_t));
2489 if(!compiler->code)
2490 return E_OUTOFMEMORY;
2491
2492 compiler->code->ref = 1;
2493 compiler->code->source_context = source_context;
2494 compiler->code->start_line = start_line;
2495 heap_pool_init(&compiler->code->heap);
2496
2497 compiler->code->source = malloc((len + 1) * sizeof(WCHAR));
2498 if(!compiler->code->source) {
2499 release_bytecode(compiler->code);
2500 return E_OUTOFMEMORY;
2501 }
2502 if(len)
2503 memcpy(compiler->code->source, source, len * sizeof(WCHAR));
2504 compiler->code->source[len] = 0;
2505
2506 compiler->code->instrs = malloc(64 * sizeof(instr_t));
2507 if(!compiler->code->instrs) {
2508 release_bytecode(compiler->code);
2509 return E_OUTOFMEMORY;
2510 }
2511
2512 compiler->code_size = 64;
2513 compiler->code_off = 1;
2514 return S_OK;
2515}
2516
2518 BOOL from_eval, function_code_t *func)
2519{
2522 unsigned off, i, scope;
2523 HRESULT hres;
2524
2525 TRACE("\n");
2526
2527 func->bytecode = ctx->code;
2528 func->local_ref = INVALID_LOCAL_REF;
2529 func->scope_index = 0;
2530 ctx->func_head = ctx->func_tail = NULL;
2531 ctx->from_eval = from_eval;
2532 ctx->func = func;
2533 ctx->local_scope_count = 0;
2534 if (!alloc_local_scope(ctx, &scope))
2535 return E_OUTOFMEMORY;
2536 assert(!scope);
2537
2538 if(func_expr) {
2539 parameter_t *param_iter;
2540
2541 if(func_expr->identifier) {
2542 func->name = compiler_alloc_bstr(ctx, func_expr->identifier);
2543 if(!func->name)
2544 return E_OUTOFMEMORY;
2545 }
2546
2547 if(func_expr->event_target) {
2548 func->event_target = compiler_alloc_bstr(ctx, func_expr->event_target);
2549 if(!func->event_target)
2550 return E_OUTOFMEMORY;
2551 }
2552
2553 func->source = func_expr->src_str;
2554 func->source_len = func_expr->src_len;
2555
2556 for(param_iter = func_expr->parameter_list; param_iter; param_iter = param_iter->next)
2557 func->param_cnt++;
2558
2559 func->params = compiler_alloc(ctx->code, func->param_cnt * sizeof(*func->params));
2560 if(!func->params)
2561 return E_OUTOFMEMORY;
2562
2563 for(param_iter = func_expr->parameter_list, i=0; param_iter; param_iter = param_iter->next, i++) {
2564 func->params[i] = compiler_alloc_bstr(ctx, param_iter->identifier);
2565 if(!func->params[i])
2566 return E_OUTOFMEMORY;
2567 }
2568 }
2569
2570 for(i = func->param_cnt; i--;) {
2571 if(!find_local(ctx, func->params[i], 0) && !alloc_local(ctx, func->params[i], -i-1, 0))
2572 return E_OUTOFMEMORY;
2573 }
2574
2576 if(FAILED(hres))
2577 return hres;
2578
2579 func->local_scope_count = ctx->local_scope_count;
2580 func->local_scopes = compiler_alloc(ctx->code, func->local_scope_count * sizeof(*func->local_scopes));
2581 if(!func->local_scopes)
2582 return E_OUTOFMEMORY;
2583
2584 func->variables = compiler_alloc(ctx->code, func->var_cnt * sizeof(*func->variables));
2585 if(!func->variables)
2586 return E_OUTOFMEMORY;
2587
2588 for (scope = 0; scope < func->local_scope_count; ++scope)
2589 {
2590 func->local_scopes[scope].locals = compiler_alloc(ctx->code,
2591 ctx->local_scopes[scope].locals_cnt * sizeof(*func->local_scopes[scope].locals));
2592 if(!func->local_scopes[scope].locals)
2593 return E_OUTOFMEMORY;
2594 func->local_scopes[scope].locals_cnt = ctx->local_scopes[scope].locals_cnt;
2595
2596 i = 0;
2597 WINE_RB_FOR_EACH_ENTRY(local, &ctx->local_scopes[scope].locals, function_local_t, entry) {
2598 func->local_scopes[scope].locals[i].name = local->name;
2599 func->local_scopes[scope].locals[i].ref = local->ref;
2600 if(local->ref >= 0) {
2601 func->variables[local->ref].name = local->name;
2602 func->variables[local->ref].func_id = -1;
2603 }
2604 i++;
2605 }
2606 assert(i == ctx->local_scopes[scope].locals_cnt);
2607 }
2608
2609 func->funcs = compiler_alloc(ctx->code, func->func_cnt * sizeof(*func->funcs));
2610 if(!func->funcs)
2611 return E_OUTOFMEMORY;
2612 memset(func->funcs, 0, func->func_cnt * sizeof(*func->funcs));
2613
2614 ctx->current_function_expr = ctx->func_head;
2615 off = ctx->code_off;
2617 if(FAILED(hres))
2618 return hres;
2619
2620 resolve_labels(ctx, off);
2621
2622 hres = push_instr_uint(ctx, OP_ret, !from_eval);
2623 if(FAILED(hres))
2624 return hres;
2625
2626 if(TRACE_ON(jscript_disas))
2627 dump_code(ctx, off);
2628
2629 func->instr_off = off;
2630
2631 for(iter = ctx->func_head, i=0; iter; iter = iter->next, i++) {
2632 hres = compile_function(ctx, iter->statement_list, iter, FALSE, func->funcs+i);
2633 if(FAILED(hres))
2634 return hres;
2635
2636 func->funcs[i].scope_index = iter->scope_index;
2637
2638 TRACE("[%d] func %s, scope_index %u\n", i, debugstr_w(func->funcs[i].name), iter->scope_index);
2639 if((ctx->parser->script->version < SCRIPTLANGUAGEVERSION_ES5 || iter->is_statement) &&
2640 func->funcs[i].name && !func->funcs[i].event_target) {
2641 local_ref_t *local_ref = lookup_local(func, func->funcs[i].name, func->funcs[i].scope_index);
2642
2643 func->funcs[i].local_ref = local_ref->ref;
2644 TRACE("found ref %s %d for %s\n", debugstr_w(local_ref->name), local_ref->ref, debugstr_w(func->funcs[i].name));
2645 if(local_ref->ref >= 0)
2646 func->variables[local_ref->ref].func_id = i;
2647 }
2648 }
2649
2650 assert(i == func->func_cnt);
2651
2652 return S_OK;
2653}
2654
2655static HRESULT parse_arguments(compiler_ctx_t *ctx, const WCHAR *args, BSTR *arg_array, unsigned *args_size)
2656{
2657 const WCHAR *ptr = args, *ptr2;
2658 unsigned arg_cnt = 0;
2659
2660 while(iswspace(*ptr))
2661 ptr++;
2662 if(!*ptr) {
2663 if(args_size)
2664 *args_size = 0;
2665 return S_OK;
2666 }
2667
2668 while(1) {
2669 if(!iswalpha(*ptr) && *ptr != '_') {
2670 FIXME("expected alpha or '_': %s\n", debugstr_w(ptr));
2671 return E_FAIL;
2672 }
2673
2674 ptr2 = ptr;
2675 while(iswalnum(*ptr) || *ptr == '_')
2676 ptr++;
2677
2678 if(*ptr && *ptr != ',' && !iswspace(*ptr)) {
2679 FIXME("unexpected har %s\n", debugstr_w(ptr));
2680 return E_FAIL;
2681 }
2682
2683 if(arg_array) {
2684 arg_array[arg_cnt] = compiler_alloc_bstr_len(ctx, ptr2, ptr-ptr2);
2685 if(!arg_array[arg_cnt])
2686 return E_OUTOFMEMORY;
2687 }
2688 arg_cnt++;
2689
2690 while(iswspace(*ptr))
2691 ptr++;
2692 if(!*ptr)
2693 break;
2694 if(*ptr != ',') {
2695 FIXME("expected ',': %s\n", debugstr_w(ptr));
2696 return E_FAIL;
2697 }
2698
2699 ptr++;
2700 while(iswspace(*ptr))
2701 ptr++;
2702 }
2703
2704 if(args_size)
2705 *args_size = arg_cnt;
2706 return S_OK;
2707}
2708
2710{
2711 HRESULT hres;
2712
2713 hres = parse_arguments(ctx, args, NULL, &ctx->code->global_code.param_cnt);
2714 if(FAILED(hres))
2715 return hres;
2716
2717 ctx->code->global_code.params = compiler_alloc(ctx->code,
2718 ctx->code->global_code.param_cnt * sizeof(*ctx->code->global_code.params));
2719 if(!ctx->code->global_code.params)
2720 return E_OUTOFMEMORY;
2721
2722 return parse_arguments(ctx, args, ctx->code->global_code.params, NULL);
2723}
2724
2725HRESULT compile_script(script_ctx_t *ctx, const WCHAR *code, UINT64 source_context, unsigned start_line,
2726 const WCHAR *args, const WCHAR *delimiter, BOOL from_eval, BOOL use_decode,
2727 named_item_t *named_item, bytecode_t **ret)
2728{
2729 compiler_ctx_t compiler = {0};
2730 HRESULT hres;
2731
2732 hres = init_code(&compiler, code, source_context, start_line);
2733 if(FAILED(hres))
2734 return hres;
2735
2736 if(args) {
2737 hres = compile_arguments(&compiler, args);
2738 if(FAILED(hres))
2739 return hres;
2740 }
2741
2742 if(use_decode) {
2743 hres = decode_source(compiler.code->source);
2744 if(FAILED(hres)) {
2745 WARN("Decoding failed\n");
2746 return hres;
2747 }
2748 }
2749
2750 hres = script_parse(ctx, &compiler, compiler.code, delimiter, from_eval, &compiler.parser);
2751 if(FAILED(hres)) {
2752 release_bytecode(compiler.code);
2753 return hres;
2754 }
2755
2756 heap_pool_init(&compiler.heap);
2757 hres = compile_function(&compiler, compiler.parser->source, NULL, from_eval, &compiler.code->global_code);
2758 free(compiler.local_scopes);
2759 heap_pool_free(&compiler.heap);
2760 parser_release(compiler.parser);
2761 if(FAILED(hres)) {
2762 if(hres != DISP_E_EXCEPTION)
2764 set_error_location(ctx->ei, compiler.code, compiler.loc, IDS_COMPILATION_ERROR, NULL);
2765 release_bytecode(compiler.code);
2766 return DISP_E_EXCEPTION;
2767 }
2768
2769 if(named_item) {
2770 compiler.code->named_item = named_item;
2771 named_item->ref++;
2772 }
2773
2774 *ret = compiler.code;
2775 return S_OK;
2776}
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
#define ARG_NONE
Definition: amlcode.h:216
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
Definition: list.h:37
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_FAIL
Definition: ddrawi.h:102
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT op
Definition: effect.c:236
#define TRACE_(x)
Definition: compat.h:76
OLECHAR * BSTR
Definition: compat.h:2293
#define TRACE_ON(x)
Definition: compat.h:75
#define WINE_DECLARE_DEBUG_CHANNEL(x)
Definition: compat.h:45
#define lstrlenW
Definition: compat.h:750
HRESULT throw_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str)
Definition: error.c:398
void release_named_item(named_item_t *item)
Definition: jscript.c:186
expression_type_t
Definition: parser.h:227
@ EXPR_MEMBER
Definition: parser.h:277
@ EXPR_PREDEC
Definition: parser.h:249
@ EXPR_RSHIFT
Definition: parser.h:261
@ EXPR_LESS
Definition: parser.h:254
@ EXPR_ASSIGNADD
Definition: parser.h:267
@ EXPR_GREATER
Definition: parser.h:256
@ EXPR_THIS
Definition: parser.h:280
@ EXPR_BOR
Definition: parser.h:231
@ EXPR_LITERAL
Definition: parser.h:285
@ EXPR_EQEQ
Definition: parser.h:251
@ EXPR_ASSIGNRRSHIFT
Definition: parser.h:266
@ EXPR_ASSIGNDIV
Definition: parser.h:270
@ EXPR_ARRAY
Definition: parser.h:276
@ EXPR_ASSIGNMUL
Definition: parser.h:269
@ EXPR_BXOR
Definition: parser.h:232
@ EXPR_ASSIGNMOD
Definition: parser.h:271
@ EXPR_MOD
Definition: parser.h:240
@ EXPR_FUNC
Definition: parser.h:281
@ EXPR_BAND
Definition: parser.h:233
@ EXPR_VOID
Definition: parser.h:242
@ EXPR_NEW
Definition: parser.h:278
@ EXPR_POSTDEC
Definition: parser.h:247
@ EXPR_ASSIGNOR
Definition: parser.h:273
@ EXPR_GREATEREQ
Definition: parser.h:257
@ EXPR_ASSIGNLSHIFT
Definition: parser.h:264
@ EXPR_CALL
Definition: parser.h:279
@ EXPR_LSHIFT
Definition: parser.h:260
@ EXPR_LOGNEG
Definition: parser.h:259
@ EXPR_PROPVAL
Definition: parser.h:284
@ EXPR_DELETE
Definition: parser.h:241
@ EXPR_ARRAYLIT
Definition: parser.h:283
@ EXPR_DIV
Definition: parser.h:239
@ EXPR_ADD
Definition: parser.h:236
@ EXPR_ASSIGN
Definition: parser.h:263
@ EXPR_TYPEOF
Definition: parser.h:243
@ EXPR_IDENT
Definition: parser.h:282
@ EXPR_IN
Definition: parser.h:235
@ EXPR_INSTANCEOF
Definition: parser.h:234
@ EXPR_PLUS
Definition: parser.h:245
@ EXPR_MUL
Definition: parser.h:238
@ EXPR_BITNEG
Definition: parser.h:258
@ EXPR_COND
Definition: parser.h:275
@ EXPR_PREINC
Definition: parser.h:248
@ EXPR_OR
Definition: parser.h:229
@ EXPR_NOTEQ
Definition: parser.h:252
@ EXPR_NOTEQEQ
Definition: parser.h:253
@ EXPR_POSTINC
Definition: parser.h:246
@ EXPR_ASSIGNAND
Definition: parser.h:272
@ EXPR_RRSHIFT
Definition: parser.h:262
@ EXPR_ASSIGNSUB
Definition: parser.h:268
@ EXPR_SUB
Definition: parser.h:237
@ EXPR_EQ
Definition: parser.h:250
@ EXPR_ASSIGNRSHIFT
Definition: parser.h:265
@ EXPR_LESSEQ
Definition: parser.h:255
@ EXPR_MINUS
Definition: parser.h:244
@ EXPR_COMMA
Definition: parser.h:228
@ EXPR_ASSIGNXOR
Definition: parser.h:274
@ EXPR_AND
Definition: parser.h:230
HRESULT script_parse(script_ctx_t *, struct _compiler_ctx_t *, struct _bytecode_t *, const WCHAR *, BOOL, parser_ctx_t **)
@ LT_BOOL
Definition: parser.h:78
@ LT_STRING
Definition: parser.h:77
@ LT_NULL
Definition: parser.h:79
@ LT_REGEXP
Definition: parser.h:80
@ LT_DOUBLE
Definition: parser.h:76
void parser_release(parser_ctx_t *)
statement_type_t
Definition: parser.h:108
@ STAT_CONTINUE
Definition: parser.h:111
@ STAT_FOR
Definition: parser.h:114
@ STAT_EMPTY
Definition: parser.h:112
@ STAT_THROW
Definition: parser.h:120
@ STAT_SWITCH
Definition: parser.h:119
@ STAT_VAR
Definition: parser.h:122
@ STAT_EXPR
Definition: parser.h:113
@ STAT_TRY
Definition: parser.h:121
@ STAT_RETURN
Definition: parser.h:118
@ STAT_BLOCK
Definition: parser.h:109
@ STAT_WITH
Definition: parser.h:124
@ STAT_IF
Definition: parser.h:116
@ STAT_FORIN
Definition: parser.h:115
@ STAT_BREAK
Definition: parser.h:110
@ STAT_LABEL
Definition: parser.h:117
@ STAT_WHILE
Definition: parser.h:123
#define IDS_COMPILATION_ERROR
Definition: resource.h:89
#define assert(_expr)
Definition: assert.h:32
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1977
#define INT32_MAX
Definition: stdint.h:80
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
local_ref_t * lookup_local(const function_code_t *function, const WCHAR *identifier, unsigned int scope)
Definition: engine.c:865
static jsval_t stack_pop(script_ctx_t *ctx)
Definition: engine.c:108
void set_error_location(jsexcept_t *, bytecode_t *, unsigned, unsigned, jsstr_t *)
Definition: error.c:426
#define OP_LIST
Definition: engine.h:21
instr_arg_type_t
Definition: engine.h:121
@ ARG_DBL
Definition: engine.h:125
@ ARG_INT
Definition: engine.h:127
@ ARG_ADDR
Definition: engine.h:123
@ ARG_BSTR
Definition: engine.h:124
@ ARG_FUNC
Definition: engine.h:126
@ ARG_STR
Definition: engine.h:128
@ ARG_UINT
Definition: engine.h:129
#define INVALID_LOCAL_REF
Definition: engine.h:152
jsop_t
Definition: engine.h:105
@ OP_LAST
Definition: engine.h:109
size_t const new_size
Definition: expand.cpp:66
unsigned int BOOL
Definition: ntddk_ex.h:94
#define local
Definition: zutil.h:30
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLenum func
Definition: glext.h:6028
GLdouble n
Definition: glext.h:7729
GLsizeiptr size
Definition: glext.h:5919
GLuint GLuint GLuint GLuint arg1
Definition: glext.h:9513
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
Definition: glext.h:9514
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
uint32_t entry
Definition: isohybrid.c:63
static HRESULT push_instr_bstr(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg)
Definition: compile.c:335
static HRESULT compile_for_statement(compiler_ctx_t *ctx, for_statement_t *stat)
Definition: compile.c:1385
static HRESULT compile_forin_statement(compiler_ctx_t *ctx, forin_statement_t *stat)
Definition: compile.c:1468
static void dump_code(compiler_ctx_t *ctx, unsigned off)
Definition: compile.c:122
static HRESULT compile_continue_statement(compiler_ctx_t *ctx, branch_statement_t *stat)
Definition: compile.c:1562
void release_bytecode(bytecode_t *code)
Definition: compile.c:2459
static HRESULT compile_arguments(compiler_ctx_t *ctx, const WCHAR *args)
Definition: compile.c:2709
static HRESULT emit_member_expression(compiler_ctx_t *ctx, expression_t *expr)
Definition: compile.c:532
static HRESULT compile_comma_expression(compiler_ctx_t *ctx, binary_expression_t *expr, BOOL emit_ret)
Definition: compile.c:625
static BSTR compiler_alloc_bstr(compiler_ctx_t *ctx, const WCHAR *str)
Definition: compile.c:243
static BSTR compiler_alloc_bstr_len(compiler_ctx_t *ctx, const WCHAR *str, size_t len)
Definition: compile.c:255
static HRESULT visit_statement(compiler_ctx_t *, statement_ctx_t *, statement_t *)
Definition: compile.c:2225
static HRESULT compile_expression(compiler_ctx_t *, expression_t *, BOOL)
Definition: compile.c:1021
static HRESULT compile_new_expression(compiler_ctx_t *ctx, call_expression_t *expr)
Definition: compile.c:693
static HRESULT compile_return_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
Definition: compile.c:1652
static HRESULT parse_arguments(compiler_ctx_t *ctx, const WCHAR *args, BSTR *arg_array, unsigned *args_size)
Definition: compile.c:2655
static HRESULT init_code(compiler_ctx_t *compiler, const WCHAR *source, UINT64 source_context, unsigned start_line)
Definition: compile.c:2481
static HRESULT push_instr_uint_str(compiler_ctx_t *ctx, jsop_t op, unsigned arg1, const WCHAR *arg2)
Definition: compile.c:370
static BOOL ensure_bstr_slot(compiler_ctx_t *ctx)
Definition: compile.c:222
static HRESULT compile_conditional_expression(compiler_ctx_t *ctx, conditional_expression_t *expr)
Definition: compile.c:659
static HRESULT compile_while_statement(compiler_ctx_t *ctx, while_statement_t *stat)
Definition: compile.c:1333
static void * compiler_alloc(bytecode_t *code, size_t size)
Definition: compile.c:184
static HRESULT compile_member_expression(compiler_ctx_t *ctx, member_expression_t *expr)
Definition: compile.c:444
static BOOL alloc_variable(compiler_ctx_t *ctx, const WCHAR *name, unsigned int scope)
Definition: compile.c:1998
instr_arg_type_t arg2_type
Definition: compile.c:92
static HRESULT compile_statement(compiler_ctx_t *, statement_ctx_t *, statement_t *)
Definition: compile.c:1911
static unsigned push_instr(compiler_ctx_t *ctx, jsop_t op)
Definition: compile.c:272
static HRESULT compile_logical_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
Definition: compile.c:637
static void resolve_labels(compiler_ctx_t *ctx, unsigned off)
Definition: compile.c:2430
static BOOL is_loop_statement(statement_type_t type)
Definition: compile.c:1205
static HRESULT literal_as_string(compiler_ctx_t *ctx, literal_t *literal, jsstr_t **str)
Definition: compile.c:937
static HRESULT compile_function(compiler_ctx_t *ctx, statement_t *source, function_expression_t *func_expr, BOOL from_eval, function_code_t *func)
Definition: compile.c:2517
static unsigned alloc_label(compiler_ctx_t *ctx)
Definition: compile.c:457
static void pop_compiler_statement_ctx(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx)
Definition: compile.c:580
static function_local_t * find_local(compiler_ctx_t *ctx, const WCHAR *name, unsigned int scope)
Definition: compile.c:1977
#define LABEL_FLAG
Definition: compile.c:455
static HRESULT compile_binary_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
Definition: compile.c:417
static HRESULT compile_labelled_statement(compiler_ctx_t *ctx, labelled_statement_t *stat)
Definition: compile.c:1700
static void dump_instr_arg(instr_arg_type_t type, instr_arg_t *arg)
Definition: compile.c:99
instr_arg_type_t arg1_type
Definition: compile.c:91
static BOOL alloc_local_scope(compiler_ctx_t *ctx, unsigned int *scope_index)
Definition: compile.c:147
static HRESULT compile_typeof_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
Definition: compile.c:898
static HRESULT compile_throw_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
Definition: compile.c:1822
static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal)
Definition: compile.c:919
static HRESULT compile_variable_list(compiler_ctx_t *ctx, variable_declaration_t *list)
Definition: compile.c:1242
static BOOL bind_local(compiler_ctx_t *ctx, const WCHAR *identifier, int *ret_ref)
Definition: compile.c:489
static HRESULT compile_if_statement(compiler_ctx_t *ctx, if_statement_t *stat)
Definition: compile.c:1294
const char * op_str
Definition: compile.c:90
static HRESULT visit_variable_list(compiler_ctx_t *ctx, variable_declaration_t *list)
Definition: compile.c:2167
static HRESULT compile_array_literal(compiler_ctx_t *ctx, array_literal_expression_t *expr)
Definition: compile.c:951
static HRESULT pop_to_stat(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx)
Definition: compile.c:1529
static HRESULT visit_function_expression(compiler_ctx_t *ctx, function_expression_t *expr)
Definition: compile.c:2012
static HRESULT push_instr_str_uint(compiler_ctx_t *ctx, jsop_t op, jsstr_t *str, unsigned arg2)
Definition: compile.c:322
static HRESULT push_instr_double(compiler_ctx_t *ctx, jsop_t op, double arg)
Definition: compile.c:388
static HRESULT compile_var_statement(compiler_ctx_t *ctx, var_statement_t *stat)
Definition: compile.c:1276
static HRESULT compile_expression_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
Definition: compile.c:1282
static HRESULT compile_unary_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op)
Definition: compile.c:432
static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr, BOOL emit_ret)
Definition: compile.c:1004
static jsstr_t * compiler_alloc_string(compiler_ctx_t *ctx, const WCHAR *str)
Definition: compile.c:217
static BOOL is_memberid_expr(expression_type_t type)
Definition: compile.c:484
static HRESULT compile_break_statement(compiler_ctx_t *ctx, branch_statement_t *stat)
Definition: compile.c:1615
static void remove_local_scope(compiler_ctx_t *ctx, unsigned int scope_index)
Definition: compile.c:170
static HRESULT compile_assign_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
Definition: compile.c:824
static HRESULT emit_identifier(compiler_ctx_t *ctx, const WCHAR *identifier)
Definition: compile.c:524
static HRESULT compile_switch_statement(compiler_ctx_t *ctx, switch_statement_t *stat)
Definition: compile.c:1726
static HRESULT compile_increment_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op, int n)
Definition: compile.c:605
jsstr_t * compiler_alloc_string_len(compiler_ctx_t *ctx, const WCHAR *str, unsigned len)
Definition: compile.c:189
static void label_set_addr(compiler_ctx_t *ctx, unsigned label)
Definition: compile.c:478
static void set_arg_uint(compiler_ctx_t *ctx, unsigned instr, unsigned arg)
Definition: compile.c:400
static void push_compiler_statement_ctx(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx)
Definition: compile.c:571
static HRESULT push_instr_uint(compiler_ctx_t *ctx, jsop_t op, unsigned arg)
Definition: compile.c:405
static HRESULT visit_expression(compiler_ctx_t *ctx, expression_t *expr)
Definition: compile.c:2037
HRESULT compile_script(script_ctx_t *ctx, const WCHAR *code, UINT64 source_context, unsigned start_line, const WCHAR *args, const WCHAR *delimiter, BOOL from_eval, BOOL use_decode, named_item_t *named_item, bytecode_t **ret)
Definition: compile.c:2725
static HRESULT visit_block_statement(compiler_ctx_t *ctx, block_statement_t *block, statement_t *iter)
Definition: compile.c:2195
static HRESULT push_instr_bstr_uint(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg1, unsigned arg2)
Definition: compile.c:352
static instr_t * instr_ptr(compiler_ctx_t *ctx, unsigned off)
Definition: compile.c:292
static int function_local_cmp(const void *key, const struct wine_rb_entry *entry)
Definition: compile.c:141
static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expression_t *expr)
Definition: compile.c:978
static HRESULT compile_call_expression(compiler_ctx_t *ctx, call_expression_t *expr, BOOL emit_ret)
Definition: compile.c:721
void set_compiler_loc(compiler_ctx_t *ctx, unsigned loc)
Definition: compile.c:267
static HRESULT emit_identifier_ref(compiler_ctx_t *ctx, const WCHAR *identifier, unsigned flags)
Definition: compile.c:516
struct _statement_ctx_t statement_ctx_t
static HRESULT compile_memberid_expression(compiler_ctx_t *ctx, expression_t *expr, unsigned flags)
Definition: compile.c:589
static HRESULT push_instr_int(compiler_ctx_t *ctx, jsop_t op, LONG arg)
Definition: compile.c:298
static BOOL alloc_local(compiler_ctx_t *ctx, BSTR name, int ref, unsigned int scope)
Definition: compile.c:1983
unsigned get_location_line(bytecode_t *code, unsigned loc, unsigned *char_pos)
Definition: compile.c:2445
static HRESULT compile_try_statement(compiler_ctx_t *ctx, try_statement_t *stat)
Definition: compile.c:1834
static HRESULT push_instr_str(compiler_ctx_t *ctx, jsop_t op, jsstr_t *str)
Definition: compile.c:310
static HRESULT compile_with_statement(compiler_ctx_t *ctx, with_statement_t *stat)
Definition: compile.c:1677
static HRESULT compile_block_statement(compiler_ctx_t *ctx, block_statement_t *block, statement_t *iter)
Definition: compile.c:1211
static HRESULT compile_delete_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
Definition: compile.c:767
struct _compiler_ctx_t compiler_ctx_t
HRESULT decode_source(WCHAR *code)
Definition: decode.c:111
#define JS_E_ILLEGAL_ASSIGN
Definition: jscript.h:556
#define JS_E_INVALID_BREAK
Definition: jscript.h:545
#define JS_E_MISPLACED_RETURN
Definition: jscript.h:544
#define JS_E_LABEL_REDEFINED
Definition: jscript.h:547
#define JS_E_LABEL_NOT_FOUND
Definition: jscript.h:548
#define JS_E_INVALID_CONTINUE
Definition: jscript.h:546
void heap_pool_init(heap_pool_t *)
Definition: jsutils.c:66
#define SCRIPTLANGUAGEVERSION_ES5
Definition: jscript.h:53
HRESULT double_to_string(double, jsstr_t **)
Definition: jsutils.c:767
void * heap_pool_alloc(heap_pool_t *, DWORD) __WINE_ALLOC_SIZE(2)
Definition: jsutils.c:72
void heap_pool_free(heap_pool_t *)
Definition: jsutils.c:164
#define JS_E_INVALID_DELETE
Definition: jscript.h:560
jsstr_t * jsstr_alloc_len(const WCHAR *buf, unsigned len)
Definition: jsstr.c:86
const char * debugstr_jsstr(jsstr_t *str)
Definition: jsstr.c:37
static void jsstr_release(jsstr_t *str)
Definition: jsstr.h:107
#define debugstr_wn
Definition: kernel32.h:33
#define debugstr_w
Definition: kernel32.h:32
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
static PVOID ptr
Definition: dispmode.c:27
static const WCHAR label[]
Definition: itemdlg.c:1546
const char * var
Definition: shader.c:5666
HRESULT hres
Definition: protocol.c:465
const char * delimiter
Definition: string.c:1779
#define DEFAULT_UNREACHABLE
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
UINT WINAPI SysStringLen(BSTR str)
Definition: oleaut.c:196
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len)
Definition: oleaut.c:339
short WCHAR
Definition: pedump.c:58
long LONG
Definition: pedump.c:60
#define calloc
Definition: rosglue.h:14
const WCHAR * str
#define iswspace(_c)
Definition: ctype.h:669
#define iswalnum(_c)
Definition: ctype.h:671
#define iswalpha(_c)
Definition: ctype.h:664
#define wine_rb_entry
Definition: rbtree.h:404
#define WINE_RB_ENTRY_VALUE
Definition: rbtree.h:414
#define wine_rb_put
Definition: rbtree.h:410
#define WINE_RB_FOR_EACH_ENTRY
Definition: rbtree.h:415
#define wine_rb_tree
Definition: rbtree.h:405
#define wine_rb_init
Definition: rbtree.h:406
#define wine_rb_get
Definition: rbtree.h:409
#define memset(x, y, z)
Definition: compat.h:39
#define args
Definition: format.c:66
#define TRACE(s)
Definition: solgame.cpp:4
expression_t * expr
Definition: parser.h:360
struct _array_element_t * next
Definition: parser.h:362
instr_t * instrs
Definition: engine.h:195
LONG ref
Definition: engine.h:192
WCHAR * source
Definition: engine.h:201
heap_pool_t heap
Definition: engine.h:196
UINT64 source_context
Definition: engine.h:202
unsigned start_line
Definition: engine.h:203
named_item_t * named_item
Definition: engine.h:199
function_code_t global_code
Definition: engine.h:198
struct _case_clausule_t * next
Definition: parser.h:205
statement_t * stat
Definition: parser.h:203
expression_t * expr
Definition: parser.h:201
unsigned loc
Definition: parser.h:202
bytecode_t * code
Definition: compile.c:56
function_expression_t * func_head
Definition: compile.c:82
BOOL from_eval
Definition: compile.c:58
heap_pool_t heap
Definition: compile.c:86
unsigned code_size
Definition: compile.c:61
unsigned * labels
Definition: compile.c:63
function_expression_t * func_tail
Definition: compile.c:83
unsigned local_scope_size
Definition: compile.c:75
unsigned int locals_cnt
Definition: compile.c:70
function_code_t * func
Definition: compile.c:78
function_expression_t * current_function_expr
Definition: compile.c:84
unsigned int * ref_index
Definition: compile.c:71
unsigned code_off
Definition: compile.c:60
struct _compiler_ctx_t::@429 * local_scopes
struct wine_rb_tree locals
Definition: compile.c:69
unsigned loc
Definition: compile.c:80
parser_ctx_t * parser
Definition: compile.c:55
unsigned local_scope_count
Definition: compile.c:74
unsigned labels_cnt
Definition: compile.c:65
unsigned labels_size
Definition: compile.c:64
statement_ctx_t * stat_ctx
Definition: compile.c:77
expression_type_t type
Definition: parser.h:289
const WCHAR * event_target
Definition: parser.h:300
unsigned int scope_index
Definition: parser.h:307
parameter_t * parameter_list
Definition: parser.h:301
const WCHAR * src_str
Definition: parser.h:303
struct _function_expression_t * next
Definition: parser.h:309
statement_t * statement_list
Definition: parser.h:302
const WCHAR * identifier
Definition: parser.h:299
Definition: jsstr.h:36
struct _parameter_t * next
Definition: parser.h:294
const WCHAR * identifier
Definition: parser.h:293
struct _property_definition_t * next
Definition: parser.h:376
literal_t * name
Definition: parser.h:373
expression_t * value
Definition: parser.h:374
BOOL scope_has_functions
Definition: compile.c:44
BOOL using_scope
Definition: compile.c:34
const labelled_statement_t * labelled_stat
Definition: compile.c:40
BOOL block_scope
Definition: compile.c:43
unsigned int scope_index
Definition: compile.c:42
unsigned continue_label
Definition: compile.c:38
BOOL using_except
Definition: compile.c:35
unsigned break_label
Definition: compile.c:37
unsigned stack_use
Definition: compile.c:33
struct _statement_ctx_t * next
Definition: compile.c:45
statement_type_t type
Definition: parser.h:128
statement_t * next
Definition: parser.h:129
const WCHAR * identifier
Definition: parser.h:100
expression_t * expr
Definition: parser.h:102
struct _variable_declaration_t * next
Definition: parser.h:104
Definition: match.c:390
array_element_t * element_list
Definition: parser.h:367
expression_t * expression1
Definition: parser.h:314
expression_t * expression2
Definition: parser.h:315
expression_t * expression
Definition: parser.h:344
argument_t * argument_list
Definition: parser.h:345
statement_t * statement
Definition: parser.h:216
Definition: inflate.c:139
expression_t * true_expression
Definition: parser.h:326
expression_t * expression
Definition: parser.h:325
expression_t * false_expression
Definition: parser.h:327
char * name
Definition: compiler.c:66
struct list entry
Definition: wpp.c:51
Definition: query.h:86
int type
Definition: query.h:87
expression_t * expr
Definition: parser.h:146
expression_t * expr
Definition: parser.h:167
statement_t * statement
Definition: parser.h:171
expression_t * end_expr
Definition: parser.h:169
unsigned int scope_index
Definition: parser.h:172
expression_t * begin_expr
Definition: parser.h:166
variable_declaration_t * variable_list
Definition: parser.h:165
variable_declaration_t * variable
Definition: parser.h:177
statement_t * statement
Definition: parser.h:180
expression_t * in_expr
Definition: parser.h:179
expression_t * expr
Definition: parser.h:178
const WCHAR * identifier
Definition: parser.h:350
statement_t * if_stat
Definition: parser.h:152
expression_t * expr
Definition: parser.h:151
statement_t * else_stat
Definition: parser.h:153
instr_arg_t arg[2]
Definition: engine.h:136
jsop_t op
Definition: engine.h:133
double dbl
Definition: engine.h:137
union instr_t::@435 u
Definition: copy.c:22
const WCHAR * identifier
Definition: parser.h:196
statement_t * statement
Definition: parser.h:197
Definition: parser.c:49
struct literal_t::@444::@445 regexp
BOOL bval
Definition: parser.h:88
double dval
Definition: parser.h:86
union literal_t::@444 u
literal_type_t type
Definition: parser.h:84
jsstr_t * str
Definition: parser.h:87
int ref
Definition: engine.h:149
BSTR name
Definition: engine.h:148
const WCHAR * identifier
Definition: parser.h:333
expression_t * expression
Definition: parser.h:332
Definition: name.c:39
unsigned ref
Definition: jscript.h:152
Definition: send.c:48
Definition: stat.h:66
expression_t * expr
Definition: parser.h:210
case_clausule_t * case_list
Definition: parser.h:211
catch_block_t * catch_block
Definition: parser.h:222
statement_t * try_statement
Definition: parser.h:221
statement_t * finally_statement
Definition: parser.h:223
expression_t * expr
Definition: parser.h:159
statement_t * statement
Definition: parser.h:160
statement_t * statement
Definition: parser.h:191
expression_t * expr
Definition: parser.h:190
#define max(a, b)
Definition: svc.c:63
unsigned uint
Definition: engine.h:118
LONG lng
Definition: engine.h:116
jsstr_t * str
Definition: engine.h:117
BSTR bstr
Definition: engine.h:115
static unsigned arg_cnt(const DISPPARAMS *dp)
Definition: vbscript.h:175
_In_ ULONG _In_ ULONG_PTR ident
Definition: winddi.h:3994
void * arg
Definition: msvc.h:10
#define DISP_E_EXCEPTION
Definition: winerror.h:3621
static unsigned int block
Definition: xmlmemory.c:101