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
;
64 struct wine_rb_tree locals
;
67 statement_ctx_t
*stat_ctx
;
68 function_code_t
*func
;
70 function_expression_t
*func_head
;
71 function_expression_t
*func_tail
;
78 instr_arg_type_t arg1_type
;
79 instr_arg_type_t arg2_type
;
81 #define X(n,a,b,c) {#n,b,c},
86 static void dump_instr_arg(instr_arg_type_t type
, instr_arg_t
*arg
)
90 TRACE_(jscript_disas
)("\t%s", debugstr_jsstr(arg
->str
));
93 TRACE_(jscript_disas
)("\t%s", debugstr_wn(arg
->bstr
, SysStringLen(arg
->bstr
)));
96 TRACE_(jscript_disas
)("\t%d", arg
->uint
);
100 TRACE_(jscript_disas
)("\t%u", arg
->uint
);
109 static void dump_code(compiler_ctx_t
*ctx
, unsigned off
)
113 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->code_off
; instr
++) {
114 TRACE_(jscript_disas
)("%d:\t%s", (int)(instr
-ctx
->code
->instrs
), instr_info
[instr
->op
].op_str
);
115 if(instr_info
[instr
->op
].arg1_type
== ARG_DBL
) {
116 TRACE_(jscript_disas
)("\t%lf", instr
->u
.dbl
);
118 dump_instr_arg(instr_info
[instr
->op
].arg1_type
, instr
->u
.arg
);
119 dump_instr_arg(instr_info
[instr
->op
].arg2_type
, instr
->u
.arg
+1);
121 TRACE_(jscript_disas
)("\n");
125 static HRESULT
compile_expression(compiler_ctx_t
*,expression_t
*,BOOL
);
126 static HRESULT
compile_statement(compiler_ctx_t
*,statement_ctx_t
*,statement_t
*);
128 static inline void *compiler_alloc(bytecode_t
*code
, size_t size
)
130 return heap_pool_alloc(&code
->heap
, size
);
133 static jsstr_t
*compiler_alloc_string_len(compiler_ctx_t
*ctx
, const WCHAR
*str
, unsigned len
)
137 if(!ctx
->code
->str_pool_size
) {
138 ctx
->code
->str_pool
= heap_alloc(8 * sizeof(jsstr_t
*));
139 if(!ctx
->code
->str_pool
)
141 ctx
->code
->str_pool_size
= 8;
142 }else if(ctx
->code
->str_pool_size
== ctx
->code
->str_cnt
) {
145 new_pool
= heap_realloc(ctx
->code
->str_pool
, ctx
->code
->str_pool_size
*2*sizeof(jsstr_t
*));
149 ctx
->code
->str_pool
= new_pool
;
150 ctx
->code
->str_pool_size
*= 2;
153 new_str
= jsstr_alloc_len(str
, len
);
157 ctx
->code
->str_pool
[ctx
->code
->str_cnt
++] = new_str
;
161 static jsstr_t
*compiler_alloc_string(compiler_ctx_t
*ctx
, const WCHAR
*str
)
163 return compiler_alloc_string_len(ctx
, str
, strlenW(str
));
166 static BOOL
ensure_bstr_slot(compiler_ctx_t
*ctx
)
168 if(!ctx
->code
->bstr_pool_size
) {
169 ctx
->code
->bstr_pool
= heap_alloc(8 * sizeof(BSTR
));
170 if(!ctx
->code
->bstr_pool
)
172 ctx
->code
->bstr_pool_size
= 8;
173 }else if(ctx
->code
->bstr_pool_size
== ctx
->code
->bstr_cnt
) {
176 new_pool
= heap_realloc(ctx
->code
->bstr_pool
, ctx
->code
->bstr_pool_size
*2*sizeof(BSTR
));
180 ctx
->code
->bstr_pool
= new_pool
;
181 ctx
->code
->bstr_pool_size
*= 2;
187 static BSTR
compiler_alloc_bstr(compiler_ctx_t
*ctx
, const WCHAR
*str
)
189 if(!ensure_bstr_slot(ctx
))
192 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocString(str
);
193 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
196 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
199 static BSTR
compiler_alloc_bstr_len(compiler_ctx_t
*ctx
, const WCHAR
*str
, size_t len
)
201 if(!ensure_bstr_slot(ctx
))
204 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocStringLen(str
, len
);
205 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
208 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
211 static unsigned push_instr(compiler_ctx_t
*ctx
, jsop_t op
)
213 assert(ctx
->code_size
>= ctx
->code_off
);
215 if(ctx
->code_size
== ctx
->code_off
) {
218 new_instrs
= heap_realloc(ctx
->code
->instrs
, ctx
->code_size
*2*sizeof(instr_t
));
222 ctx
->code
->instrs
= new_instrs
;
226 ctx
->code
->instrs
[ctx
->code_off
].op
= op
;
227 return ctx
->code_off
++;
230 static inline instr_t
*instr_ptr(compiler_ctx_t
*ctx
, unsigned off
)
232 assert(off
< ctx
->code_off
);
233 return ctx
->code
->instrs
+ off
;
236 static HRESULT
push_instr_int(compiler_ctx_t
*ctx
, jsop_t op
, LONG arg
)
240 instr
= push_instr(ctx
, op
);
242 return E_OUTOFMEMORY
;
244 instr_ptr(ctx
, instr
)->u
.arg
->lng
= arg
;
248 static HRESULT
push_instr_str(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
253 str
= compiler_alloc_string(ctx
, arg
);
255 return E_OUTOFMEMORY
;
257 instr
= push_instr(ctx
, op
);
259 return E_OUTOFMEMORY
;
261 instr_ptr(ctx
, instr
)->u
.arg
->str
= str
;
265 static HRESULT
push_instr_bstr(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
270 str
= compiler_alloc_bstr(ctx
, arg
);
272 return E_OUTOFMEMORY
;
274 instr
= push_instr(ctx
, op
);
276 return E_OUTOFMEMORY
;
278 instr_ptr(ctx
, instr
)->u
.arg
->bstr
= str
;
282 static HRESULT
push_instr_bstr_uint(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg1
, unsigned arg2
)
287 str
= compiler_alloc_bstr(ctx
, arg1
);
289 return E_OUTOFMEMORY
;
291 instr
= push_instr(ctx
, op
);
293 return E_OUTOFMEMORY
;
295 instr_ptr(ctx
, instr
)->u
.arg
[0].bstr
= str
;
296 instr_ptr(ctx
, instr
)->u
.arg
[1].uint
= arg2
;
300 static HRESULT
push_instr_uint_str(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg1
, const WCHAR
*arg2
)
305 str
= compiler_alloc_string(ctx
, arg2
);
307 return E_OUTOFMEMORY
;
309 instr
= push_instr(ctx
, op
);
311 return E_OUTOFMEMORY
;
313 instr_ptr(ctx
, instr
)->u
.arg
[0].uint
= arg1
;
314 instr_ptr(ctx
, instr
)->u
.arg
[1].str
= str
;
318 static HRESULT
push_instr_double(compiler_ctx_t
*ctx
, jsop_t op
, double arg
)
322 instr
= push_instr(ctx
, op
);
324 return E_OUTOFMEMORY
;
326 instr_ptr(ctx
, instr
)->u
.dbl
= arg
;
330 static inline void set_arg_uint(compiler_ctx_t
*ctx
, unsigned instr
, unsigned arg
)
332 instr_ptr(ctx
, instr
)->u
.arg
->uint
= arg
;
335 static HRESULT
push_instr_uint(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg
)
339 instr
= push_instr(ctx
, op
);
341 return E_OUTOFMEMORY
;
343 set_arg_uint(ctx
, instr
, arg
);
347 static HRESULT
compile_binary_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
351 hres
= compile_expression(ctx
, expr
->expression1
, TRUE
);
355 hres
= compile_expression(ctx
, expr
->expression2
, TRUE
);
359 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
362 static HRESULT
compile_unary_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
)
366 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
370 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
373 /* ECMA-262 3rd Edition 11.2.1 */
374 static HRESULT
compile_member_expression(compiler_ctx_t
*ctx
, member_expression_t
*expr
)
378 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
382 return push_instr_bstr(ctx
, OP_member
, expr
->identifier
);
385 #define LABEL_FLAG 0x80000000
387 static unsigned alloc_label(compiler_ctx_t
*ctx
)
389 if(!ctx
->labels_size
) {
390 ctx
->labels
= heap_alloc(8 * sizeof(*ctx
->labels
));
393 ctx
->labels_size
= 8;
394 }else if(ctx
->labels_size
== ctx
->labels_cnt
) {
395 unsigned *new_labels
;
397 new_labels
= heap_realloc(ctx
->labels
, 2*ctx
->labels_size
*sizeof(*ctx
->labels
));
401 ctx
->labels
= new_labels
;
402 ctx
->labels_size
*= 2;
405 return ctx
->labels_cnt
++ | LABEL_FLAG
;
408 static void label_set_addr(compiler_ctx_t
*ctx
, unsigned label
)
410 assert(label
& LABEL_FLAG
);
411 ctx
->labels
[label
& ~LABEL_FLAG
] = ctx
->code_off
;
414 static inline BOOL
is_memberid_expr(expression_type_t type
)
416 return type
== EXPR_IDENT
|| type
== EXPR_MEMBER
|| type
== EXPR_ARRAY
;
419 static BOOL
bind_local(compiler_ctx_t
*ctx
, const WCHAR
*identifier
, int *ret_ref
)
421 statement_ctx_t
*iter
;
424 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
425 if(iter
->using_scope
)
429 ref
= lookup_local(ctx
->func
, identifier
);
437 static HRESULT
emit_identifier_ref(compiler_ctx_t
*ctx
, const WCHAR
*identifier
, unsigned flags
)
440 if(bind_local(ctx
, identifier
, &local_ref
))
441 return push_instr_int(ctx
, OP_local_ref
, local_ref
);
442 return push_instr_bstr_uint(ctx
, OP_identid
, identifier
, flags
);
445 static HRESULT
emit_identifier(compiler_ctx_t
*ctx
, const WCHAR
*identifier
)
448 if(bind_local(ctx
, identifier
, &local_ref
))
449 return push_instr_int(ctx
, OP_local
, local_ref
);
450 return push_instr_bstr(ctx
, OP_ident
, identifier
);
453 static HRESULT
compile_memberid_expression(compiler_ctx_t
*ctx
, expression_t
*expr
, unsigned flags
)
459 identifier_expression_t
*ident_expr
= (identifier_expression_t
*)expr
;
461 hres
= emit_identifier_ref(ctx
, ident_expr
->identifier
, flags
);
465 binary_expression_t
*array_expr
= (binary_expression_t
*)expr
;
467 hres
= compile_expression(ctx
, array_expr
->expression1
, TRUE
);
471 hres
= compile_expression(ctx
, array_expr
->expression2
, TRUE
);
475 hres
= push_instr_uint(ctx
, OP_memberid
, flags
);
479 member_expression_t
*member_expr
= (member_expression_t
*)expr
;
481 hres
= compile_expression(ctx
, member_expr
->expression
, TRUE
);
485 /* FIXME: Potential optimization */
486 hres
= push_instr_str(ctx
, OP_str
, member_expr
->identifier
);
490 hres
= push_instr_uint(ctx
, OP_memberid
, flags
);
499 static HRESULT
compile_increment_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
, int n
)
503 if(!is_memberid_expr(expr
->expression
->type
)) {
504 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
508 return push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
511 hres
= compile_memberid_expression(ctx
, expr
->expression
, fdexNameEnsure
);
515 return push_instr_int(ctx
, op
, n
);
518 /* ECMA-262 3rd Edition 11.14 */
519 static HRESULT
compile_comma_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, BOOL emit_ret
)
523 hres
= compile_expression(ctx
, expr
->expression1
, FALSE
);
527 return compile_expression(ctx
, expr
->expression2
, emit_ret
);
530 /* ECMA-262 3rd Edition 11.11 */
531 static HRESULT
compile_logical_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
536 hres
= compile_expression(ctx
, expr
->expression1
, TRUE
);
540 instr
= push_instr(ctx
, op
);
542 return E_OUTOFMEMORY
;
544 hres
= compile_expression(ctx
, expr
->expression2
, TRUE
);
548 set_arg_uint(ctx
, instr
, ctx
->code_off
);
552 /* ECMA-262 3rd Edition 11.12 */
553 static HRESULT
compile_conditional_expression(compiler_ctx_t
*ctx
, conditional_expression_t
*expr
)
555 unsigned jmp_false
, jmp_end
;
558 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
562 jmp_false
= push_instr(ctx
, OP_cnd_z
);
564 return E_OUTOFMEMORY
;
566 hres
= compile_expression(ctx
, expr
->true_expression
, TRUE
);
570 jmp_end
= push_instr(ctx
, OP_jmp
);
572 return E_OUTOFMEMORY
;
574 set_arg_uint(ctx
, jmp_false
, ctx
->code_off
);
575 hres
= push_instr_uint(ctx
, OP_pop
, 1);
579 hres
= compile_expression(ctx
, expr
->false_expression
, TRUE
);
583 set_arg_uint(ctx
, jmp_end
, ctx
->code_off
);
587 static HRESULT
compile_new_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
)
589 unsigned arg_cnt
= 0;
593 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
597 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
598 hres
= compile_expression(ctx
, arg
->expr
, TRUE
);
604 hres
= push_instr_uint(ctx
, OP_new
, arg_cnt
);
608 hres
= push_instr_uint(ctx
, OP_pop
, arg_cnt
+1);
612 return push_instr(ctx
, OP_push_ret
) ? S_OK
: E_OUTOFMEMORY
;
615 static HRESULT
compile_call_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
, BOOL emit_ret
)
617 unsigned arg_cnt
= 0, extra_args
;
623 if(is_memberid_expr(expr
->expression
->type
)) {
626 hres
= compile_memberid_expression(ctx
, expr
->expression
, 0);
630 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
636 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
637 hres
= compile_expression(ctx
, arg
->expr
, TRUE
);
643 instr
= push_instr(ctx
, op
);
645 return E_OUTOFMEMORY
;
647 instr_ptr(ctx
, instr
)->u
.arg
[0].uint
= arg_cnt
;
648 instr_ptr(ctx
, instr
)->u
.arg
[1].lng
= emit_ret
;
650 hres
= push_instr_uint(ctx
, OP_pop
, arg_cnt
+ extra_args
);
654 return !emit_ret
|| push_instr(ctx
, OP_push_ret
) ? S_OK
: E_OUTOFMEMORY
;
657 static HRESULT
compile_delete_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
661 switch(expr
->expression
->type
) {
663 binary_expression_t
*array_expr
= (binary_expression_t
*)expr
->expression
;
665 hres
= compile_expression(ctx
, array_expr
->expression1
, TRUE
);
669 hres
= compile_expression(ctx
, array_expr
->expression2
, TRUE
);
673 if(!push_instr(ctx
, OP_delete
))
674 return E_OUTOFMEMORY
;
678 member_expression_t
*member_expr
= (member_expression_t
*)expr
->expression
;
680 hres
= compile_expression(ctx
, member_expr
->expression
, TRUE
);
684 /* FIXME: Potential optimization */
685 hres
= push_instr_str(ctx
, OP_str
, member_expr
->identifier
);
689 if(!push_instr(ctx
, OP_delete
))
690 return E_OUTOFMEMORY
;
694 return push_instr_bstr(ctx
, OP_delete_ident
, ((identifier_expression_t
*)expr
->expression
)->identifier
);
696 const WCHAR fixmeW
[] = {'F','I','X','M','E',0};
698 WARN("invalid delete, unimplemented exception message\n");
700 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
704 return push_instr_uint_str(ctx
, OP_throw_type
, JS_E_INVALID_DELETE
, fixmeW
);
711 static HRESULT
compile_assign_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
713 BOOL use_throw_path
= FALSE
;
714 unsigned arg_cnt
= 0;
717 if(expr
->expression1
->type
== EXPR_CALL
) {
718 call_expression_t
*call_expr
= (call_expression_t
*)expr
->expression1
;
722 FIXME("op %d not supported on parametrized assign expressions\n", op
);
726 if(is_memberid_expr(call_expr
->expression
->type
) && call_expr
->argument_list
) {
727 hres
= compile_memberid_expression(ctx
, call_expr
->expression
, fdexNameEnsure
);
731 for(arg
= call_expr
->argument_list
; arg
; arg
= arg
->next
) {
732 hres
= compile_expression(ctx
, arg
->expr
, TRUE
);
738 use_throw_path
= TRUE
;
740 }else if(is_memberid_expr(expr
->expression1
->type
)) {
741 hres
= compile_memberid_expression(ctx
, expr
->expression1
, fdexNameEnsure
);
745 use_throw_path
= TRUE
;
749 /* Illegal assignment: evaluate and throw */
750 hres
= compile_expression(ctx
, expr
->expression1
, TRUE
);
754 hres
= compile_expression(ctx
, expr
->expression2
, TRUE
);
758 if(op
!= OP_LAST
&& !push_instr(ctx
, op
))
759 return E_OUTOFMEMORY
;
761 return push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
764 if(op
!= OP_LAST
&& !push_instr(ctx
, OP_refval
))
765 return E_OUTOFMEMORY
;
767 hres
= compile_expression(ctx
, expr
->expression2
, TRUE
);
771 if(op
!= OP_LAST
&& !push_instr(ctx
, op
))
772 return E_OUTOFMEMORY
;
775 return push_instr_uint(ctx
, OP_assign_call
, arg_cnt
);
777 if(!push_instr(ctx
, OP_assign
))
778 return E_OUTOFMEMORY
;
783 static HRESULT
compile_typeof_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
788 if(is_memberid_expr(expr
->expression
->type
)) {
789 if(expr
->expression
->type
== EXPR_IDENT
)
790 return push_instr_bstr(ctx
, OP_typeofident
, ((identifier_expression_t
*)expr
->expression
)->identifier
);
793 hres
= compile_memberid_expression(ctx
, expr
->expression
, 0);
796 hres
= compile_expression(ctx
, expr
->expression
, TRUE
);
801 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
804 static HRESULT
compile_literal(compiler_ctx_t
*ctx
, literal_t
*literal
)
806 switch(literal
->type
) {
808 return push_instr_int(ctx
, OP_bool
, literal
->u
.bval
);
810 return push_instr_double(ctx
, OP_double
, literal
->u
.dval
);
812 return push_instr(ctx
, OP_null
) ? S_OK
: E_OUTOFMEMORY
;
814 return push_instr_str(ctx
, OP_str
, literal
->u
.wstr
);
819 str
= compiler_alloc_string_len(ctx
, literal
->u
.regexp
.str
, literal
->u
.regexp
.str_len
);
821 return E_OUTOFMEMORY
;
823 instr
= push_instr(ctx
, OP_regexp
);
825 return E_OUTOFMEMORY
;
827 instr_ptr(ctx
, instr
)->u
.arg
[0].str
= str
;
828 instr_ptr(ctx
, instr
)->u
.arg
[1].uint
= literal
->u
.regexp
.flags
;
836 static HRESULT
literal_as_bstr(compiler_ctx_t
*ctx
, literal_t
*literal
, BSTR
*str
)
838 switch(literal
->type
) {
840 *str
= compiler_alloc_bstr(ctx
, literal
->u
.wstr
);
846 hres
= double_to_string(literal
->u
.dval
, &jsstr
);
850 *str
= compiler_alloc_bstr_len(ctx
, NULL
, jsstr_length(jsstr
));
852 jsstr_flush(jsstr
, *str
);
853 jsstr_release(jsstr
);
859 return *str
? S_OK
: E_OUTOFMEMORY
;
862 static HRESULT
compile_array_literal(compiler_ctx_t
*ctx
, array_literal_expression_t
*expr
)
864 unsigned i
, elem_cnt
= expr
->length
;
865 array_element_t
*iter
;
868 for(iter
= expr
->element_list
; iter
; iter
= iter
->next
) {
869 elem_cnt
+= iter
->elision
+1;
871 for(i
=0; i
< iter
->elision
; i
++) {
872 if(!push_instr(ctx
, OP_undefined
))
873 return E_OUTOFMEMORY
;
876 hres
= compile_expression(ctx
, iter
->expr
, TRUE
);
881 for(i
=0; i
< expr
->length
; i
++) {
882 if(!push_instr(ctx
, OP_undefined
))
883 return E_OUTOFMEMORY
;
886 return push_instr_uint(ctx
, OP_carray
, elem_cnt
);
889 static HRESULT
compile_object_literal(compiler_ctx_t
*ctx
, property_value_expression_t
*expr
)
896 if(!push_instr(ctx
, OP_new_obj
))
897 return E_OUTOFMEMORY
;
899 for(iter
= expr
->property_list
; iter
; iter
= iter
->next
) {
900 hres
= literal_as_bstr(ctx
, iter
->name
, &name
);
904 hres
= compile_expression(ctx
, iter
->value
, TRUE
);
908 instr
= push_instr(ctx
, OP_obj_prop
);
910 return E_OUTOFMEMORY
;
912 instr_ptr(ctx
, instr
)->u
.arg
->bstr
= name
;
918 static HRESULT
compile_function_expression(compiler_ctx_t
*ctx
, function_expression_t
*expr
, BOOL emit_ret
)
920 return emit_ret
? push_instr_uint(ctx
, OP_func
, expr
->func_id
) : S_OK
;
923 static HRESULT
compile_expression(compiler_ctx_t
*ctx
, expression_t
*expr
, BOOL emit_ret
)
929 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
932 hres
= compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_cnd_z
);
935 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_array
);
938 hres
= compile_array_literal(ctx
, (array_literal_expression_t
*)expr
);
941 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_LAST
);
944 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
947 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
950 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
953 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
956 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
959 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
962 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
964 case EXPR_ASSIGNLSHIFT
:
965 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_lshift
);
967 case EXPR_ASSIGNRSHIFT
:
968 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift
);
970 case EXPR_ASSIGNRRSHIFT
:
971 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift2
);
974 hres
= compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
977 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
980 hres
= compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_bneg
);
983 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
986 return compile_call_expression(ctx
, (call_expression_t
*)expr
, emit_ret
);
988 return compile_comma_expression(ctx
, (binary_expression_t
*)expr
, emit_ret
);
990 hres
= compile_conditional_expression(ctx
, (conditional_expression_t
*)expr
);
993 hres
= compile_delete_expression(ctx
, (unary_expression_t
*)expr
);
996 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
999 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq
);
1002 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq2
);
1005 return compile_function_expression(ctx
, (function_expression_t
*)expr
, emit_ret
);
1007 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gt
);
1009 case EXPR_GREATEREQ
:
1010 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gteq
);
1013 hres
= emit_identifier(ctx
, ((identifier_expression_t
*)expr
)->identifier
);
1016 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_in
);
1018 case EXPR_INSTANCEOF
:
1019 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_instanceof
);
1022 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lt
);
1025 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lteq
);
1028 hres
= compile_literal(ctx
, ((literal_expression_t
*)expr
)->literal
);
1031 hres
= compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_neg
);
1034 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lshift
);
1037 hres
= compile_member_expression(ctx
, (member_expression_t
*)expr
);
1040 hres
= compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_minus
);
1043 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
1046 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
1049 hres
= compile_new_expression(ctx
, (call_expression_t
*)expr
);
1052 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq
);
1055 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq2
);
1058 hres
= compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_cnd_nz
);
1061 hres
= compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_tonum
);
1064 hres
= compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_postinc
, -1);
1067 hres
= compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_postinc
, 1);
1070 hres
= compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_preinc
, -1);
1073 hres
= compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_preinc
, 1);
1076 hres
= compile_object_literal(ctx
, (property_value_expression_t
*)expr
);
1079 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift
);
1082 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift2
);
1085 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
1088 return !emit_ret
|| push_instr(ctx
, OP_this
) ? S_OK
: E_OUTOFMEMORY
;
1090 hres
= compile_typeof_expression(ctx
, (unary_expression_t
*)expr
);
1093 hres
= compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_void
);
1096 hres
= compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
1098 DEFAULT_UNREACHABLE
;
1104 return emit_ret
? S_OK
: push_instr_uint(ctx
, OP_pop
, 1);
1107 static inline BOOL
is_loop_statement(statement_type_t type
)
1109 return type
== STAT_FOR
|| type
== STAT_FORIN
|| type
== STAT_WHILE
;
1112 /* ECMA-262 3rd Edition 12.1 */
1113 static HRESULT
compile_block_statement(compiler_ctx_t
*ctx
, statement_t
*iter
)
1118 hres
= compile_statement(ctx
, NULL
, iter
);
1128 /* ECMA-262 3rd Edition 12.2 */
1129 static HRESULT
compile_variable_list(compiler_ctx_t
*ctx
, variable_declaration_t
*list
)
1131 variable_declaration_t
*iter
;
1134 assert(list
!= NULL
);
1136 for(iter
= list
; iter
; iter
= iter
->next
) {
1140 hres
= emit_identifier_ref(ctx
, iter
->identifier
, 0);
1144 hres
= compile_expression(ctx
, iter
->expr
, TRUE
);
1148 if(!push_instr(ctx
, OP_assign
))
1149 return E_OUTOFMEMORY
;
1151 hres
= push_instr_uint(ctx
, OP_pop
, 1);
1159 /* ECMA-262 3rd Edition 12.2 */
1160 static HRESULT
compile_var_statement(compiler_ctx_t
*ctx
, var_statement_t
*stat
)
1162 return compile_variable_list(ctx
, stat
->variable_list
);
1165 /* ECMA-262 3rd Edition 12.4 */
1166 static HRESULT
compile_expression_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1170 hres
= compile_expression(ctx
, stat
->expr
, ctx
->from_eval
);
1174 return !ctx
->from_eval
|| push_instr(ctx
, OP_setret
) ? S_OK
: E_OUTOFMEMORY
;
1177 /* ECMA-262 3rd Edition 12.5 */
1178 static HRESULT
compile_if_statement(compiler_ctx_t
*ctx
, if_statement_t
*stat
)
1183 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1187 jmp_else
= push_instr(ctx
, OP_jmp_z
);
1189 return E_OUTOFMEMORY
;
1191 hres
= compile_statement(ctx
, NULL
, stat
->if_stat
);
1195 if(stat
->else_stat
) {
1198 jmp_end
= push_instr(ctx
, OP_jmp
);
1200 return E_OUTOFMEMORY
;
1202 set_arg_uint(ctx
, jmp_else
, ctx
->code_off
);
1204 hres
= compile_statement(ctx
, NULL
, stat
->else_stat
);
1208 set_arg_uint(ctx
, jmp_end
, ctx
->code_off
);
1210 set_arg_uint(ctx
, jmp_else
, ctx
->code_off
);
1216 /* ECMA-262 3rd Edition 12.6.2 */
1217 static HRESULT
compile_while_statement(compiler_ctx_t
*ctx
, while_statement_t
*stat
)
1219 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1223 stat_ctx
.break_label
= alloc_label(ctx
);
1224 if(!stat_ctx
.break_label
)
1225 return E_OUTOFMEMORY
;
1227 stat_ctx
.continue_label
= alloc_label(ctx
);
1228 if(!stat_ctx
.continue_label
)
1229 return E_OUTOFMEMORY
;
1231 jmp_off
= ctx
->code_off
;
1233 if(!stat
->do_while
) {
1234 label_set_addr(ctx
, stat_ctx
.continue_label
);
1235 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1239 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1244 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1248 if(stat
->do_while
) {
1249 label_set_addr(ctx
, stat_ctx
.continue_label
);
1250 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1254 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1259 hres
= push_instr_uint(ctx
, OP_jmp
, jmp_off
);
1263 label_set_addr(ctx
, stat_ctx
.break_label
);
1267 /* ECMA-262 3rd Edition 12.6.3 */
1268 static HRESULT
compile_for_statement(compiler_ctx_t
*ctx
, for_statement_t
*stat
)
1270 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1274 if(stat
->variable_list
) {
1275 hres
= compile_variable_list(ctx
, stat
->variable_list
);
1278 }else if(stat
->begin_expr
) {
1279 hres
= compile_expression(ctx
, stat
->begin_expr
, FALSE
);
1284 stat_ctx
.break_label
= alloc_label(ctx
);
1285 if(!stat_ctx
.break_label
)
1286 return E_OUTOFMEMORY
;
1288 stat_ctx
.continue_label
= alloc_label(ctx
);
1289 if(!stat_ctx
.continue_label
)
1290 return E_OUTOFMEMORY
;
1292 expr_off
= ctx
->code_off
;
1295 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1299 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1304 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1308 label_set_addr(ctx
, stat_ctx
.continue_label
);
1310 if(stat
->end_expr
) {
1311 hres
= compile_expression(ctx
, stat
->end_expr
, FALSE
);
1316 hres
= push_instr_uint(ctx
, OP_jmp
, expr_off
);
1320 label_set_addr(ctx
, stat_ctx
.break_label
);
1324 /* ECMA-262 3rd Edition 12.6.4 */
1325 static HRESULT
compile_forin_statement(compiler_ctx_t
*ctx
, forin_statement_t
*stat
)
1327 statement_ctx_t stat_ctx
= {4, FALSE
, FALSE
};
1330 if(stat
->variable
) {
1331 hres
= compile_variable_list(ctx
, stat
->variable
);
1336 stat_ctx
.break_label
= alloc_label(ctx
);
1337 if(!stat_ctx
.break_label
)
1338 return E_OUTOFMEMORY
;
1340 stat_ctx
.continue_label
= alloc_label(ctx
);
1341 if(!stat_ctx
.continue_label
)
1342 return E_OUTOFMEMORY
;
1344 hres
= compile_expression(ctx
, stat
->in_expr
, TRUE
);
1348 if(stat
->variable
) {
1349 hres
= emit_identifier_ref(ctx
, stat
->variable
->identifier
, fdexNameEnsure
);
1352 }else if(is_memberid_expr(stat
->expr
->type
)) {
1353 hres
= compile_memberid_expression(ctx
, stat
->expr
, fdexNameEnsure
);
1357 hres
= push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
1361 /* FIXME: compile statement anyways when we depend on compiler to check errors */
1365 hres
= push_instr_int(ctx
, OP_int
, DISPID_STARTENUM
);
1369 label_set_addr(ctx
, stat_ctx
.continue_label
);
1370 hres
= push_instr_uint(ctx
, OP_forin
, stat_ctx
.break_label
);
1372 return E_OUTOFMEMORY
;
1374 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1378 hres
= push_instr_uint(ctx
, OP_jmp
, stat_ctx
.continue_label
);
1382 label_set_addr(ctx
, stat_ctx
.break_label
);
1386 static HRESULT
pop_to_stat(compiler_ctx_t
*ctx
, BOOL var_stack
, BOOL scope_stack
, statement_ctx_t
*stat_ctx
)
1388 unsigned stack_pop
= 0;
1389 statement_ctx_t
*iter
;
1391 for(iter
= ctx
->stat_ctx
; iter
!= stat_ctx
; iter
= iter
->next
) {
1393 if(iter
->using_scope
&& !push_instr(ctx
, OP_pop_scope
))
1394 return E_OUTOFMEMORY
;
1395 if(iter
->using_except
&& !push_instr(ctx
, OP_pop_except
))
1396 return E_OUTOFMEMORY
;
1398 stack_pop
+= iter
->stack_use
;
1401 if(var_stack
&& stack_pop
) {
1404 hres
= push_instr_uint(ctx
, OP_pop
, stack_pop
);
1412 /* ECMA-262 3rd Edition 12.7 */
1413 static HRESULT
compile_continue_statement(compiler_ctx_t
*ctx
, branch_statement_t
*stat
)
1415 statement_ctx_t
*pop_ctx
;
1418 if(stat
->identifier
) {
1419 statement_t
*label_stat
;
1420 statement_ctx_t
*iter
;
1424 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1425 if(iter
->continue_label
)
1427 if(iter
->labelled_stat
&& !strcmpW(iter
->labelled_stat
->identifier
, stat
->identifier
))
1432 WARN("Label not found\n");
1433 return JS_E_LABEL_NOT_FOUND
;
1436 /* Labelled continue are allowed only on loops */
1437 for(label_stat
= iter
->labelled_stat
->statement
;
1438 label_stat
->type
== STAT_LABEL
;
1439 label_stat
= ((labelled_statement_t
*)label_stat
)->statement
);
1440 if(!is_loop_statement(label_stat
->type
)) {
1441 WARN("Label is not a loop\n");
1442 return JS_E_INVALID_CONTINUE
;
1445 assert(pop_ctx
!= NULL
);
1447 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1448 if(pop_ctx
->continue_label
)
1453 WARN("continue outside loop\n");
1454 return JS_E_INVALID_CONTINUE
;
1458 hres
= pop_to_stat(ctx
, TRUE
, TRUE
, pop_ctx
);
1462 return push_instr_uint(ctx
, OP_jmp
, pop_ctx
->continue_label
);
1465 /* ECMA-262 3rd Edition 12.8 */
1466 static HRESULT
compile_break_statement(compiler_ctx_t
*ctx
, branch_statement_t
*stat
)
1468 statement_ctx_t
*pop_ctx
;
1471 if(stat
->identifier
) {
1472 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1473 if(pop_ctx
->labelled_stat
&& !strcmpW(pop_ctx
->labelled_stat
->identifier
, stat
->identifier
)) {
1474 assert(pop_ctx
->break_label
);
1480 WARN("Label not found\n");
1481 return JS_E_LABEL_NOT_FOUND
;
1484 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1485 if(pop_ctx
->break_label
&& !pop_ctx
->labelled_stat
)
1490 WARN("Break outside loop\n");
1491 return JS_E_INVALID_BREAK
;
1495 hres
= pop_to_stat(ctx
, TRUE
, TRUE
, pop_ctx
->next
);
1499 return push_instr_uint(ctx
, OP_jmp
, pop_ctx
->break_label
);
1502 /* ECMA-262 3rd Edition 12.9 */
1503 static HRESULT
compile_return_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1507 if(ctx
->from_eval
) {
1508 WARN("misplaced return statement\n");
1509 return JS_E_MISPLACED_RETURN
;
1512 hres
= pop_to_stat(ctx
, TRUE
, FALSE
, NULL
);
1517 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1520 if(!push_instr(ctx
, OP_setret
))
1521 return E_OUTOFMEMORY
;
1524 hres
= pop_to_stat(ctx
, FALSE
, TRUE
, NULL
);
1528 return push_instr_uint(ctx
, OP_ret
, !stat
->expr
);
1531 /* ECMA-262 3rd Edition 12.10 */
1532 static HRESULT
compile_with_statement(compiler_ctx_t
*ctx
, with_statement_t
*stat
)
1534 statement_ctx_t stat_ctx
= {0, TRUE
, FALSE
};
1537 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1541 if(!push_instr(ctx
, OP_push_scope
))
1542 return E_OUTOFMEMORY
;
1544 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1548 if(!push_instr(ctx
, OP_pop_scope
))
1549 return E_OUTOFMEMORY
;
1554 /* ECMA-262 3rd Edition 12.10 */
1555 static HRESULT
compile_labelled_statement(compiler_ctx_t
*ctx
, labelled_statement_t
*stat
)
1557 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
, 0, 0, stat
}, *iter
;
1560 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1561 if(iter
->labelled_stat
&& !strcmpW(iter
->labelled_stat
->identifier
, stat
->identifier
)) {
1562 WARN("Label %s redefined\n", debugstr_w(stat
->identifier
));
1563 return JS_E_LABEL_REDEFINED
;
1567 /* Labelled breaks are allowed for any labelled statements, not only loops (violating spec) */
1568 stat_ctx
.break_label
= alloc_label(ctx
);
1569 if(!stat_ctx
.break_label
)
1570 return E_OUTOFMEMORY
;
1572 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1576 label_set_addr(ctx
, stat_ctx
.break_label
);
1580 /* ECMA-262 3rd Edition 12.13 */
1581 static HRESULT
compile_switch_statement(compiler_ctx_t
*ctx
, switch_statement_t
*stat
)
1583 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1584 unsigned case_cnt
= 0, *case_jmps
, i
, default_jmp
;
1585 BOOL have_default
= FALSE
;
1586 statement_t
*stat_iter
;
1587 case_clausule_t
*iter
;
1590 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1594 stat_ctx
.break_label
= alloc_label(ctx
);
1595 if(!stat_ctx
.break_label
)
1596 return E_OUTOFMEMORY
;
1598 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1603 case_jmps
= heap_alloc(case_cnt
* sizeof(*case_jmps
));
1605 return E_OUTOFMEMORY
;
1608 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1610 have_default
= TRUE
;
1614 hres
= compile_expression(ctx
, iter
->expr
, TRUE
);
1618 case_jmps
[i
] = push_instr(ctx
, OP_case
);
1620 hres
= E_OUTOFMEMORY
;
1626 if(SUCCEEDED(hres
)) {
1627 hres
= push_instr_uint(ctx
, OP_pop
, 1);
1628 if(SUCCEEDED(hres
)) {
1629 default_jmp
= push_instr(ctx
, OP_jmp
);
1631 hres
= E_OUTOFMEMORY
;
1636 heap_free(case_jmps
);
1641 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1642 while(iter
->next
&& iter
->next
->stat
== iter
->stat
) {
1643 set_arg_uint(ctx
, iter
->expr
? case_jmps
[i
++] : default_jmp
, ctx
->code_off
);
1647 set_arg_uint(ctx
, iter
->expr
? case_jmps
[i
++] : default_jmp
, ctx
->code_off
);
1649 for(stat_iter
= iter
->stat
; stat_iter
&& (!iter
->next
|| iter
->next
->stat
!= stat_iter
);
1650 stat_iter
= stat_iter
->next
) {
1651 hres
= compile_statement(ctx
, &stat_ctx
, stat_iter
);
1659 heap_free(case_jmps
);
1662 assert(i
== case_cnt
);
1665 hres
= push_instr_uint(ctx
, OP_jmp
, stat_ctx
.break_label
);
1668 set_arg_uint(ctx
, default_jmp
, ctx
->code_off
);
1671 label_set_addr(ctx
, stat_ctx
.break_label
);
1675 /* ECMA-262 3rd Edition 12.13 */
1676 static HRESULT
compile_throw_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1680 hres
= compile_expression(ctx
, stat
->expr
, TRUE
);
1684 return push_instr(ctx
, OP_throw
) ? S_OK
: E_OUTOFMEMORY
;
1687 /* ECMA-262 3rd Edition 12.14 */
1688 static HRESULT
compile_try_statement(compiler_ctx_t
*ctx
, try_statement_t
*stat
)
1690 statement_ctx_t try_ctx
= {0, FALSE
, TRUE
}, catch_ctx
= {0, TRUE
, FALSE
};
1691 statement_ctx_t finally_ctx
= {2, FALSE
, FALSE
};
1692 unsigned push_except
;
1696 push_except
= push_instr(ctx
, OP_push_except
);
1698 return E_OUTOFMEMORY
;
1700 if(stat
->catch_block
) {
1701 ident
= compiler_alloc_bstr(ctx
, stat
->catch_block
->identifier
);
1703 return E_OUTOFMEMORY
;
1708 instr_ptr(ctx
, push_except
)->u
.arg
[1].bstr
= ident
;
1710 if(!stat
->catch_block
)
1711 try_ctx
.stack_use
= 2;
1713 hres
= compile_statement(ctx
, &try_ctx
, stat
->try_statement
);
1717 if(!push_instr(ctx
, OP_pop_except
))
1718 return E_OUTOFMEMORY
;
1720 if(stat
->catch_block
) {
1721 unsigned jmp_finally
;
1723 jmp_finally
= push_instr(ctx
, OP_jmp
);
1725 return E_OUTOFMEMORY
;
1727 instr_ptr(ctx
, push_except
)->u
.arg
[0].uint
= ctx
->code_off
;
1729 hres
= compile_statement(ctx
, &catch_ctx
, stat
->catch_block
->statement
);
1733 if(!push_instr(ctx
, OP_pop_scope
))
1734 return E_OUTOFMEMORY
;
1736 set_arg_uint(ctx
, jmp_finally
, ctx
->code_off
);
1738 set_arg_uint(ctx
, push_except
, ctx
->code_off
);
1741 if(stat
->finally_statement
) {
1742 hres
= compile_statement(ctx
, stat
->catch_block
? NULL
: &finally_ctx
, stat
->finally_statement
);
1746 if(!stat
->catch_block
&& !push_instr(ctx
, OP_end_finally
))
1747 return E_OUTOFMEMORY
;
1753 static HRESULT
compile_statement(compiler_ctx_t
*ctx
, statement_ctx_t
*stat_ctx
, statement_t
*stat
)
1758 stat_ctx
->next
= ctx
->stat_ctx
;
1759 ctx
->stat_ctx
= stat_ctx
;
1762 switch(stat
->type
) {
1764 hres
= compile_block_statement(ctx
, ((block_statement_t
*)stat
)->stat_list
);
1767 hres
= compile_break_statement(ctx
, (branch_statement_t
*)stat
);
1770 hres
= compile_continue_statement(ctx
, (branch_statement_t
*)stat
);
1777 hres
= compile_expression_statement(ctx
, (expression_statement_t
*)stat
);
1780 hres
= compile_for_statement(ctx
, (for_statement_t
*)stat
);
1783 hres
= compile_forin_statement(ctx
, (forin_statement_t
*)stat
);
1786 hres
= compile_if_statement(ctx
, (if_statement_t
*)stat
);
1789 hres
= compile_labelled_statement(ctx
, (labelled_statement_t
*)stat
);
1792 hres
= compile_return_statement(ctx
, (expression_statement_t
*)stat
);
1795 hres
= compile_switch_statement(ctx
, (switch_statement_t
*)stat
);
1798 hres
= compile_throw_statement(ctx
, (expression_statement_t
*)stat
);
1801 hres
= compile_try_statement(ctx
, (try_statement_t
*)stat
);
1804 hres
= compile_var_statement(ctx
, (var_statement_t
*)stat
);
1807 hres
= compile_while_statement(ctx
, (while_statement_t
*)stat
);
1810 hres
= compile_with_statement(ctx
, (with_statement_t
*)stat
);
1812 DEFAULT_UNREACHABLE
;
1816 assert(ctx
->stat_ctx
== stat_ctx
);
1817 ctx
->stat_ctx
= stat_ctx
->next
;
1823 static int function_local_cmp(const void *key
, const struct wine_rb_entry
*entry
)
1825 function_local_t
*local
= WINE_RB_ENTRY_VALUE(entry
, function_local_t
, entry
);
1826 return strcmpW(key
, local
->name
);
1829 static inline function_local_t
*find_local(compiler_ctx_t
*ctx
, const WCHAR
*name
)
1831 struct wine_rb_entry
*entry
= wine_rb_get(&ctx
->locals
, name
);
1832 return entry
? WINE_RB_ENTRY_VALUE(entry
, function_local_t
, entry
) : NULL
;
1835 static BOOL
alloc_local(compiler_ctx_t
*ctx
, BSTR name
, int ref
)
1837 function_local_t
*local
;
1839 local
= heap_pool_alloc(&ctx
->heap
, sizeof(*local
));
1845 wine_rb_put(&ctx
->locals
, name
, &local
->entry
);
1850 static BOOL
alloc_variable(compiler_ctx_t
*ctx
, const WCHAR
*name
)
1854 if(find_local(ctx
, name
))
1857 ident
= compiler_alloc_bstr(ctx
, name
);
1861 return alloc_local(ctx
, ident
, ctx
->func
->var_cnt
++);
1864 static BOOL
visit_function_expression(compiler_ctx_t
*ctx
, function_expression_t
*expr
)
1866 expr
->func_id
= ctx
->func
->func_cnt
++;
1867 ctx
->func_tail
= ctx
->func_tail
? (ctx
->func_tail
->next
= expr
) : (ctx
->func_head
= expr
);
1869 return !expr
->identifier
|| expr
->event_target
|| alloc_variable(ctx
, expr
->identifier
);
1872 static HRESULT
visit_expression(compiler_ctx_t
*ctx
, expression_t
*expr
)
1874 HRESULT hres
= S_OK
;
1876 switch(expr
->type
) {
1881 case EXPR_ASSIGNADD
:
1882 case EXPR_ASSIGNAND
:
1883 case EXPR_ASSIGNSUB
:
1884 case EXPR_ASSIGNMUL
:
1885 case EXPR_ASSIGNDIV
:
1886 case EXPR_ASSIGNMOD
:
1888 case EXPR_ASSIGNLSHIFT
:
1889 case EXPR_ASSIGNRSHIFT
:
1890 case EXPR_ASSIGNRRSHIFT
:
1891 case EXPR_ASSIGNXOR
:
1899 case EXPR_GREATEREQ
:
1901 case EXPR_INSTANCEOF
:
1914 binary_expression_t
*binary_expr
= (binary_expression_t
*)expr
;
1916 hres
= visit_expression(ctx
, binary_expr
->expression1
);
1920 hres
= visit_expression(ctx
, binary_expr
->expression2
);
1934 hres
= visit_expression(ctx
, ((unary_expression_t
*)expr
)->expression
);
1940 case EXPR_ARRAYLIT
: {
1941 array_literal_expression_t
*array_expr
= (array_literal_expression_t
*)expr
;
1942 array_element_t
*iter
;
1944 for(iter
= array_expr
->element_list
; iter
; iter
= iter
->next
) {
1945 hres
= visit_expression(ctx
, iter
->expr
);
1953 call_expression_t
*call_expr
= (call_expression_t
*)expr
;
1956 hres
= visit_expression(ctx
, call_expr
->expression
);
1960 for(arg
= call_expr
->argument_list
; arg
; arg
= arg
->next
) {
1961 hres
= visit_expression(ctx
, arg
->expr
);
1968 conditional_expression_t
*cond_expr
= (conditional_expression_t
*)expr
;
1970 hres
= visit_expression(ctx
, cond_expr
->expression
);
1974 hres
= visit_expression(ctx
, cond_expr
->true_expression
);
1978 hres
= visit_expression(ctx
, cond_expr
->false_expression
);
1982 visit_function_expression(ctx
, (function_expression_t
*)expr
);
1985 hres
= visit_expression(ctx
, ((member_expression_t
*)expr
)->expression
);
1987 case EXPR_PROPVAL
: {
1989 for(iter
= ((property_value_expression_t
*)expr
)->property_list
; iter
; iter
= iter
->next
) {
1990 hres
= visit_expression(ctx
, iter
->value
);
1996 DEFAULT_UNREACHABLE
;
2002 static HRESULT
visit_variable_list(compiler_ctx_t
*ctx
, variable_declaration_t
*list
)
2004 variable_declaration_t
*iter
;
2007 for(iter
= list
; iter
; iter
= iter
->next
) {
2008 if(!alloc_variable(ctx
, iter
->identifier
))
2009 return E_OUTOFMEMORY
;
2012 hres
= visit_expression(ctx
, iter
->expr
);
2021 static HRESULT
visit_statement(compiler_ctx_t
*,statement_t
*);
2023 static HRESULT
visit_block_statement(compiler_ctx_t
*ctx
, statement_t
*iter
)
2028 hres
= visit_statement(ctx
, iter
);
2038 static HRESULT
visit_statement(compiler_ctx_t
*ctx
, statement_t
*stat
)
2040 HRESULT hres
= S_OK
;
2042 switch(stat
->type
) {
2044 hres
= visit_block_statement(ctx
, ((block_statement_t
*)stat
)->stat_list
);
2053 expression_statement_t
*expr_stat
= (expression_statement_t
*)stat
;
2055 hres
= visit_expression(ctx
, expr_stat
->expr
);
2059 for_statement_t
*for_stat
= (for_statement_t
*)stat
;
2061 if(for_stat
->variable_list
)
2062 hres
= visit_variable_list(ctx
, for_stat
->variable_list
);
2063 else if(for_stat
->begin_expr
)
2064 hres
= visit_expression(ctx
, for_stat
->begin_expr
);
2068 if(for_stat
->expr
) {
2069 hres
= visit_expression(ctx
, for_stat
->expr
);
2074 hres
= visit_statement(ctx
, for_stat
->statement
);
2078 if(for_stat
->end_expr
)
2079 hres
= visit_expression(ctx
, for_stat
->end_expr
);
2083 forin_statement_t
*forin_stat
= (forin_statement_t
*)stat
;
2085 if(forin_stat
->variable
) {
2086 hres
= visit_variable_list(ctx
, forin_stat
->variable
);
2091 hres
= visit_expression(ctx
, forin_stat
->in_expr
);
2095 if(forin_stat
->expr
) {
2096 hres
= visit_expression(ctx
, forin_stat
->expr
);
2101 hres
= visit_statement(ctx
, forin_stat
->statement
);
2105 if_statement_t
*if_stat
= (if_statement_t
*)stat
;
2107 hres
= visit_expression(ctx
, if_stat
->expr
);
2111 hres
= visit_statement(ctx
, if_stat
->if_stat
);
2115 if(if_stat
->else_stat
)
2116 hres
= visit_statement(ctx
, if_stat
->else_stat
);
2120 hres
= visit_statement(ctx
, ((labelled_statement_t
*)stat
)->statement
);
2123 switch_statement_t
*switch_stat
= (switch_statement_t
*)stat
;
2124 statement_t
*stat_iter
;
2125 case_clausule_t
*iter
;
2127 hres
= visit_expression(ctx
, switch_stat
->expr
);
2131 for(iter
= switch_stat
->case_list
; iter
; iter
= iter
->next
) {
2134 hres
= visit_expression(ctx
, iter
->expr
);
2139 for(iter
= switch_stat
->case_list
; iter
; iter
= iter
->next
) {
2140 while(iter
->next
&& iter
->next
->stat
== iter
->stat
)
2142 for(stat_iter
= iter
->stat
; stat_iter
&& (!iter
->next
|| iter
->next
->stat
!= stat_iter
);
2143 stat_iter
= stat_iter
->next
) {
2144 hres
= visit_statement(ctx
, stat_iter
);
2152 try_statement_t
*try_stat
= (try_statement_t
*)stat
;
2154 hres
= visit_statement(ctx
, try_stat
->try_statement
);
2158 if(try_stat
->catch_block
) {
2159 hres
= visit_statement(ctx
, try_stat
->catch_block
->statement
);
2164 if(try_stat
->finally_statement
)
2165 hres
= visit_statement(ctx
, try_stat
->finally_statement
);
2169 hres
= visit_variable_list(ctx
, ((var_statement_t
*)stat
)->variable_list
);
2172 while_statement_t
*while_stat
= (while_statement_t
*)stat
;
2174 hres
= visit_expression(ctx
, while_stat
->expr
);
2178 hres
= visit_statement(ctx
, while_stat
->statement
);
2182 with_statement_t
*with_stat
= (with_statement_t
*)stat
;
2184 hres
= visit_expression(ctx
, with_stat
->expr
);
2188 hres
= visit_statement(ctx
, with_stat
->statement
);
2191 DEFAULT_UNREACHABLE
;
2197 static void resolve_labels(compiler_ctx_t
*ctx
, unsigned off
)
2201 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->code_off
; instr
++) {
2202 if(instr_info
[instr
->op
].arg1_type
== ARG_ADDR
&& (instr
->u
.arg
->uint
& LABEL_FLAG
)) {
2203 assert((instr
->u
.arg
->uint
& ~LABEL_FLAG
) < ctx
->labels_cnt
);
2204 instr
->u
.arg
->uint
= ctx
->labels
[instr
->u
.arg
->uint
& ~LABEL_FLAG
];
2206 assert(instr_info
[instr
->op
].arg2_type
!= ARG_ADDR
);
2209 ctx
->labels_cnt
= 0;
2212 void release_bytecode(bytecode_t
*code
)
2219 for(i
=0; i
< code
->bstr_cnt
; i
++)
2220 SysFreeString(code
->bstr_pool
[i
]);
2221 for(i
=0; i
< code
->str_cnt
; i
++)
2222 jsstr_release(code
->str_pool
[i
]);
2224 heap_free(code
->source
);
2225 heap_pool_free(&code
->heap
);
2226 heap_free(code
->bstr_pool
);
2227 heap_free(code
->str_pool
);
2228 heap_free(code
->instrs
);
2232 static HRESULT
init_code(compiler_ctx_t
*compiler
, const WCHAR
*source
)
2234 compiler
->code
= heap_alloc_zero(sizeof(bytecode_t
));
2236 return E_OUTOFMEMORY
;
2238 compiler
->code
->ref
= 1;
2239 heap_pool_init(&compiler
->code
->heap
);
2241 compiler
->code
->source
= heap_strdupW(source
);
2242 if(!compiler
->code
->source
) {
2243 release_bytecode(compiler
->code
);
2244 return E_OUTOFMEMORY
;
2247 compiler
->code
->instrs
= heap_alloc(64 * sizeof(instr_t
));
2248 if(!compiler
->code
->instrs
) {
2249 release_bytecode(compiler
->code
);
2250 return E_OUTOFMEMORY
;
2253 compiler
->code_size
= 64;
2254 compiler
->code_off
= 1;
2258 static HRESULT
compile_function(compiler_ctx_t
*ctx
, source_elements_t
*source
, function_expression_t
*func_expr
,
2259 BOOL from_eval
, function_code_t
*func
)
2261 function_expression_t
*iter
;
2262 function_local_t
*local
;
2268 ctx
->func_head
= ctx
->func_tail
= NULL
;
2269 ctx
->from_eval
= from_eval
;
2271 ctx
->locals_cnt
= 0;
2272 wine_rb_init(&ctx
->locals
, function_local_cmp
);
2275 parameter_t
*param_iter
;
2277 if(func_expr
->identifier
) {
2278 func
->name
= compiler_alloc_bstr(ctx
, func_expr
->identifier
);
2280 return E_OUTOFMEMORY
;
2283 if(func_expr
->event_target
) {
2284 func
->event_target
= compiler_alloc_bstr(ctx
, func_expr
->event_target
);
2285 if(!func
->event_target
)
2286 return E_OUTOFMEMORY
;
2289 func
->source
= func_expr
->src_str
;
2290 func
->source_len
= func_expr
->src_len
;
2292 for(param_iter
= func_expr
->parameter_list
; param_iter
; param_iter
= param_iter
->next
)
2295 func
->params
= compiler_alloc(ctx
->code
, func
->param_cnt
* sizeof(*func
->params
));
2297 return E_OUTOFMEMORY
;
2299 for(param_iter
= func_expr
->parameter_list
, i
=0; param_iter
; param_iter
= param_iter
->next
, i
++) {
2300 func
->params
[i
] = compiler_alloc_bstr(ctx
, param_iter
->identifier
);
2301 if(!func
->params
[i
])
2302 return E_OUTOFMEMORY
;
2306 for(i
= 0; i
< func
->param_cnt
; i
++) {
2307 if(!find_local(ctx
, func
->params
[i
]) && !alloc_local(ctx
, func
->params
[i
], -i
-1))
2308 return E_OUTOFMEMORY
;
2311 hres
= visit_block_statement(ctx
, source
->statement
);
2315 func
->locals
= compiler_alloc(ctx
->code
, ctx
->locals_cnt
* sizeof(*func
->locals
));
2317 return E_OUTOFMEMORY
;
2318 func
->locals_cnt
= ctx
->locals_cnt
;
2320 func
->variables
= compiler_alloc(ctx
->code
, func
->var_cnt
* sizeof(*func
->variables
));
2321 if(!func
->variables
)
2322 return E_OUTOFMEMORY
;
2325 WINE_RB_FOR_EACH_ENTRY(local
, &ctx
->locals
, function_local_t
, entry
) {
2326 func
->locals
[i
].name
= local
->name
;
2327 func
->locals
[i
].ref
= local
->ref
;
2328 if(local
->ref
>= 0) {
2329 func
->variables
[local
->ref
].name
= local
->name
;
2330 func
->variables
[local
->ref
].func_id
= -1;
2334 assert(i
== ctx
->locals_cnt
);
2336 func
->funcs
= compiler_alloc(ctx
->code
, func
->func_cnt
* sizeof(*func
->funcs
));
2338 return E_OUTOFMEMORY
;
2339 memset(func
->funcs
, 0, func
->func_cnt
* sizeof(*func
->funcs
));
2341 off
= ctx
->code_off
;
2342 hres
= compile_block_statement(ctx
, source
->statement
);
2346 resolve_labels(ctx
, off
);
2348 hres
= push_instr_uint(ctx
, OP_ret
, !from_eval
);
2352 if(TRACE_ON(jscript_disas
))
2353 dump_code(ctx
, off
);
2355 func
->instr_off
= off
;
2357 for(iter
= ctx
->func_head
, i
=0; iter
; iter
= iter
->next
, i
++) {
2358 hres
= compile_function(ctx
, iter
->source_elements
, iter
, FALSE
, func
->funcs
+i
);
2362 TRACE("[%d] func %s\n", i
, debugstr_w(func
->funcs
[i
].name
));
2363 if(func
->funcs
[i
].name
&& !func
->funcs
[i
].event_target
) {
2364 local_ref_t
*local_ref
= lookup_local(func
, func
->funcs
[i
].name
);
2365 func
->funcs
[i
].local_ref
= local_ref
->ref
;
2366 TRACE("found ref %s %d for %s\n", debugstr_w(local_ref
->name
), local_ref
->ref
, debugstr_w(func
->funcs
[i
].name
));
2367 if(local_ref
->ref
>= 0)
2368 func
->variables
[local_ref
->ref
].func_id
= i
;
2372 assert(i
== func
->func_cnt
);
2377 static HRESULT
parse_arguments(compiler_ctx_t
*ctx
, const WCHAR
*args
, BSTR
*arg_array
, unsigned *args_size
)
2379 const WCHAR
*ptr
= args
, *ptr2
;
2380 unsigned arg_cnt
= 0;
2382 while(isspaceW(*ptr
))
2391 if(!isalphaW(*ptr
) && *ptr
!= '_') {
2392 FIXME("expected alpha or '_': %s\n", debugstr_w(ptr
));
2397 while(isalnumW(*ptr
) || *ptr
== '_')
2400 if(*ptr
&& *ptr
!= ',' && !isspaceW(*ptr
)) {
2401 FIXME("unexpected har %s\n", debugstr_w(ptr
));
2406 arg_array
[arg_cnt
] = compiler_alloc_bstr_len(ctx
, ptr2
, ptr
-ptr2
);
2407 if(!arg_array
[arg_cnt
])
2408 return E_OUTOFMEMORY
;
2412 while(isspaceW(*ptr
))
2417 FIXME("expected ',': %s\n", debugstr_w(ptr
));
2422 while(isspaceW(*ptr
))
2427 *args_size
= arg_cnt
;
2431 static HRESULT
compile_arguments(compiler_ctx_t
*ctx
, const WCHAR
*args
)
2435 hres
= parse_arguments(ctx
, args
, NULL
, &ctx
->code
->global_code
.param_cnt
);
2439 ctx
->code
->global_code
.params
= compiler_alloc(ctx
->code
,
2440 ctx
->code
->global_code
.param_cnt
* sizeof(*ctx
->code
->global_code
.params
));
2441 if(!ctx
->code
->global_code
.params
)
2442 return E_OUTOFMEMORY
;
2444 return parse_arguments(ctx
, args
, ctx
->code
->global_code
.params
, NULL
);
2447 HRESULT
compile_script(script_ctx_t
*ctx
, const WCHAR
*code
, const WCHAR
*args
, const WCHAR
*delimiter
,
2448 BOOL from_eval
, BOOL use_decode
, bytecode_t
**ret
)
2450 compiler_ctx_t compiler
= {0};
2453 hres
= init_code(&compiler
, code
);
2458 hres
= compile_arguments(&compiler
, args
);
2464 hres
= decode_source(compiler
.code
->source
);
2466 WARN("Decoding failed\n");
2471 hres
= script_parse(ctx
, compiler
.code
->source
, delimiter
, from_eval
, &compiler
.parser
);
2473 release_bytecode(compiler
.code
);
2477 heap_pool_init(&compiler
.heap
);
2478 hres
= compile_function(&compiler
, compiler
.parser
->source
, NULL
, from_eval
, &compiler
.code
->global_code
);
2479 heap_pool_free(&compiler
.heap
);
2480 parser_release(compiler
.parser
);
2482 release_bytecode(compiler
.code
);
2486 *ret
= compiler
.code
;