include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / vbscript / compile.c
blobbaddc51d7e477288c9ef8fedf0688533f514c8dd
1 /*
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
19 #include <assert.h>
21 #include "vbscript.h"
22 #include "parse.h"
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 {
31 unsigned stack_use;
33 unsigned while_end_label;
34 unsigned for_end_label;
35 unsigned with_stack_offset;
37 struct _statement_ctx_t *next;
38 } statement_ctx_t;
40 typedef struct {
41 parser_ctx_t parser;
43 unsigned instr_cnt;
44 unsigned instr_size;
45 vbscode_t *code;
47 unsigned loc;
48 statement_ctx_t *stat_ctx;
50 unsigned *labels;
51 unsigned labels_size;
52 unsigned labels_cnt;
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;
64 function_t *func;
65 function_decl_t *func_decls;
66 } compile_ctx_t;
68 static HRESULT compile_expression(compile_ctx_t*,expression_t*);
69 static HRESULT compile_statement(compile_ctx_t*,statement_ctx_t*,statement_t*);
71 static const struct {
72 const char *op_str;
73 instr_arg_type_t arg1_type;
74 instr_arg_type_t arg2_type;
75 } instr_info[] = {
76 #define X(n,a,b,c) {#n,b,c},
77 OP_LIST
78 #undef X
81 static void dump_instr_arg(instr_arg_type_t type, instr_arg_t *arg)
83 switch(type) {
84 case ARG_STR:
85 case ARG_BSTR:
86 TRACE_(vbscript_disas)("\t%s", debugstr_w(arg->str));
87 break;
88 case ARG_INT:
89 TRACE_(vbscript_disas)("\t%d", arg->uint);
90 break;
91 case ARG_UINT:
92 case ARG_ADDR:
93 TRACE_(vbscript_disas)("\t%u", arg->uint);
94 break;
95 case ARG_DATE:
96 case ARG_DOUBLE:
97 TRACE_(vbscript_disas)("\t%lf", *arg->dbl);
98 break;
99 case ARG_NONE:
100 break;
101 DEFAULT_UNREACHABLE;
105 static void dump_code(compile_ctx_t *ctx)
107 instr_t *instr;
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)
125 void *ret;
127 ret = heap_pool_alloc(&vbscode->heap, size);
128 if(ret)
129 memset(ret, 0, size);
130 return ret;
133 static WCHAR *compiler_alloc_string(vbscode_t *vbscode, const WCHAR *str)
135 size_t size;
136 WCHAR *ret;
138 size = (lstrlenW(str)+1)*sizeof(WCHAR);
139 ret = compiler_alloc(vbscode, size);
140 if(ret)
141 memcpy(ret, str, size);
142 return ret;
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) {
156 instr_t *new_instr;
158 new_instr = realloc(ctx->code->instrs, ctx->instr_size*2*sizeof(instr_t));
159 if(!new_instr)
160 return 0;
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)
173 unsigned ret;
175 ret = push_instr(ctx, op);
176 if(!ret)
177 return E_OUTOFMEMORY;
179 instr_ptr(ctx, ret)->arg1.lng = arg;
180 return S_OK;
183 static HRESULT push_instr_uint(compile_ctx_t *ctx, vbsop_t op, unsigned arg)
185 unsigned ret;
187 ret = push_instr(ctx, op);
188 if(!ret)
189 return E_OUTOFMEMORY;
191 instr_ptr(ctx, ret)->arg1.uint = arg;
192 return S_OK;
195 static HRESULT push_instr_addr(compile_ctx_t *ctx, vbsop_t op, unsigned arg)
197 unsigned ret;
199 ret = push_instr(ctx, op);
200 if(!ret)
201 return E_OUTOFMEMORY;
203 instr_ptr(ctx, ret)->arg1.uint = arg;
204 return S_OK;
207 static HRESULT push_instr_str(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg)
209 unsigned instr;
210 WCHAR *str;
212 str = compiler_alloc_string(ctx->code, arg);
213 if(!str)
214 return E_OUTOFMEMORY;
216 instr = push_instr(ctx, op);
217 if(!instr)
218 return E_OUTOFMEMORY;
220 instr_ptr(ctx, instr)->arg1.str = str;
221 return S_OK;
224 static HRESULT push_instr_double(compile_ctx_t *ctx, vbsop_t op, double arg)
226 unsigned instr;
227 double *d;
229 d = compiler_alloc(ctx->code, sizeof(double));
230 if(!d)
231 return E_OUTOFMEMORY;
233 instr = push_instr(ctx, op);
234 if(!instr)
235 return E_OUTOFMEMORY;
237 *d = arg;
238 instr_ptr(ctx, instr)->arg1.dbl = d;
239 return S_OK;
242 static HRESULT push_instr_date(compile_ctx_t *ctx, vbsop_t op, DATE arg)
244 unsigned instr;
245 DATE *d;
247 d = compiler_alloc(ctx->code, sizeof(DATE));
248 if(!d)
249 return E_OUTOFMEMORY;
251 instr = push_instr(ctx, op);
252 if(!instr)
253 return E_OUTOFMEMORY;
255 *d = arg;
256 instr_ptr(ctx, instr)->arg1.date = d;
257 return S_OK;
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 = malloc(8 * sizeof(BSTR));
264 if(!ctx->code->bstr_pool)
265 return NULL;
266 ctx->code->bstr_pool_size = 8;
267 }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) {
268 BSTR *new_pool;
270 new_pool = realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR));
271 if(!new_pool)
272 return NULL;
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])
280 return NULL;
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)
287 unsigned instr;
288 BSTR bstr;
290 bstr = alloc_bstr_arg(ctx, arg);
291 if(!bstr)
292 return E_OUTOFMEMORY;
294 instr = push_instr(ctx, op);
295 if(!instr)
296 return E_OUTOFMEMORY;
298 instr_ptr(ctx, instr)->arg1.bstr = bstr;
299 return S_OK;
302 static HRESULT push_instr_bstr_uint(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg1, unsigned arg2)
304 unsigned instr;
305 BSTR bstr;
307 bstr = alloc_bstr_arg(ctx, arg1);
308 if(!bstr)
309 return E_OUTOFMEMORY;
311 instr = push_instr(ctx, op);
312 if(!instr)
313 return E_OUTOFMEMORY;
315 instr_ptr(ctx, instr)->arg1.bstr = bstr;
316 instr_ptr(ctx, instr)->arg2.uint = arg2;
317 return S_OK;
320 static HRESULT push_instr_uint_bstr(compile_ctx_t *ctx, vbsop_t op, unsigned arg1, const WCHAR *arg2)
322 unsigned instr;
323 BSTR bstr;
325 bstr = alloc_bstr_arg(ctx, arg2);
326 if(!bstr)
327 return E_OUTOFMEMORY;
329 instr = push_instr(ctx, op);
330 if(!instr)
331 return E_OUTOFMEMORY;
333 instr_ptr(ctx, instr)->arg1.uint = arg1;
334 instr_ptr(ctx, instr)->arg2.bstr = bstr;
335 return S_OK;
338 #define LABEL_FLAG 0x80000000
340 static unsigned alloc_label(compile_ctx_t *ctx)
342 if(!ctx->labels_size) {
343 ctx->labels = malloc(8 * sizeof(*ctx->labels));
344 if(!ctx->labels)
345 return 0;
346 ctx->labels_size = 8;
347 }else if(ctx->labels_size == ctx->labels_cnt) {
348 unsigned *new_labels;
350 new_labels = realloc(ctx->labels, 2*ctx->labels_size*sizeof(*ctx->labels));
351 if(!new_labels)
352 return 0;
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;
370 unsigned ret = 0;
372 for(iter = ctx->stat_ctx; iter; iter = iter->next)
373 ret += iter->stack_use;
375 return ret;
378 static BOOL emit_catch_jmp(compile_ctx_t *ctx, unsigned stack_off, unsigned code_off)
380 unsigned code;
382 code = push_instr(ctx, OP_catch);
383 if(!code)
384 return FALSE;
386 instr_ptr(ctx, code)->arg1.uint = code_off;
387 instr_ptr(ctx, code)->arg2.uint = stack_off + stack_offset(ctx);
388 return TRUE;
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)
399 return error;
401 clear_ei(&ctx->ei);
402 ctx->ei.scode = error;
403 ctx->ei.bstrSource = get_vbscript_string(VBS_COMPILE_ERROR);
404 map_vbs_exception(&ctx->ei);
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)
410 const_decl_t *decl;
412 for(decl = ctx->const_decls; decl; decl = decl->next) {
413 if(!wcsicmp(decl->name, name))
414 return decl->value_expr;
417 if(!lookup_global)
418 return NULL;
420 for(decl = ctx->global_consts; decl; decl = decl->next) {
421 if(!wcsicmp(decl->name, name))
422 return decl->value_expr;
425 return NULL;
428 static BOOL lookup_args_name(compile_ctx_t *ctx, const WCHAR *name)
430 unsigned i;
432 for(i = 0; i < ctx->func->arg_cnt; i++) {
433 if(!wcsicmp(ctx->func->args[i].name, name))
434 return TRUE;
437 return FALSE;
440 static BOOL lookup_dim_decls(compile_ctx_t *ctx, const WCHAR *name)
442 dim_decl_t *dim_decl;
444 for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
445 if(!wcsicmp(dim_decl->name, name))
446 return TRUE;
449 return FALSE;
452 static HRESULT compile_args(compile_ctx_t *ctx, expression_t *args, unsigned *ret)
454 unsigned arg_cnt = 0;
455 HRESULT hres;
457 while(args) {
458 hres = compile_expression(ctx, args);
459 if(FAILED(hres))
460 return hres;
462 if(args->type == EXPR_BRACKETS && !push_instr(ctx, OP_deref))
463 return E_OUTOFMEMORY;
465 arg_cnt++;
466 args = args->next;
469 *ret = arg_cnt;
470 return S_OK;
473 static HRESULT compile_member_call_expression(compile_ctx_t *ctx, member_expression_t *expr,
474 unsigned arg_cnt, BOOL ret_val)
476 HRESULT hres;
478 if(ret_val && !arg_cnt) {
479 expression_t *const_expr;
481 const_expr = lookup_const_decls(ctx, expr->identifier, TRUE);
482 if(const_expr)
483 return compile_expression(ctx, const_expr);
486 if(expr->obj_expr) {
487 hres = compile_expression(ctx, expr->obj_expr);
488 if(FAILED(hres))
489 return hres;
491 hres = push_instr_bstr_uint(ctx, ret_val ? OP_mcall : OP_mcallv, expr->identifier, arg_cnt);
492 }else {
493 hres = push_instr_bstr_uint(ctx, ret_val ? OP_icall : OP_icallv, expr->identifier, arg_cnt);
496 return hres;
499 static HRESULT compile_member_expression(compile_ctx_t *ctx, member_expression_t *expr)
501 expression_t *const_expr;
503 if (expr->obj_expr) /* FIXME: we should probably have a dedicated opcode as well */
504 return compile_member_call_expression(ctx, expr, 0, TRUE);
506 if (!lookup_dim_decls(ctx, expr->identifier) && !lookup_args_name(ctx, expr->identifier)) {
507 const_expr = lookup_const_decls(ctx, expr->identifier, TRUE);
508 if(const_expr)
509 return compile_expression(ctx, const_expr);
511 return push_instr_bstr(ctx, OP_ident, expr->identifier);
514 static HRESULT compile_call_expression(compile_ctx_t *ctx, call_expression_t *expr, BOOL ret_val)
516 unsigned arg_cnt = 0;
517 expression_t *call;
518 HRESULT hres;
520 hres = compile_args(ctx, expr->args, &arg_cnt);
521 if(FAILED(hres))
522 return hres;
524 for(call = expr->call_expr; call->type == EXPR_BRACKETS; call = ((unary_expression_t*)call)->subexpr);
526 if(call->type == EXPR_MEMBER)
527 return compile_member_call_expression(ctx, (member_expression_t*)call, arg_cnt, ret_val);
529 hres = compile_expression(ctx, call);
530 if(FAILED(hres))
531 return hres;
533 return push_instr_uint(ctx, ret_val ? OP_vcall : OP_vcallv, arg_cnt);
536 static HRESULT compile_dot_expression(compile_ctx_t *ctx)
538 statement_ctx_t *stat_ctx;
540 for(stat_ctx = ctx->stat_ctx; stat_ctx; stat_ctx = stat_ctx->next) {
541 if(!stat_ctx->with_stack_offset)
542 continue;
544 return push_instr_uint(ctx, OP_stack, stat_ctx->with_stack_offset - 1);
547 WARN("dot expression outside with statement\n");
548 return push_instr_uint(ctx, OP_stack, ~0);
551 static HRESULT compile_unary_expression(compile_ctx_t *ctx, unary_expression_t *expr, vbsop_t op)
553 HRESULT hres;
555 hres = compile_expression(ctx, expr->subexpr);
556 if(FAILED(hres))
557 return hres;
559 return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
562 static HRESULT compile_binary_expression(compile_ctx_t *ctx, binary_expression_t *expr, vbsop_t op)
564 HRESULT hres;
566 hres = compile_expression(ctx, expr->left);
567 if(FAILED(hres))
568 return hres;
570 hres = compile_expression(ctx, expr->right);
571 if(FAILED(hres))
572 return hres;
574 return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
577 static HRESULT compile_expression(compile_ctx_t *ctx, expression_t *expr)
579 switch(expr->type) {
580 case EXPR_ADD:
581 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add);
582 case EXPR_AND:
583 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_and);
584 case EXPR_BOOL:
585 return push_instr_int(ctx, OP_bool, ((bool_expression_t*)expr)->value);
586 case EXPR_BRACKETS:
587 return compile_expression(ctx, ((unary_expression_t*)expr)->subexpr);
588 case EXPR_CALL:
589 return compile_call_expression(ctx, (call_expression_t*)expr, TRUE);
590 case EXPR_CONCAT:
591 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_concat);
592 case EXPR_DATE:
593 return push_instr_date(ctx, OP_date, ((date_expression_t*)expr)->value);
594 case EXPR_DIV:
595 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div);
596 case EXPR_DOT:
597 return compile_dot_expression(ctx);
598 case EXPR_DOUBLE:
599 return push_instr_double(ctx, OP_double, ((double_expression_t*)expr)->value);
600 case EXPR_EMPTY:
601 return push_instr(ctx, OP_empty) ? S_OK : E_OUTOFMEMORY;
602 case EXPR_EQUAL:
603 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_equal);
604 case EXPR_EQV:
605 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eqv);
606 case EXPR_EXP:
607 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_exp);
608 case EXPR_GT:
609 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gt);
610 case EXPR_GTEQ:
611 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gteq);
612 case EXPR_IDIV:
613 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_idiv);
614 case EXPR_IS:
615 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_is);
616 case EXPR_IMP:
617 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_imp);
618 case EXPR_LT:
619 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lt);
620 case EXPR_LTEQ:
621 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lteq);
622 case EXPR_ME:
623 return push_instr(ctx, OP_me) ? S_OK : E_OUTOFMEMORY;
624 case EXPR_MEMBER:
625 return compile_member_expression(ctx, (member_expression_t*)expr);
626 case EXPR_MOD:
627 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod);
628 case EXPR_MUL:
629 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul);
630 case EXPR_NEG:
631 return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg);
632 case EXPR_NEQUAL:
633 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_nequal);
634 case EXPR_NEW:
635 return push_instr_str(ctx, OP_new, ((string_expression_t*)expr)->value);
636 case EXPR_NOARG:
637 return push_instr_int(ctx, OP_hres, DISP_E_PARAMNOTFOUND);
638 case EXPR_NOT:
639 return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_not);
640 case EXPR_NOTHING:
641 return push_instr(ctx, OP_nothing) ? S_OK : E_OUTOFMEMORY;
642 case EXPR_NULL:
643 return push_instr(ctx, OP_null) ? S_OK : E_OUTOFMEMORY;
644 case EXPR_OR:
645 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_or);
646 case EXPR_STRING:
647 return push_instr_str(ctx, OP_string, ((string_expression_t*)expr)->value);
648 case EXPR_SUB:
649 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
650 case EXPR_INT:
651 return push_instr_int(ctx, OP_int, ((int_expression_t*)expr)->value);
652 case EXPR_XOR:
653 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor);
654 default:
655 FIXME("Unimplemented expression type %d\n", expr->type);
656 return E_NOTIMPL;
659 return S_OK;
662 static HRESULT compile_if_statement(compile_ctx_t *ctx, if_statement_t *stat)
664 unsigned cnd_jmp, endif_label = 0;
665 elseif_decl_t *elseif_decl;
666 HRESULT hres;
668 hres = compile_expression(ctx, stat->expr);
669 if(FAILED(hres))
670 return hres;
672 cnd_jmp = push_instr(ctx, OP_jmp_false);
673 if(!cnd_jmp)
674 return E_OUTOFMEMORY;
676 if(!emit_catch(ctx, 0))
677 return E_OUTOFMEMORY;
679 hres = compile_statement(ctx, NULL, stat->if_stat);
680 if(FAILED(hres))
681 return hres;
683 if(stat->else_stat || stat->elseifs) {
684 endif_label = alloc_label(ctx);
685 if(!endif_label)
686 return E_OUTOFMEMORY;
688 hres = push_instr_addr(ctx, OP_jmp, endif_label);
689 if(FAILED(hres))
690 return hres;
693 for(elseif_decl = stat->elseifs; elseif_decl; elseif_decl = elseif_decl->next) {
694 instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;
696 ctx->loc = elseif_decl->loc;
698 hres = compile_expression(ctx, elseif_decl->expr);
699 if(FAILED(hres))
700 return hres;
702 cnd_jmp = push_instr(ctx, OP_jmp_false);
703 if(!cnd_jmp)
704 return E_OUTOFMEMORY;
706 if(!emit_catch(ctx, 0))
707 return E_OUTOFMEMORY;
709 hres = compile_statement(ctx, NULL, elseif_decl->stat);
710 if(FAILED(hres))
711 return hres;
713 hres = push_instr_addr(ctx, OP_jmp, endif_label);
714 if(FAILED(hres))
715 return hres;
718 instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;
720 if(stat->else_stat) {
721 hres = compile_statement(ctx, NULL, stat->else_stat);
722 if(FAILED(hres))
723 return hres;
726 if(endif_label)
727 label_set_addr(ctx, endif_label);
728 return S_OK;
731 static HRESULT compile_while_statement(compile_ctx_t *ctx, while_statement_t *stat)
733 statement_ctx_t stat_ctx = {0}, *loop_ctx;
734 unsigned start_addr;
735 unsigned jmp_end;
736 HRESULT hres;
738 start_addr = ctx->instr_cnt;
740 hres = compile_expression(ctx, stat->expr);
741 if(FAILED(hres))
742 return hres;
744 jmp_end = push_instr(ctx, stat->stat.type == STAT_UNTIL ? OP_jmp_true : OP_jmp_false);
745 if(!jmp_end)
746 return E_OUTOFMEMORY;
748 if(!emit_catch(ctx, 0))
749 return E_OUTOFMEMORY;
751 if(stat->stat.type == STAT_WHILE) {
752 loop_ctx = NULL;
753 }else {
754 if(!(stat_ctx.while_end_label = alloc_label(ctx)))
755 return E_OUTOFMEMORY;
756 loop_ctx = &stat_ctx;
759 hres = compile_statement(ctx, loop_ctx, stat->body);
760 if(FAILED(hres))
761 return hres;
763 hres = push_instr_addr(ctx, OP_jmp, start_addr);
764 if(FAILED(hres))
765 return hres;
767 instr_ptr(ctx, jmp_end)->arg1.uint = ctx->instr_cnt;
769 if(loop_ctx)
770 label_set_addr(ctx, stat_ctx.while_end_label);
772 return S_OK;
775 static HRESULT compile_dowhile_statement(compile_ctx_t *ctx, while_statement_t *stat)
777 statement_ctx_t loop_ctx = {0};
778 unsigned start_addr;
779 vbsop_t jmp_op;
780 HRESULT hres;
782 start_addr = ctx->instr_cnt;
784 if(!(loop_ctx.while_end_label = alloc_label(ctx)))
785 return E_OUTOFMEMORY;
787 hres = compile_statement(ctx, &loop_ctx, stat->body);
788 if(FAILED(hres))
789 return hres;
791 ctx->loc = stat->stat.loc;
792 if(stat->expr) {
793 hres = compile_expression(ctx, stat->expr);
794 if(FAILED(hres))
795 return hres;
797 jmp_op = stat->stat.type == STAT_DOUNTIL ? OP_jmp_false : OP_jmp_true;
798 }else {
799 jmp_op = OP_jmp;
802 hres = push_instr_addr(ctx, jmp_op, start_addr);
803 if(FAILED(hres))
804 return hres;
806 label_set_addr(ctx, loop_ctx.while_end_label);
808 if(!emit_catch(ctx, 0))
809 return E_OUTOFMEMORY;
811 return S_OK;
814 static HRESULT compile_foreach_statement(compile_ctx_t *ctx, foreach_statement_t *stat)
816 statement_ctx_t loop_ctx = {1};
817 unsigned loop_start;
818 HRESULT hres;
820 /* Preserve a place on the stack in case we throw before having proper enum collection. */
821 if(!push_instr(ctx, OP_empty))
822 return E_OUTOFMEMORY;
824 hres = compile_expression(ctx, stat->group_expr);
825 if(FAILED(hres))
826 return hres;
828 if(!push_instr(ctx, OP_newenum))
829 return E_OUTOFMEMORY;
831 if(!(loop_ctx.for_end_label = alloc_label(ctx)))
832 return E_OUTOFMEMORY;
834 hres = push_instr_uint_bstr(ctx, OP_enumnext, loop_ctx.for_end_label, stat->identifier);
835 if(FAILED(hres))
836 return hres;
838 if(!emit_catch(ctx, 1))
839 return E_OUTOFMEMORY;
841 loop_start = ctx->instr_cnt;
842 hres = compile_statement(ctx, &loop_ctx, stat->body);
843 if(FAILED(hres))
844 return hres;
846 /* We need a separated enumnext here, because we need to jump out of the loop on exception. */
847 ctx->loc = stat->stat.loc;
848 hres = push_instr_uint_bstr(ctx, OP_enumnext, loop_ctx.for_end_label, stat->identifier);
849 if(FAILED(hres))
850 return hres;
852 hres = push_instr_addr(ctx, OP_jmp, loop_start);
853 if(FAILED(hres))
854 return hres;
856 label_set_addr(ctx, loop_ctx.for_end_label);
858 if(!emit_catch(ctx, 0))
859 return E_OUTOFMEMORY;
861 return S_OK;
864 static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *stat)
866 statement_ctx_t loop_ctx = {2};
867 unsigned step_instr, instr;
868 BSTR identifier;
869 HRESULT hres;
871 identifier = alloc_bstr_arg(ctx, stat->identifier);
872 if(!identifier)
873 return E_OUTOFMEMORY;
875 hres = compile_expression(ctx, stat->from_expr);
876 if(FAILED(hres))
877 return hres;
878 if(!push_instr(ctx, OP_numval))
879 return E_OUTOFMEMORY;
881 /* FIXME: Assign should happen after both expressions evaluation. */
882 instr = push_instr(ctx, OP_assign_ident);
883 if(!instr)
884 return E_OUTOFMEMORY;
885 instr_ptr(ctx, instr)->arg1.bstr = identifier;
886 instr_ptr(ctx, instr)->arg2.uint = 0;
888 hres = compile_expression(ctx, stat->to_expr);
889 if(FAILED(hres))
890 return hres;
892 if(!push_instr(ctx, OP_numval))
893 return E_OUTOFMEMORY;
895 if(stat->step_expr) {
896 hres = compile_expression(ctx, stat->step_expr);
897 if(FAILED(hres))
898 return hres;
900 if(!push_instr(ctx, OP_numval))
901 return E_OUTOFMEMORY;
902 }else {
903 hres = push_instr_int(ctx, OP_int, 1);
904 if(FAILED(hres))
905 return hres;
908 loop_ctx.for_end_label = alloc_label(ctx);
909 if(!loop_ctx.for_end_label)
910 return E_OUTOFMEMORY;
912 step_instr = push_instr(ctx, OP_step);
913 if(!step_instr)
914 return E_OUTOFMEMORY;
915 instr_ptr(ctx, step_instr)->arg2.bstr = identifier;
916 instr_ptr(ctx, step_instr)->arg1.uint = loop_ctx.for_end_label;
918 if(!emit_catch(ctx, 2))
919 return E_OUTOFMEMORY;
921 hres = compile_statement(ctx, &loop_ctx, stat->body);
922 if(FAILED(hres))
923 return hres;
925 /* FIXME: Error handling can't be done compatible with native using OP_incc here. */
926 instr = push_instr(ctx, OP_incc);
927 if(!instr)
928 return E_OUTOFMEMORY;
929 instr_ptr(ctx, instr)->arg1.bstr = identifier;
931 hres = push_instr_addr(ctx, OP_jmp, step_instr);
932 if(FAILED(hres))
933 return hres;
935 hres = push_instr_uint(ctx, OP_pop, 2);
936 if(FAILED(hres))
937 return hres;
939 label_set_addr(ctx, loop_ctx.for_end_label);
941 /* FIXME: reconsider after OP_incc fixup. */
942 if(!emit_catch(ctx, 0))
943 return E_OUTOFMEMORY;
945 return S_OK;
948 static HRESULT compile_with_statement(compile_ctx_t *ctx, with_statement_t *stat)
950 statement_ctx_t with_ctx = { 1 };
951 HRESULT hres;
953 hres = compile_expression(ctx, stat->expr);
954 if(FAILED(hres))
955 return hres;
957 if(!emit_catch(ctx, 1))
958 return E_OUTOFMEMORY;
960 with_ctx.with_stack_offset = stack_offset(ctx) + 1;
961 hres = compile_statement(ctx, &with_ctx, stat->body);
962 if(FAILED(hres))
963 return hres;
965 return push_instr_uint(ctx, OP_pop, 1);
968 static HRESULT compile_select_statement(compile_ctx_t *ctx, select_statement_t *stat)
970 unsigned end_label, case_cnt = 0, *case_labels = NULL, i;
971 case_clausule_t *case_iter;
972 expression_t *expr_iter;
973 HRESULT hres;
975 hres = compile_expression(ctx, stat->expr);
976 if(FAILED(hres))
977 return hres;
979 if(!push_instr(ctx, OP_val))
980 return E_OUTOFMEMORY;
982 end_label = alloc_label(ctx);
983 if(!end_label)
984 return E_OUTOFMEMORY;
986 if(!emit_catch_jmp(ctx, 0, end_label))
987 return E_OUTOFMEMORY;
989 for(case_iter = stat->case_clausules; case_iter; case_iter = case_iter->next)
990 case_cnt++;
992 if(case_cnt) {
993 case_labels = malloc(case_cnt*sizeof(*case_labels));
994 if(!case_labels)
995 return E_OUTOFMEMORY;
998 for(case_iter = stat->case_clausules, i=0; case_iter; case_iter = case_iter->next, i++) {
999 case_labels[i] = alloc_label(ctx);
1000 if(!case_labels[i]) {
1001 hres = E_OUTOFMEMORY;
1002 break;
1005 if(!case_iter->expr)
1006 break;
1008 for(expr_iter = case_iter->expr; expr_iter; expr_iter = expr_iter->next) {
1009 hres = compile_expression(ctx, expr_iter);
1010 if(FAILED(hres))
1011 break;
1013 hres = push_instr_addr(ctx, OP_case, case_labels[i]);
1014 if(FAILED(hres))
1015 break;
1017 if(!emit_catch_jmp(ctx, 0, case_labels[i])) {
1018 hres = E_OUTOFMEMORY;
1019 break;
1024 if(FAILED(hres)) {
1025 free(case_labels);
1026 return hres;
1029 hres = push_instr_uint(ctx, OP_pop, 1);
1030 if(FAILED(hres)) {
1031 free(case_labels);
1032 return hres;
1035 hres = push_instr_addr(ctx, OP_jmp, case_iter ? case_labels[i] : end_label);
1036 if(FAILED(hres)) {
1037 free(case_labels);
1038 return hres;
1041 for(case_iter = stat->case_clausules, i=0; case_iter; case_iter = case_iter->next, i++) {
1042 label_set_addr(ctx, case_labels[i]);
1043 hres = compile_statement(ctx, NULL, case_iter->stat);
1044 if(FAILED(hres))
1045 break;
1047 if(!case_iter->next)
1048 break;
1050 hres = push_instr_addr(ctx, OP_jmp, end_label);
1051 if(FAILED(hres))
1052 break;
1055 free(case_labels);
1056 if(FAILED(hres))
1057 return hres;
1059 label_set_addr(ctx, end_label);
1060 return S_OK;
1063 static HRESULT compile_assignment(compile_ctx_t *ctx, expression_t *left, expression_t *value_expr, BOOL is_set)
1065 call_expression_t *call_expr = NULL;
1066 member_expression_t *member_expr;
1067 unsigned args_cnt = 0;
1068 vbsop_t op;
1069 HRESULT hres;
1071 switch(left->type) {
1072 case EXPR_MEMBER:
1073 member_expr = (member_expression_t*)left;
1074 break;
1075 case EXPR_CALL:
1076 call_expr = (call_expression_t*)left;
1077 assert(call_expr->call_expr->type == EXPR_MEMBER);
1078 member_expr = (member_expression_t*)call_expr->call_expr;
1079 break;
1080 default:
1081 assert(0);
1082 return E_FAIL;
1085 if(member_expr->obj_expr) {
1086 hres = compile_expression(ctx, member_expr->obj_expr);
1087 if(FAILED(hres))
1088 return hres;
1090 op = is_set ? OP_set_member : OP_assign_member;
1091 }else {
1092 op = is_set ? OP_set_ident : OP_assign_ident;
1095 hres = compile_expression(ctx, value_expr);
1096 if(FAILED(hres))
1097 return hres;
1099 if(call_expr) {
1100 hres = compile_args(ctx, call_expr->args, &args_cnt);
1101 if(FAILED(hres))
1102 return hres;
1105 hres = push_instr_bstr_uint(ctx, op, member_expr->identifier, args_cnt);
1106 if(FAILED(hres))
1107 return hres;
1109 if(!emit_catch(ctx, 0))
1110 return E_OUTOFMEMORY;
1112 return S_OK;
1115 static HRESULT compile_assign_statement(compile_ctx_t *ctx, assign_statement_t *stat, BOOL is_set)
1117 return compile_assignment(ctx, stat->left_expr, stat->value_expr, is_set);
1120 static HRESULT compile_call_statement(compile_ctx_t *ctx, call_statement_t *stat)
1122 HRESULT hres;
1124 hres = compile_call_expression(ctx, stat->expr, FALSE);
1125 if(FAILED(hres))
1126 return hres;
1128 if(!emit_catch(ctx, 0))
1129 return E_OUTOFMEMORY;
1131 return S_OK;
1134 static HRESULT compile_dim_statement(compile_ctx_t *ctx, dim_statement_t *stat)
1136 dim_decl_t *dim_decl = stat->dim_decls;
1138 while(1) {
1139 if(lookup_dim_decls(ctx, dim_decl->name) || lookup_args_name(ctx, dim_decl->name)
1140 || lookup_const_decls(ctx, dim_decl->name, FALSE)) {
1141 FIXME("dim %s name redefined\n", debugstr_w(dim_decl->name));
1142 return E_FAIL;
1145 ctx->func->var_cnt++;
1147 if(dim_decl->is_array) {
1148 HRESULT hres = push_instr_bstr_uint(ctx, OP_dim, dim_decl->name, ctx->func->array_cnt++);
1149 if(FAILED(hres))
1150 return hres;
1152 if(!emit_catch(ctx, 0))
1153 return E_OUTOFMEMORY;
1156 if(!dim_decl->next)
1157 break;
1158 dim_decl = dim_decl->next;
1161 if(ctx->dim_decls_tail)
1162 ctx->dim_decls_tail->next = stat->dim_decls;
1163 else
1164 ctx->dim_decls = stat->dim_decls;
1165 ctx->dim_decls_tail = dim_decl;
1166 return S_OK;
1169 static HRESULT compile_redim_statement(compile_ctx_t *ctx, redim_statement_t *stat)
1171 redim_decl_t *decl = stat->redim_decls;
1172 unsigned arg_cnt;
1173 HRESULT hres;
1175 while(1) {
1176 hres = compile_args(ctx, decl->dims, &arg_cnt);
1177 if(FAILED(hres))
1178 return hres;
1180 hres = push_instr_bstr_uint(ctx, stat->preserve ? OP_redim_preserve : OP_redim, decl->identifier, arg_cnt);
1181 if(FAILED(hres))
1182 return hres;
1184 if(!emit_catch(ctx, 0))
1185 return E_OUTOFMEMORY;
1187 if(!decl->next)
1188 break;
1189 decl = decl->next;
1192 return S_OK;
1195 static HRESULT compile_const_statement(compile_ctx_t *ctx, const_statement_t *stat)
1197 const_decl_t *decl, *next_decl = stat->decls;
1199 do {
1200 decl = next_decl;
1202 if(lookup_const_decls(ctx, decl->name, FALSE) || lookup_args_name(ctx, decl->name)
1203 || lookup_dim_decls(ctx, decl->name)) {
1204 FIXME("%s redefined\n", debugstr_w(decl->name));
1205 return E_FAIL;
1208 if(ctx->func->type == FUNC_GLOBAL) {
1209 HRESULT hres;
1211 hres = compile_expression(ctx, decl->value_expr);
1212 if(FAILED(hres))
1213 return hres;
1215 hres = push_instr_bstr(ctx, OP_const, decl->name);
1216 if(FAILED(hres))
1217 return hres;
1219 if(!emit_catch(ctx, 0))
1220 return E_OUTOFMEMORY;
1223 next_decl = decl->next;
1224 decl->next = ctx->const_decls;
1225 ctx->const_decls = decl;
1226 } while(next_decl);
1228 return S_OK;
1231 static HRESULT compile_function_statement(compile_ctx_t *ctx, function_statement_t *stat)
1233 if(ctx->func != &ctx->code->main_code) {
1234 FIXME("Function is not in the global code\n");
1235 return E_FAIL;
1238 stat->func_decl->next = ctx->func_decls;
1239 ctx->func_decls = stat->func_decl;
1240 return S_OK;
1243 static HRESULT compile_exitdo_statement(compile_ctx_t *ctx)
1245 statement_ctx_t *iter;
1246 unsigned pop_cnt = 0;
1248 for(iter = ctx->stat_ctx; iter; iter = iter->next) {
1249 pop_cnt += iter->stack_use;
1250 if(iter->while_end_label)
1251 break;
1253 if(!iter) {
1254 FIXME("Exit Do outside Do Loop\n");
1255 return E_FAIL;
1258 if(pop_cnt) {
1259 HRESULT hres;
1261 hres = push_instr_uint(ctx, OP_pop, pop_cnt);
1262 if(FAILED(hres))
1263 return hres;
1266 return push_instr_addr(ctx, OP_jmp, iter->while_end_label);
1269 static HRESULT compile_exitfor_statement(compile_ctx_t *ctx)
1271 statement_ctx_t *iter;
1272 unsigned pop_cnt = 0;
1274 for(iter = ctx->stat_ctx; iter; iter = iter->next) {
1275 pop_cnt += iter->stack_use;
1276 if(iter->for_end_label)
1277 break;
1279 if(!iter) {
1280 FIXME("Exit For outside For loop\n");
1281 return E_FAIL;
1284 if(pop_cnt) {
1285 HRESULT hres;
1287 hres = push_instr_uint(ctx, OP_pop, pop_cnt);
1288 if(FAILED(hres))
1289 return hres;
1292 return push_instr_addr(ctx, OP_jmp, iter->for_end_label);
1295 static HRESULT exit_label(compile_ctx_t *ctx, unsigned jmp_label)
1297 unsigned pop_cnt = stack_offset(ctx);
1299 if(pop_cnt) {
1300 HRESULT hres;
1302 hres = push_instr_uint(ctx, OP_pop, pop_cnt);
1303 if(FAILED(hres))
1304 return hres;
1307 return push_instr_addr(ctx, OP_jmp, jmp_label);
1310 static HRESULT compile_exitsub_statement(compile_ctx_t *ctx)
1312 if(!ctx->sub_end_label) {
1313 FIXME("Exit Sub outside Sub?\n");
1314 return E_FAIL;
1317 return exit_label(ctx, ctx->sub_end_label);
1320 static HRESULT compile_exitfunc_statement(compile_ctx_t *ctx)
1322 if(!ctx->func_end_label) {
1323 FIXME("Exit Function outside Function?\n");
1324 return E_FAIL;
1327 return exit_label(ctx, ctx->func_end_label);
1330 static HRESULT compile_exitprop_statement(compile_ctx_t *ctx)
1332 if(!ctx->prop_end_label) {
1333 FIXME("Exit Property outside Property?\n");
1334 return E_FAIL;
1337 return exit_label(ctx, ctx->prop_end_label);
1340 static HRESULT compile_onerror_statement(compile_ctx_t *ctx, onerror_statement_t *stat)
1342 return push_instr_int(ctx, OP_errmode, stat->resume_next);
1345 static HRESULT compile_retval_statement(compile_ctx_t *ctx, retval_statement_t *stat)
1347 HRESULT hres;
1349 hres = compile_expression(ctx, stat->expr);
1350 if(FAILED(hres))
1351 return hres;
1353 hres = push_instr(ctx, OP_retval);
1354 if(FAILED(hres))
1355 return hres;
1357 return S_OK;
1360 static HRESULT compile_statement(compile_ctx_t *ctx, statement_ctx_t *stat_ctx, statement_t *stat)
1362 HRESULT hres;
1364 if(stat_ctx) {
1365 stat_ctx->next = ctx->stat_ctx;
1366 ctx->stat_ctx = stat_ctx;
1369 while(stat) {
1370 ctx->loc = stat->loc;
1372 switch(stat->type) {
1373 case STAT_ASSIGN:
1374 hres = compile_assign_statement(ctx, (assign_statement_t*)stat, FALSE);
1375 break;
1376 case STAT_CALL:
1377 hres = compile_call_statement(ctx, (call_statement_t*)stat);
1378 break;
1379 case STAT_CONST:
1380 hres = compile_const_statement(ctx, (const_statement_t*)stat);
1381 break;
1382 case STAT_DIM:
1383 hres = compile_dim_statement(ctx, (dim_statement_t*)stat);
1384 break;
1385 case STAT_DOWHILE:
1386 case STAT_DOUNTIL:
1387 hres = compile_dowhile_statement(ctx, (while_statement_t*)stat);
1388 break;
1389 case STAT_EXITDO:
1390 hres = compile_exitdo_statement(ctx);
1391 break;
1392 case STAT_EXITFOR:
1393 hres = compile_exitfor_statement(ctx);
1394 break;
1395 case STAT_EXITFUNC:
1396 hres = compile_exitfunc_statement(ctx);
1397 break;
1398 case STAT_EXITPROP:
1399 hres = compile_exitprop_statement(ctx);
1400 break;
1401 case STAT_EXITSUB:
1402 hres = compile_exitsub_statement(ctx);
1403 break;
1404 case STAT_FOREACH:
1405 hres = compile_foreach_statement(ctx, (foreach_statement_t*)stat);
1406 break;
1407 case STAT_FORTO:
1408 hres = compile_forto_statement(ctx, (forto_statement_t*)stat);
1409 break;
1410 case STAT_FUNC:
1411 hres = compile_function_statement(ctx, (function_statement_t*)stat);
1412 break;
1413 case STAT_IF:
1414 hres = compile_if_statement(ctx, (if_statement_t*)stat);
1415 break;
1416 case STAT_ONERROR:
1417 hres = compile_onerror_statement(ctx, (onerror_statement_t*)stat);
1418 break;
1419 case STAT_REDIM:
1420 hres = compile_redim_statement(ctx, (redim_statement_t*)stat);
1421 break;
1422 case STAT_SELECT:
1423 hres = compile_select_statement(ctx, (select_statement_t*)stat);
1424 break;
1425 case STAT_SET:
1426 hres = compile_assign_statement(ctx, (assign_statement_t*)stat, TRUE);
1427 break;
1428 case STAT_STOP:
1429 hres = push_instr(ctx, OP_stop) ? S_OK : E_OUTOFMEMORY;
1430 break;
1431 case STAT_UNTIL:
1432 case STAT_WHILE:
1433 case STAT_WHILELOOP:
1434 hres = compile_while_statement(ctx, (while_statement_t*)stat);
1435 break;
1436 case STAT_WITH:
1437 hres = compile_with_statement(ctx, (with_statement_t*)stat);
1438 break;
1439 case STAT_RETVAL:
1440 hres = compile_retval_statement(ctx, (retval_statement_t*)stat);
1441 break;
1442 default:
1443 FIXME("Unimplemented statement type %d\n", stat->type);
1444 hres = E_NOTIMPL;
1447 if(FAILED(hres))
1448 return hres;
1449 stat = stat->next;
1452 if(stat_ctx) {
1453 assert(ctx->stat_ctx == stat_ctx);
1454 ctx->stat_ctx = stat_ctx->next;
1457 return S_OK;
1460 static void resolve_labels(compile_ctx_t *ctx, unsigned off)
1462 instr_t *instr;
1464 for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->instr_cnt; instr++) {
1465 if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->arg1.uint & LABEL_FLAG)) {
1466 assert((instr->arg1.uint & ~LABEL_FLAG) < ctx->labels_cnt);
1467 instr->arg1.uint = ctx->labels[instr->arg1.uint & ~LABEL_FLAG];
1469 assert(instr_info[instr->op].arg2_type != ARG_ADDR);
1472 ctx->labels_cnt = 0;
1475 static HRESULT fill_array_desc(compile_ctx_t *ctx, dim_decl_t *dim_decl, array_desc_t *array_desc)
1477 unsigned dim_cnt = 0, i;
1478 dim_list_t *iter;
1480 for(iter = dim_decl->dims; iter; iter = iter->next)
1481 dim_cnt++;
1483 array_desc->bounds = compiler_alloc(ctx->code, dim_cnt * sizeof(SAFEARRAYBOUND));
1484 if(!array_desc->bounds)
1485 return E_OUTOFMEMORY;
1487 array_desc->dim_cnt = dim_cnt;
1489 for(iter = dim_decl->dims, i=0; iter; iter = iter->next, i++) {
1490 array_desc->bounds[i].cElements = iter->val+1;
1491 array_desc->bounds[i].lLbound = 0;
1494 return S_OK;
1497 static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *func)
1499 HRESULT hres;
1501 func->code_off = ctx->instr_cnt;
1503 ctx->sub_end_label = 0;
1504 ctx->func_end_label = 0;
1505 ctx->prop_end_label = 0;
1507 switch(func->type) {
1508 case FUNC_FUNCTION:
1509 ctx->func_end_label = alloc_label(ctx);
1510 if(!ctx->func_end_label)
1511 return E_OUTOFMEMORY;
1512 break;
1513 case FUNC_SUB:
1514 ctx->sub_end_label = alloc_label(ctx);
1515 if(!ctx->sub_end_label)
1516 return E_OUTOFMEMORY;
1517 break;
1518 case FUNC_PROPGET:
1519 case FUNC_PROPLET:
1520 case FUNC_PROPSET:
1521 ctx->prop_end_label = alloc_label(ctx);
1522 if(!ctx->prop_end_label)
1523 return E_OUTOFMEMORY;
1524 break;
1525 case FUNC_GLOBAL:
1526 break;
1529 ctx->func = func;
1530 ctx->dim_decls = ctx->dim_decls_tail = NULL;
1531 ctx->const_decls = NULL;
1532 hres = compile_statement(ctx, NULL, stat);
1533 ctx->func = NULL;
1534 if(FAILED(hres))
1535 return hres;
1537 if(ctx->sub_end_label)
1538 label_set_addr(ctx, ctx->sub_end_label);
1539 if(ctx->func_end_label)
1540 label_set_addr(ctx, ctx->func_end_label);
1541 if(ctx->prop_end_label)
1542 label_set_addr(ctx, ctx->prop_end_label);
1544 if(!push_instr(ctx, OP_ret))
1545 return E_OUTOFMEMORY;
1547 resolve_labels(ctx, func->code_off);
1549 if(func->var_cnt) {
1550 dim_decl_t *dim_decl;
1551 unsigned i;
1553 func->vars = compiler_alloc(ctx->code, func->var_cnt * sizeof(var_desc_t));
1554 if(!func->vars)
1555 return E_OUTOFMEMORY;
1557 for(dim_decl = ctx->dim_decls, i=0; dim_decl; dim_decl = dim_decl->next, i++) {
1558 func->vars[i].name = compiler_alloc_string(ctx->code, dim_decl->name);
1559 if(!func->vars[i].name)
1560 return E_OUTOFMEMORY;
1563 assert(i == func->var_cnt);
1566 if(func->array_cnt) {
1567 unsigned array_id = 0;
1568 dim_decl_t *dim_decl;
1570 func->array_descs = compiler_alloc(ctx->code, func->array_cnt * sizeof(array_desc_t));
1571 if(!func->array_descs)
1572 return E_OUTOFMEMORY;
1574 for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
1575 if(dim_decl->is_array) {
1576 hres = fill_array_desc(ctx, dim_decl, func->array_descs + array_id++);
1577 if(FAILED(hres))
1578 return hres;
1582 assert(array_id == func->array_cnt);
1585 return S_OK;
1588 static BOOL lookup_funcs_name(compile_ctx_t *ctx, const WCHAR *name)
1590 function_t *iter;
1592 for(iter = ctx->code->funcs; iter; iter = iter->next) {
1593 if(!wcsicmp(iter->name, name))
1594 return TRUE;
1597 return FALSE;
1600 static HRESULT create_function(compile_ctx_t *ctx, function_decl_t *decl, function_t **ret)
1602 function_t *func;
1603 HRESULT hres;
1605 if(lookup_dim_decls(ctx, decl->name) || lookup_const_decls(ctx, decl->name, FALSE)) {
1606 FIXME("%s: redefinition\n", debugstr_w(decl->name));
1607 return E_FAIL;
1610 func = compiler_alloc(ctx->code, sizeof(*func));
1611 if(!func)
1612 return E_OUTOFMEMORY;
1614 func->name = compiler_alloc_string(ctx->code, decl->name);
1615 if(!func->name)
1616 return E_OUTOFMEMORY;
1618 func->vars = NULL;
1619 func->var_cnt = 0;
1620 func->array_cnt = 0;
1621 func->code_ctx = ctx->code;
1622 func->type = decl->type;
1623 func->is_public = decl->is_public;
1625 func->arg_cnt = 0;
1626 if(decl->args) {
1627 arg_decl_t *arg;
1628 unsigned i;
1630 for(arg = decl->args; arg; arg = arg->next)
1631 func->arg_cnt++;
1633 func->args = compiler_alloc(ctx->code, func->arg_cnt * sizeof(arg_desc_t));
1634 if(!func->args)
1635 return E_OUTOFMEMORY;
1637 for(i = 0, arg = decl->args; arg; arg = arg->next, i++) {
1638 func->args[i].name = compiler_alloc_string(ctx->code, arg->name);
1639 if(!func->args[i].name)
1640 return E_OUTOFMEMORY;
1641 func->args[i].by_ref = arg->by_ref;
1643 }else {
1644 func->args = NULL;
1647 hres = compile_func(ctx, decl->body, func);
1648 if(FAILED(hres))
1649 return hres;
1651 *ret = func;
1652 return S_OK;
1655 static BOOL lookup_class_name(compile_ctx_t *ctx, const WCHAR *name)
1657 class_desc_t *iter;
1659 for(iter = ctx->code->classes; iter; iter = iter->next) {
1660 if(!wcsicmp(iter->name, name))
1661 return TRUE;
1664 return FALSE;
1667 static HRESULT create_class_funcprop(compile_ctx_t *ctx, function_decl_t *func_decl, vbdisp_funcprop_desc_t *desc)
1669 vbdisp_invoke_type_t invoke_type;
1670 function_decl_t *funcprop_decl;
1671 HRESULT hres;
1673 desc->name = compiler_alloc_string(ctx->code, func_decl->name);
1674 if(!desc->name)
1675 return E_OUTOFMEMORY;
1677 for(funcprop_decl = func_decl; funcprop_decl; funcprop_decl = funcprop_decl->next_prop_func) {
1678 switch(funcprop_decl->type) {
1679 case FUNC_FUNCTION:
1680 case FUNC_SUB:
1681 case FUNC_PROPGET:
1682 invoke_type = VBDISP_CALLGET;
1683 break;
1684 case FUNC_PROPLET:
1685 invoke_type = VBDISP_LET;
1686 break;
1687 case FUNC_PROPSET:
1688 invoke_type = VBDISP_SET;
1689 break;
1690 DEFAULT_UNREACHABLE;
1693 assert(!desc->entries[invoke_type]);
1695 if(funcprop_decl->is_public)
1696 desc->is_public = TRUE;
1698 hres = create_function(ctx, funcprop_decl, desc->entries+invoke_type);
1699 if(FAILED(hres))
1700 return hres;
1703 return S_OK;
1706 static BOOL lookup_class_funcs(class_desc_t *class_desc, const WCHAR *name)
1708 unsigned i;
1710 for(i=0; i < class_desc->func_cnt; i++) {
1711 if(class_desc->funcs[i].name && !wcsicmp(class_desc->funcs[i].name, name))
1712 return TRUE;
1715 return FALSE;
1718 static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl)
1720 function_decl_t *func_decl, *func_prop_decl;
1721 BOOL is_default, have_default = FALSE;
1722 class_desc_t *class_desc;
1723 dim_decl_t *prop_decl;
1724 unsigned i;
1725 HRESULT hres;
1727 if(lookup_dim_decls(ctx, class_decl->name) || lookup_funcs_name(ctx, class_decl->name)
1728 || lookup_const_decls(ctx, class_decl->name, FALSE) || lookup_class_name(ctx, class_decl->name)) {
1729 FIXME("%s: redefinition\n", debugstr_w(class_decl->name));
1730 return E_FAIL;
1733 class_desc = compiler_alloc_zero(ctx->code, sizeof(*class_desc));
1734 if(!class_desc)
1735 return E_OUTOFMEMORY;
1737 class_desc->name = compiler_alloc_string(ctx->code, class_decl->name);
1738 if(!class_desc->name)
1739 return E_OUTOFMEMORY;
1741 class_desc->func_cnt = 1; /* always allocate slot for default getter or method */
1743 for(func_decl = class_decl->funcs; func_decl; func_decl = func_decl->next) {
1744 is_default = FALSE;
1745 for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) {
1746 if(func_prop_decl->is_default) {
1747 if(have_default) {
1748 FIXME("multiple default getters or methods\n");
1749 return E_FAIL;
1751 is_default = have_default = TRUE;
1752 break;
1755 if(!is_default)
1756 class_desc->func_cnt++;
1759 class_desc->funcs = compiler_alloc(ctx->code, class_desc->func_cnt*sizeof(*class_desc->funcs));
1760 if(!class_desc->funcs)
1761 return E_OUTOFMEMORY;
1762 memset(class_desc->funcs, 0, class_desc->func_cnt*sizeof(*class_desc->funcs));
1764 for(func_decl = class_decl->funcs, i=1; func_decl; func_decl = func_decl->next, i++) {
1765 for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) {
1766 if(func_prop_decl->is_default) {
1767 i--;
1768 break;
1772 if(!wcsicmp(L"class_initialize", func_decl->name)) {
1773 if(func_decl->type != FUNC_SUB) {
1774 FIXME("class initializer is not sub\n");
1775 return E_FAIL;
1778 class_desc->class_initialize_id = i;
1779 }else if(!wcsicmp(L"class_terminate", func_decl->name)) {
1780 if(func_decl->type != FUNC_SUB) {
1781 FIXME("class terminator is not sub\n");
1782 return E_FAIL;
1785 class_desc->class_terminate_id = i;
1788 hres = create_class_funcprop(ctx, func_decl, class_desc->funcs + (func_prop_decl ? 0 : i));
1789 if(FAILED(hres))
1790 return hres;
1793 for(prop_decl = class_decl->props; prop_decl; prop_decl = prop_decl->next)
1794 class_desc->prop_cnt++;
1796 class_desc->props = compiler_alloc(ctx->code, class_desc->prop_cnt*sizeof(*class_desc->props));
1797 if(!class_desc->props)
1798 return E_OUTOFMEMORY;
1800 for(prop_decl = class_decl->props, i=0; prop_decl; prop_decl = prop_decl->next, i++) {
1801 if(lookup_class_funcs(class_desc, prop_decl->name)) {
1802 FIXME("Property %s redefined\n", debugstr_w(prop_decl->name));
1803 return E_FAIL;
1806 class_desc->props[i].name = compiler_alloc_string(ctx->code, prop_decl->name);
1807 if(!class_desc->props[i].name)
1808 return E_OUTOFMEMORY;
1810 class_desc->props[i].is_public = prop_decl->is_public;
1811 class_desc->props[i].is_array = prop_decl->is_array;
1813 if(prop_decl->is_array)
1814 class_desc->array_cnt++;
1817 if(class_desc->array_cnt) {
1818 class_desc->array_descs = compiler_alloc(ctx->code, class_desc->array_cnt*sizeof(*class_desc->array_descs));
1819 if(!class_desc->array_descs)
1820 return E_OUTOFMEMORY;
1822 for(prop_decl = class_decl->props, i=0; prop_decl; prop_decl = prop_decl->next) {
1823 if(prop_decl->is_array) {
1824 hres = fill_array_desc(ctx, prop_decl, class_desc->array_descs + i++);
1825 if(FAILED(hres))
1826 return hres;
1831 class_desc->next = ctx->code->classes;
1832 ctx->code->classes = class_desc;
1833 return S_OK;
1836 static BOOL lookup_script_identifier(compile_ctx_t *ctx, script_ctx_t *script, const WCHAR *identifier)
1838 ScriptDisp *contexts[] = {
1839 ctx->code->named_item ? ctx->code->named_item->script_obj : NULL,
1840 script->script_obj
1842 class_desc_t *class;
1843 vbscode_t *code;
1844 unsigned c, i;
1846 for(c = 0; c < ARRAY_SIZE(contexts); c++) {
1847 if(!contexts[c]) continue;
1849 for(i = 0; i < contexts[c]->global_vars_cnt; i++) {
1850 if(!wcsicmp(contexts[c]->global_vars[i]->name, identifier))
1851 return TRUE;
1854 for(i = 0; i < contexts[c]->global_funcs_cnt; i++) {
1855 if(!wcsicmp(contexts[c]->global_funcs[i]->name, identifier))
1856 return TRUE;
1859 for(class = contexts[c]->classes; class; class = class->next) {
1860 if(!wcsicmp(class->name, identifier))
1861 return TRUE;
1865 LIST_FOR_EACH_ENTRY(code, &script->code_list, vbscode_t, entry) {
1866 unsigned var_cnt = code->main_code.var_cnt;
1867 var_desc_t *vars = code->main_code.vars;
1868 function_t *func;
1870 if(!code->pending_exec || (code->named_item && code->named_item != ctx->code->named_item))
1871 continue;
1873 for(i = 0; i < var_cnt; i++) {
1874 if(!wcsicmp(vars[i].name, identifier))
1875 return TRUE;
1878 for(func = code->funcs; func; func = func->next) {
1879 if(!wcsicmp(func->name, identifier))
1880 return TRUE;
1883 for(class = code->classes; class; class = class->next) {
1884 if(!wcsicmp(class->name, identifier))
1885 return TRUE;
1889 return FALSE;
1892 static HRESULT check_script_collisions(compile_ctx_t *ctx, script_ctx_t *script)
1894 unsigned i, var_cnt = ctx->code->main_code.var_cnt;
1895 var_desc_t *vars = ctx->code->main_code.vars;
1896 class_desc_t *class;
1898 for(i = 0; i < var_cnt; i++) {
1899 if(lookup_script_identifier(ctx, script, vars[i].name)) {
1900 FIXME("%s: redefined\n", debugstr_w(vars[i].name));
1901 return E_FAIL;
1905 for(class = ctx->code->classes; class; class = class->next) {
1906 if(lookup_script_identifier(ctx, script, class->name)) {
1907 FIXME("%s: redefined\n", debugstr_w(class->name));
1908 return E_FAIL;
1912 return S_OK;
1915 void release_vbscode(vbscode_t *code)
1917 unsigned i;
1919 if(--code->ref)
1920 return;
1922 for(i=0; i < code->bstr_cnt; i++)
1923 SysFreeString(code->bstr_pool[i]);
1925 if(code->named_item)
1926 release_named_item(code->named_item);
1927 heap_pool_free(&code->heap);
1929 free(code->bstr_pool);
1930 free(code->source);
1931 free(code->instrs);
1932 free(code);
1935 static vbscode_t *alloc_vbscode(compile_ctx_t *ctx, const WCHAR *source, DWORD_PTR cookie, unsigned start_line)
1937 vbscode_t *ret;
1938 size_t len;
1940 len = source ? lstrlenW(source) : 0;
1941 if(len > INT32_MAX)
1942 return NULL;
1944 ret = calloc(1, sizeof(*ret));
1945 if(!ret)
1946 return NULL;
1948 ret->source = malloc((len + 1) * sizeof(WCHAR));
1949 if(!ret->source) {
1950 free(ret);
1951 return NULL;
1953 if(len)
1954 memcpy(ret->source, source, len * sizeof(WCHAR));
1955 ret->source[len] = 0;
1957 ret->ref = 1;
1958 ret->cookie = cookie;
1959 ret->start_line = start_line;
1961 ret->instrs = malloc(32*sizeof(instr_t));
1962 if(!ret->instrs) {
1963 release_vbscode(ret);
1964 return NULL;
1967 ctx->instr_cnt = 1;
1968 ctx->instr_size = 32;
1969 heap_pool_init(&ret->heap);
1971 ret->main_code.type = FUNC_GLOBAL;
1972 ret->main_code.code_ctx = ret;
1974 list_init(&ret->entry);
1975 return ret;
1978 static void release_compiler(compile_ctx_t *ctx)
1980 parser_release(&ctx->parser);
1981 free(ctx->labels);
1982 if(ctx->code)
1983 release_vbscode(ctx->code);
1986 HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *item_name, const WCHAR *delimiter,
1987 DWORD_PTR cookie, unsigned start_line, DWORD flags, vbscode_t **ret)
1989 function_decl_t *func_decl;
1990 named_item_t *item = NULL;
1991 class_decl_t *class_decl;
1992 function_t *new_func;
1993 compile_ctx_t ctx;
1994 vbscode_t *code;
1995 HRESULT hres;
1997 if(item_name) {
1998 item = lookup_named_item(script, item_name, 0);
1999 if(!item) {
2000 WARN("Unknown context %s\n", debugstr_w(item_name));
2001 return E_INVALIDARG;
2003 if(!item->script_obj) item = NULL;
2006 memset(&ctx, 0, sizeof(ctx));
2007 code = ctx.code = alloc_vbscode(&ctx, src, cookie, start_line);
2008 if(!ctx.code)
2009 return E_OUTOFMEMORY;
2010 if(item) {
2011 code->named_item = item;
2012 item->ref++;
2015 ctx.parser.lcid = script->lcid;
2016 hres = parse_script(&ctx.parser, code->source, delimiter, flags);
2017 if(FAILED(hres)) {
2018 if(ctx.parser.error_loc != -1)
2019 ctx.loc = ctx.parser.error_loc;
2020 hres = compile_error(script, &ctx, hres);
2021 release_vbscode(code);
2022 return hres;
2025 hres = compile_func(&ctx, ctx.parser.stats, &ctx.code->main_code);
2026 if(FAILED(hres)) {
2027 hres = compile_error(script, &ctx, hres);
2028 release_compiler(&ctx);
2029 return hres;
2032 code->option_explicit = ctx.parser.option_explicit;
2033 ctx.global_consts = ctx.const_decls;
2034 code->option_explicit = ctx.parser.option_explicit;
2037 for(func_decl = ctx.func_decls; func_decl; func_decl = func_decl->next) {
2038 hres = create_function(&ctx, func_decl, &new_func);
2039 if(FAILED(hres)) {
2040 hres = compile_error(script, &ctx, hres);
2041 release_compiler(&ctx);
2042 return hres;
2045 new_func->next = ctx.code->funcs;
2046 ctx.code->funcs = new_func;
2049 for(class_decl = ctx.parser.class_decls; class_decl; class_decl = class_decl->next) {
2050 hres = compile_class(&ctx, class_decl);
2051 if(FAILED(hres)) {
2052 hres = compile_error(script, &ctx, hres);
2053 release_compiler(&ctx);
2054 return hres;
2058 hres = check_script_collisions(&ctx, script);
2059 if(FAILED(hres)) {
2060 hres = compile_error(script, &ctx, hres);
2061 release_compiler(&ctx);
2062 return hres;
2065 code->is_persistent = (flags & SCRIPTTEXT_ISPERSISTENT) != 0;
2067 if(TRACE_ON(vbscript_disas))
2068 dump_code(&ctx);
2070 ctx.code = NULL;
2071 release_compiler(&ctx);
2073 list_add_tail(&script->code_list, &code->entry);
2074 *ret = code;
2075 return S_OK;
2078 HRESULT compile_procedure(script_ctx_t *script, const WCHAR *src, const WCHAR *item_name, const WCHAR *delimiter,
2079 DWORD_PTR cookie, unsigned start_line, DWORD flags, class_desc_t **ret)
2081 class_desc_t *desc;
2082 vbscode_t *code;
2083 HRESULT hres;
2085 hres = compile_script(script, src, item_name, delimiter, cookie, start_line,
2086 flags & ~SCRIPTTEXT_ISPERSISTENT, &code);
2087 if(FAILED(hres))
2088 return hres;
2090 if(!(desc = compiler_alloc_zero(code, sizeof(*desc))))
2091 return E_OUTOFMEMORY;
2092 if(!(desc->funcs = compiler_alloc_zero(code, sizeof(*desc->funcs))))
2093 return E_OUTOFMEMORY;
2095 desc->ctx = script;
2096 desc->func_cnt = 1;
2097 desc->funcs->entries[VBDISP_CALLGET] = &code->main_code;
2099 *ret = desc;
2100 return S_OK;