ntoskrnl.exe: Add KeQueryActiveProcessorCountEx() function.
[wine.git] / dlls / vbscript / compile.c
blob164c2d15cfa7ca954d3901aecdce7c7bc643aa85
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_DOUBLE:
96 TRACE_(vbscript_disas)("\t%lf", *arg->dbl);
97 break;
98 case ARG_NONE:
99 break;
100 DEFAULT_UNREACHABLE;
104 static void dump_code(compile_ctx_t *ctx)
106 instr_t *instr;
108 for(instr = ctx->code->instrs+1; instr < ctx->code->instrs+ctx->instr_cnt; instr++) {
109 assert(instr->op < OP_LAST);
110 TRACE_(vbscript_disas)("%d:\t%s", (int)(instr-ctx->code->instrs), instr_info[instr->op].op_str);
111 dump_instr_arg(instr_info[instr->op].arg1_type, &instr->arg1);
112 dump_instr_arg(instr_info[instr->op].arg2_type, &instr->arg2);
113 TRACE_(vbscript_disas)("\n");
117 static inline void *compiler_alloc(vbscode_t *vbscode, size_t size)
119 return heap_pool_alloc(&vbscode->heap, size);
122 static inline void *compiler_alloc_zero(vbscode_t *vbscode, size_t size)
124 void *ret;
126 ret = heap_pool_alloc(&vbscode->heap, size);
127 if(ret)
128 memset(ret, 0, size);
129 return ret;
132 static WCHAR *compiler_alloc_string(vbscode_t *vbscode, const WCHAR *str)
134 size_t size;
135 WCHAR *ret;
137 size = (lstrlenW(str)+1)*sizeof(WCHAR);
138 ret = compiler_alloc(vbscode, size);
139 if(ret)
140 memcpy(ret, str, size);
141 return ret;
144 static inline instr_t *instr_ptr(compile_ctx_t *ctx, unsigned id)
146 assert(id < ctx->instr_cnt);
147 return ctx->code->instrs + id;
150 static unsigned push_instr(compile_ctx_t *ctx, vbsop_t op)
152 assert(ctx->instr_size && ctx->instr_size >= ctx->instr_cnt);
154 if(ctx->instr_size == ctx->instr_cnt) {
155 instr_t *new_instr;
157 new_instr = heap_realloc(ctx->code->instrs, ctx->instr_size*2*sizeof(instr_t));
158 if(!new_instr)
159 return 0;
161 ctx->code->instrs = new_instr;
162 ctx->instr_size *= 2;
165 ctx->code->instrs[ctx->instr_cnt].op = op;
166 ctx->code->instrs[ctx->instr_cnt].loc = ctx->loc;
167 return ctx->instr_cnt++;
170 static HRESULT push_instr_int(compile_ctx_t *ctx, vbsop_t op, LONG arg)
172 unsigned ret;
174 ret = push_instr(ctx, op);
175 if(!ret)
176 return E_OUTOFMEMORY;
178 instr_ptr(ctx, ret)->arg1.lng = arg;
179 return S_OK;
182 static HRESULT push_instr_uint(compile_ctx_t *ctx, vbsop_t op, unsigned arg)
184 unsigned ret;
186 ret = push_instr(ctx, op);
187 if(!ret)
188 return E_OUTOFMEMORY;
190 instr_ptr(ctx, ret)->arg1.uint = arg;
191 return S_OK;
194 static HRESULT push_instr_addr(compile_ctx_t *ctx, vbsop_t op, unsigned arg)
196 unsigned ret;
198 ret = push_instr(ctx, op);
199 if(!ret)
200 return E_OUTOFMEMORY;
202 instr_ptr(ctx, ret)->arg1.uint = arg;
203 return S_OK;
206 static HRESULT push_instr_str(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg)
208 unsigned instr;
209 WCHAR *str;
211 str = compiler_alloc_string(ctx->code, arg);
212 if(!str)
213 return E_OUTOFMEMORY;
215 instr = push_instr(ctx, op);
216 if(!instr)
217 return E_OUTOFMEMORY;
219 instr_ptr(ctx, instr)->arg1.str = str;
220 return S_OK;
223 static HRESULT push_instr_double(compile_ctx_t *ctx, vbsop_t op, double arg)
225 unsigned instr;
226 double *d;
228 d = compiler_alloc(ctx->code, sizeof(double));
229 if(!d)
230 return E_OUTOFMEMORY;
232 instr = push_instr(ctx, op);
233 if(!instr)
234 return E_OUTOFMEMORY;
236 *d = arg;
237 instr_ptr(ctx, instr)->arg1.dbl = d;
238 return S_OK;
241 static BSTR alloc_bstr_arg(compile_ctx_t *ctx, const WCHAR *str)
243 if(!ctx->code->bstr_pool_size) {
244 ctx->code->bstr_pool = heap_alloc(8 * sizeof(BSTR));
245 if(!ctx->code->bstr_pool)
246 return NULL;
247 ctx->code->bstr_pool_size = 8;
248 }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) {
249 BSTR *new_pool;
251 new_pool = heap_realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR));
252 if(!new_pool)
253 return NULL;
255 ctx->code->bstr_pool = new_pool;
256 ctx->code->bstr_pool_size *= 2;
259 ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocString(str);
260 if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
261 return NULL;
263 return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
266 static HRESULT push_instr_bstr(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg)
268 unsigned instr;
269 BSTR bstr;
271 bstr = alloc_bstr_arg(ctx, arg);
272 if(!bstr)
273 return E_OUTOFMEMORY;
275 instr = push_instr(ctx, op);
276 if(!instr)
277 return E_OUTOFMEMORY;
279 instr_ptr(ctx, instr)->arg1.bstr = bstr;
280 return S_OK;
283 static HRESULT push_instr_bstr_uint(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg1, unsigned arg2)
285 unsigned instr;
286 BSTR bstr;
288 bstr = alloc_bstr_arg(ctx, arg1);
289 if(!bstr)
290 return E_OUTOFMEMORY;
292 instr = push_instr(ctx, op);
293 if(!instr)
294 return E_OUTOFMEMORY;
296 instr_ptr(ctx, instr)->arg1.bstr = bstr;
297 instr_ptr(ctx, instr)->arg2.uint = arg2;
298 return S_OK;
301 static HRESULT push_instr_uint_bstr(compile_ctx_t *ctx, vbsop_t op, unsigned arg1, const WCHAR *arg2)
303 unsigned instr;
304 BSTR bstr;
306 bstr = alloc_bstr_arg(ctx, arg2);
307 if(!bstr)
308 return E_OUTOFMEMORY;
310 instr = push_instr(ctx, op);
311 if(!instr)
312 return E_OUTOFMEMORY;
314 instr_ptr(ctx, instr)->arg1.uint = arg1;
315 instr_ptr(ctx, instr)->arg2.bstr = bstr;
316 return S_OK;
319 #define LABEL_FLAG 0x80000000
321 static unsigned alloc_label(compile_ctx_t *ctx)
323 if(!ctx->labels_size) {
324 ctx->labels = heap_alloc(8 * sizeof(*ctx->labels));
325 if(!ctx->labels)
326 return 0;
327 ctx->labels_size = 8;
328 }else if(ctx->labels_size == ctx->labels_cnt) {
329 unsigned *new_labels;
331 new_labels = heap_realloc(ctx->labels, 2*ctx->labels_size*sizeof(*ctx->labels));
332 if(!new_labels)
333 return 0;
335 ctx->labels = new_labels;
336 ctx->labels_size *= 2;
339 return ctx->labels_cnt++ | LABEL_FLAG;
342 static inline void label_set_addr(compile_ctx_t *ctx, unsigned label)
344 assert(label & LABEL_FLAG);
345 ctx->labels[label & ~LABEL_FLAG] = ctx->instr_cnt;
348 static inline unsigned stack_offset(compile_ctx_t *ctx)
350 statement_ctx_t *iter;
351 unsigned ret = 0;
353 for(iter = ctx->stat_ctx; iter; iter = iter->next)
354 ret += iter->stack_use;
356 return ret;
359 static BOOL emit_catch_jmp(compile_ctx_t *ctx, unsigned stack_off, unsigned code_off)
361 unsigned code;
363 code = push_instr(ctx, OP_catch);
364 if(!code)
365 return FALSE;
367 instr_ptr(ctx, code)->arg1.uint = code_off;
368 instr_ptr(ctx, code)->arg2.uint = stack_off + stack_offset(ctx);
369 return TRUE;
372 static inline BOOL emit_catch(compile_ctx_t *ctx, unsigned off)
374 return emit_catch_jmp(ctx, off, ctx->instr_cnt);
377 static HRESULT compile_error(script_ctx_t *ctx, compile_ctx_t *compiler, HRESULT error)
379 if(error == SCRIPT_E_REPORTED)
380 return error;
382 clear_ei(&ctx->ei);
383 ctx->ei.scode = error = map_hres(error);
384 ctx->ei.bstrSource = get_vbscript_string(VBS_COMPILE_ERROR);
385 ctx->ei.bstrDescription = get_vbscript_error_string(error);
386 return report_script_error(ctx, compiler->code, compiler->loc);
389 static expression_t *lookup_const_decls(compile_ctx_t *ctx, const WCHAR *name, BOOL lookup_global)
391 const_decl_t *decl;
393 for(decl = ctx->const_decls; decl; decl = decl->next) {
394 if(!wcsicmp(decl->name, name))
395 return decl->value_expr;
398 if(!lookup_global)
399 return NULL;
401 for(decl = ctx->global_consts; decl; decl = decl->next) {
402 if(!wcsicmp(decl->name, name))
403 return decl->value_expr;
406 return NULL;
409 static HRESULT compile_args(compile_ctx_t *ctx, expression_t *args, unsigned *ret)
411 unsigned arg_cnt = 0;
412 HRESULT hres;
414 while(args) {
415 hres = compile_expression(ctx, args);
416 if(FAILED(hres))
417 return hres;
419 if(args->type == EXPR_BRACKETS && !push_instr(ctx, OP_deref))
420 return E_OUTOFMEMORY;
422 arg_cnt++;
423 args = args->next;
426 *ret = arg_cnt;
427 return S_OK;
430 static HRESULT compile_member_expression(compile_ctx_t *ctx, member_expression_t *expr, unsigned arg_cnt, BOOL ret_val)
432 HRESULT hres;
434 if(ret_val && !arg_cnt) {
435 expression_t *const_expr;
437 const_expr = lookup_const_decls(ctx, expr->identifier, TRUE);
438 if(const_expr)
439 return compile_expression(ctx, const_expr);
442 if(expr->obj_expr) {
443 hres = compile_expression(ctx, expr->obj_expr);
444 if(FAILED(hres))
445 return hres;
447 hres = push_instr_bstr_uint(ctx, ret_val ? OP_mcall : OP_mcallv, expr->identifier, arg_cnt);
448 }else {
449 hres = push_instr_bstr_uint(ctx, ret_val ? OP_icall : OP_icallv, expr->identifier, arg_cnt);
452 return hres;
455 static HRESULT compile_call_expression(compile_ctx_t *ctx, call_expression_t *expr, BOOL ret_val)
457 unsigned arg_cnt = 0;
458 expression_t *call;
459 HRESULT hres;
461 hres = compile_args(ctx, expr->args, &arg_cnt);
462 if(FAILED(hres))
463 return hres;
465 for(call = expr->call_expr; call->type == EXPR_BRACKETS; call = ((unary_expression_t*)call)->subexpr);
467 if(call->type == EXPR_MEMBER)
468 return compile_member_expression(ctx, (member_expression_t*)call, arg_cnt, ret_val);
470 hres = compile_expression(ctx, call);
471 if(FAILED(hres))
472 return hres;
474 return push_instr_uint(ctx, ret_val ? OP_vcall : OP_vcallv, arg_cnt);
477 static HRESULT compile_dot_expression(compile_ctx_t *ctx)
479 statement_ctx_t *stat_ctx;
481 for(stat_ctx = ctx->stat_ctx; stat_ctx; stat_ctx = stat_ctx->next) {
482 if(!stat_ctx->with_stack_offset)
483 continue;
485 return push_instr_uint(ctx, OP_stack, stat_ctx->with_stack_offset - 1);
488 WARN("dot expression outside with statement\n");
489 return push_instr_uint(ctx, OP_stack, ~0);
492 static HRESULT compile_unary_expression(compile_ctx_t *ctx, unary_expression_t *expr, vbsop_t op)
494 HRESULT hres;
496 hres = compile_expression(ctx, expr->subexpr);
497 if(FAILED(hres))
498 return hres;
500 return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
503 static HRESULT compile_binary_expression(compile_ctx_t *ctx, binary_expression_t *expr, vbsop_t op)
505 HRESULT hres;
507 hres = compile_expression(ctx, expr->left);
508 if(FAILED(hres))
509 return hres;
511 hres = compile_expression(ctx, expr->right);
512 if(FAILED(hres))
513 return hres;
515 return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
518 static HRESULT compile_expression(compile_ctx_t *ctx, expression_t *expr)
520 switch(expr->type) {
521 case EXPR_ADD:
522 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add);
523 case EXPR_AND:
524 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_and);
525 case EXPR_BOOL:
526 return push_instr_int(ctx, OP_bool, ((bool_expression_t*)expr)->value);
527 case EXPR_BRACKETS:
528 return compile_expression(ctx, ((unary_expression_t*)expr)->subexpr);
529 case EXPR_CALL:
530 return compile_call_expression(ctx, (call_expression_t*)expr, TRUE);
531 case EXPR_CONCAT:
532 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_concat);
533 case EXPR_DIV:
534 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div);
535 case EXPR_DOT:
536 return compile_dot_expression(ctx);
537 case EXPR_DOUBLE:
538 return push_instr_double(ctx, OP_double, ((double_expression_t*)expr)->value);
539 case EXPR_EMPTY:
540 return push_instr(ctx, OP_empty) ? S_OK : E_OUTOFMEMORY;
541 case EXPR_EQUAL:
542 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_equal);
543 case EXPR_EQV:
544 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eqv);
545 case EXPR_EXP:
546 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_exp);
547 case EXPR_GT:
548 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gt);
549 case EXPR_GTEQ:
550 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gteq);
551 case EXPR_IDIV:
552 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_idiv);
553 case EXPR_IS:
554 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_is);
555 case EXPR_IMP:
556 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_imp);
557 case EXPR_LT:
558 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lt);
559 case EXPR_LTEQ:
560 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lteq);
561 case EXPR_ME:
562 return push_instr(ctx, OP_me) ? S_OK : E_OUTOFMEMORY;
563 case EXPR_MEMBER:
564 return compile_member_expression(ctx, (member_expression_t*)expr, 0, TRUE);
565 case EXPR_MOD:
566 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod);
567 case EXPR_MUL:
568 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul);
569 case EXPR_NEG:
570 return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg);
571 case EXPR_NEQUAL:
572 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_nequal);
573 case EXPR_NEW:
574 return push_instr_str(ctx, OP_new, ((string_expression_t*)expr)->value);
575 case EXPR_NOARG:
576 return push_instr_int(ctx, OP_hres, DISP_E_PARAMNOTFOUND);
577 case EXPR_NOT:
578 return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_not);
579 case EXPR_NOTHING:
580 return push_instr(ctx, OP_nothing) ? S_OK : E_OUTOFMEMORY;
581 case EXPR_NULL:
582 return push_instr(ctx, OP_null) ? S_OK : E_OUTOFMEMORY;
583 case EXPR_OR:
584 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_or);
585 case EXPR_STRING:
586 return push_instr_str(ctx, OP_string, ((string_expression_t*)expr)->value);
587 case EXPR_SUB:
588 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
589 case EXPR_INT:
590 return push_instr_int(ctx, OP_int, ((int_expression_t*)expr)->value);
591 case EXPR_XOR:
592 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor);
593 default:
594 FIXME("Unimplemented expression type %d\n", expr->type);
595 return E_NOTIMPL;
598 return S_OK;
601 static HRESULT compile_if_statement(compile_ctx_t *ctx, if_statement_t *stat)
603 unsigned cnd_jmp, endif_label = 0;
604 elseif_decl_t *elseif_decl;
605 HRESULT hres;
607 hres = compile_expression(ctx, stat->expr);
608 if(FAILED(hres))
609 return hres;
611 cnd_jmp = push_instr(ctx, OP_jmp_false);
612 if(!cnd_jmp)
613 return E_OUTOFMEMORY;
615 if(!emit_catch(ctx, 0))
616 return E_OUTOFMEMORY;
618 hres = compile_statement(ctx, NULL, stat->if_stat);
619 if(FAILED(hres))
620 return hres;
622 if(stat->else_stat || stat->elseifs) {
623 endif_label = alloc_label(ctx);
624 if(!endif_label)
625 return E_OUTOFMEMORY;
627 hres = push_instr_addr(ctx, OP_jmp, endif_label);
628 if(FAILED(hres))
629 return hres;
632 for(elseif_decl = stat->elseifs; elseif_decl; elseif_decl = elseif_decl->next) {
633 instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;
635 ctx->loc = elseif_decl->loc;
637 hres = compile_expression(ctx, elseif_decl->expr);
638 if(FAILED(hres))
639 return hres;
641 cnd_jmp = push_instr(ctx, OP_jmp_false);
642 if(!cnd_jmp)
643 return E_OUTOFMEMORY;
645 if(!emit_catch(ctx, 0))
646 return E_OUTOFMEMORY;
648 hres = compile_statement(ctx, NULL, elseif_decl->stat);
649 if(FAILED(hres))
650 return hres;
652 hres = push_instr_addr(ctx, OP_jmp, endif_label);
653 if(FAILED(hres))
654 return hres;
657 instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;
659 if(stat->else_stat) {
660 hres = compile_statement(ctx, NULL, stat->else_stat);
661 if(FAILED(hres))
662 return hres;
665 if(endif_label)
666 label_set_addr(ctx, endif_label);
667 return S_OK;
670 static HRESULT compile_while_statement(compile_ctx_t *ctx, while_statement_t *stat)
672 statement_ctx_t stat_ctx = {0}, *loop_ctx;
673 unsigned start_addr;
674 unsigned jmp_end;
675 HRESULT hres;
677 start_addr = ctx->instr_cnt;
679 hres = compile_expression(ctx, stat->expr);
680 if(FAILED(hres))
681 return hres;
683 jmp_end = push_instr(ctx, stat->stat.type == STAT_UNTIL ? OP_jmp_true : OP_jmp_false);
684 if(!jmp_end)
685 return E_OUTOFMEMORY;
687 if(!emit_catch(ctx, 0))
688 return E_OUTOFMEMORY;
690 if(stat->stat.type == STAT_WHILE) {
691 loop_ctx = NULL;
692 }else {
693 if(!(stat_ctx.while_end_label = alloc_label(ctx)))
694 return E_OUTOFMEMORY;
695 loop_ctx = &stat_ctx;
698 hres = compile_statement(ctx, loop_ctx, stat->body);
699 if(FAILED(hres))
700 return hres;
702 hres = push_instr_addr(ctx, OP_jmp, start_addr);
703 if(FAILED(hres))
704 return hres;
706 instr_ptr(ctx, jmp_end)->arg1.uint = ctx->instr_cnt;
708 if(loop_ctx)
709 label_set_addr(ctx, stat_ctx.while_end_label);
711 return S_OK;
714 static HRESULT compile_dowhile_statement(compile_ctx_t *ctx, while_statement_t *stat)
716 statement_ctx_t loop_ctx = {0};
717 unsigned start_addr;
718 vbsop_t jmp_op;
719 HRESULT hres;
721 start_addr = ctx->instr_cnt;
723 if(!(loop_ctx.while_end_label = alloc_label(ctx)))
724 return E_OUTOFMEMORY;
726 hres = compile_statement(ctx, &loop_ctx, stat->body);
727 if(FAILED(hres))
728 return hres;
730 ctx->loc = stat->stat.loc;
731 if(stat->expr) {
732 hres = compile_expression(ctx, stat->expr);
733 if(FAILED(hres))
734 return hres;
736 jmp_op = stat->stat.type == STAT_DOUNTIL ? OP_jmp_false : OP_jmp_true;
737 }else {
738 jmp_op = OP_jmp;
741 hres = push_instr_addr(ctx, jmp_op, start_addr);
742 if(FAILED(hres))
743 return hres;
745 label_set_addr(ctx, loop_ctx.while_end_label);
747 if(!emit_catch(ctx, 0))
748 return E_OUTOFMEMORY;
750 return S_OK;
753 static HRESULT compile_foreach_statement(compile_ctx_t *ctx, foreach_statement_t *stat)
755 statement_ctx_t loop_ctx = {1};
756 unsigned loop_start;
757 HRESULT hres;
759 /* Preserve a place on the stack in case we throw before having proper enum collection. */
760 if(!push_instr(ctx, OP_empty))
761 return E_OUTOFMEMORY;
763 hres = compile_expression(ctx, stat->group_expr);
764 if(FAILED(hres))
765 return hres;
767 if(!push_instr(ctx, OP_newenum))
768 return E_OUTOFMEMORY;
770 if(!(loop_ctx.for_end_label = alloc_label(ctx)))
771 return E_OUTOFMEMORY;
773 hres = push_instr_uint_bstr(ctx, OP_enumnext, loop_ctx.for_end_label, stat->identifier);
774 if(FAILED(hres))
775 return hres;
777 if(!emit_catch(ctx, 1))
778 return E_OUTOFMEMORY;
780 loop_start = ctx->instr_cnt;
781 hres = compile_statement(ctx, &loop_ctx, stat->body);
782 if(FAILED(hres))
783 return hres;
785 /* We need a separated enumnext here, because we need to jump out of the loop on exception. */
786 ctx->loc = stat->stat.loc;
787 hres = push_instr_uint_bstr(ctx, OP_enumnext, loop_ctx.for_end_label, stat->identifier);
788 if(FAILED(hres))
789 return hres;
791 hres = push_instr_addr(ctx, OP_jmp, loop_start);
792 if(FAILED(hres))
793 return hres;
795 label_set_addr(ctx, loop_ctx.for_end_label);
796 return S_OK;
799 static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *stat)
801 statement_ctx_t loop_ctx = {2};
802 unsigned step_instr, instr;
803 BSTR identifier;
804 HRESULT hres;
806 identifier = alloc_bstr_arg(ctx, stat->identifier);
807 if(!identifier)
808 return E_OUTOFMEMORY;
810 hres = compile_expression(ctx, stat->from_expr);
811 if(FAILED(hres))
812 return hres;
814 /* FIXME: Assign should happen after both expressions evaluation. */
815 instr = push_instr(ctx, OP_assign_ident);
816 if(!instr)
817 return E_OUTOFMEMORY;
818 instr_ptr(ctx, instr)->arg1.bstr = identifier;
819 instr_ptr(ctx, instr)->arg2.uint = 0;
821 hres = compile_expression(ctx, stat->to_expr);
822 if(FAILED(hres))
823 return hres;
825 if(!push_instr(ctx, OP_val))
826 return E_OUTOFMEMORY;
828 if(stat->step_expr) {
829 hres = compile_expression(ctx, stat->step_expr);
830 if(FAILED(hres))
831 return hres;
833 if(!push_instr(ctx, OP_val))
834 return E_OUTOFMEMORY;
835 }else {
836 hres = push_instr_int(ctx, OP_int, 1);
837 if(FAILED(hres))
838 return hres;
841 loop_ctx.for_end_label = alloc_label(ctx);
842 if(!loop_ctx.for_end_label)
843 return E_OUTOFMEMORY;
845 step_instr = push_instr(ctx, OP_step);
846 if(!step_instr)
847 return E_OUTOFMEMORY;
848 instr_ptr(ctx, step_instr)->arg2.bstr = identifier;
849 instr_ptr(ctx, step_instr)->arg1.uint = loop_ctx.for_end_label;
851 if(!emit_catch(ctx, 2))
852 return E_OUTOFMEMORY;
854 hres = compile_statement(ctx, &loop_ctx, stat->body);
855 if(FAILED(hres))
856 return hres;
858 /* FIXME: Error handling can't be done compatible with native using OP_incc here. */
859 instr = push_instr(ctx, OP_incc);
860 if(!instr)
861 return E_OUTOFMEMORY;
862 instr_ptr(ctx, instr)->arg1.bstr = identifier;
864 hres = push_instr_addr(ctx, OP_jmp, step_instr);
865 if(FAILED(hres))
866 return hres;
868 hres = push_instr_uint(ctx, OP_pop, 2);
869 if(FAILED(hres))
870 return hres;
872 label_set_addr(ctx, loop_ctx.for_end_label);
874 /* FIXME: reconsider after OP_incc fixup. */
875 if(!emit_catch(ctx, 0))
876 return E_OUTOFMEMORY;
878 return S_OK;
881 static HRESULT compile_with_statement(compile_ctx_t *ctx, with_statement_t *stat)
883 statement_ctx_t with_ctx = { 1 };
884 HRESULT hres;
886 hres = compile_expression(ctx, stat->expr);
887 if(FAILED(hres))
888 return hres;
890 if(!emit_catch(ctx, 1))
891 return E_OUTOFMEMORY;
893 with_ctx.with_stack_offset = stack_offset(ctx) + 1;
894 hres = compile_statement(ctx, &with_ctx, stat->body);
895 if(FAILED(hres))
896 return hres;
898 return push_instr_uint(ctx, OP_pop, 1);
901 static HRESULT compile_select_statement(compile_ctx_t *ctx, select_statement_t *stat)
903 unsigned end_label, case_cnt = 0, *case_labels = NULL, i;
904 case_clausule_t *case_iter;
905 expression_t *expr_iter;
906 HRESULT hres;
908 hres = compile_expression(ctx, stat->expr);
909 if(FAILED(hres))
910 return hres;
912 if(!push_instr(ctx, OP_val))
913 return E_OUTOFMEMORY;
915 end_label = alloc_label(ctx);
916 if(!end_label)
917 return E_OUTOFMEMORY;
919 if(!emit_catch_jmp(ctx, 0, end_label))
920 return E_OUTOFMEMORY;
922 for(case_iter = stat->case_clausules; case_iter; case_iter = case_iter->next)
923 case_cnt++;
925 if(case_cnt) {
926 case_labels = heap_alloc(case_cnt*sizeof(*case_labels));
927 if(!case_labels)
928 return E_OUTOFMEMORY;
931 for(case_iter = stat->case_clausules, i=0; case_iter; case_iter = case_iter->next, i++) {
932 case_labels[i] = alloc_label(ctx);
933 if(!case_labels[i]) {
934 hres = E_OUTOFMEMORY;
935 break;
938 if(!case_iter->expr)
939 break;
941 for(expr_iter = case_iter->expr; expr_iter; expr_iter = expr_iter->next) {
942 hres = compile_expression(ctx, expr_iter);
943 if(FAILED(hres))
944 break;
946 hres = push_instr_addr(ctx, OP_case, case_labels[i]);
947 if(FAILED(hres))
948 break;
950 if(!emit_catch_jmp(ctx, 0, case_labels[i])) {
951 hres = E_OUTOFMEMORY;
952 break;
957 if(FAILED(hres)) {
958 heap_free(case_labels);
959 return hres;
962 hres = push_instr_uint(ctx, OP_pop, 1);
963 if(FAILED(hres)) {
964 heap_free(case_labels);
965 return hres;
968 hres = push_instr_addr(ctx, OP_jmp, case_iter ? case_labels[i] : end_label);
969 if(FAILED(hres)) {
970 heap_free(case_labels);
971 return hres;
974 for(case_iter = stat->case_clausules, i=0; case_iter; case_iter = case_iter->next, i++) {
975 label_set_addr(ctx, case_labels[i]);
976 hres = compile_statement(ctx, NULL, case_iter->stat);
977 if(FAILED(hres))
978 break;
980 if(!case_iter->next)
981 break;
983 hres = push_instr_addr(ctx, OP_jmp, end_label);
984 if(FAILED(hres))
985 break;
988 heap_free(case_labels);
989 if(FAILED(hres))
990 return hres;
992 label_set_addr(ctx, end_label);
993 return S_OK;
996 static HRESULT compile_assignment(compile_ctx_t *ctx, expression_t *left, expression_t *value_expr, BOOL is_set)
998 call_expression_t *call_expr = NULL;
999 member_expression_t *member_expr;
1000 unsigned args_cnt = 0;
1001 vbsop_t op;
1002 HRESULT hres;
1004 switch(left->type) {
1005 case EXPR_MEMBER:
1006 member_expr = (member_expression_t*)left;
1007 break;
1008 case EXPR_CALL:
1009 call_expr = (call_expression_t*)left;
1010 assert(call_expr->call_expr->type == EXPR_MEMBER);
1011 member_expr = (member_expression_t*)call_expr->call_expr;
1012 break;
1013 default:
1014 assert(0);
1015 return E_FAIL;
1018 if(member_expr->obj_expr) {
1019 hres = compile_expression(ctx, member_expr->obj_expr);
1020 if(FAILED(hres))
1021 return hres;
1023 op = is_set ? OP_set_member : OP_assign_member;
1024 }else {
1025 op = is_set ? OP_set_ident : OP_assign_ident;
1028 hres = compile_expression(ctx, value_expr);
1029 if(FAILED(hres))
1030 return hres;
1032 if(call_expr) {
1033 hres = compile_args(ctx, call_expr->args, &args_cnt);
1034 if(FAILED(hres))
1035 return hres;
1038 hres = push_instr_bstr_uint(ctx, op, member_expr->identifier, args_cnt);
1039 if(FAILED(hres))
1040 return hres;
1042 if(!emit_catch(ctx, 0))
1043 return E_OUTOFMEMORY;
1045 return S_OK;
1048 static HRESULT compile_assign_statement(compile_ctx_t *ctx, assign_statement_t *stat, BOOL is_set)
1050 return compile_assignment(ctx, stat->left_expr, stat->value_expr, is_set);
1053 static HRESULT compile_call_statement(compile_ctx_t *ctx, call_statement_t *stat)
1055 HRESULT hres;
1057 hres = compile_call_expression(ctx, stat->expr, FALSE);
1058 if(FAILED(hres))
1059 return hres;
1061 if(!emit_catch(ctx, 0))
1062 return E_OUTOFMEMORY;
1064 return S_OK;
1067 static BOOL lookup_dim_decls(compile_ctx_t *ctx, const WCHAR *name)
1069 dim_decl_t *dim_decl;
1071 for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
1072 if(!wcsicmp(dim_decl->name, name))
1073 return TRUE;
1076 return FALSE;
1079 static BOOL lookup_args_name(compile_ctx_t *ctx, const WCHAR *name)
1081 unsigned i;
1083 for(i = 0; i < ctx->func->arg_cnt; i++) {
1084 if(!wcsicmp(ctx->func->args[i].name, name))
1085 return TRUE;
1088 return FALSE;
1091 static HRESULT compile_dim_statement(compile_ctx_t *ctx, dim_statement_t *stat)
1093 dim_decl_t *dim_decl = stat->dim_decls;
1095 while(1) {
1096 if(lookup_dim_decls(ctx, dim_decl->name) || lookup_args_name(ctx, dim_decl->name)
1097 || lookup_const_decls(ctx, dim_decl->name, FALSE)) {
1098 FIXME("dim %s name redefined\n", debugstr_w(dim_decl->name));
1099 return E_FAIL;
1102 ctx->func->var_cnt++;
1104 if(dim_decl->is_array) {
1105 HRESULT hres = push_instr_bstr_uint(ctx, OP_dim, dim_decl->name, ctx->func->array_cnt++);
1106 if(FAILED(hres))
1107 return hres;
1109 if(!emit_catch(ctx, 0))
1110 return E_OUTOFMEMORY;
1113 if(!dim_decl->next)
1114 break;
1115 dim_decl = dim_decl->next;
1118 if(ctx->dim_decls_tail)
1119 ctx->dim_decls_tail->next = stat->dim_decls;
1120 else
1121 ctx->dim_decls = stat->dim_decls;
1122 ctx->dim_decls_tail = dim_decl;
1123 return S_OK;
1126 static HRESULT compile_redim_statement(compile_ctx_t *ctx, redim_statement_t *stat)
1128 unsigned arg_cnt;
1129 HRESULT hres;
1131 if(stat->preserve) {
1132 FIXME("Preserving redim not supported\n");
1133 return E_NOTIMPL;
1136 hres = compile_args(ctx, stat->dims, &arg_cnt);
1137 if(FAILED(hres))
1138 return hres;
1140 return push_instr_bstr_uint(ctx, OP_redim, stat->identifier, arg_cnt);
1143 static HRESULT compile_const_statement(compile_ctx_t *ctx, const_statement_t *stat)
1145 const_decl_t *decl, *next_decl = stat->decls;
1147 do {
1148 decl = next_decl;
1150 if(lookup_const_decls(ctx, decl->name, FALSE) || lookup_args_name(ctx, decl->name)
1151 || lookup_dim_decls(ctx, decl->name)) {
1152 FIXME("%s redefined\n", debugstr_w(decl->name));
1153 return E_FAIL;
1156 if(ctx->func->type == FUNC_GLOBAL) {
1157 HRESULT hres;
1159 hres = compile_expression(ctx, decl->value_expr);
1160 if(FAILED(hres))
1161 return hres;
1163 hres = push_instr_bstr(ctx, OP_const, decl->name);
1164 if(FAILED(hres))
1165 return hres;
1167 if(!emit_catch(ctx, 0))
1168 return E_OUTOFMEMORY;
1171 next_decl = decl->next;
1172 decl->next = ctx->const_decls;
1173 ctx->const_decls = decl;
1174 } while(next_decl);
1176 return S_OK;
1179 static HRESULT compile_function_statement(compile_ctx_t *ctx, function_statement_t *stat)
1181 if(ctx->func != &ctx->code->main_code) {
1182 FIXME("Function is not in the global code\n");
1183 return E_FAIL;
1186 stat->func_decl->next = ctx->func_decls;
1187 ctx->func_decls = stat->func_decl;
1188 return S_OK;
1191 static HRESULT compile_exitdo_statement(compile_ctx_t *ctx)
1193 statement_ctx_t *iter;
1194 unsigned pop_cnt = 0;
1196 for(iter = ctx->stat_ctx; iter; iter = iter->next) {
1197 pop_cnt += iter->stack_use;
1198 if(iter->while_end_label)
1199 break;
1201 if(!iter) {
1202 FIXME("Exit Do outside Do Loop\n");
1203 return E_FAIL;
1206 if(pop_cnt) {
1207 HRESULT hres;
1209 hres = push_instr_uint(ctx, OP_pop, pop_cnt);
1210 if(FAILED(hres))
1211 return hres;
1214 return push_instr_addr(ctx, OP_jmp, iter->while_end_label);
1217 static HRESULT compile_exitfor_statement(compile_ctx_t *ctx)
1219 statement_ctx_t *iter;
1220 unsigned pop_cnt = 0;
1222 for(iter = ctx->stat_ctx; iter; iter = iter->next) {
1223 pop_cnt += iter->stack_use;
1224 if(iter->for_end_label)
1225 break;
1227 if(!iter) {
1228 FIXME("Exit For outside For loop\n");
1229 return E_FAIL;
1232 if(pop_cnt) {
1233 HRESULT hres;
1235 hres = push_instr_uint(ctx, OP_pop, pop_cnt);
1236 if(FAILED(hres))
1237 return hres;
1240 return push_instr_addr(ctx, OP_jmp, iter->for_end_label);
1243 static HRESULT exit_label(compile_ctx_t *ctx, unsigned jmp_label)
1245 unsigned pop_cnt = stack_offset(ctx);
1247 if(pop_cnt) {
1248 HRESULT hres;
1250 hres = push_instr_uint(ctx, OP_pop, pop_cnt);
1251 if(FAILED(hres))
1252 return hres;
1255 return push_instr_addr(ctx, OP_jmp, jmp_label);
1258 static HRESULT compile_exitsub_statement(compile_ctx_t *ctx)
1260 if(!ctx->sub_end_label) {
1261 FIXME("Exit Sub outside Sub?\n");
1262 return E_FAIL;
1265 return exit_label(ctx, ctx->sub_end_label);
1268 static HRESULT compile_exitfunc_statement(compile_ctx_t *ctx)
1270 if(!ctx->func_end_label) {
1271 FIXME("Exit Function outside Function?\n");
1272 return E_FAIL;
1275 return exit_label(ctx, ctx->func_end_label);
1278 static HRESULT compile_exitprop_statement(compile_ctx_t *ctx)
1280 if(!ctx->prop_end_label) {
1281 FIXME("Exit Property outside Property?\n");
1282 return E_FAIL;
1285 return exit_label(ctx, ctx->prop_end_label);
1288 static HRESULT compile_onerror_statement(compile_ctx_t *ctx, onerror_statement_t *stat)
1290 return push_instr_int(ctx, OP_errmode, stat->resume_next);
1293 static HRESULT compile_retval_statement(compile_ctx_t *ctx, retval_statement_t *stat)
1295 HRESULT hres;
1297 hres = compile_expression(ctx, stat->expr);
1298 if(FAILED(hres))
1299 return hres;
1301 hres = push_instr(ctx, OP_retval);
1302 if(FAILED(hres))
1303 return hres;
1305 return S_OK;
1308 static HRESULT compile_statement(compile_ctx_t *ctx, statement_ctx_t *stat_ctx, statement_t *stat)
1310 HRESULT hres;
1312 if(stat_ctx) {
1313 stat_ctx->next = ctx->stat_ctx;
1314 ctx->stat_ctx = stat_ctx;
1317 while(stat) {
1318 ctx->loc = stat->loc;
1320 switch(stat->type) {
1321 case STAT_ASSIGN:
1322 hres = compile_assign_statement(ctx, (assign_statement_t*)stat, FALSE);
1323 break;
1324 case STAT_CALL:
1325 hres = compile_call_statement(ctx, (call_statement_t*)stat);
1326 break;
1327 case STAT_CONST:
1328 hres = compile_const_statement(ctx, (const_statement_t*)stat);
1329 break;
1330 case STAT_DIM:
1331 hres = compile_dim_statement(ctx, (dim_statement_t*)stat);
1332 break;
1333 case STAT_DOWHILE:
1334 case STAT_DOUNTIL:
1335 hres = compile_dowhile_statement(ctx, (while_statement_t*)stat);
1336 break;
1337 case STAT_EXITDO:
1338 hres = compile_exitdo_statement(ctx);
1339 break;
1340 case STAT_EXITFOR:
1341 hres = compile_exitfor_statement(ctx);
1342 break;
1343 case STAT_EXITFUNC:
1344 hres = compile_exitfunc_statement(ctx);
1345 break;
1346 case STAT_EXITPROP:
1347 hres = compile_exitprop_statement(ctx);
1348 break;
1349 case STAT_EXITSUB:
1350 hres = compile_exitsub_statement(ctx);
1351 break;
1352 case STAT_FOREACH:
1353 hres = compile_foreach_statement(ctx, (foreach_statement_t*)stat);
1354 break;
1355 case STAT_FORTO:
1356 hres = compile_forto_statement(ctx, (forto_statement_t*)stat);
1357 break;
1358 case STAT_FUNC:
1359 hres = compile_function_statement(ctx, (function_statement_t*)stat);
1360 break;
1361 case STAT_IF:
1362 hres = compile_if_statement(ctx, (if_statement_t*)stat);
1363 break;
1364 case STAT_ONERROR:
1365 hres = compile_onerror_statement(ctx, (onerror_statement_t*)stat);
1366 break;
1367 case STAT_REDIM:
1368 hres = compile_redim_statement(ctx, (redim_statement_t*)stat);
1369 break;
1370 case STAT_SELECT:
1371 hres = compile_select_statement(ctx, (select_statement_t*)stat);
1372 break;
1373 case STAT_SET:
1374 hres = compile_assign_statement(ctx, (assign_statement_t*)stat, TRUE);
1375 break;
1376 case STAT_STOP:
1377 hres = push_instr(ctx, OP_stop) ? S_OK : E_OUTOFMEMORY;
1378 break;
1379 case STAT_UNTIL:
1380 case STAT_WHILE:
1381 case STAT_WHILELOOP:
1382 hres = compile_while_statement(ctx, (while_statement_t*)stat);
1383 break;
1384 case STAT_WITH:
1385 hres = compile_with_statement(ctx, (with_statement_t*)stat);
1386 break;
1387 case STAT_RETVAL:
1388 hres = compile_retval_statement(ctx, (retval_statement_t*)stat);
1389 break;
1390 default:
1391 FIXME("Unimplemented statement type %d\n", stat->type);
1392 hres = E_NOTIMPL;
1395 if(FAILED(hres))
1396 return hres;
1397 stat = stat->next;
1400 if(stat_ctx) {
1401 assert(ctx->stat_ctx == stat_ctx);
1402 ctx->stat_ctx = stat_ctx->next;
1405 return S_OK;
1408 static void resolve_labels(compile_ctx_t *ctx, unsigned off)
1410 instr_t *instr;
1412 for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->instr_cnt; instr++) {
1413 if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->arg1.uint & LABEL_FLAG)) {
1414 assert((instr->arg1.uint & ~LABEL_FLAG) < ctx->labels_cnt);
1415 instr->arg1.uint = ctx->labels[instr->arg1.uint & ~LABEL_FLAG];
1417 assert(instr_info[instr->op].arg2_type != ARG_ADDR);
1420 ctx->labels_cnt = 0;
1423 static HRESULT fill_array_desc(compile_ctx_t *ctx, dim_decl_t *dim_decl, array_desc_t *array_desc)
1425 unsigned dim_cnt = 0, i;
1426 dim_list_t *iter;
1428 for(iter = dim_decl->dims; iter; iter = iter->next)
1429 dim_cnt++;
1431 array_desc->bounds = compiler_alloc(ctx->code, dim_cnt * sizeof(SAFEARRAYBOUND));
1432 if(!array_desc->bounds)
1433 return E_OUTOFMEMORY;
1435 array_desc->dim_cnt = dim_cnt;
1437 for(iter = dim_decl->dims, i=0; iter; iter = iter->next, i++) {
1438 array_desc->bounds[i].cElements = iter->val+1;
1439 array_desc->bounds[i].lLbound = 0;
1442 return S_OK;
1445 static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *func)
1447 HRESULT hres;
1449 func->code_off = ctx->instr_cnt;
1451 ctx->sub_end_label = 0;
1452 ctx->func_end_label = 0;
1453 ctx->prop_end_label = 0;
1455 switch(func->type) {
1456 case FUNC_FUNCTION:
1457 ctx->func_end_label = alloc_label(ctx);
1458 if(!ctx->func_end_label)
1459 return E_OUTOFMEMORY;
1460 break;
1461 case FUNC_SUB:
1462 ctx->sub_end_label = alloc_label(ctx);
1463 if(!ctx->sub_end_label)
1464 return E_OUTOFMEMORY;
1465 break;
1466 case FUNC_PROPGET:
1467 case FUNC_PROPLET:
1468 case FUNC_PROPSET:
1469 case FUNC_DEFGET:
1470 ctx->prop_end_label = alloc_label(ctx);
1471 if(!ctx->prop_end_label)
1472 return E_OUTOFMEMORY;
1473 break;
1474 case FUNC_GLOBAL:
1475 break;
1478 ctx->func = func;
1479 ctx->dim_decls = ctx->dim_decls_tail = NULL;
1480 ctx->const_decls = NULL;
1481 hres = compile_statement(ctx, NULL, stat);
1482 ctx->func = NULL;
1483 if(FAILED(hres))
1484 return hres;
1486 if(ctx->sub_end_label)
1487 label_set_addr(ctx, ctx->sub_end_label);
1488 if(ctx->func_end_label)
1489 label_set_addr(ctx, ctx->func_end_label);
1490 if(ctx->prop_end_label)
1491 label_set_addr(ctx, ctx->prop_end_label);
1493 if(!push_instr(ctx, OP_ret))
1494 return E_OUTOFMEMORY;
1496 resolve_labels(ctx, func->code_off);
1498 if(func->var_cnt) {
1499 dim_decl_t *dim_decl;
1500 unsigned i;
1502 func->vars = compiler_alloc(ctx->code, func->var_cnt * sizeof(var_desc_t));
1503 if(!func->vars)
1504 return E_OUTOFMEMORY;
1506 for(dim_decl = ctx->dim_decls, i=0; dim_decl; dim_decl = dim_decl->next, i++) {
1507 func->vars[i].name = compiler_alloc_string(ctx->code, dim_decl->name);
1508 if(!func->vars[i].name)
1509 return E_OUTOFMEMORY;
1512 assert(i == func->var_cnt);
1515 if(func->array_cnt) {
1516 unsigned array_id = 0;
1517 dim_decl_t *dim_decl;
1519 func->array_descs = compiler_alloc(ctx->code, func->array_cnt * sizeof(array_desc_t));
1520 if(!func->array_descs)
1521 return E_OUTOFMEMORY;
1523 for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
1524 if(dim_decl->is_array) {
1525 hres = fill_array_desc(ctx, dim_decl, func->array_descs + array_id++);
1526 if(FAILED(hres))
1527 return hres;
1531 assert(array_id == func->array_cnt);
1534 return S_OK;
1537 static BOOL lookup_funcs_name(compile_ctx_t *ctx, const WCHAR *name)
1539 function_t *iter;
1541 for(iter = ctx->code->funcs; iter; iter = iter->next) {
1542 if(!wcsicmp(iter->name, name))
1543 return TRUE;
1546 return FALSE;
1549 static HRESULT create_function(compile_ctx_t *ctx, function_decl_t *decl, function_t **ret)
1551 function_t *func;
1552 HRESULT hres;
1554 if(lookup_dim_decls(ctx, decl->name) || lookup_const_decls(ctx, decl->name, FALSE)) {
1555 FIXME("%s: redefinition\n", debugstr_w(decl->name));
1556 return E_FAIL;
1559 func = compiler_alloc(ctx->code, sizeof(*func));
1560 if(!func)
1561 return E_OUTOFMEMORY;
1563 func->name = compiler_alloc_string(ctx->code, decl->name);
1564 if(!func->name)
1565 return E_OUTOFMEMORY;
1567 func->vars = NULL;
1568 func->var_cnt = 0;
1569 func->array_cnt = 0;
1570 func->code_ctx = ctx->code;
1571 func->type = decl->type;
1572 func->is_public = decl->is_public;
1574 func->arg_cnt = 0;
1575 if(decl->args) {
1576 arg_decl_t *arg;
1577 unsigned i;
1579 for(arg = decl->args; arg; arg = arg->next)
1580 func->arg_cnt++;
1582 func->args = compiler_alloc(ctx->code, func->arg_cnt * sizeof(arg_desc_t));
1583 if(!func->args)
1584 return E_OUTOFMEMORY;
1586 for(i = 0, arg = decl->args; arg; arg = arg->next, i++) {
1587 func->args[i].name = compiler_alloc_string(ctx->code, arg->name);
1588 if(!func->args[i].name)
1589 return E_OUTOFMEMORY;
1590 func->args[i].by_ref = arg->by_ref;
1592 }else {
1593 func->args = NULL;
1596 hres = compile_func(ctx, decl->body, func);
1597 if(FAILED(hres))
1598 return hres;
1600 *ret = func;
1601 return S_OK;
1604 static BOOL lookup_class_name(compile_ctx_t *ctx, const WCHAR *name)
1606 class_desc_t *iter;
1608 for(iter = ctx->code->classes; iter; iter = iter->next) {
1609 if(!wcsicmp(iter->name, name))
1610 return TRUE;
1613 return FALSE;
1616 static HRESULT create_class_funcprop(compile_ctx_t *ctx, function_decl_t *func_decl, vbdisp_funcprop_desc_t *desc)
1618 vbdisp_invoke_type_t invoke_type;
1619 function_decl_t *funcprop_decl;
1620 HRESULT hres;
1622 desc->name = compiler_alloc_string(ctx->code, func_decl->name);
1623 if(!desc->name)
1624 return E_OUTOFMEMORY;
1626 for(funcprop_decl = func_decl; funcprop_decl; funcprop_decl = funcprop_decl->next_prop_func) {
1627 switch(funcprop_decl->type) {
1628 case FUNC_FUNCTION:
1629 case FUNC_SUB:
1630 case FUNC_PROPGET:
1631 case FUNC_DEFGET:
1632 invoke_type = VBDISP_CALLGET;
1633 break;
1634 case FUNC_PROPLET:
1635 invoke_type = VBDISP_LET;
1636 break;
1637 case FUNC_PROPSET:
1638 invoke_type = VBDISP_SET;
1639 break;
1640 DEFAULT_UNREACHABLE;
1643 assert(!desc->entries[invoke_type]);
1645 if(funcprop_decl->is_public)
1646 desc->is_public = TRUE;
1648 hres = create_function(ctx, funcprop_decl, desc->entries+invoke_type);
1649 if(FAILED(hres))
1650 return hres;
1653 return S_OK;
1656 static BOOL lookup_class_funcs(class_desc_t *class_desc, const WCHAR *name)
1658 unsigned i;
1660 for(i=0; i < class_desc->func_cnt; i++) {
1661 if(class_desc->funcs[i].name && !wcsicmp(class_desc->funcs[i].name, name))
1662 return TRUE;
1665 return FALSE;
1668 static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl)
1670 function_decl_t *func_decl, *func_prop_decl;
1671 class_desc_t *class_desc;
1672 dim_decl_t *prop_decl;
1673 unsigned i;
1674 HRESULT hres;
1676 static const WCHAR class_initializeW[] = {'c','l','a','s','s','_','i','n','i','t','i','a','l','i','z','e',0};
1677 static const WCHAR class_terminateW[] = {'c','l','a','s','s','_','t','e','r','m','i','n','a','t','e',0};
1679 if(lookup_dim_decls(ctx, class_decl->name) || lookup_funcs_name(ctx, class_decl->name)
1680 || lookup_const_decls(ctx, class_decl->name, FALSE) || lookup_class_name(ctx, class_decl->name)) {
1681 FIXME("%s: redefinition\n", debugstr_w(class_decl->name));
1682 return E_FAIL;
1685 class_desc = compiler_alloc_zero(ctx->code, sizeof(*class_desc));
1686 if(!class_desc)
1687 return E_OUTOFMEMORY;
1689 class_desc->name = compiler_alloc_string(ctx->code, class_decl->name);
1690 if(!class_desc->name)
1691 return E_OUTOFMEMORY;
1693 class_desc->func_cnt = 1; /* always allocate slot for default getter */
1695 for(func_decl = class_decl->funcs; func_decl; func_decl = func_decl->next) {
1696 for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) {
1697 if(func_prop_decl->type == FUNC_DEFGET)
1698 break;
1700 if(!func_prop_decl)
1701 class_desc->func_cnt++;
1704 class_desc->funcs = compiler_alloc(ctx->code, class_desc->func_cnt*sizeof(*class_desc->funcs));
1705 if(!class_desc->funcs)
1706 return E_OUTOFMEMORY;
1707 memset(class_desc->funcs, 0, class_desc->func_cnt*sizeof(*class_desc->funcs));
1709 for(func_decl = class_decl->funcs, i=1; func_decl; func_decl = func_decl->next, i++) {
1710 for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) {
1711 if(func_prop_decl->type == FUNC_DEFGET) {
1712 i--;
1713 break;
1717 if(!wcsicmp(class_initializeW, func_decl->name)) {
1718 if(func_decl->type != FUNC_SUB) {
1719 FIXME("class initializer is not sub\n");
1720 return E_FAIL;
1723 class_desc->class_initialize_id = i;
1724 }else if(!wcsicmp(class_terminateW, func_decl->name)) {
1725 if(func_decl->type != FUNC_SUB) {
1726 FIXME("class terminator is not sub\n");
1727 return E_FAIL;
1730 class_desc->class_terminate_id = i;
1733 hres = create_class_funcprop(ctx, func_decl, class_desc->funcs + (func_prop_decl ? 0 : i));
1734 if(FAILED(hres))
1735 return hres;
1738 for(prop_decl = class_decl->props; prop_decl; prop_decl = prop_decl->next)
1739 class_desc->prop_cnt++;
1741 class_desc->props = compiler_alloc(ctx->code, class_desc->prop_cnt*sizeof(*class_desc->props));
1742 if(!class_desc->props)
1743 return E_OUTOFMEMORY;
1745 for(prop_decl = class_decl->props, i=0; prop_decl; prop_decl = prop_decl->next, i++) {
1746 if(lookup_class_funcs(class_desc, prop_decl->name)) {
1747 FIXME("Property %s redefined\n", debugstr_w(prop_decl->name));
1748 return E_FAIL;
1751 class_desc->props[i].name = compiler_alloc_string(ctx->code, prop_decl->name);
1752 if(!class_desc->props[i].name)
1753 return E_OUTOFMEMORY;
1755 class_desc->props[i].is_public = prop_decl->is_public;
1756 class_desc->props[i].is_array = prop_decl->is_array;
1758 if(prop_decl->is_array)
1759 class_desc->array_cnt++;
1762 if(class_desc->array_cnt) {
1763 class_desc->array_descs = compiler_alloc(ctx->code, class_desc->array_cnt*sizeof(*class_desc->array_descs));
1764 if(!class_desc->array_descs)
1765 return E_OUTOFMEMORY;
1767 for(prop_decl = class_decl->props, i=0; prop_decl; prop_decl = prop_decl->next) {
1768 if(prop_decl->is_array) {
1769 hres = fill_array_desc(ctx, prop_decl, class_desc->array_descs + i++);
1770 if(FAILED(hres))
1771 return hres;
1776 class_desc->next = ctx->code->classes;
1777 ctx->code->classes = class_desc;
1778 return S_OK;
1781 static BOOL lookup_script_identifier(compile_ctx_t *ctx, script_ctx_t *script, const WCHAR *identifier)
1783 ScriptDisp *contexts[] = {
1784 ctx->code->named_item ? ctx->code->named_item->script_obj : NULL,
1785 script->script_obj
1787 class_desc_t *class;
1788 vbscode_t *code;
1789 unsigned c, i;
1791 for(c = 0; c < ARRAY_SIZE(contexts); c++) {
1792 if(!contexts[c]) continue;
1794 for(i = 0; i < contexts[c]->global_vars_cnt; i++) {
1795 if(!wcsicmp(contexts[c]->global_vars[i]->name, identifier))
1796 return TRUE;
1799 for(i = 0; i < contexts[c]->global_funcs_cnt; i++) {
1800 if(!wcsicmp(contexts[c]->global_funcs[i]->name, identifier))
1801 return TRUE;
1804 for(class = contexts[c]->classes; class; class = class->next) {
1805 if(!wcsicmp(class->name, identifier))
1806 return TRUE;
1810 LIST_FOR_EACH_ENTRY(code, &script->code_list, vbscode_t, entry) {
1811 unsigned var_cnt = code->main_code.var_cnt;
1812 var_desc_t *vars = code->main_code.vars;
1813 function_t *func;
1815 if(!code->pending_exec || (code->named_item && code->named_item != ctx->code->named_item))
1816 continue;
1818 for(i = 0; i < var_cnt; i++) {
1819 if(!wcsicmp(vars[i].name, identifier))
1820 return TRUE;
1823 for(func = code->funcs; func; func = func->next) {
1824 if(!wcsicmp(func->name, identifier))
1825 return TRUE;
1828 for(class = code->classes; class; class = class->next) {
1829 if(!wcsicmp(class->name, identifier))
1830 return TRUE;
1834 return FALSE;
1837 static HRESULT check_script_collisions(compile_ctx_t *ctx, script_ctx_t *script)
1839 unsigned i, var_cnt = ctx->code->main_code.var_cnt;
1840 var_desc_t *vars = ctx->code->main_code.vars;
1841 class_desc_t *class;
1843 for(i = 0; i < var_cnt; i++) {
1844 if(lookup_script_identifier(ctx, script, vars[i].name)) {
1845 FIXME("%s: redefined\n", debugstr_w(vars[i].name));
1846 return E_FAIL;
1850 for(class = ctx->code->classes; class; class = class->next) {
1851 if(lookup_script_identifier(ctx, script, class->name)) {
1852 FIXME("%s: redefined\n", debugstr_w(class->name));
1853 return E_FAIL;
1857 return S_OK;
1860 void release_vbscode(vbscode_t *code)
1862 unsigned i;
1864 if(--code->ref)
1865 return;
1867 for(i=0; i < code->bstr_cnt; i++)
1868 SysFreeString(code->bstr_pool[i]);
1870 if(code->named_item)
1871 release_named_item(code->named_item);
1872 heap_pool_free(&code->heap);
1874 heap_free(code->bstr_pool);
1875 heap_free(code->source);
1876 heap_free(code->instrs);
1877 heap_free(code);
1880 static vbscode_t *alloc_vbscode(compile_ctx_t *ctx, const WCHAR *source, DWORD_PTR cookie, unsigned start_line)
1882 vbscode_t *ret;
1883 size_t len;
1885 len = source ? lstrlenW(source) : 0;
1886 if(len > INT32_MAX)
1887 return NULL;
1889 ret = heap_alloc_zero(sizeof(*ret));
1890 if(!ret)
1891 return NULL;
1893 ret->source = heap_alloc((len + 1) * sizeof(WCHAR));
1894 if(!ret->source) {
1895 heap_free(ret);
1896 return NULL;
1898 if(len)
1899 memcpy(ret->source, source, len * sizeof(WCHAR));
1900 ret->source[len] = 0;
1902 ret->cookie = cookie;
1903 ret->start_line = start_line;
1905 ret->instrs = heap_alloc(32*sizeof(instr_t));
1906 if(!ret->instrs) {
1907 release_vbscode(ret);
1908 return NULL;
1911 ctx->instr_cnt = 1;
1912 ctx->instr_size = 32;
1913 heap_pool_init(&ret->heap);
1915 ret->main_code.type = FUNC_GLOBAL;
1916 ret->main_code.code_ctx = ret;
1917 ret->ref = 1;
1919 list_init(&ret->entry);
1920 return ret;
1923 static void release_compiler(compile_ctx_t *ctx)
1925 parser_release(&ctx->parser);
1926 heap_free(ctx->labels);
1927 if(ctx->code)
1928 release_vbscode(ctx->code);
1931 HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *item_name, const WCHAR *delimiter,
1932 DWORD_PTR cookie, unsigned start_line, DWORD flags, vbscode_t **ret)
1934 function_decl_t *func_decl;
1935 named_item_t *item = NULL;
1936 class_decl_t *class_decl;
1937 function_t *new_func;
1938 compile_ctx_t ctx;
1939 vbscode_t *code;
1940 HRESULT hres;
1942 if(item_name) {
1943 item = lookup_named_item(script, item_name, 0);
1944 if(!item) {
1945 WARN("Unknown context %s\n", debugstr_w(item_name));
1946 return E_INVALIDARG;
1948 if(!item->script_obj) item = NULL;
1951 memset(&ctx, 0, sizeof(ctx));
1952 code = ctx.code = alloc_vbscode(&ctx, src, cookie, start_line);
1953 if(!ctx.code)
1954 return E_OUTOFMEMORY;
1955 if(item) {
1956 code->named_item = item;
1957 item->ref++;
1960 hres = parse_script(&ctx.parser, code->source, delimiter, flags);
1961 if(FAILED(hres)) {
1962 if(ctx.parser.error_loc != -1)
1963 ctx.loc = ctx.parser.error_loc;
1964 hres = compile_error(script, &ctx, hres);
1965 release_vbscode(code);
1966 return hres;
1969 hres = compile_func(&ctx, ctx.parser.stats, &ctx.code->main_code);
1970 if(FAILED(hres)) {
1971 hres = compile_error(script, &ctx, hres);
1972 release_compiler(&ctx);
1973 return hres;
1976 code->option_explicit = ctx.parser.option_explicit;
1977 ctx.global_consts = ctx.const_decls;
1978 code->option_explicit = ctx.parser.option_explicit;
1981 for(func_decl = ctx.func_decls; func_decl; func_decl = func_decl->next) {
1982 hres = create_function(&ctx, func_decl, &new_func);
1983 if(FAILED(hres)) {
1984 hres = compile_error(script, &ctx, hres);
1985 release_compiler(&ctx);
1986 return hres;
1989 new_func->next = ctx.code->funcs;
1990 ctx.code->funcs = new_func;
1993 for(class_decl = ctx.parser.class_decls; class_decl; class_decl = class_decl->next) {
1994 hres = compile_class(&ctx, class_decl);
1995 if(FAILED(hres)) {
1996 hres = compile_error(script, &ctx, hres);
1997 release_compiler(&ctx);
1998 return hres;
2002 hres = check_script_collisions(&ctx, script);
2003 if(FAILED(hres)) {
2004 hres = compile_error(script, &ctx, hres);
2005 release_compiler(&ctx);
2006 return hres;
2009 code->is_persistent = (flags & SCRIPTTEXT_ISPERSISTENT) != 0;
2011 if(TRACE_ON(vbscript_disas))
2012 dump_code(&ctx);
2014 ctx.code = NULL;
2015 release_compiler(&ctx);
2017 list_add_tail(&script->code_list, &code->entry);
2018 *ret = code;
2019 return S_OK;
2022 HRESULT compile_procedure(script_ctx_t *script, const WCHAR *src, const WCHAR *item_name, const WCHAR *delimiter,
2023 DWORD_PTR cookie, unsigned start_line, DWORD flags, class_desc_t **ret)
2025 class_desc_t *desc;
2026 vbscode_t *code;
2027 HRESULT hres;
2029 hres = compile_script(script, src, item_name, delimiter, cookie, start_line,
2030 flags & ~SCRIPTTEXT_ISPERSISTENT, &code);
2031 if(FAILED(hres))
2032 return hres;
2034 if(!(desc = compiler_alloc_zero(code, sizeof(*desc))))
2035 return E_OUTOFMEMORY;
2036 if(!(desc->funcs = compiler_alloc_zero(code, sizeof(*desc->funcs))))
2037 return E_OUTOFMEMORY;
2039 desc->ctx = script;
2040 desc->func_cnt = 1;
2041 desc->funcs->entries[VBDISP_CALLGET] = &code->main_code;
2043 *ret = desc;
2044 return S_OK;