riched20: Initial support for changing font properties.
[wine/multimedia.git] / dlls / vbscript / compile.c
blobc8189d6d969e2b826df8bd6a573268ed5aa1f871
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;
36 struct _statement_ctx_t *next;
37 } statement_ctx_t;
39 typedef struct {
40 parser_ctx_t parser;
42 unsigned instr_cnt;
43 unsigned instr_size;
44 vbscode_t *code;
46 statement_ctx_t *stat_ctx;
48 unsigned *labels;
49 unsigned labels_size;
50 unsigned labels_cnt;
52 unsigned sub_end_label;
53 unsigned func_end_label;
54 unsigned prop_end_label;
56 dim_decl_t *dim_decls;
57 dim_decl_t *dim_decls_tail;
58 dynamic_var_t *global_vars;
60 const_decl_t *const_decls;
61 const_decl_t *global_consts;
63 function_t *func;
64 function_t *funcs;
65 function_decl_t *func_decls;
67 class_desc_t *classes;
68 } compile_ctx_t;
70 static HRESULT compile_expression(compile_ctx_t*,expression_t*);
71 static HRESULT compile_statement(compile_ctx_t*,statement_ctx_t*,statement_t*);
73 static const struct {
74 const char *op_str;
75 instr_arg_type_t arg1_type;
76 instr_arg_type_t arg2_type;
77 } instr_info[] = {
78 #define X(n,a,b,c) {#n,b,c},
79 OP_LIST
80 #undef X
83 static void dump_instr_arg(instr_arg_type_t type, instr_arg_t *arg)
85 switch(type) {
86 case ARG_STR:
87 case ARG_BSTR:
88 TRACE_(vbscript_disas)("\t%s", debugstr_w(arg->str));
89 break;
90 case ARG_INT:
91 TRACE_(vbscript_disas)("\t%d", arg->uint);
92 break;
93 case ARG_UINT:
94 case ARG_ADDR:
95 TRACE_(vbscript_disas)("\t%u", arg->uint);
96 break;
97 case ARG_DOUBLE:
98 TRACE_(vbscript_disas)("\t%lf", *arg->dbl);
99 break;
100 case ARG_NONE:
101 break;
102 DEFAULT_UNREACHABLE;
106 static void dump_code(compile_ctx_t *ctx)
108 instr_t *instr;
110 for(instr = ctx->code->instrs+1; instr < ctx->code->instrs+ctx->instr_cnt; instr++) {
111 assert(instr->op < OP_LAST);
112 TRACE_(vbscript_disas)("%d:\t%s", (int)(instr-ctx->code->instrs), instr_info[instr->op].op_str);
113 dump_instr_arg(instr_info[instr->op].arg1_type, &instr->arg1);
114 dump_instr_arg(instr_info[instr->op].arg2_type, &instr->arg2);
115 TRACE_(vbscript_disas)("\n");
119 static inline void *compiler_alloc(vbscode_t *vbscode, size_t size)
121 return heap_pool_alloc(&vbscode->heap, size);
124 static inline void *compiler_alloc_zero(vbscode_t *vbscode, size_t size)
126 void *ret;
128 ret = heap_pool_alloc(&vbscode->heap, size);
129 if(ret)
130 memset(ret, 0, size);
131 return ret;
134 static WCHAR *compiler_alloc_string(vbscode_t *vbscode, const WCHAR *str)
136 size_t size;
137 WCHAR *ret;
139 size = (strlenW(str)+1)*sizeof(WCHAR);
140 ret = compiler_alloc(vbscode, size);
141 if(ret)
142 memcpy(ret, str, size);
143 return ret;
146 static inline instr_t *instr_ptr(compile_ctx_t *ctx, unsigned id)
148 assert(id < ctx->instr_cnt);
149 return ctx->code->instrs + id;
152 static unsigned push_instr(compile_ctx_t *ctx, vbsop_t op)
154 assert(ctx->instr_size && ctx->instr_size >= ctx->instr_cnt);
156 if(ctx->instr_size == ctx->instr_cnt) {
157 instr_t *new_instr;
159 new_instr = heap_realloc(ctx->code->instrs, ctx->instr_size*2*sizeof(instr_t));
160 if(!new_instr)
161 return 0;
163 ctx->code->instrs = new_instr;
164 ctx->instr_size *= 2;
167 ctx->code->instrs[ctx->instr_cnt].op = op;
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 BSTR alloc_bstr_arg(compile_ctx_t *ctx, const WCHAR *str)
244 if(!ctx->code->bstr_pool_size) {
245 ctx->code->bstr_pool = heap_alloc(8 * sizeof(BSTR));
246 if(!ctx->code->bstr_pool)
247 return NULL;
248 ctx->code->bstr_pool_size = 8;
249 }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) {
250 BSTR *new_pool;
252 new_pool = heap_realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR));
253 if(!new_pool)
254 return NULL;
256 ctx->code->bstr_pool = new_pool;
257 ctx->code->bstr_pool_size *= 2;
260 ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocString(str);
261 if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
262 return NULL;
264 return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
267 static HRESULT push_instr_bstr(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg)
269 unsigned instr;
270 BSTR bstr;
272 bstr = alloc_bstr_arg(ctx, arg);
273 if(!bstr)
274 return E_OUTOFMEMORY;
276 instr = push_instr(ctx, op);
277 if(!instr)
278 return E_OUTOFMEMORY;
280 instr_ptr(ctx, instr)->arg1.bstr = bstr;
281 return S_OK;
284 static HRESULT push_instr_bstr_uint(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg1, unsigned arg2)
286 unsigned instr;
287 BSTR bstr;
289 bstr = alloc_bstr_arg(ctx, arg1);
290 if(!bstr)
291 return E_OUTOFMEMORY;
293 instr = push_instr(ctx, op);
294 if(!instr)
295 return E_OUTOFMEMORY;
297 instr_ptr(ctx, instr)->arg1.bstr = bstr;
298 instr_ptr(ctx, instr)->arg2.uint = arg2;
299 return S_OK;
302 static HRESULT push_instr_uint_bstr(compile_ctx_t *ctx, vbsop_t op, unsigned arg1, const WCHAR *arg2)
304 unsigned instr;
305 BSTR bstr;
307 bstr = alloc_bstr_arg(ctx, arg2);
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.uint = arg1;
316 instr_ptr(ctx, instr)->arg2.bstr = bstr;
317 return S_OK;
320 #define LABEL_FLAG 0x80000000
322 static unsigned alloc_label(compile_ctx_t *ctx)
324 if(!ctx->labels_size) {
325 ctx->labels = heap_alloc(8 * sizeof(*ctx->labels));
326 if(!ctx->labels)
327 return 0;
328 ctx->labels_size = 8;
329 }else if(ctx->labels_size == ctx->labels_cnt) {
330 unsigned *new_labels;
332 new_labels = heap_realloc(ctx->labels, 2*ctx->labels_size*sizeof(*ctx->labels));
333 if(!new_labels)
334 return 0;
336 ctx->labels = new_labels;
337 ctx->labels_size *= 2;
340 return ctx->labels_cnt++ | LABEL_FLAG;
343 static inline void label_set_addr(compile_ctx_t *ctx, unsigned label)
345 assert(label & LABEL_FLAG);
346 ctx->labels[label & ~LABEL_FLAG] = ctx->instr_cnt;
349 static inline unsigned stack_offset(compile_ctx_t *ctx)
351 statement_ctx_t *iter;
352 unsigned ret = 0;
354 for(iter = ctx->stat_ctx; iter; iter = iter->next)
355 ret += iter->stack_use;
357 return ret;
360 static BOOL emit_catch_jmp(compile_ctx_t *ctx, unsigned stack_off, unsigned code_off)
362 unsigned code;
364 code = push_instr(ctx, OP_catch);
365 if(!code)
366 return FALSE;
368 instr_ptr(ctx, code)->arg1.uint = code_off;
369 instr_ptr(ctx, code)->arg2.uint = stack_off + stack_offset(ctx);
370 return TRUE;
373 static inline BOOL emit_catch(compile_ctx_t *ctx, unsigned off)
375 return emit_catch_jmp(ctx, off, ctx->instr_cnt);
378 static expression_t *lookup_const_decls(compile_ctx_t *ctx, const WCHAR *name, BOOL lookup_global)
380 const_decl_t *decl;
382 for(decl = ctx->const_decls; decl; decl = decl->next) {
383 if(!strcmpiW(decl->name, name))
384 return decl->value_expr;
387 if(!lookup_global)
388 return NULL;
390 for(decl = ctx->global_consts; decl; decl = decl->next) {
391 if(!strcmpiW(decl->name, name))
392 return decl->value_expr;
395 return NULL;
398 static HRESULT compile_args(compile_ctx_t *ctx, expression_t *args, unsigned *ret)
400 unsigned arg_cnt = 0;
401 HRESULT hres;
403 while(args) {
404 hres = compile_expression(ctx, args);
405 if(FAILED(hres))
406 return hres;
408 arg_cnt++;
409 args = args->next;
412 *ret = arg_cnt;
413 return S_OK;
416 static HRESULT compile_member_expression(compile_ctx_t *ctx, member_expression_t *expr, BOOL ret_val)
418 unsigned arg_cnt = 0;
419 HRESULT hres;
421 if(ret_val && !expr->args) {
422 expression_t *const_expr;
424 const_expr = lookup_const_decls(ctx, expr->identifier, TRUE);
425 if(const_expr)
426 return compile_expression(ctx, const_expr);
429 hres = compile_args(ctx, expr->args, &arg_cnt);
430 if(FAILED(hres))
431 return hres;
433 if(expr->obj_expr) {
434 hres = compile_expression(ctx, expr->obj_expr);
435 if(FAILED(hres))
436 return hres;
438 hres = push_instr_bstr_uint(ctx, ret_val ? OP_mcall : OP_mcallv, expr->identifier, arg_cnt);
439 }else {
440 hres = push_instr_bstr_uint(ctx, ret_val ? OP_icall : OP_icallv, expr->identifier, arg_cnt);
443 return hres;
446 static HRESULT compile_unary_expression(compile_ctx_t *ctx, unary_expression_t *expr, vbsop_t op)
448 HRESULT hres;
450 hres = compile_expression(ctx, expr->subexpr);
451 if(FAILED(hres))
452 return hres;
454 return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
457 static HRESULT compile_binary_expression(compile_ctx_t *ctx, binary_expression_t *expr, vbsop_t op)
459 HRESULT hres;
461 hres = compile_expression(ctx, expr->left);
462 if(FAILED(hres))
463 return hres;
465 hres = compile_expression(ctx, expr->right);
466 if(FAILED(hres))
467 return hres;
469 return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
472 static HRESULT compile_expression(compile_ctx_t *ctx, expression_t *expr)
474 switch(expr->type) {
475 case EXPR_ADD:
476 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add);
477 case EXPR_AND:
478 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_and);
479 case EXPR_BOOL:
480 return push_instr_int(ctx, OP_bool, ((bool_expression_t*)expr)->value);
481 case EXPR_BRACKETS:
482 return compile_expression(ctx, ((unary_expression_t*)expr)->subexpr);
483 case EXPR_CONCAT:
484 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_concat);
485 case EXPR_DIV:
486 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div);
487 case EXPR_DOUBLE:
488 return push_instr_double(ctx, OP_double, ((double_expression_t*)expr)->value);
489 case EXPR_EMPTY:
490 return push_instr(ctx, OP_empty) ? S_OK : E_OUTOFMEMORY;
491 case EXPR_EQUAL:
492 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_equal);
493 case EXPR_EQV:
494 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eqv);
495 case EXPR_EXP:
496 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_exp);
497 case EXPR_GT:
498 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gt);
499 case EXPR_GTEQ:
500 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gteq);
501 case EXPR_IDIV:
502 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_idiv);
503 case EXPR_IS:
504 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_is);
505 case EXPR_IMP:
506 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_imp);
507 case EXPR_LT:
508 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lt);
509 case EXPR_LTEQ:
510 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lteq);
511 case EXPR_ME:
512 return push_instr(ctx, OP_me) ? S_OK : E_OUTOFMEMORY;
513 case EXPR_MEMBER:
514 return compile_member_expression(ctx, (member_expression_t*)expr, TRUE);
515 case EXPR_MOD:
516 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod);
517 case EXPR_MUL:
518 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul);
519 case EXPR_NEG:
520 return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg);
521 case EXPR_NEQUAL:
522 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_nequal);
523 case EXPR_NEW:
524 return push_instr_str(ctx, OP_new, ((string_expression_t*)expr)->value);
525 case EXPR_NOARG:
526 return push_instr_int(ctx, OP_hres, DISP_E_PARAMNOTFOUND);
527 case EXPR_NOT:
528 return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_not);
529 case EXPR_NOTHING:
530 return push_instr(ctx, OP_nothing) ? S_OK : E_OUTOFMEMORY;
531 case EXPR_NULL:
532 return push_instr(ctx, OP_null) ? S_OK : E_OUTOFMEMORY;
533 case EXPR_OR:
534 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_or);
535 case EXPR_STRING:
536 return push_instr_str(ctx, OP_string, ((string_expression_t*)expr)->value);
537 case EXPR_SUB:
538 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
539 case EXPR_USHORT:
540 return push_instr_int(ctx, OP_short, ((int_expression_t*)expr)->value);
541 case EXPR_ULONG:
542 return push_instr_int(ctx, OP_long, ((int_expression_t*)expr)->value);
543 case EXPR_XOR:
544 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor);
545 default:
546 FIXME("Unimplemented expression type %d\n", expr->type);
547 return E_NOTIMPL;
550 return S_OK;
553 static HRESULT compile_if_statement(compile_ctx_t *ctx, if_statement_t *stat)
555 unsigned cnd_jmp, endif_label = 0;
556 elseif_decl_t *elseif_decl;
557 HRESULT hres;
559 hres = compile_expression(ctx, stat->expr);
560 if(FAILED(hres))
561 return hres;
563 cnd_jmp = push_instr(ctx, OP_jmp_false);
564 if(!cnd_jmp)
565 return E_OUTOFMEMORY;
567 if(!emit_catch(ctx, 0))
568 return E_OUTOFMEMORY;
570 hres = compile_statement(ctx, NULL, stat->if_stat);
571 if(FAILED(hres))
572 return hres;
574 if(stat->else_stat || stat->elseifs) {
575 endif_label = alloc_label(ctx);
576 if(!endif_label)
577 return E_OUTOFMEMORY;
579 hres = push_instr_addr(ctx, OP_jmp, endif_label);
580 if(FAILED(hres))
581 return hres;
584 for(elseif_decl = stat->elseifs; elseif_decl; elseif_decl = elseif_decl->next) {
585 instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;
587 hres = compile_expression(ctx, elseif_decl->expr);
588 if(FAILED(hres))
589 return hres;
591 cnd_jmp = push_instr(ctx, OP_jmp_false);
592 if(!cnd_jmp)
593 return E_OUTOFMEMORY;
595 if(!emit_catch(ctx, 0))
596 return E_OUTOFMEMORY;
598 hres = compile_statement(ctx, NULL, elseif_decl->stat);
599 if(FAILED(hres))
600 return hres;
602 hres = push_instr_addr(ctx, OP_jmp, endif_label);
603 if(FAILED(hres))
604 return hres;
607 instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;
609 if(stat->else_stat) {
610 hres = compile_statement(ctx, NULL, stat->else_stat);
611 if(FAILED(hres))
612 return hres;
615 if(endif_label)
616 label_set_addr(ctx, endif_label);
617 return S_OK;
620 static HRESULT compile_while_statement(compile_ctx_t *ctx, while_statement_t *stat)
622 statement_ctx_t stat_ctx = {0}, *loop_ctx;
623 unsigned start_addr;
624 unsigned jmp_end;
625 HRESULT hres;
627 start_addr = ctx->instr_cnt;
629 hres = compile_expression(ctx, stat->expr);
630 if(FAILED(hres))
631 return hres;
633 jmp_end = push_instr(ctx, stat->stat.type == STAT_UNTIL ? OP_jmp_true : OP_jmp_false);
634 if(!jmp_end)
635 return E_OUTOFMEMORY;
637 if(!emit_catch(ctx, 0))
638 return E_OUTOFMEMORY;
640 if(stat->stat.type == STAT_WHILE) {
641 loop_ctx = NULL;
642 }else {
643 if(!(stat_ctx.while_end_label = alloc_label(ctx)))
644 return E_OUTOFMEMORY;
645 loop_ctx = &stat_ctx;
648 hres = compile_statement(ctx, loop_ctx, stat->body);
649 if(FAILED(hres))
650 return hres;
652 hres = push_instr_addr(ctx, OP_jmp, start_addr);
653 if(FAILED(hres))
654 return hres;
656 instr_ptr(ctx, jmp_end)->arg1.uint = ctx->instr_cnt;
658 if(loop_ctx)
659 label_set_addr(ctx, stat_ctx.while_end_label);
661 return S_OK;
664 static HRESULT compile_dowhile_statement(compile_ctx_t *ctx, while_statement_t *stat)
666 statement_ctx_t loop_ctx = {0};
667 unsigned start_addr;
668 vbsop_t jmp_op;
669 HRESULT hres;
671 start_addr = ctx->instr_cnt;
673 if(!(loop_ctx.while_end_label = alloc_label(ctx)))
674 return E_OUTOFMEMORY;
676 hres = compile_statement(ctx, &loop_ctx, stat->body);
677 if(FAILED(hres))
678 return hres;
680 if(stat->expr) {
681 hres = compile_expression(ctx, stat->expr);
682 if(FAILED(hres))
683 return hres;
685 jmp_op = stat->stat.type == STAT_DOUNTIL ? OP_jmp_false : OP_jmp_true;
686 }else {
687 jmp_op = OP_jmp;
690 hres = push_instr_addr(ctx, jmp_op, start_addr);
691 if(FAILED(hres))
692 return hres;
694 label_set_addr(ctx, loop_ctx.while_end_label);
696 if(!emit_catch(ctx, 0))
697 return E_OUTOFMEMORY;
699 return S_OK;
702 static HRESULT compile_foreach_statement(compile_ctx_t *ctx, foreach_statement_t *stat)
704 statement_ctx_t loop_ctx = {1};
705 unsigned loop_start;
706 HRESULT hres;
708 /* Preserve a place on the stack in case we throw before having proper enum collection. */
709 if(!push_instr(ctx, OP_empty))
710 return E_OUTOFMEMORY;
712 hres = compile_expression(ctx, stat->group_expr);
713 if(FAILED(hres))
714 return hres;
716 if(!push_instr(ctx, OP_newenum))
717 return E_OUTOFMEMORY;
719 if(!(loop_ctx.for_end_label = alloc_label(ctx)))
720 return E_OUTOFMEMORY;
722 hres = push_instr_uint_bstr(ctx, OP_enumnext, loop_ctx.for_end_label, stat->identifier);
723 if(FAILED(hres))
724 return hres;
726 if(!emit_catch(ctx, 1))
727 return E_OUTOFMEMORY;
729 loop_start = ctx->instr_cnt;
730 hres = compile_statement(ctx, &loop_ctx, stat->body);
731 if(FAILED(hres))
732 return hres;
734 /* We need a separated enumnext here, because we need to jump out of the loop on exception. */
735 hres = push_instr_uint_bstr(ctx, OP_enumnext, loop_ctx.for_end_label, stat->identifier);
736 if(FAILED(hres))
737 return hres;
739 hres = push_instr_addr(ctx, OP_jmp, loop_start);
740 if(FAILED(hres))
741 return hres;
743 label_set_addr(ctx, loop_ctx.for_end_label);
744 return S_OK;
747 static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *stat)
749 statement_ctx_t loop_ctx = {2};
750 unsigned step_instr, instr;
751 BSTR identifier;
752 HRESULT hres;
754 identifier = alloc_bstr_arg(ctx, stat->identifier);
755 if(!identifier)
756 return E_OUTOFMEMORY;
758 hres = compile_expression(ctx, stat->from_expr);
759 if(FAILED(hres))
760 return hres;
762 /* FIXME: Assign should happen after both expressions evaluation. */
763 instr = push_instr(ctx, OP_assign_ident);
764 if(!instr)
765 return E_OUTOFMEMORY;
766 instr_ptr(ctx, instr)->arg1.bstr = identifier;
767 instr_ptr(ctx, instr)->arg2.uint = 0;
769 hres = compile_expression(ctx, stat->to_expr);
770 if(FAILED(hres))
771 return hres;
773 if(!push_instr(ctx, OP_val))
774 return E_OUTOFMEMORY;
776 if(stat->step_expr) {
777 hres = compile_expression(ctx, stat->step_expr);
778 if(FAILED(hres))
779 return hres;
781 if(!push_instr(ctx, OP_val))
782 return E_OUTOFMEMORY;
783 }else {
784 hres = push_instr_int(ctx, OP_short, 1);
785 if(FAILED(hres))
786 return hres;
789 loop_ctx.for_end_label = alloc_label(ctx);
790 if(!loop_ctx.for_end_label)
791 return E_OUTOFMEMORY;
793 step_instr = push_instr(ctx, OP_step);
794 if(!step_instr)
795 return E_OUTOFMEMORY;
796 instr_ptr(ctx, step_instr)->arg2.bstr = identifier;
797 instr_ptr(ctx, step_instr)->arg1.uint = loop_ctx.for_end_label;
799 if(!emit_catch(ctx, 2))
800 return E_OUTOFMEMORY;
802 hres = compile_statement(ctx, &loop_ctx, stat->body);
803 if(FAILED(hres))
804 return hres;
806 /* FIXME: Error handling can't be done compatible with native using OP_incc here. */
807 instr = push_instr(ctx, OP_incc);
808 if(!instr)
809 return E_OUTOFMEMORY;
810 instr_ptr(ctx, instr)->arg1.bstr = identifier;
812 hres = push_instr_addr(ctx, OP_jmp, step_instr);
813 if(FAILED(hres))
814 return hres;
816 hres = push_instr_uint(ctx, OP_pop, 2);
817 if(FAILED(hres))
818 return hres;
820 label_set_addr(ctx, loop_ctx.for_end_label);
822 /* FIXME: reconsider after OP_incc fixup. */
823 if(!emit_catch(ctx, 0))
824 return E_OUTOFMEMORY;
826 return S_OK;
829 static HRESULT compile_select_statement(compile_ctx_t *ctx, select_statement_t *stat)
831 unsigned end_label, case_cnt = 0, *case_labels = NULL, i;
832 case_clausule_t *case_iter;
833 expression_t *expr_iter;
834 HRESULT hres;
836 hres = compile_expression(ctx, stat->expr);
837 if(FAILED(hres))
838 return hres;
840 if(!push_instr(ctx, OP_val))
841 return E_OUTOFMEMORY;
843 end_label = alloc_label(ctx);
844 if(!end_label)
845 return E_OUTOFMEMORY;
847 if(!emit_catch_jmp(ctx, 0, end_label))
848 return E_OUTOFMEMORY;
850 for(case_iter = stat->case_clausules; case_iter; case_iter = case_iter->next)
851 case_cnt++;
853 if(case_cnt) {
854 case_labels = heap_alloc(case_cnt*sizeof(*case_labels));
855 if(!case_labels)
856 return E_OUTOFMEMORY;
859 for(case_iter = stat->case_clausules, i=0; case_iter; case_iter = case_iter->next, i++) {
860 case_labels[i] = alloc_label(ctx);
861 if(!case_labels[i]) {
862 hres = E_OUTOFMEMORY;
863 break;
866 if(!case_iter->expr)
867 break;
869 for(expr_iter = case_iter->expr; expr_iter; expr_iter = expr_iter->next) {
870 hres = compile_expression(ctx, expr_iter);
871 if(FAILED(hres))
872 break;
874 hres = push_instr_addr(ctx, OP_case, case_labels[i]);
875 if(FAILED(hres))
876 break;
878 if(!emit_catch_jmp(ctx, 0, case_labels[i])) {
879 hres = E_OUTOFMEMORY;
880 break;
885 if(FAILED(hres)) {
886 heap_free(case_labels);
887 return hres;
890 hres = push_instr_uint(ctx, OP_pop, 1);
891 if(FAILED(hres)) {
892 heap_free(case_labels);
893 return hres;
896 hres = push_instr_addr(ctx, OP_jmp, case_iter ? case_labels[i] : end_label);
897 if(FAILED(hres)) {
898 heap_free(case_labels);
899 return hres;
902 for(case_iter = stat->case_clausules, i=0; case_iter; case_iter = case_iter->next, i++) {
903 label_set_addr(ctx, case_labels[i]);
904 hres = compile_statement(ctx, NULL, case_iter->stat);
905 if(FAILED(hres))
906 break;
908 if(!case_iter->next)
909 break;
911 hres = push_instr_addr(ctx, OP_jmp, end_label);
912 if(FAILED(hres))
913 break;
916 heap_free(case_labels);
917 if(FAILED(hres))
918 return hres;
920 label_set_addr(ctx, end_label);
921 return S_OK;
924 static HRESULT compile_assignment(compile_ctx_t *ctx, member_expression_t *member_expr, expression_t *value_expr, BOOL is_set)
926 unsigned args_cnt;
927 vbsop_t op;
928 HRESULT hres;
930 if(member_expr->obj_expr) {
931 hres = compile_expression(ctx, member_expr->obj_expr);
932 if(FAILED(hres))
933 return hres;
935 op = is_set ? OP_set_member : OP_assign_member;
936 }else {
937 op = is_set ? OP_set_ident : OP_assign_ident;
940 hres = compile_expression(ctx, value_expr);
941 if(FAILED(hres))
942 return hres;
944 hres = compile_args(ctx, member_expr->args, &args_cnt);
945 if(FAILED(hres))
946 return hres;
948 hres = push_instr_bstr_uint(ctx, op, member_expr->identifier, args_cnt);
949 if(FAILED(hres))
950 return hres;
952 if(!emit_catch(ctx, 0))
953 return E_OUTOFMEMORY;
955 return S_OK;
958 static HRESULT compile_assign_statement(compile_ctx_t *ctx, assign_statement_t *stat, BOOL is_set)
960 return compile_assignment(ctx, stat->member_expr, stat->value_expr, is_set);
963 static HRESULT compile_call_statement(compile_ctx_t *ctx, call_statement_t *stat)
965 HRESULT hres;
967 /* It's challenging for parser to distinguish parameterized assignment with one argument from call
968 * with equality expression argument, so we do it in compiler. */
969 if(!stat->is_strict && stat->expr->args && !stat->expr->args->next && stat->expr->args->type == EXPR_EQUAL) {
970 binary_expression_t *eqexpr = (binary_expression_t*)stat->expr->args;
972 if(eqexpr->left->type == EXPR_BRACKETS) {
973 member_expression_t new_member = *stat->expr;
975 WARN("converting call expr to assign expr\n");
977 new_member.args = ((unary_expression_t*)eqexpr->left)->subexpr;
978 return compile_assignment(ctx, &new_member, eqexpr->right, FALSE);
982 hres = compile_member_expression(ctx, stat->expr, FALSE);
983 if(FAILED(hres))
984 return hres;
986 if(!emit_catch(ctx, 0))
987 return E_OUTOFMEMORY;
989 return S_OK;
992 static BOOL lookup_dim_decls(compile_ctx_t *ctx, const WCHAR *name)
994 dim_decl_t *dim_decl;
996 for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
997 if(!strcmpiW(dim_decl->name, name))
998 return TRUE;
1001 return FALSE;
1004 static BOOL lookup_args_name(compile_ctx_t *ctx, const WCHAR *name)
1006 unsigned i;
1008 for(i = 0; i < ctx->func->arg_cnt; i++) {
1009 if(!strcmpiW(ctx->func->args[i].name, name))
1010 return TRUE;
1013 return FALSE;
1016 static HRESULT compile_dim_statement(compile_ctx_t *ctx, dim_statement_t *stat)
1018 dim_decl_t *dim_decl = stat->dim_decls;
1020 while(1) {
1021 if(lookup_dim_decls(ctx, dim_decl->name) || lookup_args_name(ctx, dim_decl->name)
1022 || lookup_const_decls(ctx, dim_decl->name, FALSE)) {
1023 FIXME("dim %s name redefined\n", debugstr_w(dim_decl->name));
1024 return E_FAIL;
1027 ctx->func->var_cnt++;
1029 if(dim_decl->is_array) {
1030 HRESULT hres = push_instr_bstr_uint(ctx, OP_dim, dim_decl->name, ctx->func->array_cnt++);
1031 if(FAILED(hres))
1032 return hres;
1034 if(!emit_catch(ctx, 0))
1035 return E_OUTOFMEMORY;
1038 if(!dim_decl->next)
1039 break;
1040 dim_decl = dim_decl->next;
1043 if(ctx->dim_decls_tail)
1044 ctx->dim_decls_tail->next = stat->dim_decls;
1045 else
1046 ctx->dim_decls = stat->dim_decls;
1047 ctx->dim_decls_tail = dim_decl;
1048 return S_OK;
1051 static HRESULT compile_const_statement(compile_ctx_t *ctx, const_statement_t *stat)
1053 const_decl_t *decl, *next_decl = stat->decls;
1055 do {
1056 decl = next_decl;
1058 if(lookup_const_decls(ctx, decl->name, FALSE) || lookup_args_name(ctx, decl->name)
1059 || lookup_dim_decls(ctx, decl->name)) {
1060 FIXME("%s redefined\n", debugstr_w(decl->name));
1061 return E_FAIL;
1064 if(ctx->func->type == FUNC_GLOBAL) {
1065 HRESULT hres;
1067 hres = compile_expression(ctx, decl->value_expr);
1068 if(FAILED(hres))
1069 return hres;
1071 hres = push_instr_bstr(ctx, OP_const, decl->name);
1072 if(FAILED(hres))
1073 return hres;
1075 if(!emit_catch(ctx, 0))
1076 return E_OUTOFMEMORY;
1079 next_decl = decl->next;
1080 decl->next = ctx->const_decls;
1081 ctx->const_decls = decl;
1082 } while(next_decl);
1084 return S_OK;
1087 static HRESULT compile_function_statement(compile_ctx_t *ctx, function_statement_t *stat)
1089 if(ctx->func != &ctx->code->main_code) {
1090 FIXME("Function is not in the global code\n");
1091 return E_FAIL;
1094 stat->func_decl->next = ctx->func_decls;
1095 ctx->func_decls = stat->func_decl;
1096 return S_OK;
1099 static HRESULT compile_exitdo_statement(compile_ctx_t *ctx)
1101 statement_ctx_t *iter;
1102 unsigned pop_cnt = 0;
1104 for(iter = ctx->stat_ctx; iter; iter = iter->next) {
1105 pop_cnt += iter->stack_use;
1106 if(iter->while_end_label)
1107 break;
1109 if(!iter) {
1110 FIXME("Exit Do outside Do Loop\n");
1111 return E_FAIL;
1114 if(pop_cnt) {
1115 HRESULT hres;
1117 hres = push_instr_uint(ctx, OP_pop, pop_cnt);
1118 if(FAILED(hres))
1119 return hres;
1122 return push_instr_addr(ctx, OP_jmp, iter->while_end_label);
1125 static HRESULT compile_exitfor_statement(compile_ctx_t *ctx)
1127 statement_ctx_t *iter;
1128 unsigned pop_cnt = 0;
1130 for(iter = ctx->stat_ctx; iter; iter = iter->next) {
1131 pop_cnt += iter->stack_use;
1132 if(iter->for_end_label)
1133 break;
1135 if(!iter) {
1136 FIXME("Exit For outside For loop\n");
1137 return E_FAIL;
1140 if(pop_cnt) {
1141 HRESULT hres;
1143 hres = push_instr_uint(ctx, OP_pop, pop_cnt);
1144 if(FAILED(hres))
1145 return hres;
1148 return push_instr_addr(ctx, OP_jmp, iter->for_end_label);
1151 static HRESULT exit_label(compile_ctx_t *ctx, unsigned jmp_label)
1153 unsigned pop_cnt = stack_offset(ctx);
1155 if(pop_cnt) {
1156 HRESULT hres;
1158 hres = push_instr_uint(ctx, OP_pop, pop_cnt);
1159 if(FAILED(hres))
1160 return hres;
1163 return push_instr_addr(ctx, OP_jmp, jmp_label);
1166 static HRESULT compile_exitsub_statement(compile_ctx_t *ctx)
1168 if(!ctx->sub_end_label) {
1169 FIXME("Exit Sub outside Sub?\n");
1170 return E_FAIL;
1173 return exit_label(ctx, ctx->sub_end_label);
1176 static HRESULT compile_exitfunc_statement(compile_ctx_t *ctx)
1178 if(!ctx->func_end_label) {
1179 FIXME("Exit Function outside Function?\n");
1180 return E_FAIL;
1183 return exit_label(ctx, ctx->func_end_label);
1186 static HRESULT compile_exitprop_statement(compile_ctx_t *ctx)
1188 if(!ctx->prop_end_label) {
1189 FIXME("Exit Property outside Property?\n");
1190 return E_FAIL;
1193 return exit_label(ctx, ctx->prop_end_label);
1196 static HRESULT compile_onerror_statement(compile_ctx_t *ctx, onerror_statement_t *stat)
1198 return push_instr_int(ctx, OP_errmode, stat->resume_next);
1201 static HRESULT compile_statement(compile_ctx_t *ctx, statement_ctx_t *stat_ctx, statement_t *stat)
1203 HRESULT hres;
1205 if(stat_ctx) {
1206 stat_ctx->next = ctx->stat_ctx;
1207 ctx->stat_ctx = stat_ctx;
1210 while(stat) {
1211 switch(stat->type) {
1212 case STAT_ASSIGN:
1213 hres = compile_assign_statement(ctx, (assign_statement_t*)stat, FALSE);
1214 break;
1215 case STAT_CALL:
1216 hres = compile_call_statement(ctx, (call_statement_t*)stat);
1217 break;
1218 case STAT_CONST:
1219 hres = compile_const_statement(ctx, (const_statement_t*)stat);
1220 break;
1221 case STAT_DIM:
1222 hres = compile_dim_statement(ctx, (dim_statement_t*)stat);
1223 break;
1224 case STAT_DOWHILE:
1225 case STAT_DOUNTIL:
1226 hres = compile_dowhile_statement(ctx, (while_statement_t*)stat);
1227 break;
1228 case STAT_EXITDO:
1229 hres = compile_exitdo_statement(ctx);
1230 break;
1231 case STAT_EXITFOR:
1232 hres = compile_exitfor_statement(ctx);
1233 break;
1234 case STAT_EXITFUNC:
1235 hres = compile_exitfunc_statement(ctx);
1236 break;
1237 case STAT_EXITPROP:
1238 hres = compile_exitprop_statement(ctx);
1239 break;
1240 case STAT_EXITSUB:
1241 hres = compile_exitsub_statement(ctx);
1242 break;
1243 case STAT_FOREACH:
1244 hres = compile_foreach_statement(ctx, (foreach_statement_t*)stat);
1245 break;
1246 case STAT_FORTO:
1247 hres = compile_forto_statement(ctx, (forto_statement_t*)stat);
1248 break;
1249 case STAT_FUNC:
1250 hres = compile_function_statement(ctx, (function_statement_t*)stat);
1251 break;
1252 case STAT_IF:
1253 hres = compile_if_statement(ctx, (if_statement_t*)stat);
1254 break;
1255 case STAT_ONERROR:
1256 hres = compile_onerror_statement(ctx, (onerror_statement_t*)stat);
1257 break;
1258 case STAT_SELECT:
1259 hres = compile_select_statement(ctx, (select_statement_t*)stat);
1260 break;
1261 case STAT_SET:
1262 hres = compile_assign_statement(ctx, (assign_statement_t*)stat, TRUE);
1263 break;
1264 case STAT_STOP:
1265 hres = push_instr(ctx, OP_stop) ? S_OK : E_OUTOFMEMORY;
1266 break;
1267 case STAT_UNTIL:
1268 case STAT_WHILE:
1269 case STAT_WHILELOOP:
1270 hres = compile_while_statement(ctx, (while_statement_t*)stat);
1271 break;
1272 default:
1273 FIXME("Unimplemented statement type %d\n", stat->type);
1274 hres = E_NOTIMPL;
1277 if(FAILED(hres))
1278 return hres;
1279 stat = stat->next;
1282 if(stat_ctx) {
1283 assert(ctx->stat_ctx == stat_ctx);
1284 ctx->stat_ctx = stat_ctx->next;
1287 return S_OK;
1290 static void resolve_labels(compile_ctx_t *ctx, unsigned off)
1292 instr_t *instr;
1294 for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->instr_cnt; instr++) {
1295 if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->arg1.uint & LABEL_FLAG)) {
1296 assert((instr->arg1.uint & ~LABEL_FLAG) < ctx->labels_cnt);
1297 instr->arg1.uint = ctx->labels[instr->arg1.uint & ~LABEL_FLAG];
1299 assert(instr_info[instr->op].arg2_type != ARG_ADDR);
1302 ctx->labels_cnt = 0;
1305 static HRESULT fill_array_desc(compile_ctx_t *ctx, dim_decl_t *dim_decl, array_desc_t *array_desc)
1307 unsigned dim_cnt = 0, i;
1308 dim_list_t *iter;
1310 for(iter = dim_decl->dims; iter; iter = iter->next)
1311 dim_cnt++;
1313 array_desc->bounds = compiler_alloc(ctx->code, dim_cnt * sizeof(SAFEARRAYBOUND));
1314 if(!array_desc->bounds)
1315 return E_OUTOFMEMORY;
1317 array_desc->dim_cnt = dim_cnt;
1319 for(iter = dim_decl->dims, i=0; iter; iter = iter->next, i++) {
1320 array_desc->bounds[i].cElements = iter->val+1;
1321 array_desc->bounds[i].lLbound = 0;
1324 return S_OK;
1327 static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *func)
1329 HRESULT hres;
1331 func->code_off = ctx->instr_cnt;
1333 ctx->sub_end_label = 0;
1334 ctx->func_end_label = 0;
1335 ctx->prop_end_label = 0;
1337 switch(func->type) {
1338 case FUNC_FUNCTION:
1339 ctx->func_end_label = alloc_label(ctx);
1340 if(!ctx->func_end_label)
1341 return E_OUTOFMEMORY;
1342 break;
1343 case FUNC_SUB:
1344 ctx->sub_end_label = alloc_label(ctx);
1345 if(!ctx->sub_end_label)
1346 return E_OUTOFMEMORY;
1347 break;
1348 case FUNC_PROPGET:
1349 case FUNC_PROPLET:
1350 case FUNC_PROPSET:
1351 case FUNC_DEFGET:
1352 ctx->prop_end_label = alloc_label(ctx);
1353 if(!ctx->prop_end_label)
1354 return E_OUTOFMEMORY;
1355 break;
1356 case FUNC_GLOBAL:
1357 break;
1360 ctx->func = func;
1361 ctx->dim_decls = ctx->dim_decls_tail = NULL;
1362 ctx->const_decls = NULL;
1363 hres = compile_statement(ctx, NULL, stat);
1364 ctx->func = NULL;
1365 if(FAILED(hres))
1366 return hres;
1368 if(ctx->sub_end_label)
1369 label_set_addr(ctx, ctx->sub_end_label);
1370 if(ctx->func_end_label)
1371 label_set_addr(ctx, ctx->func_end_label);
1372 if(ctx->prop_end_label)
1373 label_set_addr(ctx, ctx->prop_end_label);
1375 if(!push_instr(ctx, OP_ret))
1376 return E_OUTOFMEMORY;
1378 resolve_labels(ctx, func->code_off);
1380 if(func->var_cnt) {
1381 dim_decl_t *dim_decl;
1383 if(func->type == FUNC_GLOBAL) {
1384 dynamic_var_t *new_var;
1386 func->var_cnt = 0;
1388 for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
1389 new_var = compiler_alloc(ctx->code, sizeof(*new_var));
1390 if(!new_var)
1391 return E_OUTOFMEMORY;
1393 new_var->name = compiler_alloc_string(ctx->code, dim_decl->name);
1394 if(!new_var->name)
1395 return E_OUTOFMEMORY;
1397 V_VT(&new_var->v) = VT_EMPTY;
1398 new_var->is_const = FALSE;
1400 new_var->next = ctx->global_vars;
1401 ctx->global_vars = new_var;
1403 }else {
1404 unsigned i;
1406 func->vars = compiler_alloc(ctx->code, func->var_cnt * sizeof(var_desc_t));
1407 if(!func->vars)
1408 return E_OUTOFMEMORY;
1410 for(dim_decl = ctx->dim_decls, i=0; dim_decl; dim_decl = dim_decl->next, i++) {
1411 func->vars[i].name = compiler_alloc_string(ctx->code, dim_decl->name);
1412 if(!func->vars[i].name)
1413 return E_OUTOFMEMORY;
1416 assert(i == func->var_cnt);
1420 if(func->array_cnt) {
1421 unsigned array_id = 0;
1422 dim_decl_t *dim_decl;
1424 func->array_descs = compiler_alloc(ctx->code, func->array_cnt * sizeof(array_desc_t));
1425 if(!func->array_descs)
1426 return E_OUTOFMEMORY;
1428 for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
1429 if(dim_decl->is_array) {
1430 hres = fill_array_desc(ctx, dim_decl, func->array_descs + array_id++);
1431 if(FAILED(hres))
1432 return hres;
1436 assert(array_id == func->array_cnt);
1439 return S_OK;
1442 static BOOL lookup_funcs_name(compile_ctx_t *ctx, const WCHAR *name)
1444 function_t *iter;
1446 for(iter = ctx->funcs; iter; iter = iter->next) {
1447 if(!strcmpiW(iter->name, name))
1448 return TRUE;
1451 return FALSE;
1454 static HRESULT create_function(compile_ctx_t *ctx, function_decl_t *decl, function_t **ret)
1456 function_t *func;
1457 HRESULT hres;
1459 if(lookup_dim_decls(ctx, decl->name) || lookup_funcs_name(ctx, decl->name) || lookup_const_decls(ctx, decl->name, FALSE)) {
1460 FIXME("%s: redefinition\n", debugstr_w(decl->name));
1461 return E_FAIL;
1464 func = compiler_alloc(ctx->code, sizeof(*func));
1465 if(!func)
1466 return E_OUTOFMEMORY;
1468 func->name = compiler_alloc_string(ctx->code, decl->name);
1469 if(!func->name)
1470 return E_OUTOFMEMORY;
1472 func->vars = NULL;
1473 func->var_cnt = 0;
1474 func->array_cnt = 0;
1475 func->code_ctx = ctx->code;
1476 func->type = decl->type;
1477 func->is_public = decl->is_public;
1479 func->arg_cnt = 0;
1480 if(decl->args) {
1481 arg_decl_t *arg;
1482 unsigned i;
1484 for(arg = decl->args; arg; arg = arg->next)
1485 func->arg_cnt++;
1487 func->args = compiler_alloc(ctx->code, func->arg_cnt * sizeof(arg_desc_t));
1488 if(!func->args)
1489 return E_OUTOFMEMORY;
1491 for(i = 0, arg = decl->args; arg; arg = arg->next, i++) {
1492 func->args[i].name = compiler_alloc_string(ctx->code, arg->name);
1493 if(!func->args[i].name)
1494 return E_OUTOFMEMORY;
1495 func->args[i].by_ref = arg->by_ref;
1497 }else {
1498 func->args = NULL;
1501 hres = compile_func(ctx, decl->body, func);
1502 if(FAILED(hres))
1503 return hres;
1505 *ret = func;
1506 return S_OK;
1509 static BOOL lookup_class_name(compile_ctx_t *ctx, const WCHAR *name)
1511 class_desc_t *iter;
1513 for(iter = ctx->classes; iter; iter = iter->next) {
1514 if(!strcmpiW(iter->name, name))
1515 return TRUE;
1518 return FALSE;
1521 static HRESULT create_class_funcprop(compile_ctx_t *ctx, function_decl_t *func_decl, vbdisp_funcprop_desc_t *desc)
1523 vbdisp_invoke_type_t invoke_type;
1524 function_decl_t *funcprop_decl;
1525 HRESULT hres;
1527 desc->name = compiler_alloc_string(ctx->code, func_decl->name);
1528 if(!desc->name)
1529 return E_OUTOFMEMORY;
1531 for(funcprop_decl = func_decl; funcprop_decl; funcprop_decl = funcprop_decl->next_prop_func) {
1532 switch(funcprop_decl->type) {
1533 case FUNC_FUNCTION:
1534 case FUNC_SUB:
1535 case FUNC_PROPGET:
1536 case FUNC_DEFGET:
1537 invoke_type = VBDISP_CALLGET;
1538 break;
1539 case FUNC_PROPLET:
1540 invoke_type = VBDISP_LET;
1541 break;
1542 case FUNC_PROPSET:
1543 invoke_type = VBDISP_SET;
1544 break;
1545 DEFAULT_UNREACHABLE;
1548 assert(!desc->entries[invoke_type]);
1550 if(funcprop_decl->is_public)
1551 desc->is_public = TRUE;
1553 hres = create_function(ctx, funcprop_decl, desc->entries+invoke_type);
1554 if(FAILED(hres))
1555 return hres;
1558 return S_OK;
1561 static BOOL lookup_class_funcs(class_desc_t *class_desc, const WCHAR *name)
1563 unsigned i;
1565 for(i=0; i < class_desc->func_cnt; i++) {
1566 if(class_desc->funcs[i].name && !strcmpiW(class_desc->funcs[i].name, name))
1567 return TRUE;
1570 return FALSE;
1573 static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl)
1575 function_decl_t *func_decl, *func_prop_decl;
1576 class_desc_t *class_desc;
1577 dim_decl_t *prop_decl;
1578 unsigned i;
1579 HRESULT hres;
1581 static const WCHAR class_initializeW[] = {'c','l','a','s','s','_','i','n','i','t','i','a','l','i','z','e',0};
1582 static const WCHAR class_terminateW[] = {'c','l','a','s','s','_','t','e','r','m','i','n','a','t','e',0};
1584 if(lookup_dim_decls(ctx, class_decl->name) || lookup_funcs_name(ctx, class_decl->name)
1585 || lookup_const_decls(ctx, class_decl->name, FALSE) || lookup_class_name(ctx, class_decl->name)) {
1586 FIXME("%s: redefinition\n", debugstr_w(class_decl->name));
1587 return E_FAIL;
1590 class_desc = compiler_alloc_zero(ctx->code, sizeof(*class_desc));
1591 if(!class_desc)
1592 return E_OUTOFMEMORY;
1594 class_desc->name = compiler_alloc_string(ctx->code, class_decl->name);
1595 if(!class_desc->name)
1596 return E_OUTOFMEMORY;
1598 class_desc->func_cnt = 1; /* always allocate slot for default getter */
1600 for(func_decl = class_decl->funcs; func_decl; func_decl = func_decl->next) {
1601 for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) {
1602 if(func_prop_decl->type == FUNC_DEFGET)
1603 break;
1605 if(!func_prop_decl)
1606 class_desc->func_cnt++;
1609 class_desc->funcs = compiler_alloc(ctx->code, class_desc->func_cnt*sizeof(*class_desc->funcs));
1610 if(!class_desc->funcs)
1611 return E_OUTOFMEMORY;
1612 memset(class_desc->funcs, 0, class_desc->func_cnt*sizeof(*class_desc->funcs));
1614 for(func_decl = class_decl->funcs, i=1; func_decl; func_decl = func_decl->next, i++) {
1615 for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) {
1616 if(func_prop_decl->type == FUNC_DEFGET) {
1617 i--;
1618 break;
1622 if(!strcmpiW(class_initializeW, func_decl->name)) {
1623 if(func_decl->type != FUNC_SUB) {
1624 FIXME("class initializer is not sub\n");
1625 return E_FAIL;
1628 class_desc->class_initialize_id = i;
1629 }else if(!strcmpiW(class_terminateW, func_decl->name)) {
1630 if(func_decl->type != FUNC_SUB) {
1631 FIXME("class terminator is not sub\n");
1632 return E_FAIL;
1635 class_desc->class_terminate_id = i;
1638 hres = create_class_funcprop(ctx, func_decl, class_desc->funcs + (func_prop_decl ? 0 : i));
1639 if(FAILED(hres))
1640 return hres;
1643 for(prop_decl = class_decl->props; prop_decl; prop_decl = prop_decl->next)
1644 class_desc->prop_cnt++;
1646 class_desc->props = compiler_alloc(ctx->code, class_desc->prop_cnt*sizeof(*class_desc->props));
1647 if(!class_desc->props)
1648 return E_OUTOFMEMORY;
1650 for(prop_decl = class_decl->props, i=0; prop_decl; prop_decl = prop_decl->next, i++) {
1651 if(lookup_class_funcs(class_desc, prop_decl->name)) {
1652 FIXME("Property %s redefined\n", debugstr_w(prop_decl->name));
1653 return E_FAIL;
1656 class_desc->props[i].name = compiler_alloc_string(ctx->code, prop_decl->name);
1657 if(!class_desc->props[i].name)
1658 return E_OUTOFMEMORY;
1660 class_desc->props[i].is_public = prop_decl->is_public;
1661 class_desc->props[i].is_array = prop_decl->is_array;
1663 if(prop_decl->is_array)
1664 class_desc->array_cnt++;
1667 if(class_desc->array_cnt) {
1668 class_desc->array_descs = compiler_alloc(ctx->code, class_desc->array_cnt*sizeof(*class_desc->array_descs));
1669 if(!class_desc->array_descs)
1670 return E_OUTOFMEMORY;
1672 for(prop_decl = class_decl->props, i=0; prop_decl; prop_decl = prop_decl->next) {
1673 if(prop_decl->is_array) {
1674 hres = fill_array_desc(ctx, prop_decl, class_desc->array_descs + i++);
1675 if(FAILED(hres))
1676 return hres;
1681 class_desc->next = ctx->classes;
1682 ctx->classes = class_desc;
1683 return S_OK;
1686 static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifier)
1688 class_desc_t *class;
1689 dynamic_var_t *var;
1690 function_t *func;
1692 for(var = script->global_vars; var; var = var->next) {
1693 if(!strcmpiW(var->name, identifier))
1694 return TRUE;
1697 for(func = script->global_funcs; func; func = func->next) {
1698 if(!strcmpiW(func->name, identifier))
1699 return TRUE;
1702 for(class = script->classes; class; class = class->next) {
1703 if(!strcmpiW(class->name, identifier))
1704 return TRUE;
1707 return FALSE;
1710 static HRESULT check_script_collisions(compile_ctx_t *ctx, script_ctx_t *script)
1712 class_desc_t *class;
1713 dynamic_var_t *var;
1714 function_t *func;
1716 for(var = ctx->global_vars; var; var = var->next) {
1717 if(lookup_script_identifier(script, var->name)) {
1718 FIXME("%s: redefined\n", debugstr_w(var->name));
1719 return E_FAIL;
1723 for(func = ctx->funcs; func; func = func->next) {
1724 if(lookup_script_identifier(script, func->name)) {
1725 FIXME("%s: redefined\n", debugstr_w(func->name));
1726 return E_FAIL;
1730 for(class = ctx->classes; class; class = class->next) {
1731 if(lookup_script_identifier(script, class->name)) {
1732 FIXME("%s: redefined\n", debugstr_w(class->name));
1733 return E_FAIL;
1737 return S_OK;
1740 void release_vbscode(vbscode_t *code)
1742 unsigned i;
1744 list_remove(&code->entry);
1746 for(i=0; i < code->bstr_cnt; i++)
1747 SysFreeString(code->bstr_pool[i]);
1749 heap_pool_free(&code->heap);
1751 heap_free(code->bstr_pool);
1752 heap_free(code->source);
1753 heap_free(code->instrs);
1754 heap_free(code);
1757 static vbscode_t *alloc_vbscode(compile_ctx_t *ctx, const WCHAR *source)
1759 vbscode_t *ret;
1761 ret = heap_alloc(sizeof(*ret));
1762 if(!ret)
1763 return NULL;
1765 ret->source = heap_strdupW(source);
1766 if(!ret->source) {
1767 heap_free(ret);
1768 return NULL;
1771 ret->instrs = heap_alloc(32*sizeof(instr_t));
1772 if(!ret->instrs) {
1773 release_vbscode(ret);
1774 return NULL;
1777 ctx->instr_cnt = 1;
1778 ctx->instr_size = 32;
1779 heap_pool_init(&ret->heap);
1781 ret->option_explicit = ctx->parser.option_explicit;
1783 ret->bstr_pool = NULL;
1784 ret->bstr_pool_size = 0;
1785 ret->bstr_cnt = 0;
1786 ret->pending_exec = FALSE;
1788 ret->main_code.type = FUNC_GLOBAL;
1789 ret->main_code.name = NULL;
1790 ret->main_code.code_ctx = ret;
1791 ret->main_code.vars = NULL;
1792 ret->main_code.var_cnt = 0;
1793 ret->main_code.array_cnt = 0;
1794 ret->main_code.arg_cnt = 0;
1795 ret->main_code.args = NULL;
1797 list_init(&ret->entry);
1798 return ret;
1801 static void release_compiler(compile_ctx_t *ctx)
1803 parser_release(&ctx->parser);
1804 heap_free(ctx->labels);
1805 if(ctx->code)
1806 release_vbscode(ctx->code);
1809 HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *delimiter, vbscode_t **ret)
1811 function_t *new_func;
1812 function_decl_t *func_decl;
1813 class_decl_t *class_decl;
1814 compile_ctx_t ctx;
1815 vbscode_t *code;
1816 HRESULT hres;
1818 hres = parse_script(&ctx.parser, src, delimiter);
1819 if(FAILED(hres))
1820 return hres;
1822 code = ctx.code = alloc_vbscode(&ctx, src);
1823 if(!ctx.code)
1824 return E_OUTOFMEMORY;
1826 ctx.funcs = NULL;
1827 ctx.func_decls = NULL;
1828 ctx.global_vars = NULL;
1829 ctx.classes = NULL;
1830 ctx.labels = NULL;
1831 ctx.global_consts = NULL;
1832 ctx.stat_ctx = NULL;
1833 ctx.labels_cnt = ctx.labels_size = 0;
1835 hres = compile_func(&ctx, ctx.parser.stats, &ctx.code->main_code);
1836 if(FAILED(hres)) {
1837 release_compiler(&ctx);
1838 return hres;
1841 ctx.global_consts = ctx.const_decls;
1843 for(func_decl = ctx.func_decls; func_decl; func_decl = func_decl->next) {
1844 hres = create_function(&ctx, func_decl, &new_func);
1845 if(FAILED(hres)) {
1846 release_compiler(&ctx);
1847 return hres;
1850 new_func->next = ctx.funcs;
1851 ctx.funcs = new_func;
1854 for(class_decl = ctx.parser.class_decls; class_decl; class_decl = class_decl->next) {
1855 hres = compile_class(&ctx, class_decl);
1856 if(FAILED(hres)) {
1857 release_compiler(&ctx);
1858 return hres;
1862 hres = check_script_collisions(&ctx, script);
1863 if(FAILED(hres)) {
1864 release_compiler(&ctx);
1865 return hres;
1868 if(ctx.global_vars) {
1869 dynamic_var_t *var;
1871 for(var = ctx.global_vars; var->next; var = var->next);
1873 var->next = script->global_vars;
1874 script->global_vars = ctx.global_vars;
1877 if(ctx.funcs) {
1878 for(new_func = ctx.funcs; new_func->next; new_func = new_func->next);
1880 new_func->next = script->global_funcs;
1881 script->global_funcs = ctx.funcs;
1884 if(ctx.classes) {
1885 class_desc_t *class = ctx.classes;
1887 while(1) {
1888 class->ctx = script;
1889 if(!class->next)
1890 break;
1891 class = class->next;
1894 class->next = script->classes;
1895 script->classes = ctx.classes;
1898 if(TRACE_ON(vbscript_disas))
1899 dump_code(&ctx);
1901 ctx.code = NULL;
1902 release_compiler(&ctx);
1904 list_add_tail(&script->code_list, &code->entry);
1905 *ret = code;
1906 return S_OK;