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
23 #include "parser.tab.h"
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(vbscript
);
28 WINE_DECLARE_DEBUG_CHANNEL(vbscript_disas
);
30 typedef struct _statement_ctx_t
{
33 unsigned while_end_label
;
34 unsigned for_end_label
;
36 struct _statement_ctx_t
*next
;
46 statement_ctx_t
*stat_ctx
;
52 unsigned sub_end_label
;
53 unsigned func_end_label
;
54 unsigned prop_end_label
;
56 dim_decl_t
*dim_decls
;
57 dynamic_var_t
*global_vars
;
59 const_decl_t
*const_decls
;
60 const_decl_t
*global_consts
;
64 function_decl_t
*func_decls
;
66 class_desc_t
*classes
;
69 static HRESULT
compile_expression(compile_ctx_t
*,expression_t
*);
70 static HRESULT
compile_statement(compile_ctx_t
*,statement_ctx_t
*,statement_t
*);
74 instr_arg_type_t arg1_type
;
75 instr_arg_type_t arg2_type
;
77 #define X(n,a,b,c) {#n,b,c},
82 static void dump_instr_arg(instr_arg_type_t type
, instr_arg_t
*arg
)
87 TRACE_(vbscript_disas
)("\t%s", debugstr_w(arg
->str
));
90 TRACE_(vbscript_disas
)("\t%d", arg
->uint
);
94 TRACE_(vbscript_disas
)("\t%u", arg
->uint
);
97 TRACE_(vbscript_disas
)("\t%lf", *arg
->dbl
);
105 static void dump_code(compile_ctx_t
*ctx
)
109 for(instr
= ctx
->code
->instrs
+1; instr
< ctx
->code
->instrs
+ctx
->instr_cnt
; instr
++) {
110 assert(instr
->op
< OP_LAST
);
111 TRACE_(vbscript_disas
)("%d:\t%s", (int)(instr
-ctx
->code
->instrs
), instr_info
[instr
->op
].op_str
);
112 dump_instr_arg(instr_info
[instr
->op
].arg1_type
, &instr
->arg1
);
113 dump_instr_arg(instr_info
[instr
->op
].arg2_type
, &instr
->arg2
);
114 TRACE_(vbscript_disas
)("\n");
118 static inline void *compiler_alloc(vbscode_t
*vbscode
, size_t size
)
120 return heap_pool_alloc(&vbscode
->heap
, size
);
123 static inline void *compiler_alloc_zero(vbscode_t
*vbscode
, size_t size
)
127 ret
= heap_pool_alloc(&vbscode
->heap
, size
);
129 memset(ret
, 0, size
);
133 static WCHAR
*compiler_alloc_string(vbscode_t
*vbscode
, const WCHAR
*str
)
138 size
= (strlenW(str
)+1)*sizeof(WCHAR
);
139 ret
= compiler_alloc(vbscode
, size
);
141 memcpy(ret
, str
, size
);
145 static inline instr_t
*instr_ptr(compile_ctx_t
*ctx
, unsigned id
)
147 assert(id
< ctx
->instr_cnt
);
148 return ctx
->code
->instrs
+ id
;
151 static unsigned push_instr(compile_ctx_t
*ctx
, vbsop_t op
)
153 assert(ctx
->instr_size
&& ctx
->instr_size
>= ctx
->instr_cnt
);
155 if(ctx
->instr_size
== ctx
->instr_cnt
) {
158 new_instr
= heap_realloc(ctx
->code
->instrs
, ctx
->instr_size
*2*sizeof(instr_t
));
162 ctx
->code
->instrs
= new_instr
;
163 ctx
->instr_size
*= 2;
166 ctx
->code
->instrs
[ctx
->instr_cnt
].op
= op
;
167 return ctx
->instr_cnt
++;
170 static HRESULT
push_instr_int(compile_ctx_t
*ctx
, vbsop_t op
, LONG arg
)
174 ret
= push_instr(ctx
, op
);
176 return E_OUTOFMEMORY
;
178 instr_ptr(ctx
, ret
)->arg1
.lng
= arg
;
182 static HRESULT
push_instr_uint(compile_ctx_t
*ctx
, vbsop_t op
, unsigned arg
)
186 ret
= push_instr(ctx
, op
);
188 return E_OUTOFMEMORY
;
190 instr_ptr(ctx
, ret
)->arg1
.uint
= arg
;
194 static HRESULT
push_instr_addr(compile_ctx_t
*ctx
, vbsop_t op
, unsigned arg
)
198 ret
= push_instr(ctx
, op
);
200 return E_OUTOFMEMORY
;
202 instr_ptr(ctx
, ret
)->arg1
.uint
= arg
;
206 static HRESULT
push_instr_str(compile_ctx_t
*ctx
, vbsop_t op
, const WCHAR
*arg
)
211 str
= compiler_alloc_string(ctx
->code
, arg
);
213 return E_OUTOFMEMORY
;
215 instr
= push_instr(ctx
, op
);
217 return E_OUTOFMEMORY
;
219 instr_ptr(ctx
, instr
)->arg1
.str
= str
;
223 static HRESULT
push_instr_double(compile_ctx_t
*ctx
, vbsop_t op
, double arg
)
228 d
= compiler_alloc(ctx
->code
, sizeof(double));
230 return E_OUTOFMEMORY
;
232 instr
= push_instr(ctx
, op
);
234 return E_OUTOFMEMORY
;
237 instr_ptr(ctx
, instr
)->arg1
.dbl
= d
;
241 static BSTR
alloc_bstr_arg(compile_ctx_t
*ctx
, const WCHAR
*str
)
243 if(!ctx
->code
->bstr_pool_size
) {
244 ctx
->code
->bstr_pool
= heap_alloc(8 * sizeof(BSTR
));
245 if(!ctx
->code
->bstr_pool
)
247 ctx
->code
->bstr_pool_size
= 8;
248 }else if(ctx
->code
->bstr_pool_size
== ctx
->code
->bstr_cnt
) {
251 new_pool
= heap_realloc(ctx
->code
->bstr_pool
, ctx
->code
->bstr_pool_size
*2*sizeof(BSTR
));
255 ctx
->code
->bstr_pool
= new_pool
;
256 ctx
->code
->bstr_pool_size
*= 2;
259 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocString(str
);
260 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
263 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
266 static HRESULT
push_instr_bstr(compile_ctx_t
*ctx
, vbsop_t op
, const WCHAR
*arg
)
271 bstr
= alloc_bstr_arg(ctx
, arg
);
273 return E_OUTOFMEMORY
;
275 instr
= push_instr(ctx
, op
);
277 return E_OUTOFMEMORY
;
279 instr_ptr(ctx
, instr
)->arg1
.bstr
= bstr
;
283 static HRESULT
push_instr_bstr_uint(compile_ctx_t
*ctx
, vbsop_t op
, const WCHAR
*arg1
, unsigned arg2
)
288 bstr
= alloc_bstr_arg(ctx
, arg1
);
290 return E_OUTOFMEMORY
;
292 instr
= push_instr(ctx
, op
);
294 return E_OUTOFMEMORY
;
296 instr_ptr(ctx
, instr
)->arg1
.bstr
= bstr
;
297 instr_ptr(ctx
, instr
)->arg2
.uint
= arg2
;
301 static HRESULT
push_instr_uint_bstr(compile_ctx_t
*ctx
, vbsop_t op
, unsigned arg1
, const WCHAR
*arg2
)
306 bstr
= alloc_bstr_arg(ctx
, arg2
);
308 return E_OUTOFMEMORY
;
310 instr
= push_instr(ctx
, op
);
312 return E_OUTOFMEMORY
;
314 instr_ptr(ctx
, instr
)->arg1
.uint
= arg1
;
315 instr_ptr(ctx
, instr
)->arg2
.bstr
= bstr
;
319 #define LABEL_FLAG 0x80000000
321 static unsigned alloc_label(compile_ctx_t
*ctx
)
323 if(!ctx
->labels_size
) {
324 ctx
->labels
= heap_alloc(8 * sizeof(*ctx
->labels
));
327 ctx
->labels_size
= 8;
328 }else if(ctx
->labels_size
== ctx
->labels_cnt
) {
329 unsigned *new_labels
;
331 new_labels
= heap_realloc(ctx
->labels
, 2*ctx
->labels_size
*sizeof(*ctx
->labels
));
335 ctx
->labels
= new_labels
;
336 ctx
->labels_size
*= 2;
339 return ctx
->labels_cnt
++ | LABEL_FLAG
;
342 static inline void label_set_addr(compile_ctx_t
*ctx
, unsigned label
)
344 assert(label
& LABEL_FLAG
);
345 ctx
->labels
[label
& ~LABEL_FLAG
] = ctx
->instr_cnt
;
348 static expression_t
*lookup_const_decls(compile_ctx_t
*ctx
, const WCHAR
*name
, BOOL lookup_global
)
352 for(decl
= ctx
->const_decls
; decl
; decl
= decl
->next
) {
353 if(!strcmpiW(decl
->name
, name
))
354 return decl
->value_expr
;
360 for(decl
= ctx
->global_consts
; decl
; decl
= decl
->next
) {
361 if(!strcmpiW(decl
->name
, name
))
362 return decl
->value_expr
;
368 static HRESULT
compile_args(compile_ctx_t
*ctx
, expression_t
*args
, unsigned *ret
)
370 unsigned arg_cnt
= 0;
374 hres
= compile_expression(ctx
, args
);
386 static HRESULT
compile_member_expression(compile_ctx_t
*ctx
, member_expression_t
*expr
, BOOL ret_val
)
388 unsigned arg_cnt
= 0;
391 if(ret_val
&& !expr
->args
) {
392 expression_t
*const_expr
;
394 const_expr
= lookup_const_decls(ctx
, expr
->identifier
, TRUE
);
396 return compile_expression(ctx
, const_expr
);
399 hres
= compile_args(ctx
, expr
->args
, &arg_cnt
);
404 hres
= compile_expression(ctx
, expr
->obj_expr
);
408 hres
= push_instr_bstr_uint(ctx
, ret_val
? OP_mcall
: OP_mcallv
, expr
->identifier
, arg_cnt
);
410 hres
= push_instr_bstr_uint(ctx
, ret_val
? OP_icall
: OP_icallv
, expr
->identifier
, arg_cnt
);
416 static HRESULT
compile_unary_expression(compile_ctx_t
*ctx
, unary_expression_t
*expr
, vbsop_t op
)
420 hres
= compile_expression(ctx
, expr
->subexpr
);
424 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
427 static HRESULT
compile_binary_expression(compile_ctx_t
*ctx
, binary_expression_t
*expr
, vbsop_t op
)
431 hres
= compile_expression(ctx
, expr
->left
);
435 hres
= compile_expression(ctx
, expr
->right
);
439 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
442 static HRESULT
compile_expression(compile_ctx_t
*ctx
, expression_t
*expr
)
446 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
448 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
450 return push_instr_int(ctx
, OP_bool
, ((bool_expression_t
*)expr
)->value
);
452 return compile_expression(ctx
, ((unary_expression_t
*)expr
)->subexpr
);
454 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_concat
);
456 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
458 return push_instr_double(ctx
, OP_double
, ((double_expression_t
*)expr
)->value
);
460 return push_instr(ctx
, OP_empty
) ? S_OK
: E_OUTOFMEMORY
;
462 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_equal
);
464 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eqv
);
466 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_exp
);
468 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gt
);
470 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gteq
);
472 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_idiv
);
474 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_is
);
476 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_imp
);
478 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lt
);
480 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lteq
);
482 return push_instr(ctx
, OP_me
) ? S_OK
: E_OUTOFMEMORY
;
484 return compile_member_expression(ctx
, (member_expression_t
*)expr
, TRUE
);
486 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
488 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
490 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_neg
);
492 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_nequal
);
494 return push_instr_str(ctx
, OP_new
, ((string_expression_t
*)expr
)->value
);
496 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_not
);
498 return push_instr(ctx
, OP_nothing
) ? S_OK
: E_OUTOFMEMORY
;
500 return push_instr(ctx
, OP_null
) ? S_OK
: E_OUTOFMEMORY
;
502 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
504 return push_instr_str(ctx
, OP_string
, ((string_expression_t
*)expr
)->value
);
506 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
508 return push_instr_int(ctx
, OP_short
, ((int_expression_t
*)expr
)->value
);
510 return push_instr_int(ctx
, OP_long
, ((int_expression_t
*)expr
)->value
);
512 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
514 FIXME("Unimplemented expression type %d\n", expr
->type
);
521 static HRESULT
compile_if_statement(compile_ctx_t
*ctx
, if_statement_t
*stat
)
523 unsigned cnd_jmp
, endif_label
= 0;
524 elseif_decl_t
*elseif_decl
;
527 hres
= compile_expression(ctx
, stat
->expr
);
531 cnd_jmp
= push_instr(ctx
, OP_jmp_false
);
533 return E_OUTOFMEMORY
;
535 hres
= compile_statement(ctx
, NULL
, stat
->if_stat
);
539 if(stat
->else_stat
|| stat
->elseifs
) {
540 endif_label
= alloc_label(ctx
);
542 return E_OUTOFMEMORY
;
544 hres
= push_instr_addr(ctx
, OP_jmp
, endif_label
);
549 for(elseif_decl
= stat
->elseifs
; elseif_decl
; elseif_decl
= elseif_decl
->next
) {
550 instr_ptr(ctx
, cnd_jmp
)->arg1
.uint
= ctx
->instr_cnt
;
552 hres
= compile_expression(ctx
, elseif_decl
->expr
);
556 cnd_jmp
= push_instr(ctx
, OP_jmp_false
);
558 return E_OUTOFMEMORY
;
560 hres
= compile_statement(ctx
, NULL
, elseif_decl
->stat
);
564 hres
= push_instr_addr(ctx
, OP_jmp
, endif_label
);
569 instr_ptr(ctx
, cnd_jmp
)->arg1
.uint
= ctx
->instr_cnt
;
571 if(stat
->else_stat
) {
572 hres
= compile_statement(ctx
, NULL
, stat
->else_stat
);
578 label_set_addr(ctx
, endif_label
);
582 static HRESULT
compile_while_statement(compile_ctx_t
*ctx
, while_statement_t
*stat
)
584 statement_ctx_t stat_ctx
= {0}, *loop_ctx
;
589 start_addr
= ctx
->instr_cnt
;
591 hres
= compile_expression(ctx
, stat
->expr
);
595 jmp_end
= push_instr(ctx
, stat
->stat
.type
== STAT_UNTIL
? OP_jmp_true
: OP_jmp_false
);
597 return E_OUTOFMEMORY
;
599 if(stat
->stat
.type
== STAT_WHILE
) {
602 if(!(stat_ctx
.while_end_label
= alloc_label(ctx
)))
603 return E_OUTOFMEMORY
;
604 loop_ctx
= &stat_ctx
;
607 hres
= compile_statement(ctx
, loop_ctx
, stat
->body
);
611 hres
= push_instr_addr(ctx
, OP_jmp
, start_addr
);
615 instr_ptr(ctx
, jmp_end
)->arg1
.uint
= ctx
->instr_cnt
;
618 label_set_addr(ctx
, stat_ctx
.while_end_label
);
623 static HRESULT
compile_dowhile_statement(compile_ctx_t
*ctx
, while_statement_t
*stat
)
625 statement_ctx_t loop_ctx
= {0};
630 start_addr
= ctx
->instr_cnt
;
632 if(!(loop_ctx
.while_end_label
= alloc_label(ctx
)))
633 return E_OUTOFMEMORY
;
635 hres
= compile_statement(ctx
, &loop_ctx
, stat
->body
);
640 hres
= compile_expression(ctx
, stat
->expr
);
644 jmp_op
= stat
->stat
.type
== STAT_DOUNTIL
? OP_jmp_false
: OP_jmp_true
;
649 hres
= push_instr_addr(ctx
, jmp_op
, start_addr
);
653 label_set_addr(ctx
, loop_ctx
.while_end_label
);
657 static HRESULT
compile_foreach_statement(compile_ctx_t
*ctx
, foreach_statement_t
*stat
)
659 statement_ctx_t loop_ctx
= {1};
663 hres
= compile_expression(ctx
, stat
->group_expr
);
667 if(!push_instr(ctx
, OP_newenum
))
668 return E_OUTOFMEMORY
;
670 loop_start
= ctx
->instr_cnt
;
671 if(!(loop_ctx
.for_end_label
= alloc_label(ctx
)))
672 return E_OUTOFMEMORY
;
674 hres
= push_instr_uint_bstr(ctx
, OP_enumnext
, loop_ctx
.for_end_label
, stat
->identifier
);
678 hres
= compile_statement(ctx
, &loop_ctx
, stat
->body
);
682 hres
= push_instr_addr(ctx
, OP_jmp
, loop_start
);
686 label_set_addr(ctx
, loop_ctx
.for_end_label
);
690 static HRESULT
compile_forto_statement(compile_ctx_t
*ctx
, forto_statement_t
*stat
)
692 statement_ctx_t loop_ctx
= {2};
693 unsigned step_instr
, instr
;
697 identifier
= alloc_bstr_arg(ctx
, stat
->identifier
);
699 return E_OUTOFMEMORY
;
701 hres
= compile_expression(ctx
, stat
->from_expr
);
705 instr
= push_instr(ctx
, OP_assign_ident
);
707 return E_OUTOFMEMORY
;
708 instr_ptr(ctx
, instr
)->arg1
.bstr
= identifier
;
709 instr_ptr(ctx
, instr
)->arg2
.uint
= 0;
711 hres
= compile_expression(ctx
, stat
->to_expr
);
715 if(!push_instr(ctx
, OP_val
))
716 return E_OUTOFMEMORY
;
718 if(stat
->step_expr
) {
719 hres
= compile_expression(ctx
, stat
->step_expr
);
723 if(!push_instr(ctx
, OP_val
))
724 return E_OUTOFMEMORY
;
726 hres
= push_instr_int(ctx
, OP_short
, 1);
731 loop_ctx
.for_end_label
= alloc_label(ctx
);
732 if(!loop_ctx
.for_end_label
)
733 return E_OUTOFMEMORY
;
735 step_instr
= push_instr(ctx
, OP_step
);
737 return E_OUTOFMEMORY
;
738 instr_ptr(ctx
, step_instr
)->arg2
.bstr
= identifier
;
739 instr_ptr(ctx
, step_instr
)->arg1
.uint
= loop_ctx
.for_end_label
;
741 hres
= compile_statement(ctx
, &loop_ctx
, stat
->body
);
745 instr
= push_instr(ctx
, OP_incc
);
747 return E_OUTOFMEMORY
;
748 instr_ptr(ctx
, instr
)->arg1
.bstr
= identifier
;
750 hres
= push_instr_addr(ctx
, OP_jmp
, step_instr
);
754 hres
= push_instr_uint(ctx
, OP_pop
, 2);
758 label_set_addr(ctx
, loop_ctx
.for_end_label
);
762 static HRESULT
compile_select_statement(compile_ctx_t
*ctx
, select_statement_t
*stat
)
764 unsigned end_label
, case_cnt
= 0, *case_labels
= NULL
, i
;
765 case_clausule_t
*case_iter
;
766 expression_t
*expr_iter
;
769 hres
= compile_expression(ctx
, stat
->expr
);
773 if(!push_instr(ctx
, OP_val
))
774 return E_OUTOFMEMORY
;
776 end_label
= alloc_label(ctx
);
778 return E_OUTOFMEMORY
;
780 for(case_iter
= stat
->case_clausules
; case_iter
; case_iter
= case_iter
->next
)
784 case_labels
= heap_alloc(case_cnt
*sizeof(*case_labels
));
786 return E_OUTOFMEMORY
;
789 for(case_iter
= stat
->case_clausules
, i
=0; case_iter
; case_iter
= case_iter
->next
, i
++) {
790 case_labels
[i
] = alloc_label(ctx
);
791 if(!case_labels
[i
]) {
792 hres
= E_OUTOFMEMORY
;
799 for(expr_iter
= case_iter
->expr
; expr_iter
; expr_iter
= expr_iter
->next
) {
800 hres
= compile_expression(ctx
, expr_iter
);
804 hres
= push_instr_addr(ctx
, OP_case
, case_labels
[i
]);
811 heap_free(case_labels
);
815 hres
= push_instr_uint(ctx
, OP_pop
, 1);
817 heap_free(case_labels
);
821 hres
= push_instr_addr(ctx
, OP_jmp
, case_iter
? case_labels
[i
] : end_label
);
823 heap_free(case_labels
);
827 for(case_iter
= stat
->case_clausules
, i
=0; case_iter
; case_iter
= case_iter
->next
, i
++) {
828 label_set_addr(ctx
, case_labels
[i
]);
829 hres
= compile_statement(ctx
, NULL
, case_iter
->stat
);
836 hres
= push_instr_addr(ctx
, OP_jmp
, end_label
);
841 heap_free(case_labels
);
845 label_set_addr(ctx
, end_label
);
849 static HRESULT
compile_assignment(compile_ctx_t
*ctx
, member_expression_t
*member_expr
, expression_t
*value_expr
, BOOL is_set
)
855 if(member_expr
->obj_expr
) {
856 hres
= compile_expression(ctx
, member_expr
->obj_expr
);
860 op
= is_set
? OP_set_member
: OP_assign_member
;
862 op
= is_set
? OP_set_ident
: OP_assign_ident
;
865 hres
= compile_expression(ctx
, value_expr
);
869 hres
= compile_args(ctx
, member_expr
->args
, &args_cnt
);
873 return push_instr_bstr_uint(ctx
, op
, member_expr
->identifier
, args_cnt
);
876 static HRESULT
compile_assign_statement(compile_ctx_t
*ctx
, assign_statement_t
*stat
, BOOL is_set
)
878 return compile_assignment(ctx
, stat
->member_expr
, stat
->value_expr
, is_set
);
881 static HRESULT
compile_call_statement(compile_ctx_t
*ctx
, call_statement_t
*stat
)
883 /* It's challenging for parser to distinguish parameterized assignment with one argument from call
884 * with equality expression argument, so we do it in compiler. */
885 if(!stat
->is_strict
&& stat
->expr
->args
&& !stat
->expr
->args
->next
&& stat
->expr
->args
->type
== EXPR_EQUAL
) {
886 binary_expression_t
*eqexpr
= (binary_expression_t
*)stat
->expr
->args
;
888 if(eqexpr
->left
->type
== EXPR_BRACKETS
) {
889 member_expression_t new_member
= *stat
->expr
;
891 WARN("converting call expr to assign expr\n");
893 new_member
.args
= ((unary_expression_t
*)eqexpr
->left
)->subexpr
;
894 return compile_assignment(ctx
, &new_member
, eqexpr
->right
, FALSE
);
898 return compile_member_expression(ctx
, stat
->expr
, FALSE
);
901 static BOOL
lookup_dim_decls(compile_ctx_t
*ctx
, const WCHAR
*name
)
903 dim_decl_t
*dim_decl
;
905 for(dim_decl
= ctx
->dim_decls
; dim_decl
; dim_decl
= dim_decl
->next
) {
906 if(!strcmpiW(dim_decl
->name
, name
))
913 static BOOL
lookup_args_name(compile_ctx_t
*ctx
, const WCHAR
*name
)
917 for(i
= 0; i
< ctx
->func
->arg_cnt
; i
++) {
918 if(!strcmpiW(ctx
->func
->args
[i
].name
, name
))
925 static HRESULT
compile_dim_statement(compile_ctx_t
*ctx
, dim_statement_t
*stat
)
927 dim_decl_t
*dim_decl
= stat
->dim_decls
;
930 if(lookup_dim_decls(ctx
, dim_decl
->name
) || lookup_args_name(ctx
, dim_decl
->name
)
931 || lookup_const_decls(ctx
, dim_decl
->name
, FALSE
)) {
932 FIXME("dim %s name redefined\n", debugstr_w(dim_decl
->name
));
936 ctx
->func
->var_cnt
++;
939 dim_decl
= dim_decl
->next
;
942 dim_decl
->next
= ctx
->dim_decls
;
943 ctx
->dim_decls
= stat
->dim_decls
;
947 static HRESULT
compile_const_statement(compile_ctx_t
*ctx
, const_statement_t
*stat
)
949 const_decl_t
*decl
, *next_decl
= stat
->decls
;
954 if(lookup_const_decls(ctx
, decl
->name
, FALSE
) || lookup_args_name(ctx
, decl
->name
)
955 || lookup_dim_decls(ctx
, decl
->name
)) {
956 FIXME("%s redefined\n", debugstr_w(decl
->name
));
960 if(ctx
->func
->type
== FUNC_GLOBAL
) {
963 hres
= compile_expression(ctx
, decl
->value_expr
);
967 hres
= push_instr_bstr(ctx
, OP_const
, decl
->name
);
972 next_decl
= decl
->next
;
973 decl
->next
= ctx
->const_decls
;
974 ctx
->const_decls
= decl
;
980 static HRESULT
compile_function_statement(compile_ctx_t
*ctx
, function_statement_t
*stat
)
982 if(ctx
->func
!= &ctx
->code
->main_code
) {
983 FIXME("Function is not in the global code\n");
987 stat
->func_decl
->next
= ctx
->func_decls
;
988 ctx
->func_decls
= stat
->func_decl
;
992 static HRESULT
compile_exitdo_statement(compile_ctx_t
*ctx
)
994 statement_ctx_t
*iter
;
995 unsigned pop_cnt
= 0;
997 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
998 pop_cnt
+= iter
->stack_use
;
999 if(iter
->while_end_label
)
1003 FIXME("Exit Do outside Do Loop\n");
1010 hres
= push_instr_uint(ctx
, OP_pop
, pop_cnt
);
1015 return push_instr_addr(ctx
, OP_jmp
, iter
->while_end_label
);
1018 static HRESULT
compile_exitfor_statement(compile_ctx_t
*ctx
)
1020 statement_ctx_t
*iter
;
1021 unsigned pop_cnt
= 0;
1023 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1024 pop_cnt
+= iter
->stack_use
;
1025 if(iter
->for_end_label
)
1029 FIXME("Exit For outside For loop\n");
1036 hres
= push_instr_uint(ctx
, OP_pop
, pop_cnt
);
1041 return push_instr_addr(ctx
, OP_jmp
, iter
->for_end_label
);
1044 static HRESULT
exit_label(compile_ctx_t
*ctx
, unsigned jmp_label
)
1046 statement_ctx_t
*iter
;
1047 unsigned pop_cnt
= 0;
1049 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
)
1050 pop_cnt
+= iter
->stack_use
;
1055 hres
= push_instr_uint(ctx
, OP_pop
, pop_cnt
);
1060 return push_instr_addr(ctx
, OP_jmp
, jmp_label
);
1063 static HRESULT
compile_exitsub_statement(compile_ctx_t
*ctx
)
1065 if(!ctx
->sub_end_label
) {
1066 FIXME("Exit Sub outside Sub?\n");
1070 return exit_label(ctx
, ctx
->sub_end_label
);
1073 static HRESULT
compile_exitfunc_statement(compile_ctx_t
*ctx
)
1075 if(!ctx
->func_end_label
) {
1076 FIXME("Exit Function outside Function?\n");
1080 return exit_label(ctx
, ctx
->func_end_label
);
1083 static HRESULT
compile_exitprop_statement(compile_ctx_t
*ctx
)
1085 if(!ctx
->prop_end_label
) {
1086 FIXME("Exit Property outside Property?\n");
1090 return exit_label(ctx
, ctx
->prop_end_label
);
1093 static HRESULT
compile_onerror_statement(compile_ctx_t
*ctx
, onerror_statement_t
*stat
)
1095 return push_instr_int(ctx
, OP_errmode
, stat
->resume_next
);
1098 static HRESULT
compile_statement(compile_ctx_t
*ctx
, statement_ctx_t
*stat_ctx
, statement_t
*stat
)
1103 stat_ctx
->next
= ctx
->stat_ctx
;
1104 ctx
->stat_ctx
= stat_ctx
;
1108 switch(stat
->type
) {
1110 hres
= compile_assign_statement(ctx
, (assign_statement_t
*)stat
, FALSE
);
1113 hres
= compile_call_statement(ctx
, (call_statement_t
*)stat
);
1116 hres
= compile_const_statement(ctx
, (const_statement_t
*)stat
);
1119 hres
= compile_dim_statement(ctx
, (dim_statement_t
*)stat
);
1123 hres
= compile_dowhile_statement(ctx
, (while_statement_t
*)stat
);
1126 hres
= compile_exitdo_statement(ctx
);
1129 hres
= compile_exitfor_statement(ctx
);
1132 hres
= compile_exitfunc_statement(ctx
);
1135 hres
= compile_exitprop_statement(ctx
);
1138 hres
= compile_exitsub_statement(ctx
);
1141 hres
= compile_foreach_statement(ctx
, (foreach_statement_t
*)stat
);
1144 hres
= compile_forto_statement(ctx
, (forto_statement_t
*)stat
);
1147 hres
= compile_function_statement(ctx
, (function_statement_t
*)stat
);
1150 hres
= compile_if_statement(ctx
, (if_statement_t
*)stat
);
1153 hres
= compile_onerror_statement(ctx
, (onerror_statement_t
*)stat
);
1156 hres
= compile_select_statement(ctx
, (select_statement_t
*)stat
);
1159 hres
= compile_assign_statement(ctx
, (assign_statement_t
*)stat
, TRUE
);
1162 hres
= push_instr(ctx
, OP_stop
) ? S_OK
: E_OUTOFMEMORY
;
1166 case STAT_WHILELOOP
:
1167 hres
= compile_while_statement(ctx
, (while_statement_t
*)stat
);
1170 FIXME("Unimplemented statement type %d\n", stat
->type
);
1180 assert(ctx
->stat_ctx
== stat_ctx
);
1181 ctx
->stat_ctx
= stat_ctx
->next
;
1187 static void resolve_labels(compile_ctx_t
*ctx
, unsigned off
)
1191 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->instr_cnt
; instr
++) {
1192 if(instr_info
[instr
->op
].arg1_type
== ARG_ADDR
&& (instr
->arg1
.uint
& LABEL_FLAG
)) {
1193 assert((instr
->arg1
.uint
& ~LABEL_FLAG
) < ctx
->labels_cnt
);
1194 instr
->arg1
.uint
= ctx
->labels
[instr
->arg1
.uint
& ~LABEL_FLAG
];
1196 assert(instr_info
[instr
->op
].arg2_type
!= ARG_ADDR
);
1199 ctx
->labels_cnt
= 0;
1202 static HRESULT
compile_func(compile_ctx_t
*ctx
, statement_t
*stat
, function_t
*func
)
1206 func
->code_off
= ctx
->instr_cnt
;
1208 ctx
->sub_end_label
= 0;
1209 ctx
->func_end_label
= 0;
1210 ctx
->prop_end_label
= 0;
1212 switch(func
->type
) {
1214 ctx
->func_end_label
= alloc_label(ctx
);
1215 if(!ctx
->func_end_label
)
1216 return E_OUTOFMEMORY
;
1219 ctx
->sub_end_label
= alloc_label(ctx
);
1220 if(!ctx
->sub_end_label
)
1221 return E_OUTOFMEMORY
;
1227 ctx
->prop_end_label
= alloc_label(ctx
);
1228 if(!ctx
->prop_end_label
)
1229 return E_OUTOFMEMORY
;
1236 ctx
->dim_decls
= NULL
;
1237 ctx
->const_decls
= NULL
;
1238 hres
= compile_statement(ctx
, NULL
, stat
);
1243 if(ctx
->sub_end_label
)
1244 label_set_addr(ctx
, ctx
->sub_end_label
);
1245 if(ctx
->func_end_label
)
1246 label_set_addr(ctx
, ctx
->func_end_label
);
1247 if(ctx
->prop_end_label
)
1248 label_set_addr(ctx
, ctx
->prop_end_label
);
1250 if(!push_instr(ctx
, OP_ret
))
1251 return E_OUTOFMEMORY
;
1253 resolve_labels(ctx
, func
->code_off
);
1256 dim_decl_t
*dim_decl
;
1258 if(func
->type
== FUNC_GLOBAL
) {
1259 dynamic_var_t
*new_var
;
1263 for(dim_decl
= ctx
->dim_decls
; dim_decl
; dim_decl
= dim_decl
->next
) {
1264 new_var
= compiler_alloc(ctx
->code
, sizeof(*new_var
));
1266 return E_OUTOFMEMORY
;
1268 new_var
->name
= compiler_alloc_string(ctx
->code
, dim_decl
->name
);
1270 return E_OUTOFMEMORY
;
1272 V_VT(&new_var
->v
) = VT_EMPTY
;
1273 new_var
->is_const
= FALSE
;
1275 new_var
->next
= ctx
->global_vars
;
1276 ctx
->global_vars
= new_var
;
1281 func
->vars
= compiler_alloc(ctx
->code
, func
->var_cnt
* sizeof(var_desc_t
));
1283 return E_OUTOFMEMORY
;
1285 for(dim_decl
= ctx
->dim_decls
, i
=0; dim_decl
; dim_decl
= dim_decl
->next
, i
++) {
1286 func
->vars
[i
].name
= compiler_alloc_string(ctx
->code
, dim_decl
->name
);
1287 if(!func
->vars
[i
].name
)
1288 return E_OUTOFMEMORY
;
1291 assert(i
== func
->var_cnt
);
1298 static BOOL
lookup_funcs_name(compile_ctx_t
*ctx
, const WCHAR
*name
)
1302 for(iter
= ctx
->funcs
; iter
; iter
= iter
->next
) {
1303 if(!strcmpiW(iter
->name
, name
))
1310 static HRESULT
create_function(compile_ctx_t
*ctx
, function_decl_t
*decl
, function_t
**ret
)
1315 if(lookup_dim_decls(ctx
, decl
->name
) || lookup_funcs_name(ctx
, decl
->name
) || lookup_const_decls(ctx
, decl
->name
, FALSE
)) {
1316 FIXME("%s: redefinition\n", debugstr_w(decl
->name
));
1320 func
= compiler_alloc(ctx
->code
, sizeof(*func
));
1322 return E_OUTOFMEMORY
;
1324 func
->name
= compiler_alloc_string(ctx
->code
, decl
->name
);
1326 return E_OUTOFMEMORY
;
1330 func
->code_ctx
= ctx
->code
;
1331 func
->type
= decl
->type
;
1332 func
->is_public
= decl
->is_public
;
1339 for(arg
= decl
->args
; arg
; arg
= arg
->next
)
1342 func
->args
= compiler_alloc(ctx
->code
, func
->arg_cnt
* sizeof(arg_desc_t
));
1344 return E_OUTOFMEMORY
;
1346 for(i
= 0, arg
= decl
->args
; arg
; arg
= arg
->next
, i
++) {
1347 func
->args
[i
].name
= compiler_alloc_string(ctx
->code
, arg
->name
);
1348 if(!func
->args
[i
].name
)
1349 return E_OUTOFMEMORY
;
1350 func
->args
[i
].by_ref
= arg
->by_ref
;
1356 hres
= compile_func(ctx
, decl
->body
, func
);
1364 static BOOL
lookup_class_name(compile_ctx_t
*ctx
, const WCHAR
*name
)
1368 for(iter
= ctx
->classes
; iter
; iter
= iter
->next
) {
1369 if(!strcmpiW(iter
->name
, name
))
1376 static HRESULT
create_class_funcprop(compile_ctx_t
*ctx
, function_decl_t
*func_decl
, vbdisp_funcprop_desc_t
*desc
)
1378 vbdisp_invoke_type_t invoke_type
;
1379 function_decl_t
*funcprop_decl
;
1382 desc
->name
= compiler_alloc_string(ctx
->code
, func_decl
->name
);
1384 return E_OUTOFMEMORY
;
1386 for(funcprop_decl
= func_decl
; funcprop_decl
; funcprop_decl
= funcprop_decl
->next_prop_func
) {
1387 switch(funcprop_decl
->type
) {
1392 invoke_type
= VBDISP_CALLGET
;
1395 invoke_type
= VBDISP_LET
;
1398 invoke_type
= VBDISP_SET
;
1400 DEFAULT_UNREACHABLE
;
1403 assert(!desc
->entries
[invoke_type
]);
1405 if(funcprop_decl
->is_public
)
1406 desc
->is_public
= TRUE
;
1408 hres
= create_function(ctx
, funcprop_decl
, desc
->entries
+invoke_type
);
1416 static BOOL
lookup_class_funcs(class_desc_t
*class_desc
, const WCHAR
*name
)
1420 for(i
=0; i
< class_desc
->func_cnt
; i
++) {
1421 if(class_desc
->funcs
[i
].name
&& !strcmpiW(class_desc
->funcs
[i
].name
, name
))
1428 static HRESULT
compile_class(compile_ctx_t
*ctx
, class_decl_t
*class_decl
)
1430 function_decl_t
*func_decl
, *func_prop_decl
;
1431 class_prop_decl_t
*prop_decl
;
1432 class_desc_t
*class_desc
;
1436 static const WCHAR class_initializeW
[] = {'c','l','a','s','s','_','i','n','i','t','i','a','l','i','z','e',0};
1437 static const WCHAR class_terminateW
[] = {'c','l','a','s','s','_','t','e','r','m','i','n','a','t','e',0};
1439 if(lookup_dim_decls(ctx
, class_decl
->name
) || lookup_funcs_name(ctx
, class_decl
->name
)
1440 || lookup_const_decls(ctx
, class_decl
->name
, FALSE
) || lookup_class_name(ctx
, class_decl
->name
)) {
1441 FIXME("%s: redefinition\n", debugstr_w(class_decl
->name
));
1445 class_desc
= compiler_alloc_zero(ctx
->code
, sizeof(*class_desc
));
1447 return E_OUTOFMEMORY
;
1449 class_desc
->name
= compiler_alloc_string(ctx
->code
, class_decl
->name
);
1450 if(!class_desc
->name
)
1451 return E_OUTOFMEMORY
;
1453 class_desc
->func_cnt
= 1; /* always allocate slot for default getter */
1455 for(func_decl
= class_decl
->funcs
; func_decl
; func_decl
= func_decl
->next
) {
1456 for(func_prop_decl
= func_decl
; func_prop_decl
; func_prop_decl
= func_prop_decl
->next_prop_func
) {
1457 if(func_prop_decl
->type
== FUNC_DEFGET
)
1461 class_desc
->func_cnt
++;
1464 class_desc
->funcs
= compiler_alloc(ctx
->code
, class_desc
->func_cnt
*sizeof(*class_desc
->funcs
));
1465 if(!class_desc
->funcs
)
1466 return E_OUTOFMEMORY
;
1467 memset(class_desc
->funcs
, 0, class_desc
->func_cnt
*sizeof(*class_desc
->funcs
));
1469 for(func_decl
= class_decl
->funcs
, i
=1; func_decl
; func_decl
= func_decl
->next
, i
++) {
1470 for(func_prop_decl
= func_decl
; func_prop_decl
; func_prop_decl
= func_prop_decl
->next_prop_func
) {
1471 if(func_prop_decl
->type
== FUNC_DEFGET
) {
1477 if(!strcmpiW(class_initializeW
, func_decl
->name
)) {
1478 if(func_decl
->type
!= FUNC_SUB
) {
1479 FIXME("class initializer is not sub\n");
1483 class_desc
->class_initialize_id
= i
;
1484 }else if(!strcmpiW(class_terminateW
, func_decl
->name
)) {
1485 if(func_decl
->type
!= FUNC_SUB
) {
1486 FIXME("class terminator is not sub\n");
1490 class_desc
->class_terminate_id
= i
;
1493 hres
= create_class_funcprop(ctx
, func_decl
, class_desc
->funcs
+ (func_prop_decl
? 0 : i
));
1498 for(prop_decl
= class_decl
->props
; prop_decl
; prop_decl
= prop_decl
->next
)
1499 class_desc
->prop_cnt
++;
1501 class_desc
->props
= compiler_alloc(ctx
->code
, class_desc
->prop_cnt
*sizeof(*class_desc
->props
));
1502 if(!class_desc
->props
)
1503 return E_OUTOFMEMORY
;
1505 for(prop_decl
= class_decl
->props
, i
=0; prop_decl
; prop_decl
= prop_decl
->next
, i
++) {
1506 if(lookup_class_funcs(class_desc
, prop_decl
->name
)) {
1507 FIXME("Property %s redefined\n", debugstr_w(prop_decl
->name
));
1511 class_desc
->props
[i
].name
= compiler_alloc_string(ctx
->code
, prop_decl
->name
);
1512 if(!class_desc
->props
[i
].name
)
1513 return E_OUTOFMEMORY
;
1515 class_desc
->props
[i
].is_public
= prop_decl
->is_public
;
1518 class_desc
->next
= ctx
->classes
;
1519 ctx
->classes
= class_desc
;
1523 static BOOL
lookup_script_identifier(script_ctx_t
*script
, const WCHAR
*identifier
)
1525 class_desc_t
*class;
1529 for(var
= script
->global_vars
; var
; var
= var
->next
) {
1530 if(!strcmpiW(var
->name
, identifier
))
1534 for(func
= script
->global_funcs
; func
; func
= func
->next
) {
1535 if(!strcmpiW(func
->name
, identifier
))
1539 for(class = script
->classes
; class; class = class->next
) {
1540 if(!strcmpiW(class->name
, identifier
))
1547 static HRESULT
check_script_collisions(compile_ctx_t
*ctx
, script_ctx_t
*script
)
1549 class_desc_t
*class;
1553 for(var
= ctx
->global_vars
; var
; var
= var
->next
) {
1554 if(lookup_script_identifier(script
, var
->name
)) {
1555 FIXME("%s: redefined\n", debugstr_w(var
->name
));
1560 for(func
= ctx
->funcs
; func
; func
= func
->next
) {
1561 if(lookup_script_identifier(script
, func
->name
)) {
1562 FIXME("%s: redefined\n", debugstr_w(func
->name
));
1567 for(class = ctx
->classes
; class; class = class->next
) {
1568 if(lookup_script_identifier(script
, class->name
)) {
1569 FIXME("%s: redefined\n", debugstr_w(class->name
));
1577 void release_vbscode(vbscode_t
*code
)
1581 list_remove(&code
->entry
);
1583 for(i
=0; i
< code
->bstr_cnt
; i
++)
1584 SysFreeString(code
->bstr_pool
[i
]);
1586 heap_pool_free(&code
->heap
);
1588 heap_free(code
->bstr_pool
);
1589 heap_free(code
->source
);
1590 heap_free(code
->instrs
);
1594 static vbscode_t
*alloc_vbscode(compile_ctx_t
*ctx
, const WCHAR
*source
)
1598 ret
= heap_alloc(sizeof(*ret
));
1602 ret
->source
= heap_strdupW(source
);
1608 ret
->instrs
= heap_alloc(32*sizeof(instr_t
));
1610 release_vbscode(ret
);
1615 ctx
->instr_size
= 32;
1616 heap_pool_init(&ret
->heap
);
1618 ret
->option_explicit
= ctx
->parser
.option_explicit
;
1620 ret
->bstr_pool
= NULL
;
1621 ret
->bstr_pool_size
= 0;
1623 ret
->pending_exec
= FALSE
;
1625 ret
->main_code
.type
= FUNC_GLOBAL
;
1626 ret
->main_code
.name
= NULL
;
1627 ret
->main_code
.code_ctx
= ret
;
1628 ret
->main_code
.vars
= NULL
;
1629 ret
->main_code
.var_cnt
= 0;
1630 ret
->main_code
.arg_cnt
= 0;
1631 ret
->main_code
.args
= NULL
;
1633 list_init(&ret
->entry
);
1637 static void release_compiler(compile_ctx_t
*ctx
)
1639 parser_release(&ctx
->parser
);
1640 heap_free(ctx
->labels
);
1642 release_vbscode(ctx
->code
);
1645 HRESULT
compile_script(script_ctx_t
*script
, const WCHAR
*src
, const WCHAR
*delimiter
, vbscode_t
**ret
)
1647 function_t
*new_func
;
1648 function_decl_t
*func_decl
;
1649 class_decl_t
*class_decl
;
1654 hres
= parse_script(&ctx
.parser
, src
, delimiter
);
1658 code
= ctx
.code
= alloc_vbscode(&ctx
, src
);
1660 return E_OUTOFMEMORY
;
1663 ctx
.func_decls
= NULL
;
1664 ctx
.global_vars
= NULL
;
1665 ctx
.dim_decls
= NULL
;
1668 ctx
.global_consts
= NULL
;
1669 ctx
.stat_ctx
= NULL
;
1670 ctx
.labels_cnt
= ctx
.labels_size
= 0;
1672 hres
= compile_func(&ctx
, ctx
.parser
.stats
, &ctx
.code
->main_code
);
1674 release_compiler(&ctx
);
1678 ctx
.global_consts
= ctx
.const_decls
;
1680 for(func_decl
= ctx
.func_decls
; func_decl
; func_decl
= func_decl
->next
) {
1681 hres
= create_function(&ctx
, func_decl
, &new_func
);
1683 release_compiler(&ctx
);
1687 new_func
->next
= ctx
.funcs
;
1688 ctx
.funcs
= new_func
;
1691 for(class_decl
= ctx
.parser
.class_decls
; class_decl
; class_decl
= class_decl
->next
) {
1692 hres
= compile_class(&ctx
, class_decl
);
1694 release_compiler(&ctx
);
1699 hres
= check_script_collisions(&ctx
, script
);
1701 release_compiler(&ctx
);
1705 if(ctx
.global_vars
) {
1708 for(var
= ctx
.global_vars
; var
->next
; var
= var
->next
);
1710 var
->next
= script
->global_vars
;
1711 script
->global_vars
= ctx
.global_vars
;
1715 for(new_func
= ctx
.funcs
; new_func
->next
; new_func
= new_func
->next
);
1717 new_func
->next
= script
->global_funcs
;
1718 script
->global_funcs
= ctx
.funcs
;
1722 class_desc_t
*class = ctx
.classes
;
1725 class->ctx
= script
;
1728 class = class->next
;
1731 class->next
= script
->classes
;
1732 script
->classes
= ctx
.classes
;
1735 if(TRACE_ON(vbscript_disas
))
1739 release_compiler(&ctx
);
1741 list_add_tail(&script
->code_list
, &code
->entry
);