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
);
41 unsigned while_end_label
;
42 unsigned for_end_label
;
43 unsigned sub_end_label
;
44 unsigned func_end_label
;
45 unsigned prop_end_label
;
47 dim_decl_t
*dim_decls
;
48 dynamic_var_t
*global_vars
;
50 const_decl_t
*const_decls
;
51 const_decl_t
*global_consts
;
55 function_decl_t
*func_decls
;
57 class_desc_t
*classes
;
60 static HRESULT
compile_expression(compile_ctx_t
*,expression_t
*);
61 static HRESULT
compile_statement(compile_ctx_t
*,statement_t
*);
65 instr_arg_type_t arg1_type
;
66 instr_arg_type_t arg2_type
;
68 #define X(n,a,b,c) {#n,b,c},
73 static void dump_instr_arg(instr_arg_type_t type
, instr_arg_t
*arg
)
78 TRACE_(vbscript_disas
)("\t%s", debugstr_w(arg
->str
));
81 TRACE_(vbscript_disas
)("\t%d", arg
->uint
);
85 TRACE_(vbscript_disas
)("\t%u", arg
->uint
);
88 TRACE_(vbscript_disas
)("\t%lf", *arg
->dbl
);
97 static void dump_code(compile_ctx_t
*ctx
)
101 for(instr
= ctx
->code
->instrs
; instr
< ctx
->code
->instrs
+ctx
->instr_cnt
; instr
++) {
102 TRACE_(vbscript_disas
)("%d:\t%s", (int)(instr
-ctx
->code
->instrs
), instr_info
[instr
->op
].op_str
);
103 dump_instr_arg(instr_info
[instr
->op
].arg1_type
, &instr
->arg1
);
104 dump_instr_arg(instr_info
[instr
->op
].arg2_type
, &instr
->arg2
);
105 TRACE_(vbscript_disas
)("\n");
109 static inline void *compiler_alloc(vbscode_t
*vbscode
, size_t size
)
111 return vbsheap_alloc(&vbscode
->heap
, size
);
114 static inline void *compiler_alloc_zero(vbscode_t
*vbscode
, size_t size
)
118 ret
= vbsheap_alloc(&vbscode
->heap
, size
);
120 memset(ret
, 0, size
);
124 static WCHAR
*compiler_alloc_string(vbscode_t
*vbscode
, const WCHAR
*str
)
129 size
= (strlenW(str
)+1)*sizeof(WCHAR
);
130 ret
= compiler_alloc(vbscode
, size
);
132 memcpy(ret
, str
, size
);
136 static inline instr_t
*instr_ptr(compile_ctx_t
*ctx
, unsigned id
)
138 assert(id
< ctx
->instr_cnt
);
139 return ctx
->code
->instrs
+ id
;
142 static unsigned push_instr(compile_ctx_t
*ctx
, vbsop_t op
)
144 assert(ctx
->instr_size
&& ctx
->instr_size
>= ctx
->instr_cnt
);
146 if(ctx
->instr_size
== ctx
->instr_cnt
) {
149 new_instr
= heap_realloc(ctx
->code
->instrs
, ctx
->instr_size
*2*sizeof(instr_t
));
153 ctx
->code
->instrs
= new_instr
;
154 ctx
->instr_size
*= 2;
157 ctx
->code
->instrs
[ctx
->instr_cnt
].op
= op
;
158 return ctx
->instr_cnt
++;
161 static HRESULT
push_instr_int(compile_ctx_t
*ctx
, vbsop_t op
, LONG arg
)
165 ret
= push_instr(ctx
, op
);
167 return E_OUTOFMEMORY
;
169 instr_ptr(ctx
, ret
)->arg1
.lng
= arg
;
173 static HRESULT
push_instr_uint(compile_ctx_t
*ctx
, vbsop_t op
, unsigned arg
)
177 ret
= push_instr(ctx
, op
);
179 return E_OUTOFMEMORY
;
181 instr_ptr(ctx
, ret
)->arg1
.uint
= arg
;
185 static HRESULT
push_instr_addr(compile_ctx_t
*ctx
, vbsop_t op
, unsigned arg
)
189 ret
= push_instr(ctx
, op
);
191 return E_OUTOFMEMORY
;
193 instr_ptr(ctx
, ret
)->arg1
.uint
= arg
;
197 static HRESULT
push_instr_str(compile_ctx_t
*ctx
, vbsop_t op
, const WCHAR
*arg
)
202 str
= compiler_alloc_string(ctx
->code
, arg
);
204 return E_OUTOFMEMORY
;
206 instr
= push_instr(ctx
, op
);
208 return E_OUTOFMEMORY
;
210 instr_ptr(ctx
, instr
)->arg1
.str
= str
;
214 static HRESULT
push_instr_double(compile_ctx_t
*ctx
, vbsop_t op
, double arg
)
219 d
= compiler_alloc(ctx
->code
, sizeof(double));
221 return E_OUTOFMEMORY
;
223 instr
= push_instr(ctx
, op
);
225 return E_OUTOFMEMORY
;
228 instr_ptr(ctx
, instr
)->arg1
.dbl
= d
;
232 static BSTR
alloc_bstr_arg(compile_ctx_t
*ctx
, const WCHAR
*str
)
234 if(!ctx
->code
->bstr_pool_size
) {
235 ctx
->code
->bstr_pool
= heap_alloc(8 * sizeof(BSTR
));
236 if(!ctx
->code
->bstr_pool
)
238 ctx
->code
->bstr_pool_size
= 8;
239 }else if(ctx
->code
->bstr_pool_size
== ctx
->code
->bstr_cnt
) {
242 new_pool
= heap_realloc(ctx
->code
->bstr_pool
, ctx
->code
->bstr_pool_size
*2*sizeof(BSTR
));
246 ctx
->code
->bstr_pool
= new_pool
;
247 ctx
->code
->bstr_pool_size
*= 2;
250 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocString(str
);
251 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
254 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
257 static HRESULT
push_instr_bstr(compile_ctx_t
*ctx
, vbsop_t op
, const WCHAR
*arg
)
262 bstr
= alloc_bstr_arg(ctx
, arg
);
264 return E_OUTOFMEMORY
;
266 instr
= push_instr(ctx
, op
);
268 return E_OUTOFMEMORY
;
270 instr_ptr(ctx
, instr
)->arg1
.bstr
= bstr
;
274 static HRESULT
push_instr_bstr_uint(compile_ctx_t
*ctx
, vbsop_t op
, const WCHAR
*arg1
, unsigned arg2
)
279 bstr
= alloc_bstr_arg(ctx
, arg1
);
281 return E_OUTOFMEMORY
;
283 instr
= push_instr(ctx
, op
);
285 return E_OUTOFMEMORY
;
287 instr_ptr(ctx
, instr
)->arg1
.bstr
= bstr
;
288 instr_ptr(ctx
, instr
)->arg2
.uint
= arg2
;
292 #define LABEL_FLAG 0x80000000
294 static unsigned alloc_label(compile_ctx_t
*ctx
)
296 if(!ctx
->labels_size
) {
297 ctx
->labels
= heap_alloc(8 * sizeof(*ctx
->labels
));
300 ctx
->labels_size
= 8;
301 }else if(ctx
->labels_size
== ctx
->labels_cnt
) {
302 unsigned *new_labels
;
304 new_labels
= heap_realloc(ctx
->labels
, 2*ctx
->labels_size
*sizeof(*ctx
->labels
));
308 ctx
->labels
= new_labels
;
309 ctx
->labels_size
*= 2;
312 return ctx
->labels_cnt
++ | LABEL_FLAG
;
315 static inline void label_set_addr(compile_ctx_t
*ctx
, unsigned label
)
317 assert(label
& LABEL_FLAG
);
318 ctx
->labels
[label
& ~LABEL_FLAG
] = ctx
->instr_cnt
;
321 static expression_t
*lookup_const_decls(compile_ctx_t
*ctx
, const WCHAR
*name
, BOOL lookup_global
)
325 for(decl
= ctx
->const_decls
; decl
; decl
= decl
->next
) {
326 if(!strcmpiW(decl
->name
, name
))
327 return decl
->value_expr
;
333 for(decl
= ctx
->global_consts
; decl
; decl
= decl
->next
) {
334 if(!strcmpiW(decl
->name
, name
))
335 return decl
->value_expr
;
341 static HRESULT
compile_args(compile_ctx_t
*ctx
, expression_t
*args
, unsigned *ret
)
343 unsigned arg_cnt
= 0;
347 hres
= compile_expression(ctx
, args
);
359 static HRESULT
compile_member_expression(compile_ctx_t
*ctx
, member_expression_t
*expr
, BOOL ret_val
)
361 unsigned arg_cnt
= 0;
364 if(ret_val
&& !expr
->args
) {
365 expression_t
*const_expr
;
367 const_expr
= lookup_const_decls(ctx
, expr
->identifier
, TRUE
);
369 return compile_expression(ctx
, const_expr
);
372 hres
= compile_args(ctx
, expr
->args
, &arg_cnt
);
377 hres
= compile_expression(ctx
, expr
->obj_expr
);
381 hres
= push_instr_bstr_uint(ctx
, ret_val
? OP_mcall
: OP_mcallv
, expr
->identifier
, arg_cnt
);
383 hres
= push_instr_bstr_uint(ctx
, ret_val
? OP_icall
: OP_icallv
, expr
->identifier
, arg_cnt
);
389 static HRESULT
compile_unary_expression(compile_ctx_t
*ctx
, unary_expression_t
*expr
, vbsop_t op
)
393 hres
= compile_expression(ctx
, expr
->subexpr
);
397 return push_instr(ctx
, op
) == -1 ? E_OUTOFMEMORY
: S_OK
;
400 static HRESULT
compile_binary_expression(compile_ctx_t
*ctx
, binary_expression_t
*expr
, vbsop_t op
)
404 hres
= compile_expression(ctx
, expr
->left
);
408 hres
= compile_expression(ctx
, expr
->right
);
412 return push_instr(ctx
, op
) == -1 ? E_OUTOFMEMORY
: S_OK
;
415 static HRESULT
compile_expression(compile_ctx_t
*ctx
, expression_t
*expr
)
419 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
421 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
423 return push_instr_int(ctx
, OP_bool
, ((bool_expression_t
*)expr
)->value
);
425 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_concat
);
427 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
429 return push_instr_double(ctx
, OP_double
, ((double_expression_t
*)expr
)->value
);
431 return push_instr(ctx
, OP_empty
) != -1 ? S_OK
: E_OUTOFMEMORY
;
433 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_equal
);
435 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eqv
);
437 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_exp
);
439 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gt
);
441 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gteq
);
443 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_idiv
);
445 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_is
);
447 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_imp
);
449 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lt
);
451 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lteq
);
453 return push_instr(ctx
, OP_me
) != -1 ? S_OK
: E_OUTOFMEMORY
;
455 return compile_member_expression(ctx
, (member_expression_t
*)expr
, TRUE
);
457 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
459 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
461 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_neg
);
463 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_nequal
);
465 return push_instr_str(ctx
, OP_new
, ((string_expression_t
*)expr
)->value
);
467 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_not
);
469 return push_instr(ctx
, OP_nothing
) != -1 ? S_OK
: E_OUTOFMEMORY
;
471 return push_instr(ctx
, OP_null
) != -1 ? S_OK
: E_OUTOFMEMORY
;
473 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
475 return push_instr_str(ctx
, OP_string
, ((string_expression_t
*)expr
)->value
);
477 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
479 return push_instr_int(ctx
, OP_short
, ((int_expression_t
*)expr
)->value
);
481 return push_instr_int(ctx
, OP_long
, ((int_expression_t
*)expr
)->value
);
483 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
485 FIXME("Unimplemented expression type %d\n", expr
->type
);
492 static HRESULT
compile_if_statement(compile_ctx_t
*ctx
, if_statement_t
*stat
)
494 unsigned cnd_jmp
, endif_label
= -1;
495 elseif_decl_t
*elseif_decl
;
498 hres
= compile_expression(ctx
, stat
->expr
);
502 cnd_jmp
= push_instr(ctx
, OP_jmp_false
);
504 return E_OUTOFMEMORY
;
506 hres
= compile_statement(ctx
, stat
->if_stat
);
510 if(stat
->else_stat
|| stat
->elseifs
) {
511 endif_label
= alloc_label(ctx
);
512 if(endif_label
== -1)
513 return E_OUTOFMEMORY
;
515 hres
= push_instr_addr(ctx
, OP_jmp
, endif_label
);
520 for(elseif_decl
= stat
->elseifs
; elseif_decl
; elseif_decl
= elseif_decl
->next
) {
521 instr_ptr(ctx
, cnd_jmp
)->arg1
.uint
= ctx
->instr_cnt
;
523 hres
= compile_expression(ctx
, elseif_decl
->expr
);
527 cnd_jmp
= push_instr(ctx
, OP_jmp_false
);
529 return E_OUTOFMEMORY
;
531 hres
= compile_statement(ctx
, elseif_decl
->stat
);
535 hres
= push_instr_addr(ctx
, OP_jmp
, endif_label
);
540 instr_ptr(ctx
, cnd_jmp
)->arg1
.uint
= ctx
->instr_cnt
;
542 if(stat
->else_stat
) {
543 hres
= compile_statement(ctx
, stat
->else_stat
);
548 if(endif_label
!= -1)
549 label_set_addr(ctx
, endif_label
);
553 static HRESULT
compile_while_statement(compile_ctx_t
*ctx
, while_statement_t
*stat
)
555 unsigned start_addr
, prev_label
;
559 start_addr
= ctx
->instr_cnt
;
561 hres
= compile_expression(ctx
, stat
->expr
);
565 jmp_end
= push_instr(ctx
, stat
->stat
.type
== STAT_UNTIL
? OP_jmp_true
: OP_jmp_false
);
567 return E_OUTOFMEMORY
;
569 prev_label
= ctx
->while_end_label
;
570 if(stat
->stat
.type
!= STAT_WHILE
&& (ctx
->while_end_label
= alloc_label(ctx
)) == -1)
571 return E_OUTOFMEMORY
;
573 hres
= compile_statement(ctx
, stat
->body
);
577 hres
= push_instr_addr(ctx
, OP_jmp
, start_addr
);
581 instr_ptr(ctx
, jmp_end
)->arg1
.uint
= ctx
->instr_cnt
;
583 if(stat
->stat
.type
!= STAT_WHILE
) {
584 label_set_addr(ctx
, ctx
->while_end_label
);
585 ctx
->while_end_label
= prev_label
;
591 static HRESULT
compile_dowhile_statement(compile_ctx_t
*ctx
, while_statement_t
*stat
)
593 unsigned start_addr
, prev_label
;
596 start_addr
= ctx
->instr_cnt
;
598 prev_label
= ctx
->while_end_label
;
599 if((ctx
->while_end_label
= alloc_label(ctx
)) == -1)
600 return E_OUTOFMEMORY
;
602 hres
= compile_statement(ctx
, stat
->body
);
606 hres
= compile_expression(ctx
, stat
->expr
);
610 hres
= push_instr_addr(ctx
, stat
->stat
.type
== STAT_DOUNTIL
? OP_jmp_false
: OP_jmp_true
, start_addr
);
614 label_set_addr(ctx
, ctx
->while_end_label
);
615 ctx
->while_end_label
= prev_label
;
619 static HRESULT
compile_forto_statement(compile_ctx_t
*ctx
, forto_statement_t
*stat
)
621 unsigned step_instr
, instr
, prev_label
;
625 identifier
= alloc_bstr_arg(ctx
, stat
->identifier
);
627 return E_OUTOFMEMORY
;
629 hres
= compile_expression(ctx
, stat
->from_expr
);
633 instr
= push_instr(ctx
, OP_assign_ident
);
635 return E_OUTOFMEMORY
;
636 instr_ptr(ctx
, instr
)->arg1
.bstr
= identifier
;
638 hres
= compile_expression(ctx
, stat
->to_expr
);
642 if(push_instr(ctx
, OP_val
) == -1)
643 return E_OUTOFMEMORY
;
645 if(stat
->step_expr
) {
646 hres
= compile_expression(ctx
, stat
->step_expr
);
650 if(push_instr(ctx
, OP_val
) == -1)
651 return E_OUTOFMEMORY
;
653 hres
= push_instr_int(ctx
, OP_short
, 1);
658 prev_label
= ctx
->for_end_label
;
659 ctx
->for_end_label
= alloc_label(ctx
);
660 if(ctx
->for_end_label
== -1)
661 return E_OUTOFMEMORY
;
663 step_instr
= push_instr(ctx
, OP_step
);
665 return E_OUTOFMEMORY
;
666 instr_ptr(ctx
, step_instr
)->arg2
.bstr
= identifier
;
667 instr_ptr(ctx
, step_instr
)->arg1
.uint
= ctx
->for_end_label
;
669 hres
= compile_statement(ctx
, stat
->body
);
673 instr
= push_instr(ctx
, OP_incc
);
675 return E_OUTOFMEMORY
;
676 instr_ptr(ctx
, instr
)->arg1
.bstr
= identifier
;
678 hres
= push_instr_addr(ctx
, OP_jmp
, step_instr
);
682 label_set_addr(ctx
, ctx
->for_end_label
);
683 ctx
->for_end_label
= prev_label
;
685 return push_instr_uint(ctx
, OP_pop
, 2);
688 static HRESULT
compile_assign_statement(compile_ctx_t
*ctx
, assign_statement_t
*stat
, BOOL is_set
)
692 hres
= compile_expression(ctx
, stat
->value_expr
);
696 if(stat
->member_expr
->args
) {
697 FIXME("arguments support not implemented\n");
701 if(stat
->member_expr
->obj_expr
) {
702 hres
= compile_expression(ctx
, stat
->member_expr
->obj_expr
);
706 hres
= push_instr_bstr(ctx
, is_set
? OP_set_member
: OP_assign_member
, stat
->member_expr
->identifier
);
708 hres
= push_instr_bstr(ctx
, is_set
? OP_set_ident
: OP_assign_ident
, stat
->member_expr
->identifier
);
714 static BOOL
lookup_dim_decls(compile_ctx_t
*ctx
, const WCHAR
*name
)
716 dim_decl_t
*dim_decl
;
718 for(dim_decl
= ctx
->dim_decls
; dim_decl
; dim_decl
= dim_decl
->next
) {
719 if(!strcmpiW(dim_decl
->name
, name
))
726 static BOOL
lookup_args_name(compile_ctx_t
*ctx
, const WCHAR
*name
)
730 for(i
= 0; i
< ctx
->func
->arg_cnt
; i
++) {
731 if(!strcmpiW(ctx
->func
->args
[i
].name
, name
))
738 static HRESULT
compile_dim_statement(compile_ctx_t
*ctx
, dim_statement_t
*stat
)
740 dim_decl_t
*dim_decl
= stat
->dim_decls
;
743 if(lookup_dim_decls(ctx
, dim_decl
->name
) || lookup_args_name(ctx
, dim_decl
->name
)
744 || lookup_const_decls(ctx
, dim_decl
->name
, FALSE
)) {
745 FIXME("dim %s name redefined\n", debugstr_w(dim_decl
->name
));
749 ctx
->func
->var_cnt
++;
752 dim_decl
= dim_decl
->next
;
755 dim_decl
->next
= ctx
->dim_decls
;
756 ctx
->dim_decls
= stat
->dim_decls
;
760 static HRESULT
compile_const_statement(compile_ctx_t
*ctx
, const_statement_t
*stat
)
762 const_decl_t
*decl
, *next_decl
= stat
->decls
;
767 if(lookup_const_decls(ctx
, decl
->name
, FALSE
) || lookup_args_name(ctx
, decl
->name
)
768 || lookup_dim_decls(ctx
, decl
->name
)) {
769 FIXME("%s redefined\n", debugstr_w(decl
->name
));
773 if(ctx
->func
->type
== FUNC_GLOBAL
) {
776 hres
= compile_expression(ctx
, decl
->value_expr
);
780 hres
= push_instr_bstr(ctx
, OP_const
, decl
->name
);
785 next_decl
= decl
->next
;
786 decl
->next
= ctx
->const_decls
;
787 ctx
->const_decls
= decl
;
793 static HRESULT
compile_function_statement(compile_ctx_t
*ctx
, function_statement_t
*stat
)
795 if(ctx
->func
!= &ctx
->code
->global_code
) {
796 FIXME("Function is not in the global code\n");
800 stat
->func_decl
->next
= ctx
->func_decls
;
801 ctx
->func_decls
= stat
->func_decl
;
805 static HRESULT
compile_exitdo_statement(compile_ctx_t
*ctx
)
807 if(ctx
->while_end_label
== -1) {
808 FIXME("Exit Do outside Do Loop\n");
812 return push_instr_addr(ctx
, OP_jmp
, ctx
->while_end_label
);
815 static HRESULT
compile_exitfor_statement(compile_ctx_t
*ctx
)
817 if(ctx
->for_end_label
== -1) {
818 FIXME("Exit For outside For Loop\n");
822 return push_instr_addr(ctx
, OP_jmp
, ctx
->for_end_label
);
825 static HRESULT
compile_exitsub_statement(compile_ctx_t
*ctx
)
827 if(ctx
->sub_end_label
== -1) {
828 FIXME("Exit Sub outside Sub?\n");
832 return push_instr_addr(ctx
, OP_jmp
, ctx
->sub_end_label
);
835 static HRESULT
compile_exitfunc_statement(compile_ctx_t
*ctx
)
837 if(ctx
->func_end_label
== -1) {
838 FIXME("Exit Function outside Function?\n");
842 return push_instr_addr(ctx
, OP_jmp
, ctx
->func_end_label
);
845 static HRESULT
compile_exitprop_statement(compile_ctx_t
*ctx
)
847 if(ctx
->prop_end_label
== -1) {
848 FIXME("Exit Property outside Property?\n");
852 return push_instr_addr(ctx
, OP_jmp
, ctx
->prop_end_label
);
855 static HRESULT
compile_onerror_statement(compile_ctx_t
*ctx
, onerror_statement_t
*stat
)
857 return push_instr_int(ctx
, OP_errmode
, stat
->resume_next
);
860 static HRESULT
compile_statement(compile_ctx_t
*ctx
, statement_t
*stat
)
867 hres
= compile_assign_statement(ctx
, (assign_statement_t
*)stat
, FALSE
);
870 hres
= compile_member_expression(ctx
, ((call_statement_t
*)stat
)->expr
, FALSE
);
873 hres
= compile_const_statement(ctx
, (const_statement_t
*)stat
);
876 hres
= compile_dim_statement(ctx
, (dim_statement_t
*)stat
);
880 hres
= compile_dowhile_statement(ctx
, (while_statement_t
*)stat
);
883 hres
= compile_exitdo_statement(ctx
);
886 hres
= compile_exitfor_statement(ctx
);
889 hres
= compile_exitfunc_statement(ctx
);
892 hres
= compile_exitprop_statement(ctx
);
895 hres
= compile_exitsub_statement(ctx
);
898 hres
= compile_forto_statement(ctx
, (forto_statement_t
*)stat
);
901 hres
= compile_function_statement(ctx
, (function_statement_t
*)stat
);
904 hres
= compile_if_statement(ctx
, (if_statement_t
*)stat
);
907 hres
= compile_onerror_statement(ctx
, (onerror_statement_t
*)stat
);
910 hres
= compile_assign_statement(ctx
, (assign_statement_t
*)stat
, TRUE
);
913 hres
= push_instr(ctx
, OP_stop
) == -1 ? E_OUTOFMEMORY
: S_OK
;
918 hres
= compile_while_statement(ctx
, (while_statement_t
*)stat
);
921 FIXME("Unimplemented statement type %d\n", stat
->type
);
933 static void resolve_labels(compile_ctx_t
*ctx
, unsigned off
)
937 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->instr_cnt
; instr
++) {
938 if(instr_info
[instr
->op
].arg1_type
== ARG_ADDR
&& (instr
->arg1
.uint
& LABEL_FLAG
)) {
939 assert((instr
->arg1
.uint
& ~LABEL_FLAG
) < ctx
->labels_cnt
);
940 instr
->arg1
.uint
= ctx
->labels
[instr
->arg1
.uint
& ~LABEL_FLAG
];
942 assert(instr_info
[instr
->op
].arg2_type
!= ARG_ADDR
);
948 static HRESULT
compile_func(compile_ctx_t
*ctx
, statement_t
*stat
, function_t
*func
)
952 func
->code_off
= ctx
->instr_cnt
;
954 ctx
->while_end_label
= -1;
955 ctx
->for_end_label
= -1;
956 ctx
->sub_end_label
= -1;
957 ctx
->func_end_label
= -1;
958 ctx
->prop_end_label
= -1;
962 ctx
->func_end_label
= alloc_label(ctx
);
963 if(ctx
->func_end_label
== -1)
964 return E_OUTOFMEMORY
; /* FIXME ! */
967 ctx
->sub_end_label
= alloc_label(ctx
);
968 if(ctx
->sub_end_label
== -1)
969 return E_OUTOFMEMORY
;
975 ctx
->prop_end_label
= alloc_label(ctx
);
976 if(ctx
->prop_end_label
== -1)
977 return E_OUTOFMEMORY
;
984 ctx
->dim_decls
= NULL
;
985 ctx
->const_decls
= NULL
;
986 hres
= compile_statement(ctx
, stat
);
991 assert(ctx
->while_end_label
== -1);
992 assert(ctx
->for_end_label
== -1);
994 if(ctx
->sub_end_label
!= -1)
995 label_set_addr(ctx
, ctx
->sub_end_label
);
996 if(ctx
->func_end_label
!= -1)
997 label_set_addr(ctx
, ctx
->func_end_label
);
998 if(ctx
->prop_end_label
!= -1)
999 label_set_addr(ctx
, ctx
->prop_end_label
);
1001 if(push_instr(ctx
, OP_ret
) == -1)
1002 return E_OUTOFMEMORY
;
1004 resolve_labels(ctx
, func
->code_off
);
1007 dim_decl_t
*dim_decl
;
1009 if(func
->type
== FUNC_GLOBAL
) {
1010 dynamic_var_t
*new_var
;
1014 for(dim_decl
= ctx
->dim_decls
; dim_decl
; dim_decl
= dim_decl
->next
) {
1015 new_var
= compiler_alloc(ctx
->code
, sizeof(*new_var
));
1017 return E_OUTOFMEMORY
;
1019 new_var
->name
= compiler_alloc_string(ctx
->code
, dim_decl
->name
);
1021 return E_OUTOFMEMORY
;
1023 V_VT(&new_var
->v
) = VT_EMPTY
;
1024 new_var
->is_const
= FALSE
;
1026 new_var
->next
= ctx
->global_vars
;
1027 ctx
->global_vars
= new_var
;
1032 func
->vars
= compiler_alloc(ctx
->code
, func
->var_cnt
* sizeof(var_desc_t
));
1034 return E_OUTOFMEMORY
;
1036 for(dim_decl
= ctx
->dim_decls
, i
=0; dim_decl
; dim_decl
= dim_decl
->next
, i
++) {
1037 func
->vars
[i
].name
= compiler_alloc_string(ctx
->code
, dim_decl
->name
);
1038 if(!func
->vars
[i
].name
)
1039 return E_OUTOFMEMORY
;
1042 assert(i
== func
->var_cnt
);
1049 static BOOL
lookup_funcs_name(compile_ctx_t
*ctx
, const WCHAR
*name
)
1053 for(iter
= ctx
->funcs
; iter
; iter
= iter
->next
) {
1054 if(!strcmpiW(iter
->name
, name
))
1061 static HRESULT
create_function(compile_ctx_t
*ctx
, function_decl_t
*decl
, function_t
**ret
)
1066 if(lookup_dim_decls(ctx
, decl
->name
) || lookup_funcs_name(ctx
, decl
->name
) || lookup_const_decls(ctx
, decl
->name
, FALSE
)) {
1067 FIXME("%s: redefinition\n", debugstr_w(decl
->name
));
1071 func
= compiler_alloc(ctx
->code
, sizeof(*func
));
1073 return E_OUTOFMEMORY
;
1075 func
->name
= compiler_alloc_string(ctx
->code
, decl
->name
);
1077 return E_OUTOFMEMORY
;
1081 func
->code_ctx
= ctx
->code
;
1082 func
->type
= decl
->type
;
1083 func
->is_public
= decl
->is_public
;
1090 for(arg
= decl
->args
; arg
; arg
= arg
->next
)
1093 func
->args
= compiler_alloc(ctx
->code
, func
->arg_cnt
* sizeof(arg_desc_t
));
1095 return E_OUTOFMEMORY
;
1097 for(i
= 0, arg
= decl
->args
; arg
; arg
= arg
->next
, i
++) {
1098 func
->args
[i
].name
= compiler_alloc_string(ctx
->code
, arg
->name
);
1099 if(!func
->args
[i
].name
)
1100 return E_OUTOFMEMORY
;
1101 func
->args
[i
].by_ref
= arg
->by_ref
;
1107 hres
= compile_func(ctx
, decl
->body
, func
);
1115 static BOOL
lookup_class_name(compile_ctx_t
*ctx
, const WCHAR
*name
)
1119 for(iter
= ctx
->classes
; iter
; iter
= iter
->next
) {
1120 if(!strcmpiW(iter
->name
, name
))
1127 static HRESULT
create_class_funcprop(compile_ctx_t
*ctx
, function_decl_t
*func_decl
, vbdisp_funcprop_desc_t
*desc
)
1129 vbdisp_invoke_type_t invoke_type
;
1130 function_decl_t
*funcprop_decl
;
1133 desc
->name
= compiler_alloc_string(ctx
->code
, func_decl
->name
);
1135 return E_OUTOFMEMORY
;
1137 for(funcprop_decl
= func_decl
; funcprop_decl
; funcprop_decl
= funcprop_decl
->next_prop_func
) {
1138 switch(funcprop_decl
->type
) {
1143 invoke_type
= VBDISP_CALLGET
;
1146 invoke_type
= VBDISP_LET
;
1149 invoke_type
= VBDISP_SET
;
1155 assert(!desc
->entries
[invoke_type
]);
1157 if(funcprop_decl
->is_public
)
1158 desc
->is_public
= TRUE
;
1160 hres
= create_function(ctx
, funcprop_decl
, desc
->entries
+invoke_type
);
1168 static BOOL
lookup_class_funcs(class_desc_t
*class_desc
, const WCHAR
*name
)
1172 for(i
=0; i
< class_desc
->func_cnt
; i
++) {
1173 if(class_desc
->funcs
[i
].name
&& !strcmpiW(class_desc
->funcs
[i
].name
, name
))
1180 static HRESULT
compile_class(compile_ctx_t
*ctx
, class_decl_t
*class_decl
)
1182 function_decl_t
*func_decl
, *func_prop_decl
;
1183 class_prop_decl_t
*prop_decl
;
1184 class_desc_t
*class_desc
;
1188 static const WCHAR class_initializeW
[] = {'c','l','a','s','s','_','i','n','i','t','i','a','l','i','z','e',0};
1189 static const WCHAR class_terminateW
[] = {'c','l','a','s','s','_','t','e','r','m','i','n','a','t','e',0};
1191 if(lookup_dim_decls(ctx
, class_decl
->name
) || lookup_funcs_name(ctx
, class_decl
->name
)
1192 || lookup_const_decls(ctx
, class_decl
->name
, FALSE
) || lookup_class_name(ctx
, class_decl
->name
)) {
1193 FIXME("%s: redefinition\n", debugstr_w(class_decl
->name
));
1197 class_desc
= compiler_alloc_zero(ctx
->code
, sizeof(*class_desc
));
1199 return E_OUTOFMEMORY
;
1201 class_desc
->name
= compiler_alloc_string(ctx
->code
, class_decl
->name
);
1202 if(!class_desc
->name
)
1203 return E_OUTOFMEMORY
;
1205 class_desc
->func_cnt
= 1; /* always allocate slot for default getter */
1207 for(func_decl
= class_decl
->funcs
; func_decl
; func_decl
= func_decl
->next
) {
1208 for(func_prop_decl
= func_decl
; func_prop_decl
; func_prop_decl
= func_prop_decl
->next_prop_func
) {
1209 if(func_prop_decl
->type
== FUNC_DEFGET
)
1213 class_desc
->func_cnt
++;
1216 class_desc
->funcs
= compiler_alloc(ctx
->code
, class_desc
->func_cnt
*sizeof(*class_desc
->funcs
));
1217 if(!class_desc
->funcs
)
1218 return E_OUTOFMEMORY
;
1219 memset(class_desc
->funcs
, 0, class_desc
->func_cnt
*sizeof(*class_desc
->funcs
));
1221 for(func_decl
= class_decl
->funcs
, i
=1; func_decl
; func_decl
= func_decl
->next
, i
++) {
1222 for(func_prop_decl
= func_decl
; func_prop_decl
; func_prop_decl
= func_prop_decl
->next_prop_func
) {
1223 if(func_prop_decl
->type
== FUNC_DEFGET
) {
1229 if(!strcmpiW(class_initializeW
, func_decl
->name
)) {
1230 if(func_decl
->type
!= FUNC_SUB
) {
1231 FIXME("class initializer is not sub\n");
1235 class_desc
->class_initialize_id
= i
;
1236 }else if(!strcmpiW(class_terminateW
, func_decl
->name
)) {
1237 if(func_decl
->type
!= FUNC_SUB
) {
1238 FIXME("class terminator is not sub\n");
1242 class_desc
->class_terminate_id
= i
;
1245 hres
= create_class_funcprop(ctx
, func_decl
, class_desc
->funcs
+ (func_prop_decl
? 0 : i
));
1250 for(prop_decl
= class_decl
->props
; prop_decl
; prop_decl
= prop_decl
->next
)
1251 class_desc
->prop_cnt
++;
1253 class_desc
->props
= compiler_alloc(ctx
->code
, class_desc
->prop_cnt
*sizeof(*class_desc
->props
));
1254 if(!class_desc
->props
)
1255 return E_OUTOFMEMORY
;
1257 for(prop_decl
= class_decl
->props
, i
=0; prop_decl
; prop_decl
= prop_decl
->next
, i
++) {
1258 if(lookup_class_funcs(class_desc
, prop_decl
->name
)) {
1259 FIXME("Property %s redefined\n", debugstr_w(prop_decl
->name
));
1263 class_desc
->props
[i
].name
= compiler_alloc_string(ctx
->code
, prop_decl
->name
);
1264 if(!class_desc
->props
[i
].name
)
1265 return E_OUTOFMEMORY
;
1267 class_desc
->props
[i
].is_public
= prop_decl
->is_public
;
1270 class_desc
->next
= ctx
->classes
;
1271 ctx
->classes
= class_desc
;
1275 static BOOL
lookup_script_identifier(script_ctx_t
*script
, const WCHAR
*identifier
)
1277 class_desc_t
*class;
1281 for(var
= script
->global_vars
; var
; var
= var
->next
) {
1282 if(!strcmpiW(var
->name
, identifier
))
1286 for(func
= script
->global_funcs
; func
; func
= func
->next
) {
1287 if(!strcmpiW(func
->name
, identifier
))
1291 for(class = script
->classes
; class; class = class->next
) {
1292 if(!strcmpiW(class->name
, identifier
))
1299 static HRESULT
check_script_collisions(compile_ctx_t
*ctx
, script_ctx_t
*script
)
1301 class_desc_t
*class;
1305 for(var
= ctx
->global_vars
; var
; var
= var
->next
) {
1306 if(lookup_script_identifier(script
, var
->name
)) {
1307 FIXME("%s: redefined\n", debugstr_w(var
->name
));
1312 for(func
= ctx
->funcs
; func
; func
= func
->next
) {
1313 if(lookup_script_identifier(script
, func
->name
)) {
1314 FIXME("%s: redefined\n", debugstr_w(func
->name
));
1319 for(class = ctx
->classes
; class; class = class->next
) {
1320 if(lookup_script_identifier(script
, class->name
)) {
1321 FIXME("%s: redefined\n", debugstr_w(class->name
));
1329 void release_vbscode(vbscode_t
*code
)
1333 list_remove(&code
->entry
);
1335 for(i
=0; i
< code
->bstr_cnt
; i
++)
1336 SysFreeString(code
->bstr_pool
[i
]);
1338 vbsheap_free(&code
->heap
);
1340 heap_free(code
->bstr_pool
);
1341 heap_free(code
->source
);
1342 heap_free(code
->instrs
);
1346 static vbscode_t
*alloc_vbscode(compile_ctx_t
*ctx
, const WCHAR
*source
)
1350 ret
= heap_alloc(sizeof(*ret
));
1354 ret
->source
= heap_strdupW(source
);
1360 ret
->instrs
= heap_alloc(32*sizeof(instr_t
));
1362 release_vbscode(ret
);
1367 ctx
->instr_size
= 32;
1368 vbsheap_init(&ret
->heap
);
1370 ret
->option_explicit
= ctx
->parser
.option_explicit
;
1372 ret
->bstr_pool
= NULL
;
1373 ret
->bstr_pool_size
= 0;
1375 ret
->global_executed
= FALSE
;
1377 ret
->global_code
.type
= FUNC_GLOBAL
;
1378 ret
->global_code
.name
= NULL
;
1379 ret
->global_code
.code_ctx
= ret
;
1380 ret
->global_code
.vars
= NULL
;
1381 ret
->global_code
.var_cnt
= 0;
1382 ret
->global_code
.arg_cnt
= 0;
1383 ret
->global_code
.args
= NULL
;
1385 list_init(&ret
->entry
);
1389 static void release_compiler(compile_ctx_t
*ctx
)
1391 parser_release(&ctx
->parser
);
1392 heap_free(ctx
->labels
);
1394 release_vbscode(ctx
->code
);
1397 HRESULT
compile_script(script_ctx_t
*script
, const WCHAR
*src
, vbscode_t
**ret
)
1399 function_t
*new_func
;
1400 function_decl_t
*func_decl
;
1401 class_decl_t
*class_decl
;
1406 hres
= parse_script(&ctx
.parser
, src
);
1410 code
= ctx
.code
= alloc_vbscode(&ctx
, src
);
1412 return E_OUTOFMEMORY
;
1415 ctx
.func_decls
= NULL
;
1416 ctx
.global_vars
= NULL
;
1417 ctx
.dim_decls
= NULL
;
1420 ctx
.global_consts
= NULL
;
1421 ctx
.labels_cnt
= ctx
.labels_size
= 0;
1423 hres
= compile_func(&ctx
, ctx
.parser
.stats
, &ctx
.code
->global_code
);
1425 release_compiler(&ctx
);
1429 ctx
.global_consts
= ctx
.const_decls
;
1431 for(func_decl
= ctx
.func_decls
; func_decl
; func_decl
= func_decl
->next
) {
1432 hres
= create_function(&ctx
, func_decl
, &new_func
);
1434 release_compiler(&ctx
);
1438 new_func
->next
= ctx
.funcs
;
1439 ctx
.funcs
= new_func
;
1442 for(class_decl
= ctx
.parser
.class_decls
; class_decl
; class_decl
= class_decl
->next
) {
1443 hres
= compile_class(&ctx
, class_decl
);
1445 release_compiler(&ctx
);
1450 hres
= check_script_collisions(&ctx
, script
);
1452 release_compiler(&ctx
);
1456 if(ctx
.global_vars
) {
1459 for(var
= ctx
.global_vars
; var
->next
; var
= var
->next
);
1461 var
->next
= script
->global_vars
;
1462 script
->global_vars
= ctx
.global_vars
;
1466 for(new_func
= ctx
.funcs
; new_func
->next
; new_func
= new_func
->next
);
1468 new_func
->next
= script
->global_funcs
;
1469 script
->global_funcs
= ctx
.funcs
;
1473 class_desc_t
*class = ctx
.classes
;
1476 class->ctx
= script
;
1479 class = class->next
;
1482 class->next
= script
->classes
;
1483 script
->classes
= ctx
.classes
;
1486 if(TRACE_ON(vbscript_disas
))
1490 release_compiler(&ctx
);
1492 list_add_tail(&script
->code_list
, &code
->entry
);