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
;
35 unsigned with_stack_offset
;
37 struct _statement_ctx_t
*next
;
48 statement_ctx_t
*stat_ctx
;
54 unsigned sub_end_label
;
55 unsigned func_end_label
;
56 unsigned prop_end_label
;
58 dim_decl_t
*dim_decls
;
59 dim_decl_t
*dim_decls_tail
;
61 const_decl_t
*const_decls
;
62 const_decl_t
*global_consts
;
65 function_decl_t
*func_decls
;
68 static HRESULT
compile_expression(compile_ctx_t
*,expression_t
*);
69 static HRESULT
compile_statement(compile_ctx_t
*,statement_ctx_t
*,statement_t
*);
73 instr_arg_type_t arg1_type
;
74 instr_arg_type_t arg2_type
;
76 #define X(n,a,b,c) {#n,b,c},
81 static void dump_instr_arg(instr_arg_type_t type
, instr_arg_t
*arg
)
86 TRACE_(vbscript_disas
)("\t%s", debugstr_w(arg
->str
));
89 TRACE_(vbscript_disas
)("\t%d", arg
->uint
);
93 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
= (lstrlenW(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 ctx
->code
->instrs
[ctx
->instr_cnt
].loc
= ctx
->loc
;
168 return ctx
->instr_cnt
++;
171 static HRESULT
push_instr_int(compile_ctx_t
*ctx
, vbsop_t op
, LONG arg
)
175 ret
= push_instr(ctx
, op
);
177 return E_OUTOFMEMORY
;
179 instr_ptr(ctx
, ret
)->arg1
.lng
= arg
;
183 static HRESULT
push_instr_uint(compile_ctx_t
*ctx
, vbsop_t op
, unsigned arg
)
187 ret
= push_instr(ctx
, op
);
189 return E_OUTOFMEMORY
;
191 instr_ptr(ctx
, ret
)->arg1
.uint
= arg
;
195 static HRESULT
push_instr_addr(compile_ctx_t
*ctx
, vbsop_t op
, unsigned arg
)
199 ret
= push_instr(ctx
, op
);
201 return E_OUTOFMEMORY
;
203 instr_ptr(ctx
, ret
)->arg1
.uint
= arg
;
207 static HRESULT
push_instr_str(compile_ctx_t
*ctx
, vbsop_t op
, const WCHAR
*arg
)
212 str
= compiler_alloc_string(ctx
->code
, arg
);
214 return E_OUTOFMEMORY
;
216 instr
= push_instr(ctx
, op
);
218 return E_OUTOFMEMORY
;
220 instr_ptr(ctx
, instr
)->arg1
.str
= str
;
224 static HRESULT
push_instr_double(compile_ctx_t
*ctx
, vbsop_t op
, double arg
)
229 d
= compiler_alloc(ctx
->code
, sizeof(double));
231 return E_OUTOFMEMORY
;
233 instr
= push_instr(ctx
, op
);
235 return E_OUTOFMEMORY
;
238 instr_ptr(ctx
, instr
)->arg1
.dbl
= d
;
242 static HRESULT
push_instr_date(compile_ctx_t
*ctx
, vbsop_t op
, DATE arg
)
247 d
= compiler_alloc(ctx
->code
, sizeof(DATE
));
249 return E_OUTOFMEMORY
;
251 instr
= push_instr(ctx
, op
);
253 return E_OUTOFMEMORY
;
256 instr_ptr(ctx
, instr
)->arg1
.date
= d
;
260 static BSTR
alloc_bstr_arg(compile_ctx_t
*ctx
, const WCHAR
*str
)
262 if(!ctx
->code
->bstr_pool_size
) {
263 ctx
->code
->bstr_pool
= heap_alloc(8 * sizeof(BSTR
));
264 if(!ctx
->code
->bstr_pool
)
266 ctx
->code
->bstr_pool_size
= 8;
267 }else if(ctx
->code
->bstr_pool_size
== ctx
->code
->bstr_cnt
) {
270 new_pool
= heap_realloc(ctx
->code
->bstr_pool
, ctx
->code
->bstr_pool_size
*2*sizeof(BSTR
));
274 ctx
->code
->bstr_pool
= new_pool
;
275 ctx
->code
->bstr_pool_size
*= 2;
278 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocString(str
);
279 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
282 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
285 static HRESULT
push_instr_bstr(compile_ctx_t
*ctx
, vbsop_t op
, const WCHAR
*arg
)
290 bstr
= alloc_bstr_arg(ctx
, arg
);
292 return E_OUTOFMEMORY
;
294 instr
= push_instr(ctx
, op
);
296 return E_OUTOFMEMORY
;
298 instr_ptr(ctx
, instr
)->arg1
.bstr
= bstr
;
302 static HRESULT
push_instr_bstr_uint(compile_ctx_t
*ctx
, vbsop_t op
, const WCHAR
*arg1
, unsigned arg2
)
307 bstr
= alloc_bstr_arg(ctx
, arg1
);
309 return E_OUTOFMEMORY
;
311 instr
= push_instr(ctx
, op
);
313 return E_OUTOFMEMORY
;
315 instr_ptr(ctx
, instr
)->arg1
.bstr
= bstr
;
316 instr_ptr(ctx
, instr
)->arg2
.uint
= arg2
;
320 static HRESULT
push_instr_uint_bstr(compile_ctx_t
*ctx
, vbsop_t op
, unsigned arg1
, const WCHAR
*arg2
)
325 bstr
= alloc_bstr_arg(ctx
, arg2
);
327 return E_OUTOFMEMORY
;
329 instr
= push_instr(ctx
, op
);
331 return E_OUTOFMEMORY
;
333 instr_ptr(ctx
, instr
)->arg1
.uint
= arg1
;
334 instr_ptr(ctx
, instr
)->arg2
.bstr
= bstr
;
338 #define LABEL_FLAG 0x80000000
340 static unsigned alloc_label(compile_ctx_t
*ctx
)
342 if(!ctx
->labels_size
) {
343 ctx
->labels
= heap_alloc(8 * sizeof(*ctx
->labels
));
346 ctx
->labels_size
= 8;
347 }else if(ctx
->labels_size
== ctx
->labels_cnt
) {
348 unsigned *new_labels
;
350 new_labels
= heap_realloc(ctx
->labels
, 2*ctx
->labels_size
*sizeof(*ctx
->labels
));
354 ctx
->labels
= new_labels
;
355 ctx
->labels_size
*= 2;
358 return ctx
->labels_cnt
++ | LABEL_FLAG
;
361 static inline void label_set_addr(compile_ctx_t
*ctx
, unsigned label
)
363 assert(label
& LABEL_FLAG
);
364 ctx
->labels
[label
& ~LABEL_FLAG
] = ctx
->instr_cnt
;
367 static inline unsigned stack_offset(compile_ctx_t
*ctx
)
369 statement_ctx_t
*iter
;
372 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
)
373 ret
+= iter
->stack_use
;
378 static BOOL
emit_catch_jmp(compile_ctx_t
*ctx
, unsigned stack_off
, unsigned code_off
)
382 code
= push_instr(ctx
, OP_catch
);
386 instr_ptr(ctx
, code
)->arg1
.uint
= code_off
;
387 instr_ptr(ctx
, code
)->arg2
.uint
= stack_off
+ stack_offset(ctx
);
391 static inline BOOL
emit_catch(compile_ctx_t
*ctx
, unsigned off
)
393 return emit_catch_jmp(ctx
, off
, ctx
->instr_cnt
);
396 static HRESULT
compile_error(script_ctx_t
*ctx
, compile_ctx_t
*compiler
, HRESULT error
)
398 if(error
== SCRIPT_E_REPORTED
)
402 ctx
->ei
.scode
= error
= map_hres(error
);
403 ctx
->ei
.bstrSource
= get_vbscript_string(VBS_COMPILE_ERROR
);
404 ctx
->ei
.bstrDescription
= get_vbscript_error_string(error
);
405 return report_script_error(ctx
, compiler
->code
, compiler
->loc
);
408 static expression_t
*lookup_const_decls(compile_ctx_t
*ctx
, const WCHAR
*name
, BOOL lookup_global
)
412 for(decl
= ctx
->const_decls
; decl
; decl
= decl
->next
) {
413 if(!wcsicmp(decl
->name
, name
))
414 return decl
->value_expr
;
420 for(decl
= ctx
->global_consts
; decl
; decl
= decl
->next
) {
421 if(!wcsicmp(decl
->name
, name
))
422 return decl
->value_expr
;
428 static HRESULT
compile_args(compile_ctx_t
*ctx
, expression_t
*args
, unsigned *ret
)
430 unsigned arg_cnt
= 0;
434 hres
= compile_expression(ctx
, args
);
438 if(args
->type
== EXPR_BRACKETS
&& !push_instr(ctx
, OP_deref
))
439 return E_OUTOFMEMORY
;
449 static HRESULT
compile_member_call_expression(compile_ctx_t
*ctx
, member_expression_t
*expr
,
450 unsigned arg_cnt
, BOOL ret_val
)
454 if(ret_val
&& !arg_cnt
) {
455 expression_t
*const_expr
;
457 const_expr
= lookup_const_decls(ctx
, expr
->identifier
, TRUE
);
459 return compile_expression(ctx
, const_expr
);
463 hres
= compile_expression(ctx
, expr
->obj_expr
);
467 hres
= push_instr_bstr_uint(ctx
, ret_val
? OP_mcall
: OP_mcallv
, expr
->identifier
, arg_cnt
);
469 hres
= push_instr_bstr_uint(ctx
, ret_val
? OP_icall
: OP_icallv
, expr
->identifier
, arg_cnt
);
475 static HRESULT
compile_member_expression(compile_ctx_t
*ctx
, member_expression_t
*expr
)
477 expression_t
*const_expr
;
479 if (expr
->obj_expr
) /* FIXME: we should probably have a dedicated opcode as well */
480 return compile_member_call_expression(ctx
, expr
, 0, TRUE
);
482 const_expr
= lookup_const_decls(ctx
, expr
->identifier
, TRUE
);
484 return compile_expression(ctx
, const_expr
);
486 return push_instr_bstr(ctx
, OP_ident
, expr
->identifier
);
489 static HRESULT
compile_call_expression(compile_ctx_t
*ctx
, call_expression_t
*expr
, BOOL ret_val
)
491 unsigned arg_cnt
= 0;
495 hres
= compile_args(ctx
, expr
->args
, &arg_cnt
);
499 for(call
= expr
->call_expr
; call
->type
== EXPR_BRACKETS
; call
= ((unary_expression_t
*)call
)->subexpr
);
501 if(call
->type
== EXPR_MEMBER
)
502 return compile_member_call_expression(ctx
, (member_expression_t
*)call
, arg_cnt
, ret_val
);
504 hres
= compile_expression(ctx
, call
);
508 return push_instr_uint(ctx
, ret_val
? OP_vcall
: OP_vcallv
, arg_cnt
);
511 static HRESULT
compile_dot_expression(compile_ctx_t
*ctx
)
513 statement_ctx_t
*stat_ctx
;
515 for(stat_ctx
= ctx
->stat_ctx
; stat_ctx
; stat_ctx
= stat_ctx
->next
) {
516 if(!stat_ctx
->with_stack_offset
)
519 return push_instr_uint(ctx
, OP_stack
, stat_ctx
->with_stack_offset
- 1);
522 WARN("dot expression outside with statement\n");
523 return push_instr_uint(ctx
, OP_stack
, ~0);
526 static HRESULT
compile_unary_expression(compile_ctx_t
*ctx
, unary_expression_t
*expr
, vbsop_t op
)
530 hres
= compile_expression(ctx
, expr
->subexpr
);
534 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
537 static HRESULT
compile_binary_expression(compile_ctx_t
*ctx
, binary_expression_t
*expr
, vbsop_t op
)
541 hres
= compile_expression(ctx
, expr
->left
);
545 hres
= compile_expression(ctx
, expr
->right
);
549 return push_instr(ctx
, op
) ? S_OK
: E_OUTOFMEMORY
;
552 static HRESULT
compile_expression(compile_ctx_t
*ctx
, expression_t
*expr
)
556 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_add
);
558 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_and
);
560 return push_instr_int(ctx
, OP_bool
, ((bool_expression_t
*)expr
)->value
);
562 return compile_expression(ctx
, ((unary_expression_t
*)expr
)->subexpr
);
564 return compile_call_expression(ctx
, (call_expression_t
*)expr
, TRUE
);
566 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_concat
);
568 return push_instr_date(ctx
, OP_date
, ((date_expression_t
*)expr
)->value
);
570 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_div
);
572 return compile_dot_expression(ctx
);
574 return push_instr_double(ctx
, OP_double
, ((double_expression_t
*)expr
)->value
);
576 return push_instr(ctx
, OP_empty
) ? S_OK
: E_OUTOFMEMORY
;
578 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_equal
);
580 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_eqv
);
582 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_exp
);
584 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gt
);
586 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_gteq
);
588 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_idiv
);
590 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_is
);
592 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_imp
);
594 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lt
);
596 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_lteq
);
598 return push_instr(ctx
, OP_me
) ? S_OK
: E_OUTOFMEMORY
;
600 return compile_member_expression(ctx
, (member_expression_t
*)expr
);
602 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mod
);
604 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_mul
);
606 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_neg
);
608 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_nequal
);
610 return push_instr_str(ctx
, OP_new
, ((string_expression_t
*)expr
)->value
);
612 return push_instr_int(ctx
, OP_hres
, DISP_E_PARAMNOTFOUND
);
614 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_not
);
616 return push_instr(ctx
, OP_nothing
) ? S_OK
: E_OUTOFMEMORY
;
618 return push_instr(ctx
, OP_null
) ? S_OK
: E_OUTOFMEMORY
;
620 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_or
);
622 return push_instr_str(ctx
, OP_string
, ((string_expression_t
*)expr
)->value
);
624 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_sub
);
626 return push_instr_int(ctx
, OP_int
, ((int_expression_t
*)expr
)->value
);
628 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_xor
);
630 FIXME("Unimplemented expression type %d\n", expr
->type
);
637 static HRESULT
compile_if_statement(compile_ctx_t
*ctx
, if_statement_t
*stat
)
639 unsigned cnd_jmp
, endif_label
= 0;
640 elseif_decl_t
*elseif_decl
;
643 hres
= compile_expression(ctx
, stat
->expr
);
647 cnd_jmp
= push_instr(ctx
, OP_jmp_false
);
649 return E_OUTOFMEMORY
;
651 if(!emit_catch(ctx
, 0))
652 return E_OUTOFMEMORY
;
654 hres
= compile_statement(ctx
, NULL
, stat
->if_stat
);
658 if(stat
->else_stat
|| stat
->elseifs
) {
659 endif_label
= alloc_label(ctx
);
661 return E_OUTOFMEMORY
;
663 hres
= push_instr_addr(ctx
, OP_jmp
, endif_label
);
668 for(elseif_decl
= stat
->elseifs
; elseif_decl
; elseif_decl
= elseif_decl
->next
) {
669 instr_ptr(ctx
, cnd_jmp
)->arg1
.uint
= ctx
->instr_cnt
;
671 ctx
->loc
= elseif_decl
->loc
;
673 hres
= compile_expression(ctx
, elseif_decl
->expr
);
677 cnd_jmp
= push_instr(ctx
, OP_jmp_false
);
679 return E_OUTOFMEMORY
;
681 if(!emit_catch(ctx
, 0))
682 return E_OUTOFMEMORY
;
684 hres
= compile_statement(ctx
, NULL
, elseif_decl
->stat
);
688 hres
= push_instr_addr(ctx
, OP_jmp
, endif_label
);
693 instr_ptr(ctx
, cnd_jmp
)->arg1
.uint
= ctx
->instr_cnt
;
695 if(stat
->else_stat
) {
696 hres
= compile_statement(ctx
, NULL
, stat
->else_stat
);
702 label_set_addr(ctx
, endif_label
);
706 static HRESULT
compile_while_statement(compile_ctx_t
*ctx
, while_statement_t
*stat
)
708 statement_ctx_t stat_ctx
= {0}, *loop_ctx
;
713 start_addr
= ctx
->instr_cnt
;
715 hres
= compile_expression(ctx
, stat
->expr
);
719 jmp_end
= push_instr(ctx
, stat
->stat
.type
== STAT_UNTIL
? OP_jmp_true
: OP_jmp_false
);
721 return E_OUTOFMEMORY
;
723 if(!emit_catch(ctx
, 0))
724 return E_OUTOFMEMORY
;
726 if(stat
->stat
.type
== STAT_WHILE
) {
729 if(!(stat_ctx
.while_end_label
= alloc_label(ctx
)))
730 return E_OUTOFMEMORY
;
731 loop_ctx
= &stat_ctx
;
734 hres
= compile_statement(ctx
, loop_ctx
, stat
->body
);
738 hres
= push_instr_addr(ctx
, OP_jmp
, start_addr
);
742 instr_ptr(ctx
, jmp_end
)->arg1
.uint
= ctx
->instr_cnt
;
745 label_set_addr(ctx
, stat_ctx
.while_end_label
);
750 static HRESULT
compile_dowhile_statement(compile_ctx_t
*ctx
, while_statement_t
*stat
)
752 statement_ctx_t loop_ctx
= {0};
757 start_addr
= ctx
->instr_cnt
;
759 if(!(loop_ctx
.while_end_label
= alloc_label(ctx
)))
760 return E_OUTOFMEMORY
;
762 hres
= compile_statement(ctx
, &loop_ctx
, stat
->body
);
766 ctx
->loc
= stat
->stat
.loc
;
768 hres
= compile_expression(ctx
, stat
->expr
);
772 jmp_op
= stat
->stat
.type
== STAT_DOUNTIL
? OP_jmp_false
: OP_jmp_true
;
777 hres
= push_instr_addr(ctx
, jmp_op
, start_addr
);
781 label_set_addr(ctx
, loop_ctx
.while_end_label
);
783 if(!emit_catch(ctx
, 0))
784 return E_OUTOFMEMORY
;
789 static HRESULT
compile_foreach_statement(compile_ctx_t
*ctx
, foreach_statement_t
*stat
)
791 statement_ctx_t loop_ctx
= {1};
795 /* Preserve a place on the stack in case we throw before having proper enum collection. */
796 if(!push_instr(ctx
, OP_empty
))
797 return E_OUTOFMEMORY
;
799 hres
= compile_expression(ctx
, stat
->group_expr
);
803 if(!push_instr(ctx
, OP_newenum
))
804 return E_OUTOFMEMORY
;
806 if(!(loop_ctx
.for_end_label
= alloc_label(ctx
)))
807 return E_OUTOFMEMORY
;
809 hres
= push_instr_uint_bstr(ctx
, OP_enumnext
, loop_ctx
.for_end_label
, stat
->identifier
);
813 if(!emit_catch(ctx
, 1))
814 return E_OUTOFMEMORY
;
816 loop_start
= ctx
->instr_cnt
;
817 hres
= compile_statement(ctx
, &loop_ctx
, stat
->body
);
821 /* We need a separated enumnext here, because we need to jump out of the loop on exception. */
822 ctx
->loc
= stat
->stat
.loc
;
823 hres
= push_instr_uint_bstr(ctx
, OP_enumnext
, loop_ctx
.for_end_label
, stat
->identifier
);
827 hres
= push_instr_addr(ctx
, OP_jmp
, loop_start
);
831 label_set_addr(ctx
, loop_ctx
.for_end_label
);
833 if(!emit_catch(ctx
, 0))
834 return E_OUTOFMEMORY
;
839 static HRESULT
compile_forto_statement(compile_ctx_t
*ctx
, forto_statement_t
*stat
)
841 statement_ctx_t loop_ctx
= {2};
842 unsigned step_instr
, instr
;
846 identifier
= alloc_bstr_arg(ctx
, stat
->identifier
);
848 return E_OUTOFMEMORY
;
850 hres
= compile_expression(ctx
, stat
->from_expr
);
854 /* FIXME: Assign should happen after both expressions evaluation. */
855 instr
= push_instr(ctx
, OP_assign_ident
);
857 return E_OUTOFMEMORY
;
858 instr_ptr(ctx
, instr
)->arg1
.bstr
= identifier
;
859 instr_ptr(ctx
, instr
)->arg2
.uint
= 0;
861 hres
= compile_expression(ctx
, stat
->to_expr
);
865 if(!push_instr(ctx
, OP_val
))
866 return E_OUTOFMEMORY
;
868 if(stat
->step_expr
) {
869 hres
= compile_expression(ctx
, stat
->step_expr
);
873 if(!push_instr(ctx
, OP_val
))
874 return E_OUTOFMEMORY
;
876 hres
= push_instr_int(ctx
, OP_int
, 1);
881 loop_ctx
.for_end_label
= alloc_label(ctx
);
882 if(!loop_ctx
.for_end_label
)
883 return E_OUTOFMEMORY
;
885 step_instr
= push_instr(ctx
, OP_step
);
887 return E_OUTOFMEMORY
;
888 instr_ptr(ctx
, step_instr
)->arg2
.bstr
= identifier
;
889 instr_ptr(ctx
, step_instr
)->arg1
.uint
= loop_ctx
.for_end_label
;
891 if(!emit_catch(ctx
, 2))
892 return E_OUTOFMEMORY
;
894 hres
= compile_statement(ctx
, &loop_ctx
, stat
->body
);
898 /* FIXME: Error handling can't be done compatible with native using OP_incc here. */
899 instr
= push_instr(ctx
, OP_incc
);
901 return E_OUTOFMEMORY
;
902 instr_ptr(ctx
, instr
)->arg1
.bstr
= identifier
;
904 hres
= push_instr_addr(ctx
, OP_jmp
, step_instr
);
908 hres
= push_instr_uint(ctx
, OP_pop
, 2);
912 label_set_addr(ctx
, loop_ctx
.for_end_label
);
914 /* FIXME: reconsider after OP_incc fixup. */
915 if(!emit_catch(ctx
, 0))
916 return E_OUTOFMEMORY
;
921 static HRESULT
compile_with_statement(compile_ctx_t
*ctx
, with_statement_t
*stat
)
923 statement_ctx_t with_ctx
= { 1 };
926 hres
= compile_expression(ctx
, stat
->expr
);
930 if(!emit_catch(ctx
, 1))
931 return E_OUTOFMEMORY
;
933 with_ctx
.with_stack_offset
= stack_offset(ctx
) + 1;
934 hres
= compile_statement(ctx
, &with_ctx
, stat
->body
);
938 return push_instr_uint(ctx
, OP_pop
, 1);
941 static HRESULT
compile_select_statement(compile_ctx_t
*ctx
, select_statement_t
*stat
)
943 unsigned end_label
, case_cnt
= 0, *case_labels
= NULL
, i
;
944 case_clausule_t
*case_iter
;
945 expression_t
*expr_iter
;
948 hres
= compile_expression(ctx
, stat
->expr
);
952 if(!push_instr(ctx
, OP_val
))
953 return E_OUTOFMEMORY
;
955 end_label
= alloc_label(ctx
);
957 return E_OUTOFMEMORY
;
959 if(!emit_catch_jmp(ctx
, 0, end_label
))
960 return E_OUTOFMEMORY
;
962 for(case_iter
= stat
->case_clausules
; case_iter
; case_iter
= case_iter
->next
)
966 case_labels
= heap_alloc(case_cnt
*sizeof(*case_labels
));
968 return E_OUTOFMEMORY
;
971 for(case_iter
= stat
->case_clausules
, i
=0; case_iter
; case_iter
= case_iter
->next
, i
++) {
972 case_labels
[i
] = alloc_label(ctx
);
973 if(!case_labels
[i
]) {
974 hres
= E_OUTOFMEMORY
;
981 for(expr_iter
= case_iter
->expr
; expr_iter
; expr_iter
= expr_iter
->next
) {
982 hres
= compile_expression(ctx
, expr_iter
);
986 hres
= push_instr_addr(ctx
, OP_case
, case_labels
[i
]);
990 if(!emit_catch_jmp(ctx
, 0, case_labels
[i
])) {
991 hres
= E_OUTOFMEMORY
;
998 heap_free(case_labels
);
1002 hres
= push_instr_uint(ctx
, OP_pop
, 1);
1004 heap_free(case_labels
);
1008 hres
= push_instr_addr(ctx
, OP_jmp
, case_iter
? case_labels
[i
] : end_label
);
1010 heap_free(case_labels
);
1014 for(case_iter
= stat
->case_clausules
, i
=0; case_iter
; case_iter
= case_iter
->next
, i
++) {
1015 label_set_addr(ctx
, case_labels
[i
]);
1016 hres
= compile_statement(ctx
, NULL
, case_iter
->stat
);
1020 if(!case_iter
->next
)
1023 hres
= push_instr_addr(ctx
, OP_jmp
, end_label
);
1028 heap_free(case_labels
);
1032 label_set_addr(ctx
, end_label
);
1036 static HRESULT
compile_assignment(compile_ctx_t
*ctx
, expression_t
*left
, expression_t
*value_expr
, BOOL is_set
)
1038 call_expression_t
*call_expr
= NULL
;
1039 member_expression_t
*member_expr
;
1040 unsigned args_cnt
= 0;
1044 switch(left
->type
) {
1046 member_expr
= (member_expression_t
*)left
;
1049 call_expr
= (call_expression_t
*)left
;
1050 assert(call_expr
->call_expr
->type
== EXPR_MEMBER
);
1051 member_expr
= (member_expression_t
*)call_expr
->call_expr
;
1058 if(member_expr
->obj_expr
) {
1059 hres
= compile_expression(ctx
, member_expr
->obj_expr
);
1063 op
= is_set
? OP_set_member
: OP_assign_member
;
1065 op
= is_set
? OP_set_ident
: OP_assign_ident
;
1068 hres
= compile_expression(ctx
, value_expr
);
1073 hres
= compile_args(ctx
, call_expr
->args
, &args_cnt
);
1078 hres
= push_instr_bstr_uint(ctx
, op
, member_expr
->identifier
, args_cnt
);
1082 if(!emit_catch(ctx
, 0))
1083 return E_OUTOFMEMORY
;
1088 static HRESULT
compile_assign_statement(compile_ctx_t
*ctx
, assign_statement_t
*stat
, BOOL is_set
)
1090 return compile_assignment(ctx
, stat
->left_expr
, stat
->value_expr
, is_set
);
1093 static HRESULT
compile_call_statement(compile_ctx_t
*ctx
, call_statement_t
*stat
)
1097 hres
= compile_call_expression(ctx
, stat
->expr
, FALSE
);
1101 if(!emit_catch(ctx
, 0))
1102 return E_OUTOFMEMORY
;
1107 static BOOL
lookup_dim_decls(compile_ctx_t
*ctx
, const WCHAR
*name
)
1109 dim_decl_t
*dim_decl
;
1111 for(dim_decl
= ctx
->dim_decls
; dim_decl
; dim_decl
= dim_decl
->next
) {
1112 if(!wcsicmp(dim_decl
->name
, name
))
1119 static BOOL
lookup_args_name(compile_ctx_t
*ctx
, const WCHAR
*name
)
1123 for(i
= 0; i
< ctx
->func
->arg_cnt
; i
++) {
1124 if(!wcsicmp(ctx
->func
->args
[i
].name
, name
))
1131 static HRESULT
compile_dim_statement(compile_ctx_t
*ctx
, dim_statement_t
*stat
)
1133 dim_decl_t
*dim_decl
= stat
->dim_decls
;
1136 if(lookup_dim_decls(ctx
, dim_decl
->name
) || lookup_args_name(ctx
, dim_decl
->name
)
1137 || lookup_const_decls(ctx
, dim_decl
->name
, FALSE
)) {
1138 FIXME("dim %s name redefined\n", debugstr_w(dim_decl
->name
));
1142 ctx
->func
->var_cnt
++;
1144 if(dim_decl
->is_array
) {
1145 HRESULT hres
= push_instr_bstr_uint(ctx
, OP_dim
, dim_decl
->name
, ctx
->func
->array_cnt
++);
1149 if(!emit_catch(ctx
, 0))
1150 return E_OUTOFMEMORY
;
1155 dim_decl
= dim_decl
->next
;
1158 if(ctx
->dim_decls_tail
)
1159 ctx
->dim_decls_tail
->next
= stat
->dim_decls
;
1161 ctx
->dim_decls
= stat
->dim_decls
;
1162 ctx
->dim_decls_tail
= dim_decl
;
1166 static HRESULT
compile_redim_statement(compile_ctx_t
*ctx
, redim_statement_t
*stat
)
1171 hres
= compile_args(ctx
, stat
->dims
, &arg_cnt
);
1175 hres
= push_instr_bstr_uint(ctx
, stat
->preserve
? OP_redim_preserve
: OP_redim
, stat
->identifier
, arg_cnt
);
1179 if(!emit_catch(ctx
, 0))
1180 return E_OUTOFMEMORY
;
1185 static HRESULT
compile_const_statement(compile_ctx_t
*ctx
, const_statement_t
*stat
)
1187 const_decl_t
*decl
, *next_decl
= stat
->decls
;
1192 if(lookup_const_decls(ctx
, decl
->name
, FALSE
) || lookup_args_name(ctx
, decl
->name
)
1193 || lookup_dim_decls(ctx
, decl
->name
)) {
1194 FIXME("%s redefined\n", debugstr_w(decl
->name
));
1198 if(ctx
->func
->type
== FUNC_GLOBAL
) {
1201 hres
= compile_expression(ctx
, decl
->value_expr
);
1205 hres
= push_instr_bstr(ctx
, OP_const
, decl
->name
);
1209 if(!emit_catch(ctx
, 0))
1210 return E_OUTOFMEMORY
;
1213 next_decl
= decl
->next
;
1214 decl
->next
= ctx
->const_decls
;
1215 ctx
->const_decls
= decl
;
1221 static HRESULT
compile_function_statement(compile_ctx_t
*ctx
, function_statement_t
*stat
)
1223 if(ctx
->func
!= &ctx
->code
->main_code
) {
1224 FIXME("Function is not in the global code\n");
1228 stat
->func_decl
->next
= ctx
->func_decls
;
1229 ctx
->func_decls
= stat
->func_decl
;
1233 static HRESULT
compile_exitdo_statement(compile_ctx_t
*ctx
)
1235 statement_ctx_t
*iter
;
1236 unsigned pop_cnt
= 0;
1238 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1239 pop_cnt
+= iter
->stack_use
;
1240 if(iter
->while_end_label
)
1244 FIXME("Exit Do outside Do Loop\n");
1251 hres
= push_instr_uint(ctx
, OP_pop
, pop_cnt
);
1256 return push_instr_addr(ctx
, OP_jmp
, iter
->while_end_label
);
1259 static HRESULT
compile_exitfor_statement(compile_ctx_t
*ctx
)
1261 statement_ctx_t
*iter
;
1262 unsigned pop_cnt
= 0;
1264 for(iter
= ctx
->stat_ctx
; iter
; iter
= iter
->next
) {
1265 pop_cnt
+= iter
->stack_use
;
1266 if(iter
->for_end_label
)
1270 FIXME("Exit For outside For loop\n");
1277 hres
= push_instr_uint(ctx
, OP_pop
, pop_cnt
);
1282 return push_instr_addr(ctx
, OP_jmp
, iter
->for_end_label
);
1285 static HRESULT
exit_label(compile_ctx_t
*ctx
, unsigned jmp_label
)
1287 unsigned pop_cnt
= stack_offset(ctx
);
1292 hres
= push_instr_uint(ctx
, OP_pop
, pop_cnt
);
1297 return push_instr_addr(ctx
, OP_jmp
, jmp_label
);
1300 static HRESULT
compile_exitsub_statement(compile_ctx_t
*ctx
)
1302 if(!ctx
->sub_end_label
) {
1303 FIXME("Exit Sub outside Sub?\n");
1307 return exit_label(ctx
, ctx
->sub_end_label
);
1310 static HRESULT
compile_exitfunc_statement(compile_ctx_t
*ctx
)
1312 if(!ctx
->func_end_label
) {
1313 FIXME("Exit Function outside Function?\n");
1317 return exit_label(ctx
, ctx
->func_end_label
);
1320 static HRESULT
compile_exitprop_statement(compile_ctx_t
*ctx
)
1322 if(!ctx
->prop_end_label
) {
1323 FIXME("Exit Property outside Property?\n");
1327 return exit_label(ctx
, ctx
->prop_end_label
);
1330 static HRESULT
compile_onerror_statement(compile_ctx_t
*ctx
, onerror_statement_t
*stat
)
1332 return push_instr_int(ctx
, OP_errmode
, stat
->resume_next
);
1335 static HRESULT
compile_retval_statement(compile_ctx_t
*ctx
, retval_statement_t
*stat
)
1339 hres
= compile_expression(ctx
, stat
->expr
);
1343 hres
= push_instr(ctx
, OP_retval
);
1350 static HRESULT
compile_statement(compile_ctx_t
*ctx
, statement_ctx_t
*stat_ctx
, statement_t
*stat
)
1355 stat_ctx
->next
= ctx
->stat_ctx
;
1356 ctx
->stat_ctx
= stat_ctx
;
1360 ctx
->loc
= stat
->loc
;
1362 switch(stat
->type
) {
1364 hres
= compile_assign_statement(ctx
, (assign_statement_t
*)stat
, FALSE
);
1367 hres
= compile_call_statement(ctx
, (call_statement_t
*)stat
);
1370 hres
= compile_const_statement(ctx
, (const_statement_t
*)stat
);
1373 hres
= compile_dim_statement(ctx
, (dim_statement_t
*)stat
);
1377 hres
= compile_dowhile_statement(ctx
, (while_statement_t
*)stat
);
1380 hres
= compile_exitdo_statement(ctx
);
1383 hres
= compile_exitfor_statement(ctx
);
1386 hres
= compile_exitfunc_statement(ctx
);
1389 hres
= compile_exitprop_statement(ctx
);
1392 hres
= compile_exitsub_statement(ctx
);
1395 hres
= compile_foreach_statement(ctx
, (foreach_statement_t
*)stat
);
1398 hres
= compile_forto_statement(ctx
, (forto_statement_t
*)stat
);
1401 hres
= compile_function_statement(ctx
, (function_statement_t
*)stat
);
1404 hres
= compile_if_statement(ctx
, (if_statement_t
*)stat
);
1407 hres
= compile_onerror_statement(ctx
, (onerror_statement_t
*)stat
);
1410 hres
= compile_redim_statement(ctx
, (redim_statement_t
*)stat
);
1413 hres
= compile_select_statement(ctx
, (select_statement_t
*)stat
);
1416 hres
= compile_assign_statement(ctx
, (assign_statement_t
*)stat
, TRUE
);
1419 hres
= push_instr(ctx
, OP_stop
) ? S_OK
: E_OUTOFMEMORY
;
1423 case STAT_WHILELOOP
:
1424 hres
= compile_while_statement(ctx
, (while_statement_t
*)stat
);
1427 hres
= compile_with_statement(ctx
, (with_statement_t
*)stat
);
1430 hres
= compile_retval_statement(ctx
, (retval_statement_t
*)stat
);
1433 FIXME("Unimplemented statement type %d\n", stat
->type
);
1443 assert(ctx
->stat_ctx
== stat_ctx
);
1444 ctx
->stat_ctx
= stat_ctx
->next
;
1450 static void resolve_labels(compile_ctx_t
*ctx
, unsigned off
)
1454 for(instr
= ctx
->code
->instrs
+off
; instr
< ctx
->code
->instrs
+ctx
->instr_cnt
; instr
++) {
1455 if(instr_info
[instr
->op
].arg1_type
== ARG_ADDR
&& (instr
->arg1
.uint
& LABEL_FLAG
)) {
1456 assert((instr
->arg1
.uint
& ~LABEL_FLAG
) < ctx
->labels_cnt
);
1457 instr
->arg1
.uint
= ctx
->labels
[instr
->arg1
.uint
& ~LABEL_FLAG
];
1459 assert(instr_info
[instr
->op
].arg2_type
!= ARG_ADDR
);
1462 ctx
->labels_cnt
= 0;
1465 static HRESULT
fill_array_desc(compile_ctx_t
*ctx
, dim_decl_t
*dim_decl
, array_desc_t
*array_desc
)
1467 unsigned dim_cnt
= 0, i
;
1470 for(iter
= dim_decl
->dims
; iter
; iter
= iter
->next
)
1473 array_desc
->bounds
= compiler_alloc(ctx
->code
, dim_cnt
* sizeof(SAFEARRAYBOUND
));
1474 if(!array_desc
->bounds
)
1475 return E_OUTOFMEMORY
;
1477 array_desc
->dim_cnt
= dim_cnt
;
1479 for(iter
= dim_decl
->dims
, i
=0; iter
; iter
= iter
->next
, i
++) {
1480 array_desc
->bounds
[i
].cElements
= iter
->val
+1;
1481 array_desc
->bounds
[i
].lLbound
= 0;
1487 static HRESULT
compile_func(compile_ctx_t
*ctx
, statement_t
*stat
, function_t
*func
)
1491 func
->code_off
= ctx
->instr_cnt
;
1493 ctx
->sub_end_label
= 0;
1494 ctx
->func_end_label
= 0;
1495 ctx
->prop_end_label
= 0;
1497 switch(func
->type
) {
1499 ctx
->func_end_label
= alloc_label(ctx
);
1500 if(!ctx
->func_end_label
)
1501 return E_OUTOFMEMORY
;
1504 ctx
->sub_end_label
= alloc_label(ctx
);
1505 if(!ctx
->sub_end_label
)
1506 return E_OUTOFMEMORY
;
1511 ctx
->prop_end_label
= alloc_label(ctx
);
1512 if(!ctx
->prop_end_label
)
1513 return E_OUTOFMEMORY
;
1520 ctx
->dim_decls
= ctx
->dim_decls_tail
= NULL
;
1521 ctx
->const_decls
= NULL
;
1522 hres
= compile_statement(ctx
, NULL
, stat
);
1527 if(ctx
->sub_end_label
)
1528 label_set_addr(ctx
, ctx
->sub_end_label
);
1529 if(ctx
->func_end_label
)
1530 label_set_addr(ctx
, ctx
->func_end_label
);
1531 if(ctx
->prop_end_label
)
1532 label_set_addr(ctx
, ctx
->prop_end_label
);
1534 if(!push_instr(ctx
, OP_ret
))
1535 return E_OUTOFMEMORY
;
1537 resolve_labels(ctx
, func
->code_off
);
1540 dim_decl_t
*dim_decl
;
1543 func
->vars
= compiler_alloc(ctx
->code
, func
->var_cnt
* sizeof(var_desc_t
));
1545 return E_OUTOFMEMORY
;
1547 for(dim_decl
= ctx
->dim_decls
, i
=0; dim_decl
; dim_decl
= dim_decl
->next
, i
++) {
1548 func
->vars
[i
].name
= compiler_alloc_string(ctx
->code
, dim_decl
->name
);
1549 if(!func
->vars
[i
].name
)
1550 return E_OUTOFMEMORY
;
1553 assert(i
== func
->var_cnt
);
1556 if(func
->array_cnt
) {
1557 unsigned array_id
= 0;
1558 dim_decl_t
*dim_decl
;
1560 func
->array_descs
= compiler_alloc(ctx
->code
, func
->array_cnt
* sizeof(array_desc_t
));
1561 if(!func
->array_descs
)
1562 return E_OUTOFMEMORY
;
1564 for(dim_decl
= ctx
->dim_decls
; dim_decl
; dim_decl
= dim_decl
->next
) {
1565 if(dim_decl
->is_array
) {
1566 hres
= fill_array_desc(ctx
, dim_decl
, func
->array_descs
+ array_id
++);
1572 assert(array_id
== func
->array_cnt
);
1578 static BOOL
lookup_funcs_name(compile_ctx_t
*ctx
, const WCHAR
*name
)
1582 for(iter
= ctx
->code
->funcs
; iter
; iter
= iter
->next
) {
1583 if(!wcsicmp(iter
->name
, name
))
1590 static HRESULT
create_function(compile_ctx_t
*ctx
, function_decl_t
*decl
, function_t
**ret
)
1595 if(lookup_dim_decls(ctx
, decl
->name
) || lookup_const_decls(ctx
, decl
->name
, FALSE
)) {
1596 FIXME("%s: redefinition\n", debugstr_w(decl
->name
));
1600 func
= compiler_alloc(ctx
->code
, sizeof(*func
));
1602 return E_OUTOFMEMORY
;
1604 func
->name
= compiler_alloc_string(ctx
->code
, decl
->name
);
1606 return E_OUTOFMEMORY
;
1610 func
->array_cnt
= 0;
1611 func
->code_ctx
= ctx
->code
;
1612 func
->type
= decl
->type
;
1613 func
->is_public
= decl
->is_public
;
1620 for(arg
= decl
->args
; arg
; arg
= arg
->next
)
1623 func
->args
= compiler_alloc(ctx
->code
, func
->arg_cnt
* sizeof(arg_desc_t
));
1625 return E_OUTOFMEMORY
;
1627 for(i
= 0, arg
= decl
->args
; arg
; arg
= arg
->next
, i
++) {
1628 func
->args
[i
].name
= compiler_alloc_string(ctx
->code
, arg
->name
);
1629 if(!func
->args
[i
].name
)
1630 return E_OUTOFMEMORY
;
1631 func
->args
[i
].by_ref
= arg
->by_ref
;
1637 hres
= compile_func(ctx
, decl
->body
, func
);
1645 static BOOL
lookup_class_name(compile_ctx_t
*ctx
, const WCHAR
*name
)
1649 for(iter
= ctx
->code
->classes
; iter
; iter
= iter
->next
) {
1650 if(!wcsicmp(iter
->name
, name
))
1657 static HRESULT
create_class_funcprop(compile_ctx_t
*ctx
, function_decl_t
*func_decl
, vbdisp_funcprop_desc_t
*desc
)
1659 vbdisp_invoke_type_t invoke_type
;
1660 function_decl_t
*funcprop_decl
;
1663 desc
->name
= compiler_alloc_string(ctx
->code
, func_decl
->name
);
1665 return E_OUTOFMEMORY
;
1667 for(funcprop_decl
= func_decl
; funcprop_decl
; funcprop_decl
= funcprop_decl
->next_prop_func
) {
1668 switch(funcprop_decl
->type
) {
1672 invoke_type
= VBDISP_CALLGET
;
1675 invoke_type
= VBDISP_LET
;
1678 invoke_type
= VBDISP_SET
;
1680 DEFAULT_UNREACHABLE
;
1683 assert(!desc
->entries
[invoke_type
]);
1685 if(funcprop_decl
->is_public
)
1686 desc
->is_public
= TRUE
;
1688 hres
= create_function(ctx
, funcprop_decl
, desc
->entries
+invoke_type
);
1696 static BOOL
lookup_class_funcs(class_desc_t
*class_desc
, const WCHAR
*name
)
1700 for(i
=0; i
< class_desc
->func_cnt
; i
++) {
1701 if(class_desc
->funcs
[i
].name
&& !wcsicmp(class_desc
->funcs
[i
].name
, name
))
1708 static HRESULT
compile_class(compile_ctx_t
*ctx
, class_decl_t
*class_decl
)
1710 function_decl_t
*func_decl
, *func_prop_decl
;
1711 BOOL is_default
, have_default
= FALSE
;
1712 class_desc_t
*class_desc
;
1713 dim_decl_t
*prop_decl
;
1717 if(lookup_dim_decls(ctx
, class_decl
->name
) || lookup_funcs_name(ctx
, class_decl
->name
)
1718 || lookup_const_decls(ctx
, class_decl
->name
, FALSE
) || lookup_class_name(ctx
, class_decl
->name
)) {
1719 FIXME("%s: redefinition\n", debugstr_w(class_decl
->name
));
1723 class_desc
= compiler_alloc_zero(ctx
->code
, sizeof(*class_desc
));
1725 return E_OUTOFMEMORY
;
1727 class_desc
->name
= compiler_alloc_string(ctx
->code
, class_decl
->name
);
1728 if(!class_desc
->name
)
1729 return E_OUTOFMEMORY
;
1731 class_desc
->func_cnt
= 1; /* always allocate slot for default getter or method */
1733 for(func_decl
= class_decl
->funcs
; func_decl
; func_decl
= func_decl
->next
) {
1735 for(func_prop_decl
= func_decl
; func_prop_decl
; func_prop_decl
= func_prop_decl
->next_prop_func
) {
1736 if(func_prop_decl
->is_default
) {
1738 FIXME("multiple default getters or methods\n");
1741 is_default
= have_default
= TRUE
;
1746 class_desc
->func_cnt
++;
1749 class_desc
->funcs
= compiler_alloc(ctx
->code
, class_desc
->func_cnt
*sizeof(*class_desc
->funcs
));
1750 if(!class_desc
->funcs
)
1751 return E_OUTOFMEMORY
;
1752 memset(class_desc
->funcs
, 0, class_desc
->func_cnt
*sizeof(*class_desc
->funcs
));
1754 for(func_decl
= class_decl
->funcs
, i
=1; func_decl
; func_decl
= func_decl
->next
, i
++) {
1755 for(func_prop_decl
= func_decl
; func_prop_decl
; func_prop_decl
= func_prop_decl
->next_prop_func
) {
1756 if(func_prop_decl
->is_default
) {
1762 if(!wcsicmp(L
"class_initialize", func_decl
->name
)) {
1763 if(func_decl
->type
!= FUNC_SUB
) {
1764 FIXME("class initializer is not sub\n");
1768 class_desc
->class_initialize_id
= i
;
1769 }else if(!wcsicmp(L
"class_terminate", func_decl
->name
)) {
1770 if(func_decl
->type
!= FUNC_SUB
) {
1771 FIXME("class terminator is not sub\n");
1775 class_desc
->class_terminate_id
= i
;
1778 hres
= create_class_funcprop(ctx
, func_decl
, class_desc
->funcs
+ (func_prop_decl
? 0 : i
));
1783 for(prop_decl
= class_decl
->props
; prop_decl
; prop_decl
= prop_decl
->next
)
1784 class_desc
->prop_cnt
++;
1786 class_desc
->props
= compiler_alloc(ctx
->code
, class_desc
->prop_cnt
*sizeof(*class_desc
->props
));
1787 if(!class_desc
->props
)
1788 return E_OUTOFMEMORY
;
1790 for(prop_decl
= class_decl
->props
, i
=0; prop_decl
; prop_decl
= prop_decl
->next
, i
++) {
1791 if(lookup_class_funcs(class_desc
, prop_decl
->name
)) {
1792 FIXME("Property %s redefined\n", debugstr_w(prop_decl
->name
));
1796 class_desc
->props
[i
].name
= compiler_alloc_string(ctx
->code
, prop_decl
->name
);
1797 if(!class_desc
->props
[i
].name
)
1798 return E_OUTOFMEMORY
;
1800 class_desc
->props
[i
].is_public
= prop_decl
->is_public
;
1801 class_desc
->props
[i
].is_array
= prop_decl
->is_array
;
1803 if(prop_decl
->is_array
)
1804 class_desc
->array_cnt
++;
1807 if(class_desc
->array_cnt
) {
1808 class_desc
->array_descs
= compiler_alloc(ctx
->code
, class_desc
->array_cnt
*sizeof(*class_desc
->array_descs
));
1809 if(!class_desc
->array_descs
)
1810 return E_OUTOFMEMORY
;
1812 for(prop_decl
= class_decl
->props
, i
=0; prop_decl
; prop_decl
= prop_decl
->next
) {
1813 if(prop_decl
->is_array
) {
1814 hres
= fill_array_desc(ctx
, prop_decl
, class_desc
->array_descs
+ i
++);
1821 class_desc
->next
= ctx
->code
->classes
;
1822 ctx
->code
->classes
= class_desc
;
1826 static BOOL
lookup_script_identifier(compile_ctx_t
*ctx
, script_ctx_t
*script
, const WCHAR
*identifier
)
1828 ScriptDisp
*contexts
[] = {
1829 ctx
->code
->named_item
? ctx
->code
->named_item
->script_obj
: NULL
,
1832 class_desc_t
*class;
1836 for(c
= 0; c
< ARRAY_SIZE(contexts
); c
++) {
1837 if(!contexts
[c
]) continue;
1839 for(i
= 0; i
< contexts
[c
]->global_vars_cnt
; i
++) {
1840 if(!wcsicmp(contexts
[c
]->global_vars
[i
]->name
, identifier
))
1844 for(i
= 0; i
< contexts
[c
]->global_funcs_cnt
; i
++) {
1845 if(!wcsicmp(contexts
[c
]->global_funcs
[i
]->name
, identifier
))
1849 for(class = contexts
[c
]->classes
; class; class = class->next
) {
1850 if(!wcsicmp(class->name
, identifier
))
1855 LIST_FOR_EACH_ENTRY(code
, &script
->code_list
, vbscode_t
, entry
) {
1856 unsigned var_cnt
= code
->main_code
.var_cnt
;
1857 var_desc_t
*vars
= code
->main_code
.vars
;
1860 if(!code
->pending_exec
|| (code
->named_item
&& code
->named_item
!= ctx
->code
->named_item
))
1863 for(i
= 0; i
< var_cnt
; i
++) {
1864 if(!wcsicmp(vars
[i
].name
, identifier
))
1868 for(func
= code
->funcs
; func
; func
= func
->next
) {
1869 if(!wcsicmp(func
->name
, identifier
))
1873 for(class = code
->classes
; class; class = class->next
) {
1874 if(!wcsicmp(class->name
, identifier
))
1882 static HRESULT
check_script_collisions(compile_ctx_t
*ctx
, script_ctx_t
*script
)
1884 unsigned i
, var_cnt
= ctx
->code
->main_code
.var_cnt
;
1885 var_desc_t
*vars
= ctx
->code
->main_code
.vars
;
1886 class_desc_t
*class;
1888 for(i
= 0; i
< var_cnt
; i
++) {
1889 if(lookup_script_identifier(ctx
, script
, vars
[i
].name
)) {
1890 FIXME("%s: redefined\n", debugstr_w(vars
[i
].name
));
1895 for(class = ctx
->code
->classes
; class; class = class->next
) {
1896 if(lookup_script_identifier(ctx
, script
, class->name
)) {
1897 FIXME("%s: redefined\n", debugstr_w(class->name
));
1905 void release_vbscode(vbscode_t
*code
)
1912 for(i
=0; i
< code
->bstr_cnt
; i
++)
1913 SysFreeString(code
->bstr_pool
[i
]);
1915 if(code
->named_item
)
1916 release_named_item(code
->named_item
);
1917 heap_pool_free(&code
->heap
);
1919 heap_free(code
->bstr_pool
);
1920 heap_free(code
->source
);
1921 heap_free(code
->instrs
);
1925 static vbscode_t
*alloc_vbscode(compile_ctx_t
*ctx
, const WCHAR
*source
, DWORD_PTR cookie
, unsigned start_line
)
1930 len
= source
? lstrlenW(source
) : 0;
1934 ret
= heap_alloc_zero(sizeof(*ret
));
1938 ret
->source
= heap_alloc((len
+ 1) * sizeof(WCHAR
));
1944 memcpy(ret
->source
, source
, len
* sizeof(WCHAR
));
1945 ret
->source
[len
] = 0;
1947 ret
->cookie
= cookie
;
1948 ret
->start_line
= start_line
;
1950 ret
->instrs
= heap_alloc(32*sizeof(instr_t
));
1952 release_vbscode(ret
);
1957 ctx
->instr_size
= 32;
1958 heap_pool_init(&ret
->heap
);
1960 ret
->main_code
.type
= FUNC_GLOBAL
;
1961 ret
->main_code
.code_ctx
= ret
;
1964 list_init(&ret
->entry
);
1968 static void release_compiler(compile_ctx_t
*ctx
)
1970 parser_release(&ctx
->parser
);
1971 heap_free(ctx
->labels
);
1973 release_vbscode(ctx
->code
);
1976 HRESULT
compile_script(script_ctx_t
*script
, const WCHAR
*src
, const WCHAR
*item_name
, const WCHAR
*delimiter
,
1977 DWORD_PTR cookie
, unsigned start_line
, DWORD flags
, vbscode_t
**ret
)
1979 function_decl_t
*func_decl
;
1980 named_item_t
*item
= NULL
;
1981 class_decl_t
*class_decl
;
1982 function_t
*new_func
;
1988 item
= lookup_named_item(script
, item_name
, 0);
1990 WARN("Unknown context %s\n", debugstr_w(item_name
));
1991 return E_INVALIDARG
;
1993 if(!item
->script_obj
) item
= NULL
;
1996 memset(&ctx
, 0, sizeof(ctx
));
1997 code
= ctx
.code
= alloc_vbscode(&ctx
, src
, cookie
, start_line
);
1999 return E_OUTOFMEMORY
;
2001 code
->named_item
= item
;
2005 ctx
.parser
.lcid
= script
->lcid
;
2006 hres
= parse_script(&ctx
.parser
, code
->source
, delimiter
, flags
);
2008 if(ctx
.parser
.error_loc
!= -1)
2009 ctx
.loc
= ctx
.parser
.error_loc
;
2010 hres
= compile_error(script
, &ctx
, hres
);
2011 release_vbscode(code
);
2015 hres
= compile_func(&ctx
, ctx
.parser
.stats
, &ctx
.code
->main_code
);
2017 hres
= compile_error(script
, &ctx
, hres
);
2018 release_compiler(&ctx
);
2022 code
->option_explicit
= ctx
.parser
.option_explicit
;
2023 ctx
.global_consts
= ctx
.const_decls
;
2024 code
->option_explicit
= ctx
.parser
.option_explicit
;
2027 for(func_decl
= ctx
.func_decls
; func_decl
; func_decl
= func_decl
->next
) {
2028 hres
= create_function(&ctx
, func_decl
, &new_func
);
2030 hres
= compile_error(script
, &ctx
, hres
);
2031 release_compiler(&ctx
);
2035 new_func
->next
= ctx
.code
->funcs
;
2036 ctx
.code
->funcs
= new_func
;
2039 for(class_decl
= ctx
.parser
.class_decls
; class_decl
; class_decl
= class_decl
->next
) {
2040 hres
= compile_class(&ctx
, class_decl
);
2042 hres
= compile_error(script
, &ctx
, hres
);
2043 release_compiler(&ctx
);
2048 hres
= check_script_collisions(&ctx
, script
);
2050 hres
= compile_error(script
, &ctx
, hres
);
2051 release_compiler(&ctx
);
2055 code
->is_persistent
= (flags
& SCRIPTTEXT_ISPERSISTENT
) != 0;
2057 if(TRACE_ON(vbscript_disas
))
2061 release_compiler(&ctx
);
2063 list_add_tail(&script
->code_list
, &code
->entry
);
2068 HRESULT
compile_procedure(script_ctx_t
*script
, const WCHAR
*src
, const WCHAR
*item_name
, const WCHAR
*delimiter
,
2069 DWORD_PTR cookie
, unsigned start_line
, DWORD flags
, class_desc_t
**ret
)
2075 hres
= compile_script(script
, src
, item_name
, delimiter
, cookie
, start_line
,
2076 flags
& ~SCRIPTTEXT_ISPERSISTENT
, &code
);
2080 if(!(desc
= compiler_alloc_zero(code
, sizeof(*desc
))))
2081 return E_OUTOFMEMORY
;
2082 if(!(desc
->funcs
= compiler_alloc_zero(code
, sizeof(*desc
->funcs
))))
2083 return E_OUTOFMEMORY
;
2087 desc
->funcs
->entries
[VBDISP_CALLGET
] = &code
->main_code
;