2 * Copyright 2011 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(jscript
);
28 WINE_DECLARE_DEBUG_CHANNEL(jscript_disas
);
30 typedef struct _statement_ctx_t
{
36 unsigned continue_label
;
38 const labelled_statement_t
*labelled_stat
;
40 struct _statement_ctx_t
*next
;
54 statement_ctx_t
*stat_ctx
;
55 function_code_t
*func
;
57 variable_declaration_t
*var_head
;
58 variable_declaration_t
*var_tail
;
60 function_expression_t
*func_head
;
61 function_expression_t
*func_tail
;
66 instr_arg_type_t arg1_type
;
67 instr_arg_type_t arg2_type
;
69 #define X(n,a,b,c) {#n,b,c},
74 static void dump_instr_arg(instr_arg_type_t type
, instr_arg_t
*arg
)
78 TRACE_(jscript_disas
)("\t%s", debugstr_jsstr(arg
->str
));
81 TRACE_(jscript_disas
)("\t%s", debugstr_wn(arg
->bstr
, SysStringLen(arg
->bstr
)));
84 TRACE_(jscript_disas
)("\t%d", arg
->uint
);
88 TRACE_(jscript_disas
)("\t%u", arg
->uint
);
98 static void dump_code(compiler_ctx_t
*ctx
, unsigned off
)
102 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->code_off
; instr
++) {
103 TRACE_(jscript_disas
)("%d:\t%s", (int)(instr
-ctx
->code
->instrs
), instr_info
[instr
->op
].op_str
);
104 if(instr_info
[instr
->op
].arg1_type
== ARG_DBL
) {
105 TRACE_(jscript_disas
)("\t%lf", instr
->u
.dbl
);
107 dump_instr_arg(instr_info
[instr
->op
].arg1_type
, instr
->u
.arg
);
108 dump_instr_arg(instr_info
[instr
->op
].arg2_type
, instr
->u
.arg
+1);
110 TRACE_(jscript_disas
)("\n");
114 static HRESULT
compile_expression(compiler_ctx_t
*,expression_t
*);
115 static HRESULT
compile_statement(compiler_ctx_t
*,statement_ctx_t
*,statement_t
*);
117 static inline void *compiler_alloc(bytecode_t
*code
, size_t size
)
119 return jsheap_alloc(&code
->heap
, size
);
122 static jsstr_t
*compiler_alloc_string_len(compiler_ctx_t
*ctx
, const WCHAR
*str
, unsigned len
)
126 if(!ctx
->code
->str_pool_size
) {
127 ctx
->code
->str_pool
= heap_alloc(8 * sizeof(jsstr_t
*));
128 if(!ctx
->code
->str_pool
)
130 ctx
->code
->str_pool_size
= 8;
131 }else if(ctx
->code
->str_pool_size
== ctx
->code
->str_cnt
) {
134 new_pool
= heap_realloc(ctx
->code
->str_pool
, ctx
->code
->str_pool_size
*2*sizeof(jsstr_t
*));
138 ctx
->code
->str_pool
= new_pool
;
139 ctx
->code
->str_pool_size
*= 2;
142 new_str
= jsstr_alloc_len(str
, len
);
146 ctx
->code
->str_pool
[ctx
->code
->str_cnt
++] = new_str
;
150 static jsstr_t
*compiler_alloc_string(compiler_ctx_t
*ctx
, const WCHAR
*str
)
152 return compiler_alloc_string_len(ctx
, str
, strlenW(str
));
155 static BOOL
ensure_bstr_slot(compiler_ctx_t
*ctx
)
157 if(!ctx
->code
->bstr_pool_size
) {
158 ctx
->code
->bstr_pool
= heap_alloc(8 * sizeof(BSTR
));
159 if(!ctx
->code
->bstr_pool
)
161 ctx
->code
->bstr_pool_size
= 8;
162 }else if(ctx
->code
->bstr_pool_size
== ctx
->code
->bstr_cnt
) {
165 new_pool
= heap_realloc(ctx
->code
->bstr_pool
, ctx
->code
->bstr_pool_size
*2*sizeof(BSTR
));
169 ctx
->code
->bstr_pool
= new_pool
;
170 ctx
->code
->bstr_pool_size
*= 2;
176 static BSTR
compiler_alloc_bstr(compiler_ctx_t
*ctx
, const WCHAR
*str
)
178 if(!ensure_bstr_slot(ctx
))
181 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocString(str
);
182 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
185 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
188 static BSTR
compiler_alloc_bstr_len(compiler_ctx_t
*ctx
, const WCHAR
*str
, size_t len
)
190 if(!ensure_bstr_slot(ctx
))
193 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocStringLen(str
, len
);
194 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
197 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
200 static unsigned push_instr(compiler_ctx_t
*ctx
, jsop_t op
)
202 assert(ctx
->code_size
>= ctx
->code_off
);
204 if(ctx
->code_size
== ctx
->code_off
) {
207 new_instrs
= heap_realloc(ctx
->code
->instrs
, ctx
->code_size
*2*sizeof(instr_t
));
211 ctx
->code
->instrs
= new_instrs
;
215 ctx
->code
->instrs
[ctx
->code_off
].op
= op
;
216 return ctx
->code_off
++;
219 static inline instr_t
*instr_ptr(compiler_ctx_t
*ctx
, unsigned off
)
221 assert(off
< ctx
->code_off
);
222 return ctx
->code
->instrs
+ off
;
225 static HRESULT
push_instr_int(compiler_ctx_t
*ctx
, jsop_t op
, LONG arg
)
229 instr
= push_instr(ctx
, op
);
231 return E_OUTOFMEMORY
;
233 instr_ptr(ctx
, instr
)->u
.arg
->lng
= arg
;
237 static HRESULT
push_instr_str(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
242 str
= compiler_alloc_string(ctx
, arg
);
244 return E_OUTOFMEMORY
;
246 instr
= push_instr(ctx
, op
);
248 return E_OUTOFMEMORY
;
250 instr_ptr(ctx
, instr
)->u
.arg
->str
= str
;
254 static HRESULT
push_instr_bstr(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg
)
259 str
= compiler_alloc_bstr(ctx
, arg
);
261 return E_OUTOFMEMORY
;
263 instr
= push_instr(ctx
, op
);
265 return E_OUTOFMEMORY
;
267 instr_ptr(ctx
, instr
)->u
.arg
->bstr
= str
;
271 static HRESULT
push_instr_bstr_uint(compiler_ctx_t
*ctx
, jsop_t op
, const WCHAR
*arg1
, unsigned arg2
)
276 str
= compiler_alloc_bstr(ctx
, arg1
);
278 return E_OUTOFMEMORY
;
280 instr
= push_instr(ctx
, op
);
282 return E_OUTOFMEMORY
;
284 instr_ptr(ctx
, instr
)->u
.arg
[0].bstr
= str
;
285 instr_ptr(ctx
, instr
)->u
.arg
[1].uint
= arg2
;
289 static HRESULT
push_instr_uint_str(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg1
, const WCHAR
*arg2
)
294 str
= compiler_alloc_string(ctx
, arg2
);
296 return E_OUTOFMEMORY
;
298 instr
= push_instr(ctx
, op
);
300 return E_OUTOFMEMORY
;
302 instr_ptr(ctx
, instr
)->u
.arg
[0].uint
= arg1
;
303 instr_ptr(ctx
, instr
)->u
.arg
[1].str
= str
;
307 static HRESULT
push_instr_double(compiler_ctx_t
*ctx
, jsop_t op
, double arg
)
311 instr
= push_instr(ctx
, op
);
313 return E_OUTOFMEMORY
;
315 instr_ptr(ctx
, instr
)->u
.dbl
= arg
;
319 static inline void set_arg_uint(compiler_ctx_t
*ctx
, unsigned instr
, unsigned arg
)
321 instr_ptr(ctx
, instr
)->u
.arg
->uint
= arg
;
324 static HRESULT
push_instr_uint(compiler_ctx_t
*ctx
, jsop_t op
, unsigned arg
)
328 instr
= push_instr(ctx
, op
);
330 return E_OUTOFMEMORY
;
332 set_arg_uint(ctx
, instr
, arg
);
336 static HRESULT
compile_binary_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
340 hres
= compile_expression(ctx
, expr
->expression1
);
344 hres
= compile_expression(ctx
, expr
->expression2
);
348 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
351 static HRESULT
compile_unary_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
)
355 hres
= compile_expression(ctx
, expr
->expression
);
359 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
362 /* ECMA-262 3rd Edition 11.2.1 */
363 static HRESULT
compile_member_expression(compiler_ctx_t
*ctx
, member_expression_t
*expr
)
367 hres
= compile_expression(ctx
, expr
->expression
);
371 return push_instr_bstr(ctx
, OP_member
, expr
->identifier
);
374 #define LABEL_FLAG 0x80000000
376 static unsigned alloc_label(compiler_ctx_t
*ctx
)
378 if(!ctx
->labels_size
) {
379 ctx
->labels
= heap_alloc(8 * sizeof(*ctx
->labels
));
382 ctx
->labels_size
= 8;
383 }else if(ctx
->labels_size
== ctx
->labels_cnt
) {
384 unsigned *new_labels
;
386 new_labels
= heap_realloc(ctx
->labels
, 2*ctx
->labels_size
*sizeof(*ctx
->labels
));
390 ctx
->labels
= new_labels
;
391 ctx
->labels_size
*= 2;
394 return ctx
->labels_cnt
++ | LABEL_FLAG
;
397 static void label_set_addr(compiler_ctx_t
*ctx
, unsigned label
)
399 assert(label
& LABEL_FLAG
);
400 ctx
->labels
[label
& ~LABEL_FLAG
] = ctx
->code_off
;
403 static inline BOOL
is_memberid_expr(expression_type_t type
)
405 return type
== EXPR_IDENT
|| type
== EXPR_MEMBER
|| type
== EXPR_ARRAY
;
408 static HRESULT
compile_memberid_expression(compiler_ctx_t
*ctx
, expression_t
*expr
, unsigned flags
)
414 identifier_expression_t
*ident_expr
= (identifier_expression_t
*)expr
;
416 hres
= push_instr_bstr_uint(ctx
, OP_identid
, ident_expr
->identifier
, flags
);
420 binary_expression_t
*array_expr
= (binary_expression_t
*)expr
;
422 hres
= compile_expression(ctx
, array_expr
->expression1
);
426 hres
= compile_expression(ctx
, array_expr
->expression2
);
430 hres
= push_instr_uint(ctx
, OP_memberid
, flags
);
434 member_expression_t
*member_expr
= (member_expression_t
*)expr
;
436 hres
= compile_expression(ctx
, member_expr
->expression
);
440 /* FIXME: Potential optimization */
441 hres
= push_instr_str(ctx
, OP_str
, member_expr
->identifier
);
445 hres
= push_instr_uint(ctx
, OP_memberid
, flags
);
455 static HRESULT
compile_increment_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
, jsop_t op
, int n
)
459 if(!is_memberid_expr(expr
->expression
->type
)) {
460 hres
= compile_expression(ctx
, expr
->expression
);
464 return push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
467 hres
= compile_memberid_expression(ctx
, expr
->expression
, fdexNameEnsure
);
471 return push_instr_int(ctx
, op
, n
);
474 /* ECMA-262 3rd Edition 11.14 */
475 static HRESULT
compile_comma_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
)
479 hres
= compile_expression(ctx
, expr
->expression1
);
483 if(!push_instr(ctx
, OP_pop
))
484 return E_OUTOFMEMORY
;
486 return compile_expression(ctx
, expr
->expression2
);
489 /* ECMA-262 3rd Edition 11.11 */
490 static HRESULT
compile_logical_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
495 hres
= compile_expression(ctx
, expr
->expression1
);
499 instr
= push_instr(ctx
, op
);
501 return E_OUTOFMEMORY
;
503 hres
= compile_expression(ctx
, expr
->expression2
);
507 set_arg_uint(ctx
, instr
, ctx
->code_off
);
511 /* ECMA-262 3rd Edition 11.12 */
512 static HRESULT
compile_conditional_expression(compiler_ctx_t
*ctx
, conditional_expression_t
*expr
)
514 unsigned jmp_false
, jmp_end
;
517 hres
= compile_expression(ctx
, expr
->expression
);
521 jmp_false
= push_instr(ctx
, OP_cnd_z
);
523 return E_OUTOFMEMORY
;
525 hres
= compile_expression(ctx
, expr
->true_expression
);
529 jmp_end
= push_instr(ctx
, OP_jmp
);
531 return E_OUTOFMEMORY
;
533 set_arg_uint(ctx
, jmp_false
, ctx
->code_off
);
534 if(!push_instr(ctx
, OP_pop
))
535 return E_OUTOFMEMORY
;
537 hres
= compile_expression(ctx
, expr
->false_expression
);
541 set_arg_uint(ctx
, jmp_end
, ctx
->code_off
);
545 static HRESULT
compile_new_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
)
547 unsigned arg_cnt
= 0;
551 hres
= compile_expression(ctx
, expr
->expression
);
555 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
556 hres
= compile_expression(ctx
, arg
->expr
);
562 return push_instr_uint(ctx
, OP_new
, arg_cnt
);
565 static HRESULT
compile_call_expression(compiler_ctx_t
*ctx
, call_expression_t
*expr
, BOOL
*no_ret
)
567 unsigned arg_cnt
= 0;
573 if(is_memberid_expr(expr
->expression
->type
)) {
575 hres
= compile_memberid_expression(ctx
, expr
->expression
, 0);
578 hres
= compile_expression(ctx
, expr
->expression
);
584 for(arg
= expr
->argument_list
; arg
; arg
= arg
->next
) {
585 hres
= compile_expression(ctx
, arg
->expr
);
591 instr
= push_instr(ctx
, op
);
593 return E_OUTOFMEMORY
;
595 instr_ptr(ctx
, instr
)->u
.arg
[0].uint
= arg_cnt
;
596 instr_ptr(ctx
, instr
)->u
.arg
[1].lng
= no_ret
== NULL
;
602 static HRESULT
compile_delete_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
606 switch(expr
->expression
->type
) {
608 binary_expression_t
*array_expr
= (binary_expression_t
*)expr
->expression
;
610 hres
= compile_expression(ctx
, array_expr
->expression1
);
614 hres
= compile_expression(ctx
, array_expr
->expression2
);
618 if(!push_instr(ctx
, OP_delete
))
619 return E_OUTOFMEMORY
;
623 member_expression_t
*member_expr
= (member_expression_t
*)expr
->expression
;
625 hres
= compile_expression(ctx
, member_expr
->expression
);
629 /* FIXME: Potential optimization */
630 hres
= push_instr_str(ctx
, OP_str
, member_expr
->identifier
);
634 if(!push_instr(ctx
, OP_delete
))
635 return E_OUTOFMEMORY
;
639 return push_instr_bstr(ctx
, OP_delete_ident
, ((identifier_expression_t
*)expr
->expression
)->identifier
);
641 const WCHAR fixmeW
[] = {'F','I','X','M','E',0};
643 WARN("invalid delete, unimplemented exception message\n");
645 hres
= compile_expression(ctx
, expr
->expression
);
649 return push_instr_uint_str(ctx
, OP_throw_type
, JS_E_INVALID_DELETE
, fixmeW
);
656 static HRESULT
compile_assign_expression(compiler_ctx_t
*ctx
, binary_expression_t
*expr
, jsop_t op
)
658 BOOL use_throw_path
= FALSE
;
659 unsigned arg_cnt
= 0;
662 if(expr
->expression1
->type
== EXPR_CALL
) {
663 call_expression_t
*call_expr
= (call_expression_t
*)expr
->expression1
;
667 FIXME("op %d not supported on parametrized assign expressions\n", op
);
671 if(is_memberid_expr(call_expr
->expression
->type
) && call_expr
->argument_list
) {
672 hres
= compile_memberid_expression(ctx
, call_expr
->expression
, fdexNameEnsure
);
676 for(arg
= call_expr
->argument_list
; arg
; arg
= arg
->next
) {
677 hres
= compile_expression(ctx
, arg
->expr
);
683 use_throw_path
= TRUE
;
685 }else if(is_memberid_expr(expr
->expression1
->type
)) {
686 hres
= compile_memberid_expression(ctx
, expr
->expression1
, fdexNameEnsure
);
690 use_throw_path
= TRUE
;
694 /* Illegal assignment: evaluate and throw */
695 hres
= compile_expression(ctx
, expr
->expression1
);
699 hres
= compile_expression(ctx
, expr
->expression2
);
703 if(op
!= OP_LAST
&& !push_instr(ctx
, op
))
704 return E_OUTOFMEMORY
;
706 return push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
709 if(op
!= OP_LAST
&& !push_instr(ctx
, OP_refval
))
710 return E_OUTOFMEMORY
;
712 hres
= compile_expression(ctx
, expr
->expression2
);
716 if(op
!= OP_LAST
&& !push_instr(ctx
, op
))
717 return E_OUTOFMEMORY
;
720 return push_instr_uint(ctx
, OP_assign_call
, arg_cnt
);
722 if(!push_instr(ctx
, OP_assign
))
723 return E_OUTOFMEMORY
;
728 static HRESULT
compile_typeof_expression(compiler_ctx_t
*ctx
, unary_expression_t
*expr
)
733 if(is_memberid_expr(expr
->expression
->type
)) {
734 if(expr
->expression
->type
== EXPR_IDENT
)
735 return push_instr_bstr(ctx
, OP_typeofident
, ((identifier_expression_t
*)expr
->expression
)->identifier
);
738 hres
= compile_memberid_expression(ctx
, expr
->expression
, 0);
741 hres
= compile_expression(ctx
, expr
->expression
);
746 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
749 static HRESULT
compile_literal(compiler_ctx_t
*ctx
, literal_t
*literal
)
751 switch(literal
->type
) {
753 return push_instr_int(ctx
, OP_bool
, literal
->u
.bval
);
755 return push_instr_double(ctx
, OP_double
, literal
->u
.dval
);
757 return push_instr(ctx
, OP_null
) ? S_OK
: E_OUTOFMEMORY
;
759 return push_instr_str(ctx
, OP_str
, literal
->u
.wstr
);
764 str
= compiler_alloc_string_len(ctx
, literal
->u
.regexp
.str
, literal
->u
.regexp
.str_len
);
766 return E_OUTOFMEMORY
;
768 instr
= push_instr(ctx
, OP_regexp
);
770 return E_OUTOFMEMORY
;
772 instr_ptr(ctx
, instr
)->u
.arg
[0].str
= str
;
773 instr_ptr(ctx
, instr
)->u
.arg
[1].uint
= literal
->u
.regexp
.flags
;
782 static HRESULT
literal_as_bstr(compiler_ctx_t
*ctx
, literal_t
*literal
, BSTR
*str
)
784 switch(literal
->type
) {
786 *str
= compiler_alloc_bstr(ctx
, literal
->u
.wstr
);
792 hres
= double_to_string(literal
->u
.dval
, &jsstr
);
796 *str
= SysAllocStringLen(jsstr
->str
, jsstr_length(jsstr
));
797 jsstr_release(jsstr
);
804 return *str
? S_OK
: E_OUTOFMEMORY
;
807 static HRESULT
compile_array_literal(compiler_ctx_t
*ctx
, array_literal_expression_t
*expr
)
809 unsigned i
, elem_cnt
= expr
->length
;
810 array_element_t
*iter
;
813 for(iter
= expr
->element_list
; iter
; iter
= iter
->next
) {
814 elem_cnt
+= iter
->elision
+1;
816 for(i
=0; i
< iter
->elision
; i
++) {
817 if(!push_instr(ctx
, OP_undefined
))
818 return E_OUTOFMEMORY
;
821 hres
= compile_expression(ctx
, iter
->expr
);
826 for(i
=0; i
< expr
->length
; i
++) {
827 if(!push_instr(ctx
, OP_undefined
))
828 return E_OUTOFMEMORY
;
831 return push_instr_uint(ctx
, OP_carray
, elem_cnt
);
834 static HRESULT
compile_object_literal(compiler_ctx_t
*ctx
, property_value_expression_t
*expr
)
841 if(!push_instr(ctx
, OP_new_obj
))
842 return E_OUTOFMEMORY
;
844 for(iter
= expr
->property_list
; iter
; iter
= iter
->next
) {
845 hres
= literal_as_bstr(ctx
, iter
->name
, &name
);
849 hres
= compile_expression(ctx
, iter
->value
);
853 instr
= push_instr(ctx
, OP_obj_prop
);
855 return E_OUTOFMEMORY
;
857 instr_ptr(ctx
, instr
)->u
.arg
->bstr
= name
;
863 static HRESULT
compile_function_expression(compiler_ctx_t
*ctx
, function_expression_t
*expr
)
865 ctx
->func_tail
= ctx
->func_tail
? (ctx
->func_tail
->next
= expr
) : (ctx
->func_head
= expr
);
867 /* FIXME: not exactly right */
868 if(expr
->identifier
) {
869 ctx
->func
->func_cnt
++;
870 return push_instr_bstr(ctx
, OP_ident
, expr
->identifier
);
873 return push_instr_uint(ctx
, OP_func
, ctx
->func
->func_cnt
++);
876 static HRESULT
compile_expression_noret(compiler_ctx_t
*ctx
, expression_t
*expr
, BOOL
*no_ret
)
880 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
882 return compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_cnd_z
);
884 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_array
);
886 return compile_array_literal(ctx
, (array_literal_expression_t
*)expr
);
888 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_LAST
);
890 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
892 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
894 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
896 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
898 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
900 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
902 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
903 case EXPR_ASSIGNLSHIFT
:
904 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_lshift
);
905 case EXPR_ASSIGNRSHIFT
:
906 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift
);
907 case EXPR_ASSIGNRRSHIFT
:
908 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift2
);
910 return compile_assign_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
912 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
914 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_bneg
);
916 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
918 return compile_call_expression(ctx
, (call_expression_t
*)expr
, no_ret
);
920 return compile_comma_expression(ctx
, (binary_expression_t
*)expr
);
922 return compile_conditional_expression(ctx
, (conditional_expression_t
*)expr
);
924 return compile_delete_expression(ctx
, (unary_expression_t
*)expr
);
926 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
928 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq
);
930 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eq2
);
932 return compile_function_expression(ctx
, (function_expression_t
*)expr
);
934 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gt
);
936 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gteq
);
938 return push_instr_bstr(ctx
, OP_ident
, ((identifier_expression_t
*)expr
)->identifier
);
940 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_in
);
941 case EXPR_INSTANCEOF
:
942 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_instanceof
);
944 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lt
);
946 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lteq
);
948 return compile_literal(ctx
, ((literal_expression_t
*)expr
)->literal
);
950 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_neg
);
952 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lshift
);
954 return compile_member_expression(ctx
, (member_expression_t
*)expr
);
956 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_minus
);
958 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
960 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
962 return compile_new_expression(ctx
, (call_expression_t
*)expr
);
964 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq
);
966 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_neq2
);
968 return compile_logical_expression(ctx
, (binary_expression_t
*)expr
, OP_cnd_nz
);
970 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_tonum
);
972 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_postinc
, -1);
974 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_postinc
, 1);
976 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_preinc
, -1);
978 return compile_increment_expression(ctx
, (unary_expression_t
*)expr
, OP_preinc
, 1);
980 return compile_object_literal(ctx
, (property_value_expression_t
*)expr
);
982 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift
);
984 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_rshift2
);
986 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
988 return push_instr(ctx
, OP_this
) ? S_OK
: E_OUTOFMEMORY
;
990 return compile_typeof_expression(ctx
, (unary_expression_t
*)expr
);
992 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_void
);
994 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
1002 static HRESULT
compile_expression(compiler_ctx_t
*ctx
, expression_t
*expr
)
1004 return compile_expression_noret(ctx
, expr
, NULL
);
1007 static inline BOOL
is_loop_statement(statement_type_t type
)
1009 return type
== STAT_FOR
|| type
== STAT_FORIN
|| type
== STAT_WHILE
;
1012 /* ECMA-262 3rd Edition 12.1 */
1013 static HRESULT
compile_block_statement(compiler_ctx_t
*ctx
, statement_t
*iter
)
1017 /* FIXME: do it only if needed */
1019 return push_instr(ctx
, OP_undefined
) ? S_OK
: E_OUTOFMEMORY
;
1022 hres
= compile_statement(ctx
, NULL
, iter
);
1030 if(!push_instr(ctx
, OP_pop
))
1031 return E_OUTOFMEMORY
;
1037 /* ECMA-262 3rd Edition 12.2 */
1038 static HRESULT
compile_variable_list(compiler_ctx_t
*ctx
, variable_declaration_t
*list
)
1040 variable_declaration_t
*iter
;
1043 assert(list
!= NULL
);
1046 ctx
->var_tail
->global_next
= list
;
1048 ctx
->var_head
= list
;
1050 for(iter
= list
; iter
; iter
= iter
->next
) {
1051 ctx
->func
->var_cnt
++;
1052 iter
->global_next
= iter
->next
;
1054 ctx
->var_tail
= iter
;
1059 hres
= compile_expression(ctx
, iter
->expr
);
1063 hres
= push_instr_bstr(ctx
, OP_var_set
, iter
->identifier
);
1071 /* ECMA-262 3rd Edition 12.2 */
1072 static HRESULT
compile_var_statement(compiler_ctx_t
*ctx
, var_statement_t
*stat
)
1076 hres
= compile_variable_list(ctx
, stat
->variable_list
);
1080 return push_instr(ctx
, OP_undefined
) ? S_OK
: E_OUTOFMEMORY
;
1083 /* ECMA-262 3rd Edition 12.4 */
1084 static HRESULT
compile_expression_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1086 BOOL no_ret
= FALSE
;
1089 hres
= compile_expression_noret(ctx
, stat
->expr
, &no_ret
);
1093 /* FIXME: that's a big potential optimization */
1094 if(no_ret
&& !push_instr(ctx
, OP_undefined
))
1095 return E_OUTOFMEMORY
;
1100 /* ECMA-262 3rd Edition 12.5 */
1101 static HRESULT
compile_if_statement(compiler_ctx_t
*ctx
, if_statement_t
*stat
)
1103 unsigned jmp_else
, jmp_end
;
1106 hres
= compile_expression(ctx
, stat
->expr
);
1110 jmp_else
= push_instr(ctx
, OP_jmp_z
);
1112 return E_OUTOFMEMORY
;
1114 hres
= compile_statement(ctx
, NULL
, stat
->if_stat
);
1118 jmp_end
= push_instr(ctx
, OP_jmp
);
1120 return E_OUTOFMEMORY
;
1122 set_arg_uint(ctx
, jmp_else
, ctx
->code_off
);
1124 if(stat
->else_stat
) {
1125 hres
= compile_statement(ctx
, NULL
, stat
->else_stat
);
1129 /* FIXME: We could sometimes avoid it */
1130 if(!push_instr(ctx
, OP_undefined
))
1131 return E_OUTOFMEMORY
;
1134 set_arg_uint(ctx
, jmp_end
, ctx
->code_off
);
1138 /* ECMA-262 3rd Edition 12.6.2 */
1139 static HRESULT
compile_while_statement(compiler_ctx_t
*ctx
, while_statement_t
*stat
)
1141 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1145 stat_ctx
.break_label
= alloc_label(ctx
);
1146 if(!stat_ctx
.break_label
)
1147 return E_OUTOFMEMORY
;
1149 stat_ctx
.continue_label
= alloc_label(ctx
);
1150 if(!stat_ctx
.continue_label
)
1151 return E_OUTOFMEMORY
;
1153 if(!stat
->do_while
) {
1155 if(!push_instr(ctx
, OP_undefined
))
1156 return E_OUTOFMEMORY
;
1158 jmp_off
= ctx
->code_off
;
1159 label_set_addr(ctx
, stat_ctx
.continue_label
);
1160 hres
= compile_expression(ctx
, stat
->expr
);
1164 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1168 if(!push_instr(ctx
, OP_pop
))
1169 return E_OUTOFMEMORY
;
1171 jmp_off
= ctx
->code_off
;
1174 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1178 if(stat
->do_while
) {
1179 label_set_addr(ctx
, stat_ctx
.continue_label
);
1180 hres
= compile_expression(ctx
, stat
->expr
);
1184 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1188 if(!push_instr(ctx
, OP_pop
))
1189 return E_OUTOFMEMORY
;
1192 hres
= push_instr_uint(ctx
, OP_jmp
, jmp_off
);
1196 label_set_addr(ctx
, stat_ctx
.break_label
);
1200 /* ECMA-262 3rd Edition 12.6.3 */
1201 static HRESULT
compile_for_statement(compiler_ctx_t
*ctx
, for_statement_t
*stat
)
1203 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1207 if(stat
->variable_list
) {
1208 hres
= compile_variable_list(ctx
, stat
->variable_list
);
1211 }else if(stat
->begin_expr
) {
1212 BOOL no_ret
= FALSE
;
1214 hres
= compile_expression_noret(ctx
, stat
->begin_expr
, &no_ret
);
1217 if(!no_ret
&& !push_instr(ctx
, OP_pop
))
1218 return E_OUTOFMEMORY
;
1221 stat_ctx
.break_label
= alloc_label(ctx
);
1222 if(!stat_ctx
.break_label
)
1223 return E_OUTOFMEMORY
;
1225 stat_ctx
.continue_label
= alloc_label(ctx
);
1226 if(!stat_ctx
.continue_label
)
1227 return E_OUTOFMEMORY
;
1230 if(!push_instr(ctx
, OP_undefined
))
1231 return E_OUTOFMEMORY
;
1233 expr_off
= ctx
->code_off
;
1236 hres
= compile_expression(ctx
, stat
->expr
);
1240 hres
= push_instr_uint(ctx
, OP_jmp_z
, stat_ctx
.break_label
);
1245 if(!push_instr(ctx
, OP_pop
))
1246 return E_OUTOFMEMORY
;
1248 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1252 label_set_addr(ctx
, stat_ctx
.continue_label
);
1254 if(stat
->end_expr
) {
1255 BOOL no_ret
= FALSE
;
1257 hres
= compile_expression_noret(ctx
, stat
->end_expr
, &no_ret
);
1261 if(!no_ret
&& !push_instr(ctx
, OP_pop
))
1262 return E_OUTOFMEMORY
;
1265 hres
= push_instr_uint(ctx
, OP_jmp
, expr_off
);
1269 label_set_addr(ctx
, stat_ctx
.break_label
);
1273 /* ECMA-262 3rd Edition 12.6.4 */
1274 static HRESULT
compile_forin_statement(compiler_ctx_t
*ctx
, forin_statement_t
*stat
)
1276 statement_ctx_t stat_ctx
= {4, FALSE
, FALSE
};
1279 if(stat
->variable
) {
1280 hres
= compile_variable_list(ctx
, stat
->variable
);
1285 stat_ctx
.break_label
= alloc_label(ctx
);
1286 if(!stat_ctx
.break_label
)
1287 return E_OUTOFMEMORY
;
1289 stat_ctx
.continue_label
= alloc_label(ctx
);
1290 if(!stat_ctx
.continue_label
)
1291 return E_OUTOFMEMORY
;
1293 hres
= compile_expression(ctx
, stat
->in_expr
);
1297 if(stat
->variable
) {
1298 hres
= push_instr_bstr_uint(ctx
, OP_identid
, stat
->variable
->identifier
, fdexNameEnsure
);
1301 }else if(is_memberid_expr(stat
->expr
->type
)) {
1302 hres
= compile_memberid_expression(ctx
, stat
->expr
, fdexNameEnsure
);
1306 hres
= push_instr_uint(ctx
, OP_throw_ref
, JS_E_ILLEGAL_ASSIGN
);
1310 /* FIXME: compile statement anyways when we depend on compiler to check errors */
1314 hres
= push_instr_int(ctx
, OP_int
, DISPID_STARTENUM
);
1319 if(!push_instr(ctx
, OP_undefined
))
1320 return E_OUTOFMEMORY
;
1322 label_set_addr(ctx
, stat_ctx
.continue_label
);
1323 hres
= push_instr_uint(ctx
, OP_forin
, stat_ctx
.break_label
);
1325 return E_OUTOFMEMORY
;
1327 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1331 hres
= push_instr_uint(ctx
, OP_jmp
, stat_ctx
.continue_label
);
1335 label_set_addr(ctx
, stat_ctx
.break_label
);
1339 static HRESULT
pop_to_stat(compiler_ctx_t
*ctx
, BOOL var_stack
, BOOL scope_stack
, statement_ctx_t
*stat_ctx
)
1341 unsigned stack_pop
= 0;
1342 statement_ctx_t
*iter
;
1344 for(iter
= ctx
->stat_ctx
; iter
!= stat_ctx
; iter
= iter
->next
) {
1346 if(iter
->using_scope
&& !push_instr(ctx
, OP_pop_scope
))
1347 return E_OUTOFMEMORY
;
1348 if(iter
->using_except
&& !push_instr(ctx
, OP_pop_except
))
1349 return E_OUTOFMEMORY
;
1351 stack_pop
+= iter
->stack_use
;
1355 /* FIXME: optimize */
1356 while(stack_pop
--) {
1357 if(!push_instr(ctx
, OP_pop
))
1358 return E_OUTOFMEMORY
;
1366 /* ECMA-262 3rd Edition 12.7 */
1367 static HRESULT
compile_continue_statement(compiler_ctx_t
*ctx
, branch_statement_t
*stat
)
1369 statement_ctx_t
*pop_ctx
;
1372 if(stat
->identifier
) {
1373 statement_t
*label_stat
;
1374 statement_ctx_t
*iter
;
1378 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1379 if(iter
->continue_label
)
1381 if(iter
->labelled_stat
&& !strcmpW(iter
->labelled_stat
->identifier
, stat
->identifier
))
1386 WARN("Label not found\n");
1387 return JS_E_LABEL_NOT_FOUND
;
1390 /* Labelled continue are allowed only on loops */
1391 for(label_stat
= iter
->labelled_stat
->statement
;
1392 label_stat
->type
== STAT_LABEL
;
1393 label_stat
= ((labelled_statement_t
*)label_stat
)->statement
);
1394 if(!is_loop_statement(label_stat
->type
)) {
1395 WARN("Label is not a loop\n");
1396 return JS_E_INVALID_CONTINUE
;
1399 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1400 if(pop_ctx
->continue_label
)
1405 WARN("continue outside loop\n");
1406 return JS_E_INVALID_CONTINUE
;
1410 hres
= pop_to_stat(ctx
, TRUE
, TRUE
, pop_ctx
);
1414 if(!push_instr(ctx
, OP_undefined
))
1415 return E_OUTOFMEMORY
;
1417 return push_instr_uint(ctx
, OP_jmp
, pop_ctx
->continue_label
);
1420 /* ECMA-262 3rd Edition 12.8 */
1421 static HRESULT
compile_break_statement(compiler_ctx_t
*ctx
, branch_statement_t
*stat
)
1423 statement_ctx_t
*pop_ctx
;
1426 if(stat
->identifier
) {
1427 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1428 if(pop_ctx
->labelled_stat
&& !strcmpW(pop_ctx
->labelled_stat
->identifier
, stat
->identifier
)) {
1429 assert(pop_ctx
->break_label
);
1435 WARN("Label not found\n");
1436 return JS_E_LABEL_NOT_FOUND
;
1439 for(pop_ctx
= ctx
->stat_ctx
; pop_ctx
; pop_ctx
= pop_ctx
->next
) {
1440 if(pop_ctx
->break_label
&& !pop_ctx
->labelled_stat
)
1445 WARN("Break outside loop\n");
1446 return JS_E_INVALID_BREAK
;
1450 hres
= pop_to_stat(ctx
, TRUE
, TRUE
, pop_ctx
->next
);
1454 if(!push_instr(ctx
, OP_undefined
))
1455 return E_OUTOFMEMORY
;
1457 return push_instr_uint(ctx
, OP_jmp
, pop_ctx
->break_label
);
1460 /* ECMA-262 3rd Edition 12.9 */
1461 static HRESULT
compile_return_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1465 hres
= pop_to_stat(ctx
, TRUE
, FALSE
, NULL
);
1470 hres
= compile_expression(ctx
, stat
->expr
);
1475 hres
= pop_to_stat(ctx
, FALSE
, TRUE
, NULL
);
1479 return push_instr(ctx
, OP_ret
) ? S_OK
: E_OUTOFMEMORY
;
1482 /* ECMA-262 3rd Edition 12.10 */
1483 static HRESULT
compile_with_statement(compiler_ctx_t
*ctx
, with_statement_t
*stat
)
1485 statement_ctx_t stat_ctx
= {0, TRUE
, FALSE
};
1488 hres
= compile_expression(ctx
, stat
->expr
);
1492 if(!push_instr(ctx
, OP_push_scope
))
1493 return E_OUTOFMEMORY
;
1495 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1499 if(!push_instr(ctx
, OP_pop_scope
))
1500 return E_OUTOFMEMORY
;
1505 /* ECMA-262 3rd Edition 12.10 */
1506 static HRESULT
compile_labelled_statement(compiler_ctx_t
*ctx
, labelled_statement_t
*stat
)
1508 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
, 0, 0, stat
}, *iter
;
1511 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1512 if(iter
->labelled_stat
&& !strcmpW(iter
->labelled_stat
->identifier
, stat
->identifier
)) {
1513 WARN("Label %s redefined\n", debugstr_w(stat
->identifier
));
1514 return JS_E_LABEL_REDEFINED
;
1518 /* Labelled breaks are allowed for any labelled statements, not only loops (violating spec) */
1519 stat_ctx
.break_label
= alloc_label(ctx
);
1520 if(!stat_ctx
.break_label
)
1521 return E_OUTOFMEMORY
;
1523 hres
= compile_statement(ctx
, &stat_ctx
, stat
->statement
);
1527 label_set_addr(ctx
, stat_ctx
.break_label
);
1531 /* ECMA-262 3rd Edition 12.13 */
1532 static HRESULT
compile_switch_statement(compiler_ctx_t
*ctx
, switch_statement_t
*stat
)
1534 statement_ctx_t stat_ctx
= {0, FALSE
, FALSE
};
1535 unsigned case_cnt
= 0, *case_jmps
, i
, default_jmp
;
1536 BOOL have_default
= FALSE
;
1537 statement_t
*stat_iter
;
1538 case_clausule_t
*iter
;
1541 hres
= compile_expression(ctx
, stat
->expr
);
1545 stat_ctx
.break_label
= alloc_label(ctx
);
1546 if(!stat_ctx
.break_label
)
1547 return E_OUTOFMEMORY
;
1549 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1554 case_jmps
= heap_alloc(case_cnt
* sizeof(*case_jmps
));
1556 return E_OUTOFMEMORY
;
1559 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1561 have_default
= TRUE
;
1565 hres
= compile_expression(ctx
, iter
->expr
);
1569 case_jmps
[i
] = push_instr(ctx
, OP_case
);
1571 hres
= E_OUTOFMEMORY
;
1577 if(SUCCEEDED(hres
)) {
1578 if(push_instr(ctx
, OP_pop
)) {
1579 default_jmp
= push_instr(ctx
, OP_jmp
);
1581 hres
= E_OUTOFMEMORY
;
1583 hres
= E_OUTOFMEMORY
;
1588 heap_free(case_jmps
);
1593 for(iter
= stat
->case_list
; iter
; iter
= iter
->next
) {
1594 while(iter
->next
&& iter
->next
->stat
== iter
->stat
) {
1595 set_arg_uint(ctx
, iter
->expr
? case_jmps
[i
++] : default_jmp
, ctx
->code_off
);
1599 set_arg_uint(ctx
, iter
->expr
? case_jmps
[i
++] : default_jmp
, ctx
->code_off
);
1602 for(stat_iter
= iter
->stat
; stat_iter
&& (!iter
->next
|| iter
->next
->stat
!= stat_iter
);
1603 stat_iter
= stat_iter
->next
) {
1604 hres
= compile_statement(ctx
, &stat_ctx
, stat_iter
);
1608 if(stat_iter
->next
&& !push_instr(ctx
, OP_pop
)) {
1609 hres
= E_OUTOFMEMORY
;
1616 if(!push_instr(ctx
, OP_undefined
)) {
1617 hres
= E_OUTOFMEMORY
;
1623 heap_free(case_jmps
);
1626 assert(i
== case_cnt
);
1629 hres
= push_instr_uint(ctx
, OP_jmp
, stat_ctx
.break_label
);
1632 set_arg_uint(ctx
, default_jmp
, ctx
->code_off
);
1633 if(!push_instr(ctx
, OP_undefined
))
1634 return E_OUTOFMEMORY
;
1637 label_set_addr(ctx
, stat_ctx
.break_label
);
1641 /* ECMA-262 3rd Edition 12.13 */
1642 static HRESULT
compile_throw_statement(compiler_ctx_t
*ctx
, expression_statement_t
*stat
)
1646 hres
= compile_expression(ctx
, stat
->expr
);
1650 return push_instr(ctx
, OP_throw
) ? S_OK
: E_OUTOFMEMORY
;
1653 /* ECMA-262 3rd Edition 12.14 */
1654 static HRESULT
compile_try_statement(compiler_ctx_t
*ctx
, try_statement_t
*stat
)
1656 statement_ctx_t try_ctx
= {0, FALSE
, TRUE
}, catch_ctx
= {0, TRUE
, FALSE
};
1657 statement_ctx_t finally_ctx
= {2, FALSE
, FALSE
};
1658 unsigned push_except
;
1662 push_except
= push_instr(ctx
, OP_push_except
);
1664 return E_OUTOFMEMORY
;
1666 if(stat
->catch_block
) {
1667 ident
= compiler_alloc_bstr(ctx
, stat
->catch_block
->identifier
);
1669 return E_OUTOFMEMORY
;
1674 instr_ptr(ctx
, push_except
)->u
.arg
[1].bstr
= ident
;
1676 if(!stat
->catch_block
)
1677 try_ctx
.stack_use
= 2;
1679 hres
= compile_statement(ctx
, &try_ctx
, stat
->try_statement
);
1683 if(!push_instr(ctx
, OP_pop_except
))
1684 return E_OUTOFMEMORY
;
1686 if(stat
->catch_block
) {
1687 unsigned jmp_finally
;
1689 jmp_finally
= push_instr(ctx
, OP_jmp
);
1691 return E_OUTOFMEMORY
;
1693 instr_ptr(ctx
, push_except
)->u
.arg
[0].uint
= ctx
->code_off
;
1695 hres
= compile_statement(ctx
, &catch_ctx
, stat
->catch_block
->statement
);
1699 if(!push_instr(ctx
, OP_pop_scope
))
1700 return E_OUTOFMEMORY
;
1702 set_arg_uint(ctx
, jmp_finally
, ctx
->code_off
);
1704 set_arg_uint(ctx
, push_except
, ctx
->code_off
);
1707 if(stat
->finally_statement
) {
1709 if(!push_instr(ctx
, OP_pop
))
1710 return E_OUTOFMEMORY
;
1712 hres
= compile_statement(ctx
, stat
->catch_block
? NULL
: &finally_ctx
, stat
->finally_statement
);
1716 if(!stat
->catch_block
&& !push_instr(ctx
, OP_end_finally
))
1717 return E_OUTOFMEMORY
;
1723 static HRESULT
compile_statement(compiler_ctx_t
*ctx
, statement_ctx_t
*stat_ctx
, statement_t
*stat
)
1728 stat_ctx
->next
= ctx
->stat_ctx
;
1729 ctx
->stat_ctx
= stat_ctx
;
1732 switch(stat
->type
) {
1734 hres
= compile_block_statement(ctx
, ((block_statement_t
*)stat
)->stat_list
);
1737 hres
= compile_break_statement(ctx
, (branch_statement_t
*)stat
);
1740 hres
= compile_continue_statement(ctx
, (branch_statement_t
*)stat
);
1743 hres
= push_instr(ctx
, OP_undefined
) ? S_OK
: E_OUTOFMEMORY
; /* FIXME */
1746 hres
= compile_expression_statement(ctx
, (expression_statement_t
*)stat
);
1749 hres
= compile_for_statement(ctx
, (for_statement_t
*)stat
);
1752 hres
= compile_forin_statement(ctx
, (forin_statement_t
*)stat
);
1755 hres
= compile_if_statement(ctx
, (if_statement_t
*)stat
);
1758 hres
= compile_labelled_statement(ctx
, (labelled_statement_t
*)stat
);
1761 hres
= compile_return_statement(ctx
, (expression_statement_t
*)stat
);
1764 hres
= compile_switch_statement(ctx
, (switch_statement_t
*)stat
);
1767 hres
= compile_throw_statement(ctx
, (expression_statement_t
*)stat
);
1770 hres
= compile_try_statement(ctx
, (try_statement_t
*)stat
);
1773 hres
= compile_var_statement(ctx
, (var_statement_t
*)stat
);
1776 hres
= compile_while_statement(ctx
, (while_statement_t
*)stat
);
1779 hres
= compile_with_statement(ctx
, (with_statement_t
*)stat
);
1787 assert(ctx
->stat_ctx
== stat_ctx
);
1788 ctx
->stat_ctx
= stat_ctx
->next
;
1794 static void resolve_labels(compiler_ctx_t
*ctx
, unsigned off
)
1798 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->code_off
; instr
++) {
1799 if(instr_info
[instr
->op
].arg1_type
== ARG_ADDR
&& (instr
->u
.arg
->uint
& LABEL_FLAG
)) {
1800 assert((instr
->u
.arg
->uint
& ~LABEL_FLAG
) < ctx
->labels_cnt
);
1801 instr
->u
.arg
->uint
= ctx
->labels
[instr
->u
.arg
->uint
& ~LABEL_FLAG
];
1803 assert(instr_info
[instr
->op
].arg2_type
!= ARG_ADDR
);
1806 ctx
->labels_cnt
= 0;
1809 void release_bytecode(bytecode_t
*code
)
1816 for(i
=0; i
< code
->bstr_cnt
; i
++)
1817 SysFreeString(code
->bstr_pool
[i
]);
1818 for(i
=0; i
< code
->str_cnt
; i
++)
1819 jsstr_release(code
->str_pool
[i
]);
1821 heap_free(code
->source
);
1822 jsheap_free(&code
->heap
);
1823 heap_free(code
->bstr_pool
);
1824 heap_free(code
->str_pool
);
1825 heap_free(code
->instrs
);
1829 static HRESULT
init_code(compiler_ctx_t
*compiler
, const WCHAR
*source
)
1831 compiler
->code
= heap_alloc_zero(sizeof(bytecode_t
));
1833 return E_OUTOFMEMORY
;
1835 compiler
->code
->ref
= 1;
1836 jsheap_init(&compiler
->code
->heap
);
1838 compiler
->code
->source
= heap_strdupW(source
);
1839 if(!compiler
->code
->source
) {
1840 release_bytecode(compiler
->code
);
1841 return E_OUTOFMEMORY
;
1844 compiler
->code
->instrs
= heap_alloc(64 * sizeof(instr_t
));
1845 if(!compiler
->code
->instrs
) {
1846 release_bytecode(compiler
->code
);
1847 return E_OUTOFMEMORY
;
1850 compiler
->code_size
= 64;
1851 compiler
->code_off
= 1;
1855 static HRESULT
compile_function(compiler_ctx_t
*ctx
, source_elements_t
*source
, function_expression_t
*func_expr
,
1856 BOOL from_eval
, function_code_t
*func
)
1858 variable_declaration_t
*var_iter
;
1859 function_expression_t
*iter
;
1865 ctx
->var_head
= ctx
->var_tail
= NULL
;
1866 ctx
->func_head
= ctx
->func_tail
= NULL
;
1868 off
= ctx
->code_off
;
1870 hres
= compile_block_statement(ctx
, source
->statement
);
1874 resolve_labels(ctx
, off
);
1876 if(!from_eval
&& !push_instr(ctx
, OP_pop
))
1877 return E_OUTOFMEMORY
;
1878 if(!push_instr(ctx
, OP_ret
))
1879 return E_OUTOFMEMORY
;
1881 if(TRACE_ON(jscript_disas
))
1882 dump_code(ctx
, off
);
1884 func
->instr_off
= off
;
1886 if(func_expr
&& func_expr
->identifier
) {
1887 func
->name
= compiler_alloc_bstr(ctx
, func_expr
->identifier
);
1889 return E_OUTOFMEMORY
;
1893 parameter_t
*param_iter
;
1895 func
->source
= func_expr
->src_str
;
1896 func
->source_len
= func_expr
->src_len
;
1898 for(param_iter
= func_expr
->parameter_list
; param_iter
; param_iter
= param_iter
->next
)
1901 func
->params
= compiler_alloc(ctx
->code
, func
->param_cnt
* sizeof(*func
->params
));
1903 return E_OUTOFMEMORY
;
1905 for(param_iter
= func_expr
->parameter_list
, i
=0; param_iter
; param_iter
= param_iter
->next
, i
++) {
1906 func
->params
[i
] = compiler_alloc_bstr(ctx
, param_iter
->identifier
);
1907 if(!func
->params
[i
])
1908 return E_OUTOFMEMORY
;
1912 func
->variables
= compiler_alloc(ctx
->code
, func
->var_cnt
* sizeof(*func
->variables
));
1913 if(!func
->variables
)
1914 return E_OUTOFMEMORY
;
1916 for(var_iter
= ctx
->var_head
, i
=0; var_iter
; var_iter
= var_iter
->global_next
, i
++) {
1917 func
->variables
[i
] = compiler_alloc_bstr(ctx
, var_iter
->identifier
);
1918 if(!func
->variables
[i
])
1919 return E_OUTOFMEMORY
;
1922 assert(i
== func
->var_cnt
);
1924 func
->funcs
= compiler_alloc(ctx
->code
, func
->func_cnt
* sizeof(*func
->funcs
));
1926 return E_OUTOFMEMORY
;
1927 memset(func
->funcs
, 0, func
->func_cnt
* sizeof(*func
->funcs
));
1929 for(iter
= ctx
->func_head
, i
=0; iter
; iter
= iter
->next
, i
++) {
1930 hres
= compile_function(ctx
, iter
->source_elements
, iter
, FALSE
, func
->funcs
+i
);
1935 assert(i
== func
->func_cnt
);
1940 static HRESULT
parse_arguments(compiler_ctx_t
*ctx
, const WCHAR
*args
, BSTR
*arg_array
, unsigned *args_size
)
1942 const WCHAR
*ptr
= args
, *ptr2
;
1943 unsigned arg_cnt
= 0;
1945 while(isspaceW(*ptr
))
1954 if(!isalphaW(*ptr
) && *ptr
!= '_') {
1955 FIXME("expected alpha or '_': %s\n", debugstr_w(ptr
));
1960 while(isalnumW(*ptr
) || *ptr
== '_')
1963 if(*ptr
&& *ptr
!= ',' && !isspaceW(*ptr
)) {
1964 FIXME("unexpected har %s\n", debugstr_w(ptr
));
1969 arg_array
[arg_cnt
] = compiler_alloc_bstr_len(ctx
, ptr2
, ptr
-ptr2
);
1970 if(!arg_array
[arg_cnt
])
1971 return E_OUTOFMEMORY
;
1975 while(isspaceW(*ptr
))
1980 FIXME("expected ',': %s\n", debugstr_w(ptr
));
1985 while(isspaceW(*ptr
))
1990 *args_size
= arg_cnt
;
1994 static HRESULT
compile_arguments(compiler_ctx_t
*ctx
, const WCHAR
*args
)
1998 hres
= parse_arguments(ctx
, args
, NULL
, &ctx
->code
->global_code
.param_cnt
);
2002 ctx
->code
->global_code
.params
= compiler_alloc(ctx
->code
,
2003 ctx
->code
->global_code
.param_cnt
* sizeof(*ctx
->code
->global_code
.params
));
2004 if(!ctx
->code
->global_code
.params
)
2005 return E_OUTOFMEMORY
;
2007 return parse_arguments(ctx
, args
, ctx
->code
->global_code
.params
, NULL
);
2010 HRESULT
compile_script(script_ctx_t
*ctx
, const WCHAR
*code
, const WCHAR
*args
, const WCHAR
*delimiter
,
2011 BOOL from_eval
, BOOL use_decode
, bytecode_t
**ret
)
2013 compiler_ctx_t compiler
= {0};
2016 hres
= init_code(&compiler
, code
);
2021 hres
= compile_arguments(&compiler
, args
);
2027 hres
= decode_source(compiler
.code
->source
);
2029 WARN("Decoding failed\n");
2034 hres
= script_parse(ctx
, compiler
.code
->source
, delimiter
, from_eval
, &compiler
.parser
);
2036 release_bytecode(compiler
.code
);
2040 hres
= compile_function(&compiler
, compiler
.parser
->source
, NULL
, from_eval
, &compiler
.code
->global_code
);
2041 parser_release(compiler
.parser
);
2043 release_bytecode(compiler
.code
);
2047 *ret
= compiler
.code
;