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
26 #include "wine/rbtree.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(jscript
);
30 WINE_DECLARE_DEBUG_CHANNEL(jscript_disas
);
32 typedef struct _statement_ctx_t
{
38 unsigned continue_label
;
40 const labelled_statement_t
*labelled_stat
;
42 struct _statement_ctx_t
*next
;
46 struct wine_rb_entry entry
;
51 typedef struct _compiler_ctx_t
{
64 struct wine_rb_tree locals
;
67 statement_ctx_t
*stat_ctx
;
68 function_code_t
*func
;
72 function_expression_t
*func_head
;
73 function_expression_t
*func_tail
;
80 instr_arg_type_t arg1_type
;
81 instr_arg_type_t arg2_type
;
83 #define X(n,a,b,c) {#n,b,c},
88 static void dump_instr_arg(instr_arg_type_t type
, instr_arg_t
*arg
)
92 TRACE_(jscript_disas
)("\t%s", debugstr_jsstr(arg
->str
));
95 TRACE_(jscript_disas
)("\t%s", debugstr_wn(arg
->bstr
, SysStringLen(arg
->bstr
)));
98 TRACE_(jscript_disas
)("\t%d", arg
->uint
);
102 TRACE_(jscript_disas
)("\t%u", arg
->uint
);
111 static void dump_code(compiler_ctx_t
*ctx
, unsigned off
)
115 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->code_off
; instr
++) {
116 TRACE_(jscript_disas
)("%d:\t%s", (int)(instr
-ctx
->code
->instrs
), instr_info
[instr
->op
].op_str
);
117 if(instr_info
[instr
->op
].arg1_type
== ARG_DBL
) {
118 TRACE_(jscript_disas
)("\t%lf", instr
->u
.dbl
);
120 dump_instr_arg(instr_info
[instr
->op
].arg1_type
, instr
->u
.arg
);
121 dump_instr_arg(instr_info
[instr
->op
].arg2_type
, instr
->u
.arg
+1);
123 TRACE_(jscript_disas
)("\n");
127 static HRESULT
compile_expression(compiler_ctx_t
*,expression_t
*,BOOL
);
128 static HRESULT
compile_statement(compiler_ctx_t
*,statement_ctx_t
*,statement_t
*);
130 static inline void *compiler_alloc(bytecode_t
*code
, size_t size
)
132 return heap_pool_alloc(&code
->heap
, size
);
135 jsstr_t
*compiler_alloc_string_len(compiler_ctx_t
*ctx
, const WCHAR
*str
, unsigned len
)
139 if(!ctx
->code
->str_pool_size
) {
140 ctx
->code
->str_pool
= heap_alloc(8 * sizeof(jsstr_t
*));
141 if(!ctx
->code
->str_pool
)
143 ctx
->code
->str_pool_size
= 8;
144 }else if(ctx
->code
->str_pool_size
== ctx
->code
->str_cnt
) {
147 new_pool
= heap_realloc(ctx
->code
->str_pool
, ctx
->code
->str_pool_size
*2*sizeof(jsstr_t
*));
151 ctx
->code
->str_pool
= new_pool
;
152 ctx
->code
->str_pool_size
*= 2;
155 new_str
= jsstr_alloc_len(str
, len
);
159 ctx
->code
->str_pool
[ctx
->code
->str_cnt
++] = new_str
;
163 static jsstr_t
*compiler_alloc_string(compiler_ctx_t
*ctx
, const WCHAR
*str
)
165 return compiler_alloc_string_len(ctx
, str
, lstrlenW(str
));
168 static BOOL
ensure_bstr_slot(compiler_ctx_t
*ctx
)
170 if(!ctx
->code
->bstr_pool_size
) {
171 ctx
->code
->bstr_pool
= heap_alloc(8 * sizeof(BSTR
));
172 if(!ctx
->code
->bstr_pool
)
174 ctx
->code
->bstr_pool_size
= 8;
175 }else if(ctx
->code
->bstr_pool_size
== ctx
->code
->bstr_cnt
) {
178 new_pool
= heap_realloc(ctx
->code
->bstr_pool
, ctx
->code
->bstr_pool_size
*2*sizeof(BSTR
));
182 ctx
->code
->bstr_pool
= new_pool
;
183 ctx
->code
->bstr_pool_size
*= 2;
189 static BSTR
compiler_alloc_bstr(compiler_ctx_t
*ctx
, const WCHAR
*str
)
191 if(!ensure_bstr_slot(ctx
))
194 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocString(str
);
195 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
198 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
201 static BSTR
compiler_alloc_bstr_len(compiler_ctx_t
*ctx
, const WCHAR
*str
, size_t len
)
203 if(!ensure_bstr_slot(ctx
))
206 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocStringLen(str
, len
);
207 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
210 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
213 void set_compiler_loc(compiler_ctx_t
*ctx
, unsigned loc
)
218 static unsigned push_instr(compiler_ctx_t
*ctx
, jsop_t op
)
220 assert(ctx
->code_size
>= ctx
->code_off
);
222 if(ctx
->code_size
== ctx
->code_off
) {
225 new_instrs
= heap_realloc(ctx
->code
->instrs
, ctx
->code_size
*2*sizeof(instr_t
));
229 ctx
->code
->instrs
= new_instrs
;
233 ctx
->code
->instrs
[ctx
->code_off
].op
= op
;
234 ctx
->code
->instrs
[ctx
->code_off
].loc
= ctx
->loc
;
235 return ctx
->code_off
++;
238 static inline instr_t
*instr_ptr(compiler_ctx_t
*ctx
, unsigned off
)
240 assert(off
< ctx
->code_off
);
241 return ctx
->code
->instrs
+ off
;
244 static HRESULT
push_instr_int(compiler_ctx_t
*ctx
, jsop_t op
, LONG arg
)
248 instr
= push_instr(ctx
, op
);
250 return E_OUTOFMEMORY
;
252 instr_ptr(ctx
, instr
)->u
.arg
->lng
= arg
;
256 static HRESULT
push_instr_str(compiler_ctx_t
*ctx
, jsop_t op
, jsstr_t
*str
)
260 instr
= push_instr(ctx
, op
);
262 return E_OUTOFMEMORY
;
264 instr_ptr(ctx
, instr
)->u
.arg
->str
= str
;
268 static HRESULT
push_instr_str_uint(compiler_ctx_t
*ctx
, jsop_t op
, jsstr_t
*str
, unsigned arg2
)
272 instr
= push_instr(ctx
, op
);
274 return E_OUTOFMEMORY
;
276 instr_ptr(ctx
, instr
)->u
.arg
[0].str
= str
;
277 instr_ptr(ctx
, instr
)->u
.arg
[1].uint
= arg2
;
281 static HRESULT
push_instr_bstr(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
286 str
= compiler_alloc_bstr(ctx
, arg
);
288 return E_OUTOFMEMORY
;
290 instr
= push_instr(ctx
, op
);
292 return E_OUTOFMEMORY
;
294 instr_ptr(ctx
, instr
)->u
.arg
->bstr
= str
;
298 static HRESULT
push_instr_bstr_uint(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg1
, unsigned arg2
)
303 str
= compiler_alloc_bstr(ctx
, arg1
);
305 return E_OUTOFMEMORY
;
307 instr
= push_instr(ctx
, op
);
309 return E_OUTOFMEMORY
;
311 instr_ptr(ctx
, instr
)->u
.arg
[0].bstr
= str
;
312 instr_ptr(ctx
, instr
)->u
.arg
[1].uint
= arg2
;
316 static HRESULT
push_instr_uint_str(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg1
, const WCHAR
*arg2
)
321 str
= compiler_alloc_string(ctx
, arg2
);
323 return E_OUTOFMEMORY
;
325 instr
= push_instr(ctx
, op
);
327 return E_OUTOFMEMORY
;
329 instr_ptr(ctx
, instr
)->u
.arg
[0].uint
= arg1
;
330 instr_ptr(ctx
, instr
)->u
.arg
[1].str
= str
;
334 static HRESULT
push_instr_double(compiler_ctx_t
*ctx
, jsop_t op
, double arg
)
338 instr
= push_instr(ctx
, op
);
340 return E_OUTOFMEMORY
;
342 instr_ptr(ctx
, instr
)->u
.dbl
= arg
;
346 static inline void set_arg_uint(compiler_ctx_t
*ctx
, unsigned instr
, unsigned arg
)
348 instr_ptr(ctx
, instr
)->u
.arg
->uint
= arg
;
351 static HRESULT
push_instr_uint(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg
)
355 instr
= push_instr(ctx
, op
);
357 return E_OUTOFMEMORY
;
359 set_arg_uint(ctx
, instr
, arg
);
363 static HRESULT
compile_binary_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
367 hres
= compile_expression(ctx
, expr
->expression1
, TRUE
);
371 hres
= compile_expression(ctx
, expr
->expression2
, TRUE
);
375 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
378 static HRESULT
compile_unary_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
)
382 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
386 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
389 /* ECMA-262 3rd Edition 11.2.1 */
390 static HRESULT
compile_member_expression(compiler_ctx_t
*ctx
, member_expression_t
*expr
)
394 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
398 return push_instr_bstr(ctx
, OP_member
, expr
->identifier
);
401 #define LABEL_FLAG 0x80000000
403 static unsigned alloc_label(compiler_ctx_t
*ctx
)
405 if(!ctx
->labels_size
) {
406 ctx
->labels
= heap_alloc(8 * sizeof(*ctx
->labels
));
409 ctx
->labels_size
= 8;
410 }else if(ctx
->labels_size
== ctx
->labels_cnt
) {
411 unsigned *new_labels
;
413 new_labels
= heap_realloc(ctx
->labels
, 2*ctx
->labels_size
*sizeof(*ctx
->labels
));
417 ctx
->labels
= new_labels
;
418 ctx
->labels_size
*= 2;
421 return ctx
->labels_cnt
++ | LABEL_FLAG
;
424 static void label_set_addr(compiler_ctx_t
*ctx
, unsigned label
)
426 assert(label
& LABEL_FLAG
);
427 ctx
->labels
[label
& ~LABEL_FLAG
] = ctx
->code_off
;
430 static inline BOOL
is_memberid_expr(expression_type_t type
)
432 return type
== EXPR_IDENT
|| type
== EXPR_MEMBER
|| type
== EXPR_ARRAY
;
435 static BOOL
bind_local(compiler_ctx_t
*ctx
, const WCHAR
*identifier
, int *ret_ref
)
437 statement_ctx_t
*iter
;
440 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
441 if(iter
->using_scope
)
445 ref
= lookup_local(ctx
->func
, identifier
);
453 static HRESULT
emit_identifier_ref(compiler_ctx_t
*ctx
, const WCHAR
*identifier
, unsigned flags
)
456 if(bind_local(ctx
, identifier
, &local_ref
))
457 return push_instr_int(ctx
, OP_local_ref
, local_ref
);
458 return push_instr_bstr_uint(ctx
, OP_identid
, identifier
, flags
);
461 static HRESULT
emit_identifier(compiler_ctx_t
*ctx
, const WCHAR
*identifier
)
464 if(bind_local(ctx
, identifier
, &local_ref
))
465 return push_instr_int(ctx
, OP_local
, local_ref
);
466 return push_instr_bstr(ctx
, OP_ident
, identifier
);
469 static HRESULT
emit_member_expression(compiler_ctx_t
*ctx
, expression_t
*expr
)
473 if(expr
->type
== EXPR_ARRAY
) {
474 binary_expression_t
*array_expr
= (binary_expression_t
*)expr
;
476 hres
= compile_expression(ctx
, array_expr
->expression1
, TRUE
);
480 hres
= compile_expression(ctx
, array_expr
->expression2
, TRUE
);
484 if(!push_instr(ctx
, OP_to_string
))
485 return E_OUTOFMEMORY
;
487 member_expression_t
*member_expr
= (member_expression_t
*)expr
;
490 assert(expr
->type
== EXPR_MEMBER
);
492 hres
= compile_expression(ctx
, member_expr
->expression
, TRUE
);
496 jsstr
= compiler_alloc_string(ctx
, member_expr
->identifier
);
498 return E_OUTOFMEMORY
;
500 hres
= push_instr_str(ctx
, OP_str
, jsstr
);
508 static HRESULT
compile_memberid_expression(compiler_ctx_t
*ctx
, expression_t
*expr
, unsigned flags
)
512 if(expr
->type
== EXPR_IDENT
) {
513 identifier_expression_t
*ident_expr
= (identifier_expression_t
*)expr
;
514 return emit_identifier_ref(ctx
, ident_expr
->identifier
, flags
);
517 hres
= emit_member_expression(ctx
, expr
);
521 return push_instr_uint(ctx
, OP_memberid
, flags
);
524 static HRESULT
compile_increment_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
, int n
)
528 if(!is_memberid_expr(expr
->expression
->type
)) {
529 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
533 return push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
536 hres
= compile_memberid_expression(ctx
, expr
->expression
, fdexNameEnsure
);
540 return push_instr_int(ctx
, op
, n
);
543 /* ECMA-262 3rd Edition 11.14 */
544 static HRESULT
compile_comma_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, BOOL emit_ret
)
548 hres
= compile_expression(ctx
, expr
->expression1
, FALSE
);
552 return compile_expression(ctx
, expr
->expression2
, emit_ret
);
555 /* ECMA-262 3rd Edition 11.11 */
556 static HRESULT
compile_logical_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
561 hres
= compile_expression(ctx
, expr
->expression1
, TRUE
);
565 instr
= push_instr(ctx
, op
);
567 return E_OUTOFMEMORY
;
569 hres
= compile_expression(ctx
, expr
->expression2
, TRUE
);
573 set_arg_uint(ctx
, instr
, ctx
->code_off
);
577 /* ECMA-262 3rd Edition 11.12 */
578 static HRESULT
compile_conditional_expression(compiler_ctx_t
*ctx
, conditional_expression_t
*expr
)
580 unsigned jmp_false
, jmp_end
;
583 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
587 jmp_false
= push_instr(ctx
, OP_cnd_z
);
589 return E_OUTOFMEMORY
;
591 hres
= compile_expression(ctx
, expr
->true_expression
, TRUE
);
595 jmp_end
= push_instr(ctx
, OP_jmp
);
597 return E_OUTOFMEMORY
;
599 set_arg_uint(ctx
, jmp_false
, ctx
->code_off
);
600 hres
= push_instr_uint(ctx
, OP_pop
, 1);
604 hres
= compile_expression(ctx
, expr
->false_expression
, TRUE
);
608 set_arg_uint(ctx
, jmp_end
, ctx
->code_off
);
612 static HRESULT
compile_new_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
)
614 unsigned arg_cnt
= 0;
618 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
622 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
623 hres
= compile_expression(ctx
, arg
->expr
, TRUE
);
629 hres
= push_instr_uint(ctx
, OP_new
, arg_cnt
);
633 hres
= push_instr_uint(ctx
, OP_pop
, arg_cnt
+1);
637 return push_instr(ctx
, OP_push_acc
) ? S_OK
: E_OUTOFMEMORY
;
640 static HRESULT
compile_call_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
, BOOL emit_ret
)
642 unsigned arg_cnt
= 0, extra_args
;
648 if(is_memberid_expr(expr
->expression
->type
)) {
651 hres
= compile_memberid_expression(ctx
, expr
->expression
, 0);
655 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
661 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
662 hres
= compile_expression(ctx
, arg
->expr
, TRUE
);
668 instr
= push_instr(ctx
, op
);
670 return E_OUTOFMEMORY
;
672 instr_ptr(ctx
, instr
)->u
.arg
[0].uint
= arg_cnt
;
673 instr_ptr(ctx
, instr
)->u
.arg
[1].lng
= emit_ret
;
675 hres
= push_instr_uint(ctx
, OP_pop
, arg_cnt
+ extra_args
);
679 return !emit_ret
|| push_instr(ctx
, OP_push_acc
) ? S_OK
: E_OUTOFMEMORY
;
682 static HRESULT
compile_delete_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
686 switch(expr
->expression
->type
) {
688 binary_expression_t
*array_expr
= (binary_expression_t
*)expr
->expression
;
690 hres
= compile_expression(ctx
, array_expr
->expression1
, TRUE
);
694 hres
= compile_expression(ctx
, array_expr
->expression2
, TRUE
);
698 if(!push_instr(ctx
, OP_delete
))
699 return E_OUTOFMEMORY
;
703 member_expression_t
*member_expr
= (member_expression_t
*)expr
->expression
;
706 hres
= compile_expression(ctx
, member_expr
->expression
, TRUE
);
710 /* FIXME: Potential optimization */
711 jsstr
= compiler_alloc_string(ctx
, member_expr
->identifier
);
713 return E_OUTOFMEMORY
;
715 hres
= push_instr_str(ctx
, OP_str
, jsstr
);
719 if(!push_instr(ctx
, OP_delete
))
720 return E_OUTOFMEMORY
;
724 return push_instr_bstr(ctx
, OP_delete_ident
, ((identifier_expression_t
*)expr
->expression
)->identifier
);
726 WARN("invalid delete, unimplemented exception message\n");
728 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
732 return push_instr_uint_str(ctx
, OP_throw_type
, JS_E_INVALID_DELETE
, L
"FIXME");
739 static HRESULT
compile_assign_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
741 jsop_t assign_op
= OP_throw_ref
;
742 unsigned arg_cnt
= 0;
745 if(expr
->expression1
->type
== EXPR_CALL
) {
746 call_expression_t
*call_expr
= (call_expression_t
*)expr
->expression1
;
749 if(is_memberid_expr(call_expr
->expression
->type
) && call_expr
->argument_list
) {
750 hres
= compile_memberid_expression(ctx
, call_expr
->expression
, fdexNameEnsure
);
754 for(arg
= call_expr
->argument_list
; arg
; arg
= arg
->next
) {
755 hres
= compile_expression(ctx
, arg
->expr
, TRUE
);
764 /* We need to call the functions twice: to get the value and to set it.
765 * JavaScript interpreted functions may to modify value on the stack,
766 * but assignment calls are allowed only on external functions, so we
767 * may reuse the stack here. */
768 instr
= push_instr(ctx
, OP_call_member
);
770 return E_OUTOFMEMORY
;
771 instr_ptr(ctx
, instr
)->u
.arg
[0].uint
= arg_cnt
;
772 instr_ptr(ctx
, instr
)->u
.arg
[1].lng
= 1;
774 if(!push_instr(ctx
, OP_push_acc
))
775 return E_OUTOFMEMORY
;
777 assign_op
= OP_assign_call
;
779 }else if(is_memberid_expr(expr
->expression1
->type
)) {
780 if(op
!= OP_LAST
|| expr
->expression1
->type
== EXPR_IDENT
) {
781 hres
= compile_memberid_expression(ctx
, expr
->expression1
, fdexNameEnsure
);
784 if(op
!= OP_LAST
&& !push_instr(ctx
, OP_refval
))
785 return E_OUTOFMEMORY
;
786 assign_op
= OP_assign
;
788 hres
= emit_member_expression(ctx
, expr
->expression1
);
791 assign_op
= OP_set_member
;
795 if(assign_op
== OP_throw_ref
) {
796 /* Illegal assignment: evaluate and throw */
797 hres
= compile_expression(ctx
, expr
->expression1
, TRUE
);
800 arg_cnt
= JS_E_ILLEGAL_ASSIGN
;
803 hres
= compile_expression(ctx
, expr
->expression2
, TRUE
);
807 if(op
!= OP_LAST
&& !push_instr(ctx
, op
))
808 return E_OUTOFMEMORY
;
810 return push_instr_uint(ctx
, assign_op
, arg_cnt
);
813 static HRESULT
compile_typeof_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
818 if(is_memberid_expr(expr
->expression
->type
)) {
819 if(expr
->expression
->type
== EXPR_IDENT
)
820 return push_instr_bstr(ctx
, OP_typeofident
, ((identifier_expression_t
*)expr
->expression
)->identifier
);
823 hres
= compile_memberid_expression(ctx
, expr
->expression
, 0);
826 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
831 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
834 static HRESULT
compile_literal(compiler_ctx_t
*ctx
, literal_t
*literal
)
836 switch(literal
->type
) {
838 return push_instr_int(ctx
, OP_bool
, literal
->u
.bval
);
840 return push_instr_double(ctx
, OP_double
, literal
->u
.dval
);
842 return push_instr(ctx
, OP_null
) ? S_OK
: E_OUTOFMEMORY
;
844 return push_instr_str(ctx
, OP_str
, literal
->u
.str
);
846 return push_instr_str_uint(ctx
, OP_regexp
, literal
->u
.regexp
.str
, literal
->u
.regexp
.flags
);
852 static HRESULT
literal_as_string(compiler_ctx_t
*ctx
, literal_t
*literal
, jsstr_t
**str
)
854 switch(literal
->type
) {
856 *str
= literal
->u
.str
;
859 return double_to_string(literal
->u
.dval
, str
);
863 return *str
? S_OK
: E_OUTOFMEMORY
;
866 static HRESULT
compile_array_literal(compiler_ctx_t
*ctx
, array_literal_expression_t
*expr
)
869 array_element_t
*iter
;
870 unsigned array_instr
;
873 array_instr
= push_instr(ctx
, OP_carray
);
875 for(iter
= expr
->element_list
; iter
; iter
= iter
->next
) {
876 length
+= iter
->elision
;
878 hres
= compile_expression(ctx
, iter
->expr
, TRUE
);
882 hres
= push_instr_uint(ctx
, OP_carray_set
, length
);
889 instr_ptr(ctx
, array_instr
)->u
.arg
[0].uint
= length
+ expr
->length
;
893 static HRESULT
compile_object_literal(compiler_ctx_t
*ctx
, property_value_expression_t
*expr
)
895 property_definition_t
*iter
;
899 if(!push_instr(ctx
, OP_new_obj
))
900 return E_OUTOFMEMORY
;
902 for(iter
= expr
->property_list
; iter
; iter
= iter
->next
) {
903 hres
= literal_as_string(ctx
, iter
->name
, &name
);
907 hres
= compile_expression(ctx
, iter
->value
, TRUE
);
911 hres
= push_instr_str_uint(ctx
, OP_obj_prop
, name
, iter
->type
);
919 static HRESULT
compile_function_expression(compiler_ctx_t
*ctx
, function_expression_t
*expr
, BOOL emit_ret
)
921 return emit_ret
? push_instr_uint(ctx
, OP_func
, expr
->func_id
) : S_OK
;
924 static HRESULT
compile_expression(compiler_ctx_t
*ctx
, expression_t
*expr
, BOOL emit_ret
)
930 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
933 hres
= compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_cnd_z
);
936 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_array
);
939 hres
= compile_array_literal(ctx
, (array_literal_expression_t
*)expr
);
942 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_LAST
);
945 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
948 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
951 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
954 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
957 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
960 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
963 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
965 case EXPR_ASSIGNLSHIFT
:
966 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_lshift
);
968 case EXPR_ASSIGNRSHIFT
:
969 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift
);
971 case EXPR_ASSIGNRRSHIFT
:
972 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift2
);
975 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
978 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
981 hres
= compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_bneg
);
984 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
987 return compile_call_expression(ctx
, (call_expression_t
*)expr
, emit_ret
);
989 return compile_comma_expression(ctx
, (binary_expression_t
*)expr
, emit_ret
);
991 hres
= compile_conditional_expression(ctx
, (conditional_expression_t
*)expr
);
994 hres
= compile_delete_expression(ctx
, (unary_expression_t
*)expr
);
997 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
1000 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq
);
1003 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq2
);
1006 return compile_function_expression(ctx
, (function_expression_t
*)expr
, emit_ret
);
1008 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gt
);
1010 case EXPR_GREATEREQ
:
1011 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gteq
);
1014 hres
= emit_identifier(ctx
, ((identifier_expression_t
*)expr
)->identifier
);
1017 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_in
);
1019 case EXPR_INSTANCEOF
:
1020 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_instanceof
);
1023 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lt
);
1026 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lteq
);
1029 hres
= compile_literal(ctx
, ((literal_expression_t
*)expr
)->literal
);
1032 hres
= compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_neg
);
1035 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lshift
);
1038 hres
= compile_member_expression(ctx
, (member_expression_t
*)expr
);
1041 hres
= compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_minus
);
1044 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
1047 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
1050 hres
= compile_new_expression(ctx
, (call_expression_t
*)expr
);
1053 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq
);
1056 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq2
);
1059 hres
= compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_cnd_nz
);
1062 hres
= compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_tonum
);
1065 hres
= compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_postinc
, -1);
1068 hres
= compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_postinc
, 1);
1071 hres
= compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_preinc
, -1);
1074 hres
= compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_preinc
, 1);
1077 hres
= compile_object_literal(ctx
, (property_value_expression_t
*)expr
);
1080 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift
);
1083 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift2
);
1086 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
1089 return !emit_ret
|| push_instr(ctx
, OP_this
) ? S_OK
: E_OUTOFMEMORY
;
1091 hres
= compile_typeof_expression(ctx
, (unary_expression_t
*)expr
);
1094 hres
= compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_void
);
1097 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
1099 DEFAULT_UNREACHABLE
;
1105 return emit_ret
? S_OK
: push_instr_uint(ctx
, OP_pop
, 1);
1108 static inline BOOL
is_loop_statement(statement_type_t type
)
1110 return type
== STAT_FOR
|| type
== STAT_FORIN
|| type
== STAT_WHILE
;
1113 /* ECMA-262 3rd Edition 12.1 */
1114 static HRESULT
compile_block_statement(compiler_ctx_t
*ctx
, statement_t
*iter
)
1119 hres
= compile_statement(ctx
, NULL
, iter
);
1129 /* ECMA-262 3rd Edition 12.2 */
1130 static HRESULT
compile_variable_list(compiler_ctx_t
*ctx
, variable_declaration_t
*list
)
1132 variable_declaration_t
*iter
;
1135 assert(list
!= NULL
);
1137 for(iter
= list
; iter
; iter
= iter
->next
) {
1141 hres
= emit_identifier_ref(ctx
, iter
->identifier
, 0);
1145 hres
= compile_expression(ctx
, iter
->expr
, TRUE
);
1149 if(!push_instr(ctx
, OP_assign
))
1150 return E_OUTOFMEMORY
;
1152 hres
= push_instr_uint(ctx
, OP_pop
, 1);
1160 /* ECMA-262 3rd Edition 12.2 */
1161 static HRESULT
compile_var_statement(compiler_ctx_t
*ctx
, var_statement_t
*stat
)
1163 return compile_variable_list(ctx
, stat
->variable_list
);
1166 /* ECMA-262 3rd Edition 12.4 */
1167 static HRESULT
compile_expression_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1171 hres
= compile_expression(ctx
, stat
->expr
, ctx
->from_eval
);
1175 return !ctx
->from_eval
|| push_instr(ctx
, OP_setret
) ? S_OK
: E_OUTOFMEMORY
;
1178 /* ECMA-262 3rd Edition 12.5 */
1179 static HRESULT
compile_if_statement(compiler_ctx_t
*ctx
, if_statement_t
*stat
)
1184 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1188 jmp_else
= push_instr(ctx
, OP_jmp_z
);
1190 return E_OUTOFMEMORY
;
1192 hres
= compile_statement(ctx
, NULL
, stat
->if_stat
);
1196 if(stat
->else_stat
) {
1199 jmp_end
= push_instr(ctx
, OP_jmp
);
1201 return E_OUTOFMEMORY
;
1203 set_arg_uint(ctx
, jmp_else
, ctx
->code_off
);
1205 hres
= compile_statement(ctx
, NULL
, stat
->else_stat
);
1209 set_arg_uint(ctx
, jmp_end
, ctx
->code_off
);
1211 set_arg_uint(ctx
, jmp_else
, ctx
->code_off
);
1217 /* ECMA-262 3rd Edition 12.6.2 */
1218 static HRESULT
compile_while_statement(compiler_ctx_t
*ctx
, while_statement_t
*stat
)
1220 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1224 stat_ctx
.break_label
= alloc_label(ctx
);
1225 if(!stat_ctx
.break_label
)
1226 return E_OUTOFMEMORY
;
1228 stat_ctx
.continue_label
= alloc_label(ctx
);
1229 if(!stat_ctx
.continue_label
)
1230 return E_OUTOFMEMORY
;
1232 jmp_off
= ctx
->code_off
;
1234 if(!stat
->do_while
) {
1235 label_set_addr(ctx
, stat_ctx
.continue_label
);
1236 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1240 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1245 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1249 set_compiler_loc(ctx
, stat
->stat
.loc
);
1250 if(stat
->do_while
) {
1251 label_set_addr(ctx
, stat_ctx
.continue_label
);
1252 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1256 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1261 hres
= push_instr_uint(ctx
, OP_jmp
, jmp_off
);
1265 label_set_addr(ctx
, stat_ctx
.break_label
);
1269 /* ECMA-262 3rd Edition 12.6.3 */
1270 static HRESULT
compile_for_statement(compiler_ctx_t
*ctx
, for_statement_t
*stat
)
1272 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1276 if(stat
->variable_list
) {
1277 hres
= compile_variable_list(ctx
, stat
->variable_list
);
1280 }else if(stat
->begin_expr
) {
1281 hres
= compile_expression(ctx
, stat
->begin_expr
, FALSE
);
1286 stat_ctx
.break_label
= alloc_label(ctx
);
1287 if(!stat_ctx
.break_label
)
1288 return E_OUTOFMEMORY
;
1290 stat_ctx
.continue_label
= alloc_label(ctx
);
1291 if(!stat_ctx
.continue_label
)
1292 return E_OUTOFMEMORY
;
1294 expr_off
= ctx
->code_off
;
1297 set_compiler_loc(ctx
, stat
->expr_loc
);
1298 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1302 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1307 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1311 label_set_addr(ctx
, stat_ctx
.continue_label
);
1313 if(stat
->end_expr
) {
1314 set_compiler_loc(ctx
, stat
->end_loc
);
1315 hres
= compile_expression(ctx
, stat
->end_expr
, FALSE
);
1320 hres
= push_instr_uint(ctx
, OP_jmp
, expr_off
);
1324 label_set_addr(ctx
, stat_ctx
.break_label
);
1328 /* ECMA-262 3rd Edition 12.6.4 */
1329 static HRESULT
compile_forin_statement(compiler_ctx_t
*ctx
, forin_statement_t
*stat
)
1331 statement_ctx_t stat_ctx
= {4, FALSE
, FALSE
};
1334 if(stat
->variable
) {
1335 hres
= compile_variable_list(ctx
, stat
->variable
);
1340 stat_ctx
.break_label
= alloc_label(ctx
);
1341 if(!stat_ctx
.break_label
)
1342 return E_OUTOFMEMORY
;
1344 stat_ctx
.continue_label
= alloc_label(ctx
);
1345 if(!stat_ctx
.continue_label
)
1346 return E_OUTOFMEMORY
;
1348 hres
= compile_expression(ctx
, stat
->in_expr
, TRUE
);
1352 if(stat
->variable
) {
1353 hres
= emit_identifier_ref(ctx
, stat
->variable
->identifier
, fdexNameEnsure
);
1356 }else if(is_memberid_expr(stat
->expr
->type
)) {
1357 hres
= compile_memberid_expression(ctx
, stat
->expr
, fdexNameEnsure
);
1361 hres
= push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
1365 /* FIXME: compile statement anyways when we depend on compiler to check errors */
1369 hres
= push_instr_int(ctx
, OP_int
, DISPID_STARTENUM
);
1373 label_set_addr(ctx
, stat_ctx
.continue_label
);
1374 hres
= push_instr_uint(ctx
, OP_forin
, stat_ctx
.break_label
);
1376 return E_OUTOFMEMORY
;
1378 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1382 hres
= push_instr_uint(ctx
, OP_jmp
, stat_ctx
.continue_label
);
1386 label_set_addr(ctx
, stat_ctx
.break_label
);
1390 static HRESULT
pop_to_stat(compiler_ctx_t
*ctx
, statement_ctx_t
*stat_ctx
)
1392 unsigned stack_pop
= 0;
1393 statement_ctx_t
*iter
;
1396 for(iter
= ctx
->stat_ctx
; iter
!= stat_ctx
; iter
= iter
->next
) {
1397 if(iter
->using_scope
&& !push_instr(ctx
, OP_pop_scope
))
1398 return E_OUTOFMEMORY
;
1399 if(iter
->using_except
) {
1401 hres
= push_instr_uint(ctx
, OP_pop
, stack_pop
);
1406 hres
= push_instr_uint(ctx
, OP_pop_except
, ctx
->code_off
+1);
1410 stack_pop
+= iter
->stack_use
;
1414 hres
= push_instr_uint(ctx
, OP_pop
, stack_pop
);
1422 /* ECMA-262 3rd Edition 12.7 */
1423 static HRESULT
compile_continue_statement(compiler_ctx_t
*ctx
, branch_statement_t
*stat
)
1425 statement_ctx_t
*pop_ctx
;
1428 if(stat
->identifier
) {
1429 statement_t
*label_stat
;
1430 statement_ctx_t
*iter
;
1434 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1435 if(iter
->continue_label
)
1437 if(iter
->labelled_stat
&& !wcscmp(iter
->labelled_stat
->identifier
, stat
->identifier
))
1442 WARN("Label not found\n");
1443 return JS_E_LABEL_NOT_FOUND
;
1446 /* Labelled continue are allowed only on loops */
1447 for(label_stat
= iter
->labelled_stat
->statement
;
1448 label_stat
->type
== STAT_LABEL
;
1449 label_stat
= ((labelled_statement_t
*)label_stat
)->statement
);
1450 if(!is_loop_statement(label_stat
->type
)) {
1451 WARN("Label is not a loop\n");
1452 return JS_E_INVALID_CONTINUE
;
1455 assert(pop_ctx
!= NULL
);
1457 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1458 if(pop_ctx
->continue_label
)
1463 WARN("continue outside loop\n");
1464 return JS_E_INVALID_CONTINUE
;
1468 hres
= pop_to_stat(ctx
, pop_ctx
);
1472 return push_instr_uint(ctx
, OP_jmp
, pop_ctx
->continue_label
);
1475 /* ECMA-262 3rd Edition 12.8 */
1476 static HRESULT
compile_break_statement(compiler_ctx_t
*ctx
, branch_statement_t
*stat
)
1478 statement_ctx_t
*pop_ctx
;
1481 if(stat
->identifier
) {
1482 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1483 if(pop_ctx
->labelled_stat
&& !wcscmp(pop_ctx
->labelled_stat
->identifier
, stat
->identifier
)) {
1484 assert(pop_ctx
->break_label
);
1490 WARN("Label not found\n");
1491 return JS_E_LABEL_NOT_FOUND
;
1494 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1495 if(pop_ctx
->break_label
&& !pop_ctx
->labelled_stat
)
1500 WARN("Break outside loop\n");
1501 return JS_E_INVALID_BREAK
;
1505 hres
= pop_to_stat(ctx
, pop_ctx
->next
);
1509 return push_instr_uint(ctx
, OP_jmp
, pop_ctx
->break_label
);
1512 /* ECMA-262 3rd Edition 12.9 */
1513 static HRESULT
compile_return_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1517 if(ctx
->from_eval
) {
1518 WARN("misplaced return statement\n");
1519 return JS_E_MISPLACED_RETURN
;
1523 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1526 if(!push_instr(ctx
, OP_setret
))
1527 return E_OUTOFMEMORY
;
1530 hres
= pop_to_stat(ctx
, NULL
);
1534 return push_instr_uint(ctx
, OP_ret
, !stat
->expr
);
1537 /* ECMA-262 3rd Edition 12.10 */
1538 static HRESULT
compile_with_statement(compiler_ctx_t
*ctx
, with_statement_t
*stat
)
1540 statement_ctx_t stat_ctx
= {0, TRUE
, FALSE
};
1543 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1547 if(!push_instr(ctx
, OP_push_scope
))
1548 return E_OUTOFMEMORY
;
1550 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1554 if(!push_instr(ctx
, OP_pop_scope
))
1555 return E_OUTOFMEMORY
;
1560 /* ECMA-262 3rd Edition 12.10 */
1561 static HRESULT
compile_labelled_statement(compiler_ctx_t
*ctx
, labelled_statement_t
*stat
)
1563 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
, 0, 0, stat
}, *iter
;
1566 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1567 if(iter
->labelled_stat
&& !wcscmp(iter
->labelled_stat
->identifier
, stat
->identifier
)) {
1568 WARN("Label %s redefined\n", debugstr_w(stat
->identifier
));
1569 return JS_E_LABEL_REDEFINED
;
1573 /* Labelled breaks are allowed for any labelled statements, not only loops (violating spec) */
1574 stat_ctx
.break_label
= alloc_label(ctx
);
1575 if(!stat_ctx
.break_label
)
1576 return E_OUTOFMEMORY
;
1578 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1582 label_set_addr(ctx
, stat_ctx
.break_label
);
1586 /* ECMA-262 3rd Edition 12.13 */
1587 static HRESULT
compile_switch_statement(compiler_ctx_t
*ctx
, switch_statement_t
*stat
)
1589 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1590 unsigned case_cnt
= 0, *case_jmps
, i
, default_jmp
;
1591 BOOL have_default
= FALSE
;
1592 statement_t
*stat_iter
;
1593 case_clausule_t
*iter
;
1596 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1600 stat_ctx
.break_label
= alloc_label(ctx
);
1601 if(!stat_ctx
.break_label
)
1602 return E_OUTOFMEMORY
;
1604 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1609 case_jmps
= heap_alloc(case_cnt
* sizeof(*case_jmps
));
1611 return E_OUTOFMEMORY
;
1614 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1616 have_default
= TRUE
;
1620 set_compiler_loc(ctx
, iter
->loc
);
1621 hres
= compile_expression(ctx
, iter
->expr
, TRUE
);
1625 case_jmps
[i
] = push_instr(ctx
, OP_case
);
1627 hres
= E_OUTOFMEMORY
;
1633 if(SUCCEEDED(hres
)) {
1634 hres
= push_instr_uint(ctx
, OP_pop
, 1);
1635 if(SUCCEEDED(hres
)) {
1636 default_jmp
= push_instr(ctx
, OP_jmp
);
1638 hres
= E_OUTOFMEMORY
;
1643 heap_free(case_jmps
);
1648 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1649 while(iter
->next
&& iter
->next
->stat
== iter
->stat
) {
1650 set_arg_uint(ctx
, iter
->expr
? case_jmps
[i
++] : default_jmp
, ctx
->code_off
);
1654 set_arg_uint(ctx
, iter
->expr
? case_jmps
[i
++] : default_jmp
, ctx
->code_off
);
1656 for(stat_iter
= iter
->stat
; stat_iter
&& (!iter
->next
|| iter
->next
->stat
!= stat_iter
);
1657 stat_iter
= stat_iter
->next
) {
1658 hres
= compile_statement(ctx
, &stat_ctx
, stat_iter
);
1666 heap_free(case_jmps
);
1669 assert(i
== case_cnt
);
1672 hres
= push_instr_uint(ctx
, OP_jmp
, stat_ctx
.break_label
);
1675 set_arg_uint(ctx
, default_jmp
, ctx
->code_off
);
1678 label_set_addr(ctx
, stat_ctx
.break_label
);
1682 /* ECMA-262 3rd Edition 12.13 */
1683 static HRESULT
compile_throw_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1687 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1691 return push_instr(ctx
, OP_throw
) ? S_OK
: E_OUTOFMEMORY
;
1694 /* ECMA-262 3rd Edition 12.14 */
1695 static HRESULT
compile_try_statement(compiler_ctx_t
*ctx
, try_statement_t
*stat
)
1697 statement_ctx_t try_ctx
= {0, FALSE
, TRUE
}, finally_ctx
= {2, FALSE
, FALSE
};
1698 unsigned push_except
, finally_off
= 0, catch_off
= 0, pop_except
, catch_pop_except
= 0;
1702 push_except
= push_instr(ctx
, OP_push_except
);
1704 return E_OUTOFMEMORY
;
1706 if(stat
->catch_block
) {
1707 ident
= compiler_alloc_bstr(ctx
, stat
->catch_block
->identifier
);
1709 return E_OUTOFMEMORY
;
1714 hres
= compile_statement(ctx
, &try_ctx
, stat
->try_statement
);
1718 pop_except
= push_instr(ctx
, OP_pop_except
);
1720 return E_OUTOFMEMORY
;
1722 if(stat
->catch_block
) {
1723 statement_ctx_t catch_ctx
= {0, TRUE
, stat
->finally_statement
!= NULL
};
1725 if(stat
->finally_statement
)
1726 catch_ctx
.using_except
= TRUE
;
1728 catch_off
= ctx
->code_off
;
1730 hres
= push_instr_bstr(ctx
, OP_enter_catch
, ident
);
1734 hres
= compile_statement(ctx
, &catch_ctx
, stat
->catch_block
->statement
);
1738 if(!push_instr(ctx
, OP_pop_scope
))
1739 return E_OUTOFMEMORY
;
1741 if(stat
->finally_statement
) {
1742 catch_pop_except
= push_instr(ctx
, OP_pop_except
);
1743 if(!catch_pop_except
)
1744 return E_OUTOFMEMORY
;
1748 if(stat
->finally_statement
) {
1750 * finally block expects two elements on the stack, which may be:
1751 * - (true, return_addr) set by OP_pop_except, OP_end_finally jumps back to passed address
1752 * - (false, exception_value) set when unwinding an exception, which OP_end_finally rethrows
1754 finally_off
= ctx
->code_off
;
1755 hres
= compile_statement(ctx
, &finally_ctx
, stat
->finally_statement
);
1759 set_compiler_loc(ctx
, stat
->finally_loc
);
1760 if(!push_instr(ctx
, OP_end_finally
))
1761 return E_OUTOFMEMORY
;
1764 instr_ptr(ctx
, pop_except
)->u
.arg
[0].uint
= ctx
->code_off
;
1765 if(catch_pop_except
)
1766 instr_ptr(ctx
, catch_pop_except
)->u
.arg
[0].uint
= ctx
->code_off
;
1767 instr_ptr(ctx
, push_except
)->u
.arg
[0].uint
= catch_off
;
1768 instr_ptr(ctx
, push_except
)->u
.arg
[1].uint
= finally_off
;
1772 static HRESULT
compile_statement(compiler_ctx_t
*ctx
, statement_ctx_t
*stat_ctx
, statement_t
*stat
)
1777 stat_ctx
->next
= ctx
->stat_ctx
;
1778 ctx
->stat_ctx
= stat_ctx
;
1781 set_compiler_loc(ctx
, stat
->loc
);
1783 switch(stat
->type
) {
1785 hres
= compile_block_statement(ctx
, ((block_statement_t
*)stat
)->stat_list
);
1788 hres
= compile_break_statement(ctx
, (branch_statement_t
*)stat
);
1791 hres
= compile_continue_statement(ctx
, (branch_statement_t
*)stat
);
1798 hres
= compile_expression_statement(ctx
, (expression_statement_t
*)stat
);
1801 hres
= compile_for_statement(ctx
, (for_statement_t
*)stat
);
1804 hres
= compile_forin_statement(ctx
, (forin_statement_t
*)stat
);
1807 hres
= compile_if_statement(ctx
, (if_statement_t
*)stat
);
1810 hres
= compile_labelled_statement(ctx
, (labelled_statement_t
*)stat
);
1813 hres
= compile_return_statement(ctx
, (expression_statement_t
*)stat
);
1816 hres
= compile_switch_statement(ctx
, (switch_statement_t
*)stat
);
1819 hres
= compile_throw_statement(ctx
, (expression_statement_t
*)stat
);
1822 hres
= compile_try_statement(ctx
, (try_statement_t
*)stat
);
1825 hres
= compile_var_statement(ctx
, (var_statement_t
*)stat
);
1828 hres
= compile_while_statement(ctx
, (while_statement_t
*)stat
);
1831 hres
= compile_with_statement(ctx
, (with_statement_t
*)stat
);
1833 DEFAULT_UNREACHABLE
;
1837 assert(ctx
->stat_ctx
== stat_ctx
);
1838 ctx
->stat_ctx
= stat_ctx
->next
;
1844 static int function_local_cmp(const void *key
, const struct wine_rb_entry
*entry
)
1846 function_local_t
*local
= WINE_RB_ENTRY_VALUE(entry
, function_local_t
, entry
);
1847 return wcscmp(key
, local
->name
);
1850 static inline function_local_t
*find_local(compiler_ctx_t
*ctx
, const WCHAR
*name
)
1852 struct wine_rb_entry
*entry
= wine_rb_get(&ctx
->locals
, name
);
1853 return entry
? WINE_RB_ENTRY_VALUE(entry
, function_local_t
, entry
) : NULL
;
1856 static BOOL
alloc_local(compiler_ctx_t
*ctx
, BSTR name
, int ref
)
1858 function_local_t
*local
;
1860 local
= heap_pool_alloc(&ctx
->heap
, sizeof(*local
));
1866 wine_rb_put(&ctx
->locals
, name
, &local
->entry
);
1871 static BOOL
alloc_variable(compiler_ctx_t
*ctx
, const WCHAR
*name
)
1875 if(find_local(ctx
, name
))
1878 ident
= compiler_alloc_bstr(ctx
, name
);
1882 return alloc_local(ctx
, ident
, ctx
->func
->var_cnt
++);
1885 static HRESULT
visit_function_expression(compiler_ctx_t
*ctx
, function_expression_t
*expr
)
1887 expr
->func_id
= ctx
->func
->func_cnt
++;
1888 ctx
->func_tail
= ctx
->func_tail
? (ctx
->func_tail
->next
= expr
) : (ctx
->func_head
= expr
);
1890 return !expr
->identifier
|| expr
->event_target
|| alloc_variable(ctx
, expr
->identifier
)
1891 ? S_OK
: E_OUTOFMEMORY
;
1894 static HRESULT
visit_expression(compiler_ctx_t
*ctx
, expression_t
*expr
)
1896 HRESULT hres
= S_OK
;
1898 switch(expr
->type
) {
1903 case EXPR_ASSIGNADD
:
1904 case EXPR_ASSIGNAND
:
1905 case EXPR_ASSIGNSUB
:
1906 case EXPR_ASSIGNMUL
:
1907 case EXPR_ASSIGNDIV
:
1908 case EXPR_ASSIGNMOD
:
1910 case EXPR_ASSIGNLSHIFT
:
1911 case EXPR_ASSIGNRSHIFT
:
1912 case EXPR_ASSIGNRRSHIFT
:
1913 case EXPR_ASSIGNXOR
:
1921 case EXPR_GREATEREQ
:
1923 case EXPR_INSTANCEOF
:
1936 binary_expression_t
*binary_expr
= (binary_expression_t
*)expr
;
1938 hres
= visit_expression(ctx
, binary_expr
->expression1
);
1942 hres
= visit_expression(ctx
, binary_expr
->expression2
);
1956 hres
= visit_expression(ctx
, ((unary_expression_t
*)expr
)->expression
);
1962 case EXPR_ARRAYLIT
: {
1963 array_literal_expression_t
*array_expr
= (array_literal_expression_t
*)expr
;
1964 array_element_t
*iter
;
1966 for(iter
= array_expr
->element_list
; iter
; iter
= iter
->next
) {
1967 hres
= visit_expression(ctx
, iter
->expr
);
1975 call_expression_t
*call_expr
= (call_expression_t
*)expr
;
1978 hres
= visit_expression(ctx
, call_expr
->expression
);
1982 for(arg
= call_expr
->argument_list
; arg
; arg
= arg
->next
) {
1983 hres
= visit_expression(ctx
, arg
->expr
);
1990 conditional_expression_t
*cond_expr
= (conditional_expression_t
*)expr
;
1992 hres
= visit_expression(ctx
, cond_expr
->expression
);
1996 hres
= visit_expression(ctx
, cond_expr
->true_expression
);
2000 hres
= visit_expression(ctx
, cond_expr
->false_expression
);
2004 hres
= visit_function_expression(ctx
, (function_expression_t
*)expr
);
2007 hres
= visit_expression(ctx
, ((member_expression_t
*)expr
)->expression
);
2009 case EXPR_PROPVAL
: {
2010 property_definition_t
*iter
;
2011 for(iter
= ((property_value_expression_t
*)expr
)->property_list
; iter
; iter
= iter
->next
) {
2012 hres
= visit_expression(ctx
, iter
->value
);
2018 DEFAULT_UNREACHABLE
;
2024 static HRESULT
visit_variable_list(compiler_ctx_t
*ctx
, variable_declaration_t
*list
)
2026 variable_declaration_t
*iter
;
2029 for(iter
= list
; iter
; iter
= iter
->next
) {
2030 if(!alloc_variable(ctx
, iter
->identifier
))
2031 return E_OUTOFMEMORY
;
2034 hres
= visit_expression(ctx
, iter
->expr
);
2043 static HRESULT
visit_statement(compiler_ctx_t
*,statement_t
*);
2045 static HRESULT
visit_block_statement(compiler_ctx_t
*ctx
, statement_t
*iter
)
2050 hres
= visit_statement(ctx
, iter
);
2060 static HRESULT
visit_statement(compiler_ctx_t
*ctx
, statement_t
*stat
)
2062 HRESULT hres
= S_OK
;
2064 switch(stat
->type
) {
2066 hres
= visit_block_statement(ctx
, ((block_statement_t
*)stat
)->stat_list
);
2075 expression_statement_t
*expr_stat
= (expression_statement_t
*)stat
;
2077 hres
= visit_expression(ctx
, expr_stat
->expr
);
2081 for_statement_t
*for_stat
= (for_statement_t
*)stat
;
2083 if(for_stat
->variable_list
)
2084 hres
= visit_variable_list(ctx
, for_stat
->variable_list
);
2085 else if(for_stat
->begin_expr
)
2086 hres
= visit_expression(ctx
, for_stat
->begin_expr
);
2090 if(for_stat
->expr
) {
2091 hres
= visit_expression(ctx
, for_stat
->expr
);
2096 hres
= visit_statement(ctx
, for_stat
->statement
);
2100 if(for_stat
->end_expr
)
2101 hres
= visit_expression(ctx
, for_stat
->end_expr
);
2105 forin_statement_t
*forin_stat
= (forin_statement_t
*)stat
;
2107 if(forin_stat
->variable
) {
2108 hres
= visit_variable_list(ctx
, forin_stat
->variable
);
2113 hres
= visit_expression(ctx
, forin_stat
->in_expr
);
2117 if(forin_stat
->expr
) {
2118 hres
= visit_expression(ctx
, forin_stat
->expr
);
2123 hres
= visit_statement(ctx
, forin_stat
->statement
);
2127 if_statement_t
*if_stat
= (if_statement_t
*)stat
;
2129 hres
= visit_expression(ctx
, if_stat
->expr
);
2133 hres
= visit_statement(ctx
, if_stat
->if_stat
);
2137 if(if_stat
->else_stat
)
2138 hres
= visit_statement(ctx
, if_stat
->else_stat
);
2142 hres
= visit_statement(ctx
, ((labelled_statement_t
*)stat
)->statement
);
2145 switch_statement_t
*switch_stat
= (switch_statement_t
*)stat
;
2146 statement_t
*stat_iter
;
2147 case_clausule_t
*iter
;
2149 hres
= visit_expression(ctx
, switch_stat
->expr
);
2153 for(iter
= switch_stat
->case_list
; iter
; iter
= iter
->next
) {
2156 hres
= visit_expression(ctx
, iter
->expr
);
2161 for(iter
= switch_stat
->case_list
; iter
; iter
= iter
->next
) {
2162 while(iter
->next
&& iter
->next
->stat
== iter
->stat
)
2164 for(stat_iter
= iter
->stat
; stat_iter
&& (!iter
->next
|| iter
->next
->stat
!= stat_iter
);
2165 stat_iter
= stat_iter
->next
) {
2166 hres
= visit_statement(ctx
, stat_iter
);
2174 try_statement_t
*try_stat
= (try_statement_t
*)stat
;
2176 hres
= visit_statement(ctx
, try_stat
->try_statement
);
2180 if(try_stat
->catch_block
) {
2181 hres
= visit_statement(ctx
, try_stat
->catch_block
->statement
);
2186 if(try_stat
->finally_statement
)
2187 hres
= visit_statement(ctx
, try_stat
->finally_statement
);
2191 hres
= visit_variable_list(ctx
, ((var_statement_t
*)stat
)->variable_list
);
2194 while_statement_t
*while_stat
= (while_statement_t
*)stat
;
2196 hres
= visit_expression(ctx
, while_stat
->expr
);
2200 hres
= visit_statement(ctx
, while_stat
->statement
);
2204 with_statement_t
*with_stat
= (with_statement_t
*)stat
;
2206 hres
= visit_expression(ctx
, with_stat
->expr
);
2210 hres
= visit_statement(ctx
, with_stat
->statement
);
2213 DEFAULT_UNREACHABLE
;
2219 static void resolve_labels(compiler_ctx_t
*ctx
, unsigned off
)
2223 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->code_off
; instr
++) {
2224 if(instr_info
[instr
->op
].arg1_type
== ARG_ADDR
&& (instr
->u
.arg
->uint
& LABEL_FLAG
)) {
2225 assert((instr
->u
.arg
->uint
& ~LABEL_FLAG
) < ctx
->labels_cnt
);
2226 instr
->u
.arg
->uint
= ctx
->labels
[instr
->u
.arg
->uint
& ~LABEL_FLAG
];
2228 assert(instr_info
[instr
->op
].arg2_type
!= ARG_ADDR
);
2231 ctx
->labels_cnt
= 0;
2234 unsigned get_location_line(bytecode_t
*code
, unsigned loc
, unsigned *char_pos
)
2236 unsigned line
= code
->start_line
;
2237 const WCHAR
*nl
, *p
;
2239 for(nl
= p
= code
->source
; p
< code
->source
+ loc
; p
++) {
2240 if(*p
!= '\n') continue;
2244 *char_pos
= loc
- (nl
- code
->source
);
2248 void release_bytecode(bytecode_t
*code
)
2255 for(i
=0; i
< code
->bstr_cnt
; i
++)
2256 SysFreeString(code
->bstr_pool
[i
]);
2257 for(i
=0; i
< code
->str_cnt
; i
++)
2258 jsstr_release(code
->str_pool
[i
]);
2260 if(code
->named_item
)
2261 release_named_item(code
->named_item
);
2262 heap_free(code
->source
);
2263 heap_pool_free(&code
->heap
);
2264 heap_free(code
->bstr_pool
);
2265 heap_free(code
->str_pool
);
2266 heap_free(code
->instrs
);
2270 static HRESULT
init_code(compiler_ctx_t
*compiler
, const WCHAR
*source
, UINT64 source_context
, unsigned start_line
)
2272 size_t len
= source
? lstrlenW(source
) : 0;
2275 return E_OUTOFMEMORY
;
2277 compiler
->code
= heap_alloc_zero(sizeof(bytecode_t
));
2279 return E_OUTOFMEMORY
;
2281 compiler
->code
->ref
= 1;
2282 compiler
->code
->source_context
= source_context
;
2283 compiler
->code
->start_line
= start_line
;
2284 heap_pool_init(&compiler
->code
->heap
);
2286 compiler
->code
->source
= heap_alloc((len
+ 1) * sizeof(WCHAR
));
2287 if(!compiler
->code
->source
) {
2288 release_bytecode(compiler
->code
);
2289 return E_OUTOFMEMORY
;
2292 memcpy(compiler
->code
->source
, source
, len
* sizeof(WCHAR
));
2293 compiler
->code
->source
[len
] = 0;
2295 compiler
->code
->instrs
= heap_alloc(64 * sizeof(instr_t
));
2296 if(!compiler
->code
->instrs
) {
2297 release_bytecode(compiler
->code
);
2298 return E_OUTOFMEMORY
;
2301 compiler
->code_size
= 64;
2302 compiler
->code_off
= 1;
2306 static HRESULT
compile_function(compiler_ctx_t
*ctx
, source_elements_t
*source
, function_expression_t
*func_expr
,
2307 BOOL from_eval
, function_code_t
*func
)
2309 function_expression_t
*iter
;
2310 function_local_t
*local
;
2316 func
->bytecode
= ctx
->code
;
2317 ctx
->func_head
= ctx
->func_tail
= NULL
;
2318 ctx
->from_eval
= from_eval
;
2320 ctx
->locals_cnt
= 0;
2321 wine_rb_init(&ctx
->locals
, function_local_cmp
);
2324 parameter_t
*param_iter
;
2326 if(func_expr
->identifier
) {
2327 func
->name
= compiler_alloc_bstr(ctx
, func_expr
->identifier
);
2329 return E_OUTOFMEMORY
;
2332 if(func_expr
->event_target
) {
2333 func
->event_target
= compiler_alloc_bstr(ctx
, func_expr
->event_target
);
2334 if(!func
->event_target
)
2335 return E_OUTOFMEMORY
;
2338 func
->source
= func_expr
->src_str
;
2339 func
->source_len
= func_expr
->src_len
;
2341 for(param_iter
= func_expr
->parameter_list
; param_iter
; param_iter
= param_iter
->next
)
2344 func
->params
= compiler_alloc(ctx
->code
, func
->param_cnt
* sizeof(*func
->params
));
2346 return E_OUTOFMEMORY
;
2348 for(param_iter
= func_expr
->parameter_list
, i
=0; param_iter
; param_iter
= param_iter
->next
, i
++) {
2349 func
->params
[i
] = compiler_alloc_bstr(ctx
, param_iter
->identifier
);
2350 if(!func
->params
[i
])
2351 return E_OUTOFMEMORY
;
2355 for(i
= 0; i
< func
->param_cnt
; i
++) {
2356 if(!find_local(ctx
, func
->params
[i
]) && !alloc_local(ctx
, func
->params
[i
], -i
-1))
2357 return E_OUTOFMEMORY
;
2360 hres
= visit_block_statement(ctx
, source
->statement
);
2364 func
->locals
= compiler_alloc(ctx
->code
, ctx
->locals_cnt
* sizeof(*func
->locals
));
2366 return E_OUTOFMEMORY
;
2367 func
->locals_cnt
= ctx
->locals_cnt
;
2369 func
->variables
= compiler_alloc(ctx
->code
, func
->var_cnt
* sizeof(*func
->variables
));
2370 if(!func
->variables
)
2371 return E_OUTOFMEMORY
;
2374 WINE_RB_FOR_EACH_ENTRY(local
, &ctx
->locals
, function_local_t
, entry
) {
2375 func
->locals
[i
].name
= local
->name
;
2376 func
->locals
[i
].ref
= local
->ref
;
2377 if(local
->ref
>= 0) {
2378 func
->variables
[local
->ref
].name
= local
->name
;
2379 func
->variables
[local
->ref
].func_id
= -1;
2383 assert(i
== ctx
->locals_cnt
);
2385 func
->funcs
= compiler_alloc(ctx
->code
, func
->func_cnt
* sizeof(*func
->funcs
));
2387 return E_OUTOFMEMORY
;
2388 memset(func
->funcs
, 0, func
->func_cnt
* sizeof(*func
->funcs
));
2390 off
= ctx
->code_off
;
2391 hres
= compile_block_statement(ctx
, source
->statement
);
2395 resolve_labels(ctx
, off
);
2397 hres
= push_instr_uint(ctx
, OP_ret
, !from_eval
);
2401 if(TRACE_ON(jscript_disas
))
2402 dump_code(ctx
, off
);
2404 func
->instr_off
= off
;
2406 for(iter
= ctx
->func_head
, i
=0; iter
; iter
= iter
->next
, i
++) {
2407 hres
= compile_function(ctx
, iter
->source_elements
, iter
, FALSE
, func
->funcs
+i
);
2411 TRACE("[%d] func %s\n", i
, debugstr_w(func
->funcs
[i
].name
));
2412 if(func
->funcs
[i
].name
&& !func
->funcs
[i
].event_target
) {
2413 local_ref_t
*local_ref
= lookup_local(func
, func
->funcs
[i
].name
);
2414 func
->funcs
[i
].local_ref
= local_ref
->ref
;
2415 TRACE("found ref %s %d for %s\n", debugstr_w(local_ref
->name
), local_ref
->ref
, debugstr_w(func
->funcs
[i
].name
));
2416 if(local_ref
->ref
>= 0)
2417 func
->variables
[local_ref
->ref
].func_id
= i
;
2421 assert(i
== func
->func_cnt
);
2426 static HRESULT
parse_arguments(compiler_ctx_t
*ctx
, const WCHAR
*args
, BSTR
*arg_array
, unsigned *args_size
)
2428 const WCHAR
*ptr
= args
, *ptr2
;
2429 unsigned arg_cnt
= 0;
2431 while(iswspace(*ptr
))
2440 if(!iswalpha(*ptr
) && *ptr
!= '_') {
2441 FIXME("expected alpha or '_': %s\n", debugstr_w(ptr
));
2446 while(iswalnum(*ptr
) || *ptr
== '_')
2449 if(*ptr
&& *ptr
!= ',' && !iswspace(*ptr
)) {
2450 FIXME("unexpected har %s\n", debugstr_w(ptr
));
2455 arg_array
[arg_cnt
] = compiler_alloc_bstr_len(ctx
, ptr2
, ptr
-ptr2
);
2456 if(!arg_array
[arg_cnt
])
2457 return E_OUTOFMEMORY
;
2461 while(iswspace(*ptr
))
2466 FIXME("expected ',': %s\n", debugstr_w(ptr
));
2471 while(iswspace(*ptr
))
2476 *args_size
= arg_cnt
;
2480 static HRESULT
compile_arguments(compiler_ctx_t
*ctx
, const WCHAR
*args
)
2484 hres
= parse_arguments(ctx
, args
, NULL
, &ctx
->code
->global_code
.param_cnt
);
2488 ctx
->code
->global_code
.params
= compiler_alloc(ctx
->code
,
2489 ctx
->code
->global_code
.param_cnt
* sizeof(*ctx
->code
->global_code
.params
));
2490 if(!ctx
->code
->global_code
.params
)
2491 return E_OUTOFMEMORY
;
2493 return parse_arguments(ctx
, args
, ctx
->code
->global_code
.params
, NULL
);
2496 HRESULT
compile_script(script_ctx_t
*ctx
, const WCHAR
*code
, UINT64 source_context
, unsigned start_line
,
2497 const WCHAR
*args
, const WCHAR
*delimiter
, BOOL from_eval
, BOOL use_decode
,
2498 named_item_t
*named_item
, bytecode_t
**ret
)
2500 compiler_ctx_t compiler
= {0};
2503 hres
= init_code(&compiler
, code
, source_context
, start_line
);
2508 hres
= compile_arguments(&compiler
, args
);
2514 hres
= decode_source(compiler
.code
->source
);
2516 WARN("Decoding failed\n");
2521 hres
= script_parse(ctx
, &compiler
, compiler
.code
, delimiter
, from_eval
, &compiler
.parser
);
2523 release_bytecode(compiler
.code
);
2527 heap_pool_init(&compiler
.heap
);
2528 hres
= compile_function(&compiler
, compiler
.parser
->source
, NULL
, from_eval
, &compiler
.code
->global_code
);
2529 heap_pool_free(&compiler
.heap
);
2530 parser_release(compiler
.parser
);
2532 if(hres
!= DISP_E_EXCEPTION
)
2533 throw_error(ctx
, hres
, NULL
);
2534 set_error_location(ctx
->ei
, compiler
.code
, compiler
.loc
, IDS_COMPILATION_ERROR
, NULL
);
2535 release_bytecode(compiler
.code
);
2536 return DISP_E_EXCEPTION
;
2540 compiler
.code
->named_item
= named_item
;
2544 *ret
= compiler
.code
;