2 * Copyright 2011 Jacek Caban for CodeWeavers
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.
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.
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
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(jscript
);
28 WINE_DECLARE_DEBUG_CHANNEL(jscript_disas
);
30 typedef struct _statement_ctx_t
{
36 unsigned continue_label
;
38 const labelled_statement_t
*labelled_stat
;
40 struct _statement_ctx_t
*next
;
54 statement_ctx_t
*stat_ctx
;
55 function_code_t
*func
;
57 variable_declaration_t
*var_head
;
58 variable_declaration_t
*var_tail
;
60 function_expression_t
*func_head
;
61 function_expression_t
*func_tail
;
66 instr_arg_type_t arg1_type
;
67 instr_arg_type_t arg2_type
;
69 #define X(n,a,b,c) {#n,b,c},
74 static void dump_instr_arg(instr_arg_type_t type
, instr_arg_t
*arg
)
78 TRACE_(jscript_disas
)("\t%s", debugstr_w(arg
->str
));
81 TRACE_(jscript_disas
)("\t%s", debugstr_wn(arg
->bstr
, SysStringLen(arg
->bstr
)));
84 TRACE_(jscript_disas
)("\t%d", arg
->uint
);
88 TRACE_(jscript_disas
)("\t%u", arg
->uint
);
98 static void dump_code(compiler_ctx_t
*ctx
, unsigned off
)
102 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->code_off
; instr
++) {
103 TRACE_(jscript_disas
)("%d:\t%s", (int)(instr
-ctx
->code
->instrs
), instr_info
[instr
->op
].op_str
);
104 if(instr_info
[instr
->op
].arg1_type
== ARG_DBL
) {
105 TRACE_(jscript_disas
)("\t%lf", instr
->u
.dbl
);
107 dump_instr_arg(instr_info
[instr
->op
].arg1_type
, instr
->u
.arg
);
108 dump_instr_arg(instr_info
[instr
->op
].arg2_type
, instr
->u
.arg
+1);
110 TRACE_(jscript_disas
)("\n");
114 static HRESULT
compile_expression(compiler_ctx_t
*,expression_t
*);
115 static HRESULT
compile_statement(compiler_ctx_t
*,statement_ctx_t
*,statement_t
*);
117 static inline void *compiler_alloc(bytecode_t
*code
, size_t size
)
119 return jsheap_alloc(&code
->heap
, size
);
122 static WCHAR
*compiler_alloc_string(bytecode_t
*code
, const WCHAR
*str
)
127 size
= (strlenW(str
)+1)*sizeof(WCHAR
);
128 ret
= compiler_alloc(code
, size
);
130 memcpy(ret
, str
, size
);
134 static BSTR
compiler_alloc_bstr(compiler_ctx_t
*ctx
, const WCHAR
*str
)
136 if(!ctx
->code
->bstr_pool_size
) {
137 ctx
->code
->bstr_pool
= heap_alloc(8 * sizeof(BSTR
));
138 if(!ctx
->code
->bstr_pool
)
140 ctx
->code
->bstr_pool_size
= 8;
141 }else if(ctx
->code
->bstr_pool_size
== ctx
->code
->bstr_cnt
) {
144 new_pool
= heap_realloc(ctx
->code
->bstr_pool
, ctx
->code
->bstr_pool_size
*2*sizeof(BSTR
));
148 ctx
->code
->bstr_pool
= new_pool
;
149 ctx
->code
->bstr_pool_size
*= 2;
152 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocString(str
);
153 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
156 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
159 static unsigned push_instr(compiler_ctx_t
*ctx
, jsop_t op
)
161 assert(ctx
->code_size
>= ctx
->code_off
);
163 if(ctx
->code_size
== ctx
->code_off
) {
166 new_instrs
= heap_realloc(ctx
->code
->instrs
, ctx
->code_size
*2*sizeof(instr_t
));
170 ctx
->code
->instrs
= new_instrs
;
174 ctx
->code
->instrs
[ctx
->code_off
].op
= op
;
175 return ctx
->code_off
++;
178 static inline instr_t
*instr_ptr(compiler_ctx_t
*ctx
, unsigned off
)
180 assert(off
< ctx
->code_off
);
181 return ctx
->code
->instrs
+ off
;
184 static HRESULT
push_instr_int(compiler_ctx_t
*ctx
, jsop_t op
, LONG arg
)
188 instr
= push_instr(ctx
, op
);
190 return E_OUTOFMEMORY
;
192 instr_ptr(ctx
, instr
)->u
.arg
->lng
= arg
;
196 static HRESULT
push_instr_str(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
201 str
= compiler_alloc_string(ctx
->code
, arg
);
203 return E_OUTOFMEMORY
;
205 instr
= push_instr(ctx
, op
);
207 return E_OUTOFMEMORY
;
209 instr_ptr(ctx
, instr
)->u
.arg
->str
= str
;
213 static HRESULT
push_instr_bstr(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
218 str
= compiler_alloc_bstr(ctx
, arg
);
220 return E_OUTOFMEMORY
;
222 instr
= push_instr(ctx
, op
);
224 return E_OUTOFMEMORY
;
226 instr_ptr(ctx
, instr
)->u
.arg
->bstr
= str
;
230 static HRESULT
push_instr_bstr_uint(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg1
, unsigned arg2
)
235 str
= compiler_alloc_bstr(ctx
, arg1
);
237 return E_OUTOFMEMORY
;
239 instr
= push_instr(ctx
, op
);
241 return E_OUTOFMEMORY
;
243 instr_ptr(ctx
, instr
)->u
.arg
[0].bstr
= str
;
244 instr_ptr(ctx
, instr
)->u
.arg
[1].uint
= arg2
;
248 static HRESULT
push_instr_uint_str(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg1
, const WCHAR
*arg2
)
253 str
= compiler_alloc_string(ctx
->code
, arg2
);
255 return E_OUTOFMEMORY
;
257 instr
= push_instr(ctx
, op
);
259 return E_OUTOFMEMORY
;
261 instr_ptr(ctx
, instr
)->u
.arg
[0].uint
= arg1
;
262 instr_ptr(ctx
, instr
)->u
.arg
[1].str
= str
;
266 static HRESULT
push_instr_double(compiler_ctx_t
*ctx
, jsop_t op
, double arg
)
270 instr
= push_instr(ctx
, op
);
272 return E_OUTOFMEMORY
;
274 instr_ptr(ctx
, instr
)->u
.dbl
= arg
;
278 static inline void set_arg_uint(compiler_ctx_t
*ctx
, unsigned instr
, unsigned arg
)
280 instr_ptr(ctx
, instr
)->u
.arg
->uint
= arg
;
283 static HRESULT
push_instr_uint(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg
)
287 instr
= push_instr(ctx
, op
);
289 return E_OUTOFMEMORY
;
291 set_arg_uint(ctx
, instr
, arg
);
295 static HRESULT
compile_binary_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
299 hres
= compile_expression(ctx
, expr
->expression1
);
303 hres
= compile_expression(ctx
, expr
->expression2
);
307 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
310 static HRESULT
compile_unary_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
)
314 hres
= compile_expression(ctx
, expr
->expression
);
318 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
321 /* ECMA-262 3rd Edition 11.2.1 */
322 static HRESULT
compile_member_expression(compiler_ctx_t
*ctx
, member_expression_t
*expr
)
326 hres
= compile_expression(ctx
, expr
->expression
);
330 return push_instr_bstr(ctx
, OP_member
, expr
->identifier
);
333 #define LABEL_FLAG 0x80000000
335 static unsigned alloc_label(compiler_ctx_t
*ctx
)
337 if(!ctx
->labels_size
) {
338 ctx
->labels
= heap_alloc(8 * sizeof(*ctx
->labels
));
341 ctx
->labels_size
= 8;
342 }else if(ctx
->labels_size
== ctx
->labels_cnt
) {
343 unsigned *new_labels
;
345 new_labels
= heap_realloc(ctx
->labels
, 2*ctx
->labels_size
*sizeof(*ctx
->labels
));
349 ctx
->labels
= new_labels
;
350 ctx
->labels_size
*= 2;
353 return ctx
->labels_cnt
++ | LABEL_FLAG
;
356 static void label_set_addr(compiler_ctx_t
*ctx
, unsigned label
)
358 assert(label
& LABEL_FLAG
);
359 ctx
->labels
[label
& ~LABEL_FLAG
] = ctx
->code_off
;
362 static inline BOOL
is_memberid_expr(expression_type_t type
)
364 return type
== EXPR_IDENT
|| type
== EXPR_MEMBER
|| type
== EXPR_ARRAY
;
367 static HRESULT
compile_memberid_expression(compiler_ctx_t
*ctx
, expression_t
*expr
, unsigned flags
)
373 identifier_expression_t
*ident_expr
= (identifier_expression_t
*)expr
;
375 hres
= push_instr_bstr_uint(ctx
, OP_identid
, ident_expr
->identifier
, flags
);
379 binary_expression_t
*array_expr
= (binary_expression_t
*)expr
;
381 hres
= compile_expression(ctx
, array_expr
->expression1
);
385 hres
= compile_expression(ctx
, array_expr
->expression2
);
389 hres
= push_instr_uint(ctx
, OP_memberid
, flags
);
393 member_expression_t
*member_expr
= (member_expression_t
*)expr
;
395 hres
= compile_expression(ctx
, member_expr
->expression
);
399 /* FIXME: Potential optimization */
400 hres
= push_instr_str(ctx
, OP_str
, member_expr
->identifier
);
404 hres
= push_instr_uint(ctx
, OP_memberid
, flags
);
414 static HRESULT
compile_increment_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
, int n
)
418 if(!is_memberid_expr(expr
->expression
->type
)) {
419 hres
= compile_expression(ctx
, expr
->expression
);
423 return push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
426 hres
= compile_memberid_expression(ctx
, expr
->expression
, fdexNameEnsure
);
430 return push_instr_int(ctx
, op
, n
);
433 /* ECMA-262 3rd Edition 11.14 */
434 static HRESULT
compile_comma_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
)
438 hres
= compile_expression(ctx
, expr
->expression1
);
442 if(!push_instr(ctx
, OP_pop
))
443 return E_OUTOFMEMORY
;
445 return compile_expression(ctx
, expr
->expression2
);
448 /* ECMA-262 3rd Edition 11.11 */
449 static HRESULT
compile_logical_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
454 hres
= compile_expression(ctx
, expr
->expression1
);
458 instr
= push_instr(ctx
, op
);
460 return E_OUTOFMEMORY
;
462 hres
= compile_expression(ctx
, expr
->expression2
);
466 set_arg_uint(ctx
, instr
, ctx
->code_off
);
470 /* ECMA-262 3rd Edition 11.12 */
471 static HRESULT
compile_conditional_expression(compiler_ctx_t
*ctx
, conditional_expression_t
*expr
)
473 unsigned jmp_false
, jmp_end
;
476 hres
= compile_expression(ctx
, expr
->expression
);
480 jmp_false
= push_instr(ctx
, OP_cnd_z
);
482 return E_OUTOFMEMORY
;
484 hres
= compile_expression(ctx
, expr
->true_expression
);
488 jmp_end
= push_instr(ctx
, OP_jmp
);
490 return E_OUTOFMEMORY
;
492 set_arg_uint(ctx
, jmp_false
, ctx
->code_off
);
493 if(!push_instr(ctx
, OP_pop
))
494 return E_OUTOFMEMORY
;
496 hres
= compile_expression(ctx
, expr
->false_expression
);
500 set_arg_uint(ctx
, jmp_end
, ctx
->code_off
);
504 static HRESULT
compile_new_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
)
506 unsigned arg_cnt
= 0;
510 hres
= compile_expression(ctx
, expr
->expression
);
514 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
515 hres
= compile_expression(ctx
, arg
->expr
);
521 return push_instr_uint(ctx
, OP_new
, arg_cnt
);
524 static HRESULT
compile_call_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
, BOOL
*no_ret
)
526 unsigned arg_cnt
= 0;
532 if(is_memberid_expr(expr
->expression
->type
)) {
534 hres
= compile_memberid_expression(ctx
, expr
->expression
, 0);
537 hres
= compile_expression(ctx
, expr
->expression
);
543 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
544 hres
= compile_expression(ctx
, arg
->expr
);
550 instr
= push_instr(ctx
, op
);
552 return E_OUTOFMEMORY
;
554 instr_ptr(ctx
, instr
)->u
.arg
[0].uint
= arg_cnt
;
555 instr_ptr(ctx
, instr
)->u
.arg
[1].lng
= no_ret
== NULL
;
561 static HRESULT
compile_delete_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
565 switch(expr
->expression
->type
) {
567 binary_expression_t
*array_expr
= (binary_expression_t
*)expr
->expression
;
569 hres
= compile_expression(ctx
, array_expr
->expression1
);
573 hres
= compile_expression(ctx
, array_expr
->expression2
);
577 if(!push_instr(ctx
, OP_delete
))
578 return E_OUTOFMEMORY
;
582 member_expression_t
*member_expr
= (member_expression_t
*)expr
->expression
;
584 hres
= compile_expression(ctx
, member_expr
->expression
);
588 /* FIXME: Potential optimization */
589 hres
= push_instr_str(ctx
, OP_str
, member_expr
->identifier
);
593 if(!push_instr(ctx
, OP_delete
))
594 return E_OUTOFMEMORY
;
598 return push_instr_bstr(ctx
, OP_delete_ident
, ((identifier_expression_t
*)expr
->expression
)->identifier
);
600 const WCHAR fixmeW
[] = {'F','I','X','M','E',0};
602 WARN("invalid delete, unimplemented exception message\n");
604 hres
= compile_expression(ctx
, expr
->expression
);
608 return push_instr_uint_str(ctx
, OP_throw_type
, JS_E_INVALID_DELETE
, fixmeW
);
615 static HRESULT
compile_assign_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
617 BOOL use_throw_path
= FALSE
;
618 unsigned arg_cnt
= 0;
621 if(expr
->expression1
->type
== EXPR_CALL
) {
622 call_expression_t
*call_expr
= (call_expression_t
*)expr
->expression1
;
626 FIXME("op %d not supported on parametrized assign expressions\n", op
);
630 if(is_memberid_expr(call_expr
->expression
->type
) && call_expr
->argument_list
) {
631 hres
= compile_memberid_expression(ctx
, call_expr
->expression
, fdexNameEnsure
);
635 for(arg
= call_expr
->argument_list
; arg
; arg
= arg
->next
) {
636 hres
= compile_expression(ctx
, arg
->expr
);
642 use_throw_path
= TRUE
;
644 }else if(is_memberid_expr(expr
->expression1
->type
)) {
645 hres
= compile_memberid_expression(ctx
, expr
->expression1
, fdexNameEnsure
);
649 use_throw_path
= TRUE
;
653 /* Illegal assignment: evaluate and throw */
654 hres
= compile_expression(ctx
, expr
->expression1
);
658 hres
= compile_expression(ctx
, expr
->expression2
);
662 if(op
!= OP_LAST
&& !push_instr(ctx
, op
))
663 return E_OUTOFMEMORY
;
665 return push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
668 if(op
!= OP_LAST
&& !push_instr(ctx
, OP_refval
))
669 return E_OUTOFMEMORY
;
671 hres
= compile_expression(ctx
, expr
->expression2
);
675 if(op
!= OP_LAST
&& !push_instr(ctx
, op
))
676 return E_OUTOFMEMORY
;
679 return push_instr_uint(ctx
, OP_assign_call
, arg_cnt
);
681 if(!push_instr(ctx
, OP_assign
))
682 return E_OUTOFMEMORY
;
687 static HRESULT
compile_typeof_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
692 if(is_memberid_expr(expr
->expression
->type
)) {
693 if(expr
->expression
->type
== EXPR_IDENT
)
694 return push_instr_str(ctx
, OP_typeofident
, ((identifier_expression_t
*)expr
->expression
)->identifier
);
697 hres
= compile_memberid_expression(ctx
, expr
->expression
, 0);
700 hres
= compile_expression(ctx
, expr
->expression
);
705 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
708 static HRESULT
compile_literal(compiler_ctx_t
*ctx
, literal_t
*literal
)
710 switch(literal
->type
) {
712 return push_instr_int(ctx
, OP_bool
, literal
->u
.bval
);
714 return push_instr_double(ctx
, OP_double
, literal
->u
.dval
);
716 return push_instr_int(ctx
, OP_int
, literal
->u
.lval
);
718 return push_instr(ctx
, OP_null
) ? S_OK
: E_OUTOFMEMORY
;
720 return push_instr_str(ctx
, OP_str
, literal
->u
.wstr
);
725 str
= compiler_alloc(ctx
->code
, (literal
->u
.regexp
.str_len
+1)*sizeof(WCHAR
));
727 return E_OUTOFMEMORY
;
728 memcpy(str
, literal
->u
.regexp
.str
, literal
->u
.regexp
.str_len
*sizeof(WCHAR
));
729 str
[literal
->u
.regexp
.str_len
] = 0;
731 instr
= push_instr(ctx
, OP_regexp
);
733 return E_OUTOFMEMORY
;
735 instr_ptr(ctx
, instr
)->u
.arg
[0].str
= str
;
736 instr_ptr(ctx
, instr
)->u
.arg
[1].uint
= literal
->u
.regexp
.flags
;
745 static HRESULT
literal_as_bstr(compiler_ctx_t
*ctx
, literal_t
*literal
, BSTR
*str
)
747 switch(literal
->type
) {
749 *str
= compiler_alloc_bstr(ctx
, literal
->u
.wstr
);
752 *str
= int_to_bstr(literal
->u
.lval
);
755 return double_to_bstr(literal
->u
.dval
, str
);
760 return *str
? S_OK
: E_OUTOFMEMORY
;
763 static HRESULT
compile_array_literal(compiler_ctx_t
*ctx
, array_literal_expression_t
*expr
)
765 unsigned i
, elem_cnt
= expr
->length
;
766 array_element_t
*iter
;
769 for(iter
= expr
->element_list
; iter
; iter
= iter
->next
) {
770 elem_cnt
+= iter
->elision
+1;
772 for(i
=0; i
< iter
->elision
; i
++) {
773 if(!push_instr(ctx
, OP_undefined
))
774 return E_OUTOFMEMORY
;
777 hres
= compile_expression(ctx
, iter
->expr
);
782 for(i
=0; i
< expr
->length
; i
++) {
783 if(!push_instr(ctx
, OP_undefined
))
784 return E_OUTOFMEMORY
;
787 return push_instr_uint(ctx
, OP_carray
, elem_cnt
);
790 static HRESULT
compile_object_literal(compiler_ctx_t
*ctx
, property_value_expression_t
*expr
)
797 if(!push_instr(ctx
, OP_new_obj
))
798 return E_OUTOFMEMORY
;
800 for(iter
= expr
->property_list
; iter
; iter
= iter
->next
) {
801 hres
= literal_as_bstr(ctx
, iter
->name
, &name
);
805 hres
= compile_expression(ctx
, iter
->value
);
809 instr
= push_instr(ctx
, OP_obj_prop
);
811 return E_OUTOFMEMORY
;
813 instr_ptr(ctx
, instr
)->u
.arg
->bstr
= name
;
819 static HRESULT
compile_function_expression(compiler_ctx_t
*ctx
, function_expression_t
*expr
)
821 ctx
->func_tail
= ctx
->func_tail
? (ctx
->func_tail
->next
= expr
) : (ctx
->func_head
= expr
);
823 /* FIXME: not exactly right */
824 if(expr
->identifier
) {
825 ctx
->func
->func_cnt
++;
826 return push_instr_bstr(ctx
, OP_ident
, expr
->identifier
);
829 return push_instr_uint(ctx
, OP_func
, ctx
->func
->func_cnt
++);
832 static HRESULT
compile_expression_noret(compiler_ctx_t
*ctx
, expression_t
*expr
, BOOL
*no_ret
)
836 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
838 return compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_cnd_z
);
840 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_array
);
842 return compile_array_literal(ctx
, (array_literal_expression_t
*)expr
);
844 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_LAST
);
846 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
848 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
850 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
852 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
854 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
856 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
858 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
859 case EXPR_ASSIGNLSHIFT
:
860 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_lshift
);
861 case EXPR_ASSIGNRSHIFT
:
862 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift
);
863 case EXPR_ASSIGNRRSHIFT
:
864 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift2
);
866 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
868 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
870 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_bneg
);
872 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
874 return compile_call_expression(ctx
, (call_expression_t
*)expr
, no_ret
);
876 return compile_comma_expression(ctx
, (binary_expression_t
*)expr
);
878 return compile_conditional_expression(ctx
, (conditional_expression_t
*)expr
);
880 return compile_delete_expression(ctx
, (unary_expression_t
*)expr
);
882 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
884 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq
);
886 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq2
);
888 return compile_function_expression(ctx
, (function_expression_t
*)expr
);
890 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gt
);
892 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gteq
);
894 return push_instr_bstr(ctx
, OP_ident
, ((identifier_expression_t
*)expr
)->identifier
);
896 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_in
);
897 case EXPR_INSTANCEOF
:
898 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_instanceof
);
900 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lt
);
902 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lteq
);
904 return compile_literal(ctx
, ((literal_expression_t
*)expr
)->literal
);
906 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_neg
);
908 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lshift
);
910 return compile_member_expression(ctx
, (member_expression_t
*)expr
);
912 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_minus
);
914 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
916 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
918 return compile_new_expression(ctx
, (call_expression_t
*)expr
);
920 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq
);
922 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq2
);
924 return compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_cnd_nz
);
926 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_tonum
);
928 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_postinc
, -1);
930 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_postinc
, 1);
932 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_preinc
, -1);
934 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_preinc
, 1);
936 return compile_object_literal(ctx
, (property_value_expression_t
*)expr
);
938 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift
);
940 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift2
);
942 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
944 return push_instr(ctx
, OP_this
) ? S_OK
: E_OUTOFMEMORY
;
946 return compile_typeof_expression(ctx
, (unary_expression_t
*)expr
);
948 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_void
);
950 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
958 static HRESULT
compile_expression(compiler_ctx_t
*ctx
, expression_t
*expr
)
960 return compile_expression_noret(ctx
, expr
, NULL
);
963 static inline BOOL
is_loop_statement(statement_type_t type
)
965 return type
== STAT_FOR
|| type
== STAT_FORIN
|| type
== STAT_WHILE
;
968 /* ECMA-262 3rd Edition 12.1 */
969 static HRESULT
compile_block_statement(compiler_ctx_t
*ctx
, statement_t
*iter
)
973 /* FIXME: do it only if needed */
975 return push_instr(ctx
, OP_undefined
) ? S_OK
: E_OUTOFMEMORY
;
978 hres
= compile_statement(ctx
, NULL
, iter
);
986 if(!push_instr(ctx
, OP_pop
))
987 return E_OUTOFMEMORY
;
993 /* ECMA-262 3rd Edition 12.2 */
994 static HRESULT
compile_variable_list(compiler_ctx_t
*ctx
, variable_declaration_t
*list
)
996 variable_declaration_t
*iter
;
999 assert(list
!= NULL
);
1002 ctx
->var_tail
->global_next
= list
;
1004 ctx
->var_head
= list
;
1006 for(iter
= list
; iter
; iter
= iter
->next
) {
1007 ctx
->func
->var_cnt
++;
1008 iter
->global_next
= iter
->next
;
1010 ctx
->var_tail
= iter
;
1015 hres
= compile_expression(ctx
, iter
->expr
);
1019 hres
= push_instr_bstr(ctx
, OP_var_set
, iter
->identifier
);
1027 /* ECMA-262 3rd Edition 12.2 */
1028 static HRESULT
compile_var_statement(compiler_ctx_t
*ctx
, var_statement_t
*stat
)
1032 hres
= compile_variable_list(ctx
, stat
->variable_list
);
1036 return push_instr(ctx
, OP_undefined
) ? S_OK
: E_OUTOFMEMORY
;
1039 /* ECMA-262 3rd Edition 12.4 */
1040 static HRESULT
compile_expression_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1042 BOOL no_ret
= FALSE
;
1045 hres
= compile_expression_noret(ctx
, stat
->expr
, &no_ret
);
1049 /* FIXME: that's a big potential optimization */
1050 if(no_ret
&& !push_instr(ctx
, OP_undefined
))
1051 return E_OUTOFMEMORY
;
1056 /* ECMA-262 3rd Edition 12.5 */
1057 static HRESULT
compile_if_statement(compiler_ctx_t
*ctx
, if_statement_t
*stat
)
1059 unsigned jmp_else
, jmp_end
;
1062 hres
= compile_expression(ctx
, stat
->expr
);
1066 jmp_else
= push_instr(ctx
, OP_jmp_z
);
1068 return E_OUTOFMEMORY
;
1070 hres
= compile_statement(ctx
, NULL
, stat
->if_stat
);
1074 jmp_end
= push_instr(ctx
, OP_jmp
);
1076 return E_OUTOFMEMORY
;
1078 set_arg_uint(ctx
, jmp_else
, ctx
->code_off
);
1080 if(stat
->else_stat
) {
1081 hres
= compile_statement(ctx
, NULL
, stat
->else_stat
);
1085 /* FIXME: We could sometimes avoid it */
1086 if(!push_instr(ctx
, OP_undefined
))
1087 return E_OUTOFMEMORY
;
1090 set_arg_uint(ctx
, jmp_end
, ctx
->code_off
);
1094 /* ECMA-262 3rd Edition 12.6.2 */
1095 static HRESULT
compile_while_statement(compiler_ctx_t
*ctx
, while_statement_t
*stat
)
1097 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1101 stat_ctx
.break_label
= alloc_label(ctx
);
1102 if(!stat_ctx
.break_label
)
1103 return E_OUTOFMEMORY
;
1105 stat_ctx
.continue_label
= alloc_label(ctx
);
1106 if(!stat_ctx
.continue_label
)
1107 return E_OUTOFMEMORY
;
1109 if(!stat
->do_while
) {
1111 if(!push_instr(ctx
, OP_undefined
))
1112 return E_OUTOFMEMORY
;
1114 jmp_off
= ctx
->code_off
;
1115 label_set_addr(ctx
, stat_ctx
.continue_label
);
1116 hres
= compile_expression(ctx
, stat
->expr
);
1120 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1124 if(!push_instr(ctx
, OP_pop
))
1125 return E_OUTOFMEMORY
;
1127 jmp_off
= ctx
->code_off
;
1130 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1134 if(stat
->do_while
) {
1135 label_set_addr(ctx
, stat_ctx
.continue_label
);
1136 hres
= compile_expression(ctx
, stat
->expr
);
1140 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1144 if(!push_instr(ctx
, OP_pop
))
1145 return E_OUTOFMEMORY
;
1148 hres
= push_instr_uint(ctx
, OP_jmp
, jmp_off
);
1152 label_set_addr(ctx
, stat_ctx
.break_label
);
1156 /* ECMA-262 3rd Edition 12.6.3 */
1157 static HRESULT
compile_for_statement(compiler_ctx_t
*ctx
, for_statement_t
*stat
)
1159 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1163 if(stat
->variable_list
) {
1164 hres
= compile_variable_list(ctx
, stat
->variable_list
);
1167 }else if(stat
->begin_expr
) {
1168 BOOL no_ret
= FALSE
;
1170 hres
= compile_expression_noret(ctx
, stat
->begin_expr
, &no_ret
);
1173 if(!no_ret
&& !push_instr(ctx
, OP_pop
))
1174 return E_OUTOFMEMORY
;
1177 stat_ctx
.break_label
= alloc_label(ctx
);
1178 if(!stat_ctx
.break_label
)
1179 return E_OUTOFMEMORY
;
1181 stat_ctx
.continue_label
= alloc_label(ctx
);
1182 if(!stat_ctx
.continue_label
)
1183 return E_OUTOFMEMORY
;
1186 if(!push_instr(ctx
, OP_undefined
))
1187 return E_OUTOFMEMORY
;
1189 expr_off
= ctx
->code_off
;
1192 hres
= compile_expression(ctx
, stat
->expr
);
1196 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1201 if(!push_instr(ctx
, OP_pop
))
1202 return E_OUTOFMEMORY
;
1204 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1208 label_set_addr(ctx
, stat_ctx
.continue_label
);
1210 if(stat
->end_expr
) {
1211 BOOL no_ret
= FALSE
;
1213 hres
= compile_expression_noret(ctx
, stat
->end_expr
, &no_ret
);
1217 if(!no_ret
&& !push_instr(ctx
, OP_pop
))
1218 return E_OUTOFMEMORY
;
1221 hres
= push_instr_uint(ctx
, OP_jmp
, expr_off
);
1225 label_set_addr(ctx
, stat_ctx
.break_label
);
1229 /* ECMA-262 3rd Edition 12.6.4 */
1230 static HRESULT
compile_forin_statement(compiler_ctx_t
*ctx
, forin_statement_t
*stat
)
1232 statement_ctx_t stat_ctx
= {4, FALSE
, FALSE
};
1235 if(stat
->variable
) {
1236 hres
= compile_variable_list(ctx
, stat
->variable
);
1241 stat_ctx
.break_label
= alloc_label(ctx
);
1242 if(!stat_ctx
.break_label
)
1243 return E_OUTOFMEMORY
;
1245 stat_ctx
.continue_label
= alloc_label(ctx
);
1246 if(!stat_ctx
.continue_label
)
1247 return E_OUTOFMEMORY
;
1249 hres
= compile_expression(ctx
, stat
->in_expr
);
1253 if(stat
->variable
) {
1254 hres
= push_instr_bstr_uint(ctx
, OP_identid
, stat
->variable
->identifier
, fdexNameEnsure
);
1257 }else if(is_memberid_expr(stat
->expr
->type
)) {
1258 hres
= compile_memberid_expression(ctx
, stat
->expr
, fdexNameEnsure
);
1262 hres
= push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
1266 /* FIXME: compile statement anyways when we depend on compiler to check errors */
1270 hres
= push_instr_int(ctx
, OP_int
, DISPID_STARTENUM
);
1275 if(!push_instr(ctx
, OP_undefined
))
1276 return E_OUTOFMEMORY
;
1278 label_set_addr(ctx
, stat_ctx
.continue_label
);
1279 hres
= push_instr_uint(ctx
, OP_forin
, stat_ctx
.break_label
);
1281 return E_OUTOFMEMORY
;
1283 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1287 hres
= push_instr_uint(ctx
, OP_jmp
, stat_ctx
.continue_label
);
1291 label_set_addr(ctx
, stat_ctx
.break_label
);
1295 static HRESULT
pop_to_stat(compiler_ctx_t
*ctx
, statement_ctx_t
*stat_ctx
)
1297 unsigned stack_pop
= 0;
1298 statement_ctx_t
*iter
;
1300 for(iter
= ctx
->stat_ctx
; iter
!= stat_ctx
; iter
= iter
->next
) {
1301 if(iter
->using_scope
&& !push_instr(ctx
, OP_pop_scope
))
1302 return E_OUTOFMEMORY
;
1303 if(iter
->using_except
&& !push_instr(ctx
, OP_pop_except
))
1304 return E_OUTOFMEMORY
;
1305 stack_pop
+= iter
->stack_use
;
1308 /* FIXME: optimize */
1309 while(stack_pop
--) {
1310 if(!push_instr(ctx
, OP_pop
))
1311 return E_OUTOFMEMORY
;
1317 /* ECMA-262 3rd Edition 12.7 */
1318 static HRESULT
compile_continue_statement(compiler_ctx_t
*ctx
, branch_statement_t
*stat
)
1320 statement_ctx_t
*pop_ctx
;
1323 if(stat
->identifier
) {
1324 statement_t
*label_stat
;
1325 statement_ctx_t
*iter
;
1329 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1330 if(iter
->continue_label
)
1332 if(iter
->labelled_stat
&& !strcmpW(iter
->labelled_stat
->identifier
, stat
->identifier
))
1337 WARN("Label not found\n");
1338 return JS_E_LABEL_NOT_FOUND
;
1341 /* Labelled continue are allowed only on loops */
1342 for(label_stat
= iter
->labelled_stat
->statement
;
1343 label_stat
->type
== STAT_LABEL
;
1344 label_stat
= ((labelled_statement_t
*)label_stat
)->statement
);
1345 if(!is_loop_statement(label_stat
->type
)) {
1346 WARN("Label is not a loop\n");
1347 return JS_E_INVALID_CONTINUE
;
1350 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1351 if(pop_ctx
->continue_label
)
1356 WARN("continue outside loop\n");
1357 return JS_E_INVALID_CONTINUE
;
1361 hres
= pop_to_stat(ctx
, pop_ctx
);
1365 if(!push_instr(ctx
, OP_undefined
))
1366 return E_OUTOFMEMORY
;
1368 return push_instr_uint(ctx
, OP_jmp
, pop_ctx
->continue_label
);
1371 /* ECMA-262 3rd Edition 12.8 */
1372 static HRESULT
compile_break_statement(compiler_ctx_t
*ctx
, branch_statement_t
*stat
)
1374 statement_ctx_t
*pop_ctx
;
1377 if(stat
->identifier
) {
1378 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1379 if(pop_ctx
->labelled_stat
&& !strcmpW(pop_ctx
->labelled_stat
->identifier
, stat
->identifier
)) {
1380 assert(pop_ctx
->break_label
);
1386 WARN("Label not found\n");
1387 return JS_E_LABEL_NOT_FOUND
;
1390 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1391 if(pop_ctx
->break_label
&& !pop_ctx
->labelled_stat
)
1396 WARN("Break outside loop\n");
1397 return JS_E_INVALID_BREAK
;
1401 hres
= pop_to_stat(ctx
, pop_ctx
->next
);
1405 if(!push_instr(ctx
, OP_undefined
))
1406 return E_OUTOFMEMORY
;
1408 return push_instr_uint(ctx
, OP_jmp
, pop_ctx
->break_label
);
1411 /* ECMA-262 3rd Edition 12.9 */
1412 static HRESULT
compile_return_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1416 hres
= pop_to_stat(ctx
, NULL
);
1421 hres
= compile_expression(ctx
, stat
->expr
);
1426 return push_instr(ctx
, OP_ret
) ? S_OK
: E_OUTOFMEMORY
;
1429 /* ECMA-262 3rd Edition 12.10 */
1430 static HRESULT
compile_with_statement(compiler_ctx_t
*ctx
, with_statement_t
*stat
)
1432 statement_ctx_t stat_ctx
= {0, TRUE
, FALSE
};
1435 hres
= compile_expression(ctx
, stat
->expr
);
1439 if(!push_instr(ctx
, OP_push_scope
))
1440 return E_OUTOFMEMORY
;
1442 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1446 if(!push_instr(ctx
, OP_pop_scope
))
1447 return E_OUTOFMEMORY
;
1452 /* ECMA-262 3rd Edition 12.10 */
1453 static HRESULT
compile_labelled_statement(compiler_ctx_t
*ctx
, labelled_statement_t
*stat
)
1455 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
, 0, 0, stat
}, *iter
;
1458 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1459 if(iter
->labelled_stat
&& !strcmpW(iter
->labelled_stat
->identifier
, stat
->identifier
)) {
1460 WARN("Label %s redefined\n", debugstr_w(stat
->identifier
));
1461 return JS_E_LABEL_REDEFINED
;
1465 /* Labelled breaks are allowed for any labelled statements, not only loops (violating spec) */
1466 stat_ctx
.break_label
= alloc_label(ctx
);
1467 if(!stat_ctx
.break_label
)
1468 return E_OUTOFMEMORY
;
1470 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1474 label_set_addr(ctx
, stat_ctx
.break_label
);
1478 /* ECMA-262 3rd Edition 12.13 */
1479 static HRESULT
compile_switch_statement(compiler_ctx_t
*ctx
, switch_statement_t
*stat
)
1481 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1482 unsigned case_cnt
= 0, *case_jmps
, i
, default_jmp
;
1483 BOOL have_default
= FALSE
;
1484 statement_t
*stat_iter
;
1485 case_clausule_t
*iter
;
1488 hres
= compile_expression(ctx
, stat
->expr
);
1492 stat_ctx
.break_label
= alloc_label(ctx
);
1493 if(!stat_ctx
.break_label
)
1494 return E_OUTOFMEMORY
;
1496 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1501 case_jmps
= heap_alloc(case_cnt
* sizeof(*case_jmps
));
1503 return E_OUTOFMEMORY
;
1506 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1508 have_default
= TRUE
;
1512 hres
= compile_expression(ctx
, iter
->expr
);
1516 case_jmps
[i
] = push_instr(ctx
, OP_case
);
1518 hres
= E_OUTOFMEMORY
;
1524 if(SUCCEEDED(hres
)) {
1525 if(push_instr(ctx
, OP_pop
)) {
1526 default_jmp
= push_instr(ctx
, OP_jmp
);
1528 hres
= E_OUTOFMEMORY
;
1530 hres
= E_OUTOFMEMORY
;
1535 heap_free(case_jmps
);
1540 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1541 while(iter
->next
&& iter
->next
->stat
== iter
->stat
) {
1542 set_arg_uint(ctx
, iter
->expr
? case_jmps
[i
++] : default_jmp
, ctx
->code_off
);
1546 set_arg_uint(ctx
, iter
->expr
? case_jmps
[i
++] : default_jmp
, ctx
->code_off
);
1548 for(stat_iter
= iter
->stat
; stat_iter
&& (!iter
->next
|| iter
->next
->stat
!= stat_iter
); stat_iter
= stat_iter
->next
) {
1549 hres
= compile_statement(ctx
, &stat_ctx
, stat_iter
);
1553 if(stat_iter
->next
&& !push_instr(ctx
, OP_pop
)) {
1554 hres
= E_OUTOFMEMORY
;
1562 heap_free(case_jmps
);
1565 assert(i
== case_cnt
);
1568 hres
= push_instr_uint(ctx
, OP_jmp
, stat_ctx
.break_label
);
1571 set_arg_uint(ctx
, default_jmp
, ctx
->code_off
);
1572 if(!push_instr(ctx
, OP_undefined
))
1573 return E_OUTOFMEMORY
;
1576 label_set_addr(ctx
, stat_ctx
.break_label
);
1580 /* ECMA-262 3rd Edition 12.13 */
1581 static HRESULT
compile_throw_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1585 hres
= compile_expression(ctx
, stat
->expr
);
1589 return push_instr(ctx
, OP_throw
) ? S_OK
: E_OUTOFMEMORY
;
1592 /* ECMA-262 3rd Edition 12.14 */
1593 static HRESULT
compile_try_statement(compiler_ctx_t
*ctx
, try_statement_t
*stat
)
1595 statement_ctx_t try_ctx
= {0, FALSE
, TRUE
}, catch_ctx
= {0, TRUE
, FALSE
};
1596 statement_ctx_t finally_ctx
= {2, FALSE
, FALSE
};
1597 unsigned push_except
;
1601 push_except
= push_instr(ctx
, OP_push_except
);
1603 return E_OUTOFMEMORY
;
1605 if(stat
->catch_block
) {
1606 ident
= compiler_alloc_bstr(ctx
, stat
->catch_block
->identifier
);
1608 return E_OUTOFMEMORY
;
1613 instr_ptr(ctx
, push_except
)->u
.arg
[1].bstr
= ident
;
1615 if(!stat
->catch_block
)
1616 try_ctx
.stack_use
= 2;
1618 hres
= compile_statement(ctx
, &try_ctx
, stat
->try_statement
);
1622 if(!push_instr(ctx
, OP_pop_except
))
1623 return E_OUTOFMEMORY
;
1625 if(stat
->catch_block
) {
1626 unsigned jmp_finally
;
1628 jmp_finally
= push_instr(ctx
, OP_jmp
);
1630 return E_OUTOFMEMORY
;
1632 instr_ptr(ctx
, push_except
)->u
.arg
[0].uint
= ctx
->code_off
;
1634 hres
= compile_statement(ctx
, &catch_ctx
, stat
->catch_block
->statement
);
1638 if(!push_instr(ctx
, OP_pop_scope
))
1639 return E_OUTOFMEMORY
;
1641 set_arg_uint(ctx
, jmp_finally
, ctx
->code_off
);
1643 set_arg_uint(ctx
, push_except
, ctx
->code_off
);
1646 if(stat
->finally_statement
) {
1648 if(!push_instr(ctx
, OP_pop
))
1649 return E_OUTOFMEMORY
;
1651 hres
= compile_statement(ctx
, stat
->catch_block
? NULL
: &finally_ctx
, stat
->finally_statement
);
1655 if(!stat
->catch_block
&& !push_instr(ctx
, OP_end_finally
))
1656 return E_OUTOFMEMORY
;
1662 static HRESULT
compile_statement(compiler_ctx_t
*ctx
, statement_ctx_t
*stat_ctx
, statement_t
*stat
)
1667 stat_ctx
->next
= ctx
->stat_ctx
;
1668 ctx
->stat_ctx
= stat_ctx
;
1671 switch(stat
->type
) {
1673 hres
= compile_block_statement(ctx
, ((block_statement_t
*)stat
)->stat_list
);
1676 hres
= compile_break_statement(ctx
, (branch_statement_t
*)stat
);
1679 hres
= compile_continue_statement(ctx
, (branch_statement_t
*)stat
);
1682 hres
= push_instr(ctx
, OP_undefined
) ? S_OK
: E_OUTOFMEMORY
; /* FIXME */
1685 hres
= compile_expression_statement(ctx
, (expression_statement_t
*)stat
);
1688 hres
= compile_for_statement(ctx
, (for_statement_t
*)stat
);
1691 hres
= compile_forin_statement(ctx
, (forin_statement_t
*)stat
);
1694 hres
= compile_if_statement(ctx
, (if_statement_t
*)stat
);
1697 hres
= compile_labelled_statement(ctx
, (labelled_statement_t
*)stat
);
1700 hres
= compile_return_statement(ctx
, (expression_statement_t
*)stat
);
1703 hres
= compile_switch_statement(ctx
, (switch_statement_t
*)stat
);
1706 hres
= compile_throw_statement(ctx
, (expression_statement_t
*)stat
);
1709 hres
= compile_try_statement(ctx
, (try_statement_t
*)stat
);
1712 hres
= compile_var_statement(ctx
, (var_statement_t
*)stat
);
1715 hres
= compile_while_statement(ctx
, (while_statement_t
*)stat
);
1718 hres
= compile_with_statement(ctx
, (with_statement_t
*)stat
);
1726 assert(ctx
->stat_ctx
== stat_ctx
);
1727 ctx
->stat_ctx
= stat_ctx
->next
;
1733 static void resolve_labels(compiler_ctx_t
*ctx
, unsigned off
)
1737 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->code_off
; instr
++) {
1738 if(instr_info
[instr
->op
].arg1_type
== ARG_ADDR
&& (instr
->u
.arg
->uint
& LABEL_FLAG
)) {
1739 assert((instr
->u
.arg
->uint
& ~LABEL_FLAG
) < ctx
->labels_cnt
);
1740 instr
->u
.arg
->uint
= ctx
->labels
[instr
->u
.arg
->uint
& ~LABEL_FLAG
];
1742 assert(instr_info
[instr
->op
].arg2_type
!= ARG_ADDR
);
1745 ctx
->labels_cnt
= 0;
1748 void release_bytecode(bytecode_t
*code
)
1755 for(i
=0; i
< code
->bstr_cnt
; i
++)
1756 SysFreeString(code
->bstr_pool
[i
]);
1758 heap_free(code
->source
);
1759 jsheap_free(&code
->heap
);
1760 heap_free(code
->bstr_pool
);
1761 heap_free(code
->instrs
);
1765 static HRESULT
init_code(compiler_ctx_t
*compiler
, const WCHAR
*source
)
1767 compiler
->code
= heap_alloc_zero(sizeof(bytecode_t
));
1769 return E_OUTOFMEMORY
;
1771 compiler
->code
->ref
= 1;
1772 jsheap_init(&compiler
->code
->heap
);
1774 compiler
->code
->source
= heap_strdupW(source
);
1775 if(!compiler
->code
->source
) {
1776 release_bytecode(compiler
->code
);
1777 return E_OUTOFMEMORY
;
1780 compiler
->code
->instrs
= heap_alloc(64 * sizeof(instr_t
));
1781 if(!compiler
->code
->instrs
) {
1782 release_bytecode(compiler
->code
);
1783 return E_OUTOFMEMORY
;
1786 compiler
->code_size
= 64;
1787 compiler
->code_off
= 1;
1791 static HRESULT
compile_function(compiler_ctx_t
*ctx
, source_elements_t
*source
, function_expression_t
*func_expr
,
1792 BOOL from_eval
, function_code_t
*func
)
1794 variable_declaration_t
*var_iter
;
1795 function_expression_t
*iter
;
1801 ctx
->var_head
= ctx
->var_tail
= NULL
;
1802 ctx
->func_head
= ctx
->func_tail
= NULL
;
1804 off
= ctx
->code_off
;
1806 hres
= compile_block_statement(ctx
, source
->statement
);
1810 resolve_labels(ctx
, off
);
1812 if(!from_eval
&& !push_instr(ctx
, OP_pop
))
1813 return E_OUTOFMEMORY
;
1814 if(!push_instr(ctx
, OP_ret
))
1815 return E_OUTOFMEMORY
;
1817 if(TRACE_ON(jscript_disas
))
1818 dump_code(ctx
, off
);
1820 func
->instr_off
= off
;
1822 if(func_expr
&& func_expr
->identifier
) {
1823 func
->name
= compiler_alloc_bstr(ctx
, func_expr
->identifier
);
1825 return E_OUTOFMEMORY
;
1829 parameter_t
*param_iter
;
1831 func
->source
= func_expr
->src_str
;
1832 func
->source_len
= func_expr
->src_len
;
1834 for(param_iter
= func_expr
->parameter_list
; param_iter
; param_iter
= param_iter
->next
)
1837 func
->params
= compiler_alloc(ctx
->code
, func
->param_cnt
* sizeof(*func
->params
));
1839 return E_OUTOFMEMORY
;
1841 for(param_iter
= func_expr
->parameter_list
, i
=0; param_iter
; param_iter
= param_iter
->next
, i
++) {
1842 func
->params
[i
] = compiler_alloc_bstr(ctx
, param_iter
->identifier
);
1843 if(!func
->params
[i
])
1844 return E_OUTOFMEMORY
;
1848 func
->variables
= compiler_alloc(ctx
->code
, func
->var_cnt
* sizeof(*func
->variables
));
1849 if(!func
->variables
)
1850 return E_OUTOFMEMORY
;
1852 for(var_iter
= ctx
->var_head
, i
=0; var_iter
; var_iter
= var_iter
->global_next
, i
++) {
1853 func
->variables
[i
] = compiler_alloc_bstr(ctx
, var_iter
->identifier
);
1854 if(!func
->variables
[i
])
1855 return E_OUTOFMEMORY
;
1858 assert(i
== func
->var_cnt
);
1860 func
->funcs
= compiler_alloc(ctx
->code
, func
->func_cnt
* sizeof(*func
->funcs
));
1862 return E_OUTOFMEMORY
;
1863 memset(func
->funcs
, 0, func
->func_cnt
* sizeof(*func
->funcs
));
1865 for(iter
= ctx
->func_head
, i
=0; iter
; iter
= iter
->next
, i
++) {
1866 hres
= compile_function(ctx
, iter
->source_elements
, iter
, FALSE
, func
->funcs
+i
);
1871 assert(i
== func
->func_cnt
);
1876 HRESULT
compile_script(script_ctx_t
*ctx
, const WCHAR
*code
, const WCHAR
*delimiter
, BOOL from_eval
, BOOL use_decode
,
1879 compiler_ctx_t compiler
= {0};
1882 hres
= init_code(&compiler
, code
);
1887 hres
= decode_source(compiler
.code
->source
);
1889 WARN("Decoding failed\n");
1894 hres
= script_parse(ctx
, compiler
.code
->source
, delimiter
, from_eval
, &compiler
.parser
);
1896 release_bytecode(compiler
.code
);
1900 hres
= compile_function(&compiler
, compiler
.parser
->source
, NULL
, from_eval
, &compiler
.code
->global_code
);
1901 parser_release(compiler
.parser
);
1903 release_bytecode(compiler
.code
);
1907 *ret
= compiler
.code
;