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
);
29 struct _compiler_ctx_t
{
37 static HRESULT
compile_expression(compiler_ctx_t
*,expression_t
*);
38 static HRESULT
compile_statement(compiler_ctx_t
*,statement_t
*);
40 static inline void *compiler_alloc(bytecode_t
*code
, size_t size
)
42 return jsheap_alloc(&code
->heap
, size
);
45 static WCHAR
*compiler_alloc_string(bytecode_t
*code
, const WCHAR
*str
)
50 size
= (strlenW(str
)+1)*sizeof(WCHAR
);
51 ret
= compiler_alloc(code
, size
);
53 memcpy(ret
, str
, size
);
57 static BSTR
compiler_alloc_bstr(compiler_ctx_t
*ctx
, const WCHAR
*str
)
59 if(!ctx
->code
->bstr_pool_size
) {
60 ctx
->code
->bstr_pool
= heap_alloc(8 * sizeof(BSTR
));
61 if(!ctx
->code
->bstr_pool
)
63 ctx
->code
->bstr_pool_size
= 8;
64 }else if(ctx
->code
->bstr_pool_size
== ctx
->code
->bstr_cnt
) {
67 new_pool
= heap_realloc(ctx
->code
->bstr_pool
, ctx
->code
->bstr_pool_size
*2*sizeof(BSTR
));
71 ctx
->code
->bstr_pool
= new_pool
;
72 ctx
->code
->bstr_pool_size
*= 2;
75 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocString(str
);
76 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
79 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
82 static unsigned push_instr(compiler_ctx_t
*ctx
, jsop_t op
)
84 assert(ctx
->code_size
>= ctx
->code_off
);
87 ctx
->code
->instrs
= heap_alloc(64 * sizeof(instr_t
));
88 if(!ctx
->code
->instrs
)
91 }else if(ctx
->code_size
== ctx
->code_off
) {
94 new_instrs
= heap_realloc(ctx
->code
->instrs
, ctx
->code_size
*2*sizeof(instr_t
));
98 ctx
->code
->instrs
= new_instrs
;
102 ctx
->code
->instrs
[ctx
->code_off
].op
= op
;
103 return ctx
->code_off
++;
106 static inline instr_t
*instr_ptr(compiler_ctx_t
*ctx
, unsigned off
)
108 assert(off
< ctx
->code_off
);
109 return ctx
->code
->instrs
+ off
;
112 static HRESULT
push_instr_int(compiler_ctx_t
*ctx
, jsop_t op
, LONG arg
)
116 instr
= push_instr(ctx
, op
);
118 return E_OUTOFMEMORY
;
120 instr_ptr(ctx
, instr
)->arg1
.lng
= arg
;
124 static HRESULT
push_instr_str(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
129 str
= compiler_alloc_string(ctx
->code
, arg
);
131 return E_OUTOFMEMORY
;
133 instr
= push_instr(ctx
, op
);
135 return E_OUTOFMEMORY
;
137 instr_ptr(ctx
, instr
)->arg1
.str
= str
;
141 static HRESULT
push_instr_bstr(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
146 str
= compiler_alloc_bstr(ctx
, arg
);
148 return E_OUTOFMEMORY
;
150 instr
= push_instr(ctx
, op
);
152 return E_OUTOFMEMORY
;
154 instr_ptr(ctx
, instr
)->arg1
.bstr
= str
;
158 static HRESULT
push_instr_bstr_uint(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg1
, unsigned arg2
)
163 str
= compiler_alloc_bstr(ctx
, arg1
);
165 return E_OUTOFMEMORY
;
167 instr
= push_instr(ctx
, op
);
169 return E_OUTOFMEMORY
;
171 instr_ptr(ctx
, instr
)->arg1
.bstr
= str
;
172 instr_ptr(ctx
, instr
)->arg2
.uint
= arg2
;
176 static HRESULT
push_instr_uint_str(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg1
, const WCHAR
*arg2
)
181 str
= compiler_alloc_string(ctx
->code
, arg2
);
183 return E_OUTOFMEMORY
;
185 instr
= push_instr(ctx
, op
);
187 return E_OUTOFMEMORY
;
189 instr_ptr(ctx
, instr
)->arg1
.uint
= arg1
;
190 instr_ptr(ctx
, instr
)->arg2
.str
= str
;
194 static HRESULT
push_instr_double(compiler_ctx_t
*ctx
, jsop_t op
, double arg
)
199 dbl
= compiler_alloc(ctx
->code
, sizeof(arg
));
201 return E_OUTOFMEMORY
;
204 instr
= push_instr(ctx
, op
);
206 return E_OUTOFMEMORY
;
208 instr_ptr(ctx
, instr
)->arg1
.dbl
= dbl
;
212 static HRESULT
push_instr_uint(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg
)
216 instr
= push_instr(ctx
, op
);
218 return E_OUTOFMEMORY
;
220 instr_ptr(ctx
, instr
)->arg1
.uint
= arg
;
224 static HRESULT
compile_binary_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
228 hres
= compile_expression(ctx
, expr
->expression1
);
232 hres
= compile_expression(ctx
, expr
->expression2
);
236 return push_instr(ctx
, op
) == -1 ? E_OUTOFMEMORY
: S_OK
;
239 static HRESULT
compile_unary_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
)
243 hres
= compile_expression(ctx
, expr
->expression
);
247 return push_instr(ctx
, op
) == -1 ? E_OUTOFMEMORY
: S_OK
;
250 /* ECMA-262 3rd Edition 11.2.1 */
251 static HRESULT
compile_member_expression(compiler_ctx_t
*ctx
, member_expression_t
*expr
)
255 hres
= compile_expression(ctx
, expr
->expression
);
259 return push_instr_bstr(ctx
, OP_member
, expr
->identifier
);
262 static inline BOOL
is_memberid_expr(expression_type_t type
)
264 return type
== EXPR_IDENT
|| type
== EXPR_MEMBER
|| type
== EXPR_ARRAY
;
267 static HRESULT
compile_memberid_expression(compiler_ctx_t
*ctx
, expression_t
*expr
, unsigned flags
)
273 identifier_expression_t
*ident_expr
= (identifier_expression_t
*)expr
;
275 hres
= push_instr_bstr_uint(ctx
, OP_identid
, ident_expr
->identifier
, flags
);
279 binary_expression_t
*array_expr
= (binary_expression_t
*)expr
;
281 hres
= compile_expression(ctx
, array_expr
->expression1
);
285 hres
= compile_expression(ctx
, array_expr
->expression2
);
289 hres
= push_instr_uint(ctx
, OP_memberid
, flags
);
293 member_expression_t
*member_expr
= (member_expression_t
*)expr
;
295 hres
= compile_expression(ctx
, member_expr
->expression
);
299 /* FIXME: Potential optimization */
300 hres
= push_instr_str(ctx
, OP_str
, member_expr
->identifier
);
304 hres
= push_instr_uint(ctx
, OP_memberid
, flags
);
314 static HRESULT
compile_increment_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
, int n
)
318 if(!is_memberid_expr(expr
->expression
->type
)) {
319 hres
= compile_expression(ctx
, expr
->expression
);
323 return push_instr_uint(ctx
, OP_throw
, JS_E_ILLEGAL_ASSIGN
);
326 hres
= compile_memberid_expression(ctx
, expr
->expression
, fdexNameEnsure
);
330 return push_instr_int(ctx
, op
, n
);
333 /* ECMA-262 3rd Edition 11.14 */
334 static HRESULT
compile_comma_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
)
338 hres
= compile_expression(ctx
, expr
->expression1
);
342 if(push_instr(ctx
, OP_pop
) == -1)
343 return E_OUTOFMEMORY
;
345 return compile_expression(ctx
, expr
->expression2
);
348 /* ECMA-262 3rd Edition 11.11 */
349 static HRESULT
compile_logical_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
354 hres
= compile_expression(ctx
, expr
->expression1
);
358 instr
= push_instr(ctx
, op
);
360 return E_OUTOFMEMORY
;
362 hres
= compile_expression(ctx
, expr
->expression2
);
366 instr_ptr(ctx
, instr
)->arg1
.uint
= ctx
->code_off
;
370 /* ECMA-262 3rd Edition 11.12 */
371 static HRESULT
compile_conditional_expression(compiler_ctx_t
*ctx
, conditional_expression_t
*expr
)
373 unsigned jmp_false
, jmp_end
;
376 hres
= compile_expression(ctx
, expr
->expression
);
380 jmp_false
= push_instr(ctx
, OP_jmp_z
);
382 return E_OUTOFMEMORY
;
384 hres
= compile_expression(ctx
, expr
->true_expression
);
388 jmp_end
= push_instr(ctx
, OP_jmp
);
390 return E_OUTOFMEMORY
;
392 instr_ptr(ctx
, jmp_false
)->arg1
.uint
= ctx
->code_off
;
393 if(push_instr(ctx
, OP_pop
) == -1)
394 return E_OUTOFMEMORY
;
396 hres
= compile_expression(ctx
, expr
->false_expression
);
400 instr_ptr(ctx
, jmp_end
)->arg1
.uint
= ctx
->code_off
;
404 static HRESULT
compile_new_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
)
406 unsigned arg_cnt
= 0;
410 hres
= compile_expression(ctx
, expr
->expression
);
414 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
415 hres
= compile_expression(ctx
, arg
->expr
);
421 return push_instr_int(ctx
, OP_new
, arg_cnt
);
424 static HRESULT
compile_interp_fallback(compiler_ctx_t
*ctx
, statement_t
*stat
)
428 instr
= push_instr(ctx
, OP_tree
);
430 return E_OUTOFMEMORY
;
432 instr_ptr(ctx
, instr
)->arg1
.stat
= stat
;
436 static HRESULT
compile_call_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
, BOOL
*no_ret
)
438 unsigned arg_cnt
= 0;
444 if(is_memberid_expr(expr
->expression
->type
)) {
446 hres
= compile_memberid_expression(ctx
, expr
->expression
, 0);
449 hres
= compile_expression(ctx
, expr
->expression
);
455 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
456 hres
= compile_expression(ctx
, arg
->expr
);
462 instr
= push_instr(ctx
, op
);
464 return E_OUTOFMEMORY
;
466 instr_ptr(ctx
, instr
)->arg1
.uint
= arg_cnt
;
467 instr_ptr(ctx
, instr
)->arg2
.lng
= no_ret
== NULL
;
473 static HRESULT
compile_delete_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
477 switch(expr
->expression
->type
) {
479 binary_expression_t
*array_expr
= (binary_expression_t
*)expr
->expression
;
481 hres
= compile_expression(ctx
, array_expr
->expression1
);
485 hres
= compile_expression(ctx
, array_expr
->expression2
);
489 if(push_instr(ctx
, OP_delete
) == -1)
490 return E_OUTOFMEMORY
;
494 member_expression_t
*member_expr
= (member_expression_t
*)expr
->expression
;
496 hres
= compile_expression(ctx
, member_expr
->expression
);
500 /* FIXME: Potential optimization */
501 hres
= push_instr_str(ctx
, OP_str
, member_expr
->identifier
);
505 if(push_instr(ctx
, OP_delete
) == -1)
506 return E_OUTOFMEMORY
;
510 return push_instr_bstr(ctx
, OP_delete_ident
, ((identifier_expression_t
*)expr
->expression
)->identifier
);
512 const WCHAR fixmeW
[] = {'F','I','X','M','E',0};
514 WARN("invalid delete, unimplemented exception message\n");
516 hres
= compile_expression(ctx
, expr
->expression
);
520 return push_instr_uint_str(ctx
, OP_throw_type
, JS_E_INVALID_DELETE
, fixmeW
);
527 static HRESULT
compile_assign_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
531 if(!is_memberid_expr(expr
->expression1
->type
)) {
532 hres
= compile_expression(ctx
, expr
->expression1
);
536 hres
= compile_expression(ctx
, expr
->expression2
);
540 if(op
!= OP_LAST
&& push_instr(ctx
, op
) == -1)
541 return E_OUTOFMEMORY
;
543 return push_instr_uint(ctx
, OP_throw
, JS_E_ILLEGAL_ASSIGN
);
546 hres
= compile_memberid_expression(ctx
, expr
->expression1
, fdexNameEnsure
);
550 if(op
!= OP_LAST
&& push_instr(ctx
, OP_refval
) == -1)
551 return E_OUTOFMEMORY
;
553 hres
= compile_expression(ctx
, expr
->expression2
);
557 if(op
!= OP_LAST
&& push_instr(ctx
, op
) == -1)
558 return E_OUTOFMEMORY
;
560 if(push_instr(ctx
, OP_assign
) == -1)
561 return E_OUTOFMEMORY
;
566 static HRESULT
compile_typeof_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
571 if(is_memberid_expr(expr
->expression
->type
)) {
572 if(expr
->expression
->type
== EXPR_IDENT
)
573 return push_instr_str(ctx
, OP_typeofident
, ((identifier_expression_t
*)expr
->expression
)->identifier
);
576 hres
= compile_memberid_expression(ctx
, expr
->expression
, 0);
579 hres
= compile_expression(ctx
, expr
->expression
);
584 return push_instr(ctx
, op
) == -1 ? E_OUTOFMEMORY
: S_OK
;
587 static HRESULT
compile_literal(compiler_ctx_t
*ctx
, literal_t
*literal
)
589 switch(literal
->type
) {
591 return push_instr_int(ctx
, OP_bool
, literal
->u
.bval
);
593 return push_instr_double(ctx
, OP_double
, literal
->u
.dval
);
595 return push_instr_int(ctx
, OP_int
, literal
->u
.lval
);
597 return push_instr(ctx
, OP_null
);
599 return push_instr_str(ctx
, OP_str
, literal
->u
.wstr
);
604 str
= compiler_alloc(ctx
->code
, (literal
->u
.regexp
.str_len
+1)*sizeof(WCHAR
));
606 return E_OUTOFMEMORY
;
607 memcpy(str
, literal
->u
.regexp
.str
, literal
->u
.regexp
.str_len
*sizeof(WCHAR
));
608 str
[literal
->u
.regexp
.str_len
] = 0;
610 instr
= push_instr(ctx
, OP_regexp
);
612 return E_OUTOFMEMORY
;
614 instr_ptr(ctx
, instr
)->arg1
.str
= str
;
615 instr_ptr(ctx
, instr
)->arg2
.lng
= literal
->u
.regexp
.flags
;
623 static HRESULT
literal_as_bstr(compiler_ctx_t
*ctx
, literal_t
*literal
, BSTR
*str
)
625 switch(literal
->type
) {
627 *str
= compiler_alloc_bstr(ctx
, literal
->u
.wstr
);
630 *str
= int_to_bstr(literal
->u
.lval
);
633 return double_to_bstr(literal
->u
.dval
, str
);
638 return *str
? S_OK
: E_OUTOFMEMORY
;
641 static HRESULT
compile_array_literal(compiler_ctx_t
*ctx
, array_literal_expression_t
*expr
)
643 unsigned i
, elem_cnt
= expr
->length
;
644 array_element_t
*iter
;
647 for(iter
= expr
->element_list
; iter
; iter
= iter
->next
) {
648 elem_cnt
+= iter
->elision
+1;
650 for(i
=0; i
< iter
->elision
; i
++) {
651 if(push_instr(ctx
, OP_undefined
) == -1)
652 return E_OUTOFMEMORY
;
655 hres
= compile_expression(ctx
, iter
->expr
);
660 for(i
=0; i
< expr
->length
; i
++) {
661 if(push_instr(ctx
, OP_undefined
) == -1)
662 return E_OUTOFMEMORY
;
665 return push_instr_uint(ctx
, OP_carray
, elem_cnt
);
668 static HRESULT
compile_object_literal(compiler_ctx_t
*ctx
, property_value_expression_t
*expr
)
675 if(push_instr(ctx
, OP_new_obj
) == -1)
676 return E_OUTOFMEMORY
;
678 for(iter
= expr
->property_list
; iter
; iter
= iter
->next
) {
679 hres
= literal_as_bstr(ctx
, iter
->name
, &name
);
683 hres
= compile_expression(ctx
, iter
->value
);
687 instr
= push_instr(ctx
, OP_obj_prop
);
689 return E_OUTOFMEMORY
;
691 instr_ptr(ctx
, instr
)->arg1
.bstr
= name
;
697 static HRESULT
compile_function_expression(compiler_ctx_t
*ctx
, function_expression_t
*expr
)
701 /* FIXME: not exactly right */
703 return push_instr_bstr(ctx
, OP_ident
, expr
->identifier
);
705 instr
= push_instr(ctx
, OP_func
);
707 return E_OUTOFMEMORY
;
709 instr_ptr(ctx
, instr
)->arg1
.func
= expr
;
713 static HRESULT
compile_expression_noret(compiler_ctx_t
*ctx
, expression_t
*expr
, BOOL
*no_ret
)
717 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
719 return compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_jmp_z
);
721 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_array
);
723 return compile_array_literal(ctx
, (array_literal_expression_t
*)expr
);
725 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_LAST
);
727 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
729 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
731 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
733 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
735 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
737 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
739 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
740 case EXPR_ASSIGNLSHIFT
:
741 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_lshift
);
742 case EXPR_ASSIGNRSHIFT
:
743 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift
);
744 case EXPR_ASSIGNRRSHIFT
:
745 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift2
);
747 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
749 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
751 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_bneg
);
753 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
755 return compile_call_expression(ctx
, (call_expression_t
*)expr
, no_ret
);
757 return compile_comma_expression(ctx
, (binary_expression_t
*)expr
);
759 return compile_conditional_expression(ctx
, (conditional_expression_t
*)expr
);
761 return compile_delete_expression(ctx
, (unary_expression_t
*)expr
);
763 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
765 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq
);
767 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq2
);
769 return compile_function_expression(ctx
, (function_expression_t
*)expr
);
771 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gt
);
773 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gteq
);
775 return push_instr_bstr(ctx
, OP_ident
, ((identifier_expression_t
*)expr
)->identifier
);
777 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_in
);
778 case EXPR_INSTANCEOF
:
779 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_instanceof
);
781 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lt
);
783 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lteq
);
785 return compile_literal(ctx
, ((literal_expression_t
*)expr
)->literal
);
787 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_neg
);
789 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lshift
);
791 return compile_member_expression(ctx
, (member_expression_t
*)expr
);
793 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_minus
);
795 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
797 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
799 return compile_new_expression(ctx
, (call_expression_t
*)expr
);
801 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq
);
803 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq2
);
805 return compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_jmp_nz
);
807 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_tonum
);
809 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_postinc
, -1);
811 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_postinc
, 1);
813 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_preinc
, -1);
815 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_preinc
, 1);
817 return compile_object_literal(ctx
, (property_value_expression_t
*)expr
);
819 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift
);
821 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift2
);
823 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
825 return push_instr(ctx
, OP_this
) == -1 ? E_OUTOFMEMORY
: S_OK
;
827 return compile_typeof_expression(ctx
, (unary_expression_t
*)expr
);
829 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_void
);
831 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
839 static HRESULT
compile_expression(compiler_ctx_t
*ctx
, expression_t
*expr
)
841 return compile_expression_noret(ctx
, expr
, NULL
);
844 static HRESULT
compile_block_statement(compiler_ctx_t
*ctx
, statement_t
*iter
)
848 /* FIXME: do it only if needed */
850 return push_instr(ctx
, OP_undefined
) == -1 ? E_OUTOFMEMORY
: S_OK
;
853 hres
= compile_statement(ctx
, iter
);
861 if(push_instr(ctx
, OP_pop
) == -1)
862 return E_OUTOFMEMORY
;
868 /* ECMA-262 3rd Edition 12.4 */
869 static HRESULT
compile_expression_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
874 hres
= compile_expression_noret(ctx
, stat
->expr
, &no_ret
);
878 /* FIXME: that's a big potential optimization */
879 if(no_ret
&& !push_instr(ctx
, OP_undefined
) == -1)
880 return E_OUTOFMEMORY
;
885 static HRESULT
compile_statement(compiler_ctx_t
*ctx
, statement_t
*stat
)
889 return compile_block_statement(ctx
, ((block_statement_t
*)stat
)->stat_list
);
891 return compile_expression_statement(ctx
, (expression_statement_t
*)stat
);
893 return compile_interp_fallback(ctx
, stat
);
897 void release_bytecode(bytecode_t
*code
)
901 for(i
=0; i
< code
->bstr_cnt
; i
++)
902 SysFreeString(code
->bstr_pool
[i
]);
904 jsheap_free(&code
->heap
);
905 heap_free(code
->bstr_pool
);
906 heap_free(code
->instrs
);
910 void release_compiler(compiler_ctx_t
*ctx
)
915 static HRESULT
init_compiler(parser_ctx_t
*parser
)
918 parser
->code
= heap_alloc_zero(sizeof(bytecode_t
));
920 return E_OUTOFMEMORY
;
921 jsheap_init(&parser
->code
->heap
);
924 if(!parser
->compiler
) {
925 parser
->compiler
= heap_alloc_zero(sizeof(compiler_ctx_t
));
926 if(!parser
->compiler
)
927 return E_OUTOFMEMORY
;
929 parser
->compiler
->parser
= parser
;
930 parser
->compiler
->code
= parser
->code
;
936 HRESULT
compile_subscript(parser_ctx_t
*parser
, expression_t
*expr
, BOOL do_ret
, unsigned *ret_off
)
941 hres
= init_compiler(parser
);
945 *ret_off
= parser
->compiler
->code_off
;
946 hres
= compile_expression_noret(parser
->compiler
, expr
, do_ret
? NULL
: &no_ret
);
950 return push_instr(parser
->compiler
, OP_ret
) == -1 ? E_OUTOFMEMORY
: S_OK
;
953 HRESULT
compile_subscript_stat(parser_ctx_t
*parser
, statement_t
*stat
, BOOL compile_block
, unsigned *ret_off
)
959 hres
= init_compiler(parser
);
963 *ret_off
= parser
->compiler
->code_off
;
964 if(compile_block
&& stat
->next
)
965 hres
= compile_block_statement(parser
->compiler
, stat
);
967 hres
= compile_statement(parser
->compiler
, stat
);
971 return push_instr(parser
->compiler
, OP_ret
) == -1 ? E_OUTOFMEMORY
: S_OK
;