vbscript: Added class_initializer support.
[wine] / dlls / vbscript / compile.c
1 /*
2  * Copyright 2011 Jacek Caban for CodeWeavers
3  *
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.
8  *
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.
13  *
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
17  */
18
19 #include <assert.h>
20
21 #include "vbscript.h"
22 #include "parse.h"
23 #include "parser.tab.h"
24
25 #include "wine/debug.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
28 WINE_DECLARE_DEBUG_CHANNEL(vbscript_disas);
29
30 typedef struct {
31     parser_ctx_t parser;
32
33     unsigned instr_cnt;
34     unsigned instr_size;
35     vbscode_t *code;
36
37     unsigned *labels;
38     unsigned labels_size;
39     unsigned labels_cnt;
40
41     unsigned sub_end_label;
42     unsigned func_end_label;
43     unsigned prop_end_label;
44
45     dim_decl_t *dim_decls;
46     dynamic_var_t *global_vars;
47
48     function_t *func;
49     function_t *funcs;
50     function_decl_t *func_decls;
51
52     class_desc_t *classes;
53 } compile_ctx_t;
54
55 static HRESULT compile_expression(compile_ctx_t*,expression_t*);
56 static HRESULT compile_statement(compile_ctx_t*,statement_t*);
57
58 static const struct {
59     const char *op_str;
60     instr_arg_type_t arg1_type;
61     instr_arg_type_t arg2_type;
62 } instr_info[] = {
63 #define X(n,a,b,c) {#n,b,c},
64 OP_LIST
65 #undef X
66 };
67
68 static void dump_instr_arg(instr_arg_type_t type, instr_arg_t *arg)
69 {
70     switch(type) {
71     case ARG_STR:
72     case ARG_BSTR:
73         TRACE_(vbscript_disas)("\t%s", debugstr_w(arg->str));
74         break;
75     case ARG_INT:
76         TRACE_(vbscript_disas)("\t%d", arg->uint);
77         break;
78     case ARG_UINT:
79     case ARG_ADDR:
80         TRACE_(vbscript_disas)("\t%u", arg->uint);
81         break;
82     case ARG_DOUBLE:
83         TRACE_(vbscript_disas)("\t%lf", *arg->dbl);
84         break;
85     case ARG_NONE:
86         break;
87     default:
88         assert(0);
89     }
90 }
91
92 static void dump_code(compile_ctx_t *ctx)
93 {
94     instr_t *instr;
95
96     for(instr = ctx->code->instrs; instr < ctx->code->instrs+ctx->instr_cnt; instr++) {
97         TRACE_(vbscript_disas)("%d:\t%s", instr-ctx->code->instrs, instr_info[instr->op].op_str);
98         dump_instr_arg(instr_info[instr->op].arg1_type, &instr->arg1);
99         dump_instr_arg(instr_info[instr->op].arg2_type, &instr->arg2);
100         TRACE_(vbscript_disas)("\n");
101     }
102 }
103
104 static inline void *compiler_alloc(vbscode_t *vbscode, size_t size)
105 {
106     return vbsheap_alloc(&vbscode->heap, size);
107 }
108
109 static WCHAR *compiler_alloc_string(vbscode_t *vbscode, const WCHAR *str)
110 {
111     size_t size;
112     WCHAR *ret;
113
114     size = (strlenW(str)+1)*sizeof(WCHAR);
115     ret = compiler_alloc(vbscode, size);
116     if(ret)
117         memcpy(ret, str, size);
118     return ret;
119 }
120
121 static inline instr_t *instr_ptr(compile_ctx_t *ctx, unsigned id)
122 {
123     assert(id < ctx->instr_cnt);
124     return ctx->code->instrs + id;
125 }
126
127 static unsigned push_instr(compile_ctx_t *ctx, vbsop_t op)
128 {
129     assert(ctx->instr_size && ctx->instr_size >= ctx->instr_cnt);
130
131     if(ctx->instr_size == ctx->instr_cnt) {
132         instr_t *new_instr;
133
134         new_instr = heap_realloc(ctx->code->instrs, ctx->instr_size*2*sizeof(instr_t));
135         if(!new_instr)
136             return -1;
137
138         ctx->code->instrs = new_instr;
139         ctx->instr_size *= 2;
140     }
141
142     ctx->code->instrs[ctx->instr_cnt].op = op;
143     return ctx->instr_cnt++;
144 }
145
146 static HRESULT push_instr_int(compile_ctx_t *ctx, vbsop_t op, LONG arg)
147 {
148     unsigned ret;
149
150     ret = push_instr(ctx, op);
151     if(ret == -1)
152         return E_OUTOFMEMORY;
153
154     instr_ptr(ctx, ret)->arg1.lng = arg;
155     return S_OK;
156 }
157
158 static HRESULT push_instr_addr(compile_ctx_t *ctx, vbsop_t op, unsigned arg)
159 {
160     unsigned ret;
161
162     ret = push_instr(ctx, op);
163     if(ret == -1)
164         return E_OUTOFMEMORY;
165
166     instr_ptr(ctx, ret)->arg1.uint = arg;
167     return S_OK;
168 }
169
170 static HRESULT push_instr_str(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg)
171 {
172     unsigned instr;
173     WCHAR *str;
174
175     str = compiler_alloc_string(ctx->code, arg);
176     if(!str)
177         return E_OUTOFMEMORY;
178
179     instr = push_instr(ctx, op);
180     if(instr == -1)
181         return E_OUTOFMEMORY;
182
183     instr_ptr(ctx, instr)->arg1.str = str;
184     return S_OK;
185 }
186
187 static HRESULT push_instr_double(compile_ctx_t *ctx, vbsop_t op, double arg)
188 {
189     unsigned instr;
190     double *d;
191
192     d = compiler_alloc(ctx->code, sizeof(double));
193     if(!d)
194         return E_OUTOFMEMORY;
195
196     instr = push_instr(ctx, op);
197     if(instr == -1)
198         return E_OUTOFMEMORY;
199
200     *d = arg;
201     instr_ptr(ctx, instr)->arg1.dbl = d;
202     return S_OK;
203 }
204
205 static BSTR alloc_bstr_arg(compile_ctx_t *ctx, const WCHAR *str)
206 {
207     if(!ctx->code->bstr_pool_size) {
208         ctx->code->bstr_pool = heap_alloc(8 * sizeof(BSTR));
209         if(!ctx->code->bstr_pool)
210             return NULL;
211         ctx->code->bstr_pool_size = 8;
212     }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) {
213        BSTR *new_pool;
214
215         new_pool = heap_realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR));
216         if(!new_pool)
217             return NULL;
218
219         ctx->code->bstr_pool = new_pool;
220         ctx->code->bstr_pool_size *= 2;
221     }
222
223     ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocString(str);
224     if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
225         return NULL;
226
227     return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
228 }
229
230 static HRESULT push_instr_bstr(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg)
231 {
232     unsigned instr;
233     BSTR bstr;
234
235     bstr = alloc_bstr_arg(ctx, arg);
236     if(!bstr)
237         return E_OUTOFMEMORY;
238
239     instr = push_instr(ctx, op);
240     if(instr == -1)
241         return E_OUTOFMEMORY;
242
243     instr_ptr(ctx, instr)->arg1.bstr = bstr;
244     return S_OK;
245 }
246
247 static HRESULT push_instr_bstr_uint(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg1, unsigned arg2)
248 {
249     unsigned instr;
250     BSTR bstr;
251
252     bstr = alloc_bstr_arg(ctx, arg1);
253     if(!bstr)
254         return E_OUTOFMEMORY;
255
256     instr = push_instr(ctx, op);
257     if(instr == -1)
258         return E_OUTOFMEMORY;
259
260     instr_ptr(ctx, instr)->arg1.bstr = bstr;
261     instr_ptr(ctx, instr)->arg2.uint = arg2;
262     return S_OK;
263 }
264
265 #define LABEL_FLAG 0x80000000
266
267 static unsigned alloc_label(compile_ctx_t *ctx)
268 {
269     if(!ctx->labels_size) {
270         ctx->labels = heap_alloc(8 * sizeof(*ctx->labels));
271         if(!ctx->labels)
272             return -1;
273         ctx->labels_size = 8;
274     }else if(ctx->labels_size == ctx->labels_cnt) {
275         unsigned *new_labels;
276
277         new_labels = heap_realloc(ctx->labels, 2*ctx->labels_size*sizeof(*ctx->labels));
278         if(!new_labels)
279             return -1;
280
281         ctx->labels = new_labels;
282         ctx->labels_size *= 2;
283     }
284
285     return ctx->labels_cnt++ | LABEL_FLAG;
286 }
287
288 static inline void label_set_addr(compile_ctx_t *ctx, unsigned label)
289 {
290     assert(label & LABEL_FLAG);
291     ctx->labels[label & ~LABEL_FLAG] = ctx->instr_cnt;
292 }
293
294 static HRESULT compile_args(compile_ctx_t *ctx, expression_t *args, unsigned *ret)
295 {
296     unsigned arg_cnt = 0;
297     HRESULT hres;
298
299     while(args) {
300         hres = compile_expression(ctx, args);
301         if(FAILED(hres))
302             return hres;
303
304         arg_cnt++;
305         args = args->next;
306     }
307
308     *ret = arg_cnt;
309     return S_OK;
310 }
311
312 static HRESULT compile_member_expression(compile_ctx_t *ctx, member_expression_t *expr, BOOL ret_val)
313 {
314     unsigned arg_cnt = 0;
315     HRESULT hres;
316
317     hres = compile_args(ctx, expr->args, &arg_cnt);
318     if(FAILED(hres))
319         return hres;
320
321     if(expr->obj_expr) {
322         hres = compile_expression(ctx, expr->obj_expr);
323         if(FAILED(hres))
324             return hres;
325
326         hres = push_instr_bstr_uint(ctx, ret_val ? OP_mcall : OP_mcallv, expr->identifier, arg_cnt);
327     }else {
328         hres = push_instr_bstr_uint(ctx, ret_val ? OP_icall : OP_icallv, expr->identifier, arg_cnt);
329     }
330
331     return hres;
332 }
333
334 static HRESULT compile_unary_expression(compile_ctx_t *ctx, unary_expression_t *expr, vbsop_t op)
335 {
336     HRESULT hres;
337
338     hres = compile_expression(ctx, expr->subexpr);
339     if(FAILED(hres))
340         return hres;
341
342     return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK;
343 }
344
345 static HRESULT compile_binary_expression(compile_ctx_t *ctx, binary_expression_t *expr, vbsop_t op)
346 {
347     HRESULT hres;
348
349     hres = compile_expression(ctx, expr->left);
350     if(FAILED(hres))
351         return hres;
352
353     hres = compile_expression(ctx, expr->right);
354     if(FAILED(hres))
355         return hres;
356
357     return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK;
358 }
359
360 static HRESULT compile_expression(compile_ctx_t *ctx, expression_t *expr)
361 {
362     switch(expr->type) {
363     case EXPR_ADD:
364         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add);
365     case EXPR_AND:
366         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_and);
367     case EXPR_BOOL:
368         return push_instr_int(ctx, OP_bool, ((bool_expression_t*)expr)->value);
369     case EXPR_CONCAT:
370         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_concat);
371     case EXPR_DIV:
372         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div);
373     case EXPR_DOUBLE:
374         return push_instr_double(ctx, OP_double, ((double_expression_t*)expr)->value);
375     case EXPR_EMPTY:
376         return push_instr(ctx, OP_empty) != -1 ? S_OK : E_OUTOFMEMORY;
377     case EXPR_EQUAL:
378         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_equal);
379     case EXPR_EQV:
380         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eqv);
381     case EXPR_EXP:
382         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_exp);
383     case EXPR_IDIV:
384         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_idiv);
385     case EXPR_IMP:
386         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_imp);
387     case EXPR_MEMBER:
388         return compile_member_expression(ctx, (member_expression_t*)expr, TRUE);
389     case EXPR_MOD:
390         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod);
391     case EXPR_MUL:
392         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul);
393     case EXPR_NEG:
394         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg);
395     case EXPR_NEQUAL:
396         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_nequal);
397     case EXPR_NEW:
398         return push_instr_str(ctx, OP_new, ((string_expression_t*)expr)->value);
399     case EXPR_NOT:
400         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_not);
401     case EXPR_NOTHING:
402         return push_instr(ctx, OP_nothing) != -1 ? S_OK : E_OUTOFMEMORY;
403     case EXPR_NULL:
404         return push_instr(ctx, OP_null) != -1 ? S_OK : E_OUTOFMEMORY;
405     case EXPR_OR:
406         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_or);
407     case EXPR_STRING:
408         return push_instr_str(ctx, OP_string, ((string_expression_t*)expr)->value);
409     case EXPR_SUB:
410         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
411     case EXPR_USHORT:
412         return push_instr_int(ctx, OP_short, ((int_expression_t*)expr)->value);
413     case EXPR_ULONG:
414         return push_instr_int(ctx, OP_long, ((int_expression_t*)expr)->value);
415     case EXPR_XOR:
416         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor);
417     default:
418         FIXME("Unimplemented expression type %d\n", expr->type);
419         return E_NOTIMPL;
420     }
421
422     return S_OK;
423 }
424
425 static HRESULT compile_if_statement(compile_ctx_t *ctx, if_statement_t *stat)
426 {
427     unsigned cnd_jmp, endif_label = -1;
428     elseif_decl_t *elseif_decl;
429     HRESULT hres;
430
431     hres = compile_expression(ctx, stat->expr);
432     if(FAILED(hres))
433         return hres;
434
435     cnd_jmp = push_instr(ctx, OP_jmp_false);
436     if(cnd_jmp == -1)
437         return E_OUTOFMEMORY;
438
439     hres = compile_statement(ctx, stat->if_stat);
440     if(FAILED(hres))
441         return hres;
442
443     if(stat->else_stat || stat->elseifs) {
444         endif_label = alloc_label(ctx);
445         if(endif_label == -1)
446             return E_OUTOFMEMORY;
447
448         hres = push_instr_addr(ctx, OP_jmp, endif_label);
449         if(FAILED(hres))
450             return hres;
451     }
452
453     for(elseif_decl = stat->elseifs; elseif_decl; elseif_decl = elseif_decl->next) {
454         instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;
455
456         hres = compile_expression(ctx, elseif_decl->expr);
457         if(FAILED(hres))
458             return hres;
459
460         cnd_jmp = push_instr(ctx, OP_jmp_false);
461         if(cnd_jmp == -1)
462             return E_OUTOFMEMORY;
463
464         hres = compile_statement(ctx, elseif_decl->stat);
465         if(FAILED(hres))
466             return hres;
467
468         hres = push_instr_addr(ctx, OP_jmp, endif_label);
469         if(FAILED(hres))
470             return hres;
471     }
472
473     instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;
474
475     if(stat->else_stat) {
476         hres = compile_statement(ctx, stat->else_stat);
477         if(FAILED(hres))
478             return hres;
479     }
480
481     if(endif_label != -1)
482         label_set_addr(ctx, endif_label);
483     return S_OK;
484 }
485
486 static HRESULT compile_assign_statement(compile_ctx_t *ctx, assign_statement_t *stat, BOOL is_set)
487 {
488     HRESULT hres;
489
490     hres = compile_expression(ctx, stat->value_expr);
491     if(FAILED(hres))
492         return hres;
493
494     if(stat->member_expr->args) {
495         FIXME("arguments support not implemented\n");
496         return E_NOTIMPL;
497     }
498
499     if(stat->member_expr->obj_expr) {
500         hres = compile_expression(ctx, stat->member_expr->obj_expr);
501         if(FAILED(hres))
502             return hres;
503
504         hres = push_instr_bstr(ctx, is_set ? OP_set_member : OP_assign_member, stat->member_expr->identifier);
505     }else {
506         hres = push_instr_bstr(ctx, is_set ? OP_set_ident : OP_assign_ident, stat->member_expr->identifier);
507     }
508
509     return hres;
510 }
511
512 static BOOL lookup_dim_decls(compile_ctx_t *ctx, const WCHAR *name)
513 {
514     dim_decl_t *dim_decl;
515
516     for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
517         if(!strcmpiW(dim_decl->name, name))
518             return TRUE;
519     }
520
521     return FALSE;
522 }
523
524 static BOOL lookup_args_name(compile_ctx_t *ctx, const WCHAR *name)
525 {
526     unsigned i;
527
528     for(i = 0; i < ctx->func->arg_cnt; i++) {
529         if(!strcmpiW(ctx->func->args[i].name, name))
530             return TRUE;
531     }
532
533     return FALSE;
534 }
535
536 static HRESULT compile_dim_statement(compile_ctx_t *ctx, dim_statement_t *stat)
537 {
538     dim_decl_t *dim_decl = stat->dim_decls;
539
540     while(1) {
541         if(lookup_dim_decls(ctx, dim_decl->name) || lookup_args_name(ctx, dim_decl->name)) {
542             FIXME("dim %s name redefined\n", debugstr_w(dim_decl->name));
543             return E_FAIL;
544         }
545
546         if(!dim_decl->next)
547             break;
548         dim_decl = dim_decl->next;
549     }
550
551     dim_decl->next = ctx->dim_decls;
552     ctx->dim_decls = stat->dim_decls;
553     ctx->func->var_cnt++;
554     return S_OK;
555 }
556
557 static HRESULT compile_function_statement(compile_ctx_t *ctx, function_statement_t *stat)
558 {
559     if(ctx->func != &ctx->code->global_code) {
560         FIXME("Function is not in the global code\n");
561         return E_FAIL;
562     }
563
564     stat->func_decl->next = ctx->func_decls;
565     ctx->func_decls = stat->func_decl;
566     return S_OK;
567 }
568
569 static HRESULT compile_exitsub_statement(compile_ctx_t *ctx)
570 {
571     if(ctx->sub_end_label == -1) {
572         FIXME("Exit Sub outside Sub?\n");
573         return E_FAIL;
574     }
575
576     return push_instr_addr(ctx, OP_jmp, ctx->sub_end_label);
577 }
578
579 static HRESULT compile_exitfunc_statement(compile_ctx_t *ctx)
580 {
581     if(ctx->func_end_label == -1) {
582         FIXME("Exit Function outside Function?\n");
583         return E_FAIL;
584     }
585
586     return push_instr_addr(ctx, OP_jmp, ctx->func_end_label);
587 }
588
589 static HRESULT compile_exitprop_statement(compile_ctx_t *ctx)
590 {
591     if(ctx->prop_end_label == -1) {
592         FIXME("Exit Property outside Property?\n");
593         return E_FAIL;
594     }
595
596     return push_instr_addr(ctx, OP_jmp, ctx->prop_end_label);
597 }
598
599 static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat)
600 {
601     HRESULT hres;
602
603     while(stat) {
604         switch(stat->type) {
605         case STAT_ASSIGN:
606             hres = compile_assign_statement(ctx, (assign_statement_t*)stat, FALSE);
607             break;
608         case STAT_CALL:
609             hres = compile_member_expression(ctx, ((call_statement_t*)stat)->expr, FALSE);
610             break;
611         case STAT_DIM:
612             hres = compile_dim_statement(ctx, (dim_statement_t*)stat);
613             break;
614         case STAT_EXITFUNC:
615             hres = compile_exitfunc_statement(ctx);
616             break;
617         case STAT_EXITPROP:
618             hres = compile_exitprop_statement(ctx);
619             break;
620         case STAT_EXITSUB:
621             hres = compile_exitsub_statement(ctx);
622             break;
623         case STAT_FUNC:
624             hres = compile_function_statement(ctx, (function_statement_t*)stat);
625             break;
626         case STAT_IF:
627             hres = compile_if_statement(ctx, (if_statement_t*)stat);
628             break;
629         case STAT_SET:
630             hres = compile_assign_statement(ctx, (assign_statement_t*)stat, TRUE);
631             break;
632         case STAT_STOP:
633             hres = push_instr(ctx, OP_stop) == -1 ? E_OUTOFMEMORY : S_OK;
634             break;
635         default:
636             FIXME("Unimplemented statement type %d\n", stat->type);
637             hres = E_NOTIMPL;
638         }
639
640         if(FAILED(hres))
641             return hres;
642         stat = stat->next;
643     }
644
645     return S_OK;
646 }
647
648 static void resolve_labels(compile_ctx_t *ctx, unsigned off)
649 {
650     instr_t *instr;
651
652     for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->instr_cnt; instr++) {
653         if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->arg1.uint & LABEL_FLAG)) {
654             assert((instr->arg1.uint & ~LABEL_FLAG) < ctx->labels_cnt);
655             instr->arg1.uint = ctx->labels[instr->arg1.uint & ~LABEL_FLAG];
656         }
657         assert(instr_info[instr->op].arg2_type != ARG_ADDR);
658     }
659
660     ctx->labels_cnt = 0;
661 }
662
663 static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *func)
664 {
665     HRESULT hres;
666
667     func->code_off = ctx->instr_cnt;
668
669     ctx->sub_end_label = -1;
670     ctx->func_end_label = -1;
671     ctx->prop_end_label = -1;
672
673     switch(func->type) {
674     case FUNC_FUNCTION:
675         ctx->func_end_label = alloc_label(ctx);
676         if(ctx->func_end_label == -1)
677             return E_OUTOFMEMORY; /* FIXME ! */
678         break;
679     case FUNC_SUB:
680         ctx->sub_end_label = alloc_label(ctx);
681         if(ctx->sub_end_label == -1)
682             return E_OUTOFMEMORY;
683         break;
684     case FUNC_PROPGET:
685     case FUNC_PROPLET:
686     case FUNC_PROPSET:
687     case FUNC_DEFGET:
688         ctx->prop_end_label = alloc_label(ctx);
689         if(ctx->prop_end_label == -1)
690             return E_OUTOFMEMORY;
691         break;
692     case FUNC_GLOBAL:
693         break;
694     }
695
696     ctx->func = func;
697     ctx->dim_decls = NULL;
698     hres = compile_statement(ctx, stat);
699     ctx->func = NULL;
700     if(FAILED(hres))
701         return hres;
702
703     if(ctx->sub_end_label != -1)
704         label_set_addr(ctx, ctx->sub_end_label);
705     if(ctx->func_end_label != -1)
706         label_set_addr(ctx, ctx->func_end_label);
707     if(ctx->prop_end_label != -1)
708         label_set_addr(ctx, ctx->prop_end_label);
709
710     if(push_instr(ctx, OP_ret) == -1)
711         return E_OUTOFMEMORY;
712
713     resolve_labels(ctx, func->code_off);
714
715     if(func->var_cnt) {
716         dim_decl_t *dim_decl;
717
718         if(func->type == FUNC_GLOBAL) {
719             dynamic_var_t *new_var;
720
721             func->var_cnt = 0;
722
723             for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
724                 new_var = compiler_alloc(ctx->code, sizeof(*new_var));
725                 if(!new_var)
726                     return E_OUTOFMEMORY;
727
728                 new_var->name = compiler_alloc_string(ctx->code, dim_decl->name);
729                 if(!new_var->name)
730                     return E_OUTOFMEMORY;
731
732                 V_VT(&new_var->v) = VT_EMPTY;
733
734                 new_var->next = ctx->global_vars;
735                 ctx->global_vars = new_var;
736             }
737         }else {
738             unsigned i;
739
740             func->vars = compiler_alloc(ctx->code, func->var_cnt * sizeof(var_desc_t));
741             if(!func->vars)
742                 return E_OUTOFMEMORY;
743
744             for(dim_decl = ctx->dim_decls, i=0; dim_decl; dim_decl = dim_decl->next, i++) {
745                 func->vars[i].name = compiler_alloc_string(ctx->code, dim_decl->name);
746                 if(!func->vars[i].name)
747                     return E_OUTOFMEMORY;
748             }
749
750             assert(i == func->var_cnt);
751         }
752     }
753
754     return S_OK;
755 }
756
757 static BOOL lookup_funcs_name(compile_ctx_t *ctx, const WCHAR *name)
758 {
759     function_t *iter;
760
761     for(iter = ctx->funcs; iter; iter = iter->next) {
762         if(!strcmpiW(iter->name, name))
763             return TRUE;
764     }
765
766     return FALSE;
767 }
768
769 static HRESULT create_function(compile_ctx_t *ctx, function_decl_t *decl, function_t **ret)
770 {
771     function_t *func;
772     HRESULT hres;
773
774     if(lookup_dim_decls(ctx, decl->name) || lookup_funcs_name(ctx, decl->name)) {
775         FIXME("%s: redefinition\n", debugstr_w(decl->name));
776         return E_FAIL;
777     }
778
779     func = compiler_alloc(ctx->code, sizeof(*func));
780     if(!func)
781         return E_OUTOFMEMORY;
782
783     func->name = compiler_alloc_string(ctx->code, decl->name);
784     if(!func->name)
785         return E_OUTOFMEMORY;
786
787     func->vars = NULL;
788     func->var_cnt = 0;
789     func->code_ctx = ctx->code;
790     func->type = decl->type;
791     func->is_public = decl->is_public;
792
793     func->arg_cnt = 0;
794     if(decl->args) {
795         arg_decl_t *arg;
796         unsigned i;
797
798         for(arg = decl->args; arg; arg = arg->next)
799             func->arg_cnt++;
800
801         func->args = compiler_alloc(ctx->code, func->arg_cnt * sizeof(arg_desc_t));
802         if(!func->args)
803             return E_OUTOFMEMORY;
804
805         for(i = 0, arg = decl->args; arg; arg = arg->next, i++) {
806             func->args[i].name = compiler_alloc_string(ctx->code, arg->name);
807             if(!func->args[i].name)
808                 return E_OUTOFMEMORY;
809             func->args[i].by_ref = arg->by_ref;
810         }
811     }else {
812         func->args = NULL;
813     }
814
815     hres = compile_func(ctx, decl->body, func);
816     if(FAILED(hres))
817         return hres;
818
819     *ret = func;
820     return S_OK;
821 }
822
823 static BOOL lookup_class_name(compile_ctx_t *ctx, const WCHAR *name)
824 {
825     class_desc_t *iter;
826
827     for(iter = ctx->classes; iter; iter = iter->next) {
828         if(!strcmpiW(iter->name, name))
829             return TRUE;
830     }
831
832     return FALSE;
833 }
834
835 static HRESULT create_class_funcprop(compile_ctx_t *ctx, function_decl_t *func_decl, vbdisp_funcprop_desc_t *desc)
836 {
837     vbdisp_invoke_type_t invoke_type;
838     function_decl_t *funcprop_decl;
839     HRESULT hres;
840
841     desc->name = compiler_alloc_string(ctx->code, func_decl->name);
842     if(!desc->name)
843         return E_OUTOFMEMORY;
844
845     for(funcprop_decl = func_decl; funcprop_decl; funcprop_decl = funcprop_decl->next_prop_func) {
846         switch(funcprop_decl->type) {
847         case FUNC_FUNCTION:
848         case FUNC_SUB:
849         case FUNC_PROPGET:
850         case FUNC_DEFGET:
851             invoke_type = VBDISP_CALLGET;
852             break;
853         case FUNC_PROPLET:
854             invoke_type = VBDISP_LET;
855             break;
856         case FUNC_PROPSET:
857             invoke_type = VBDISP_SET;
858             break;
859         default:
860             assert(0);
861         }
862
863         assert(!desc->entries[invoke_type]);
864
865         if(funcprop_decl->is_public)
866             desc->is_public = TRUE;
867
868         hres = create_function(ctx, funcprop_decl, desc->entries+invoke_type);
869         if(FAILED(hres))
870             return hres;
871     }
872
873     return S_OK;
874 }
875
876 static BOOL lookup_class_funcs(class_desc_t *class_desc, const WCHAR *name)
877 {
878     unsigned i;
879
880     for(i=0; i < class_desc->func_cnt; i++) {
881         if(class_desc->funcs[i].name && !strcmpiW(class_desc->funcs[i].name, name))
882             return TRUE;
883     }
884
885     return FALSE;
886 }
887
888 static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl)
889 {
890     function_decl_t *func_decl, *func_prop_decl;
891     class_prop_decl_t *prop_decl;
892     class_desc_t *class_desc;
893     unsigned i;
894     HRESULT hres;
895
896     static const WCHAR class_initializeW[] = {'c','l','a','s','s','_','i','n','i','t','i','a','l','i','z','e',0};
897
898     if(lookup_dim_decls(ctx, class_decl->name) || lookup_funcs_name(ctx, class_decl->name)
899             || lookup_class_name(ctx, class_decl->name)) {
900         FIXME("%s: redefinition\n", debugstr_w(class_decl->name));
901         return E_FAIL;
902     }
903
904     class_desc = compiler_alloc(ctx->code, sizeof(*class_desc));
905     if(!class_desc)
906         return E_OUTOFMEMORY;
907
908     class_desc->name = compiler_alloc_string(ctx->code, class_decl->name);
909     if(!class_desc->name)
910         return E_OUTOFMEMORY;
911
912     class_desc->func_cnt = 1; /* always allocate slot for default getter */
913     class_desc->prop_cnt = 0;
914     class_desc->class_initialize_id = 0;
915
916     for(func_decl = class_decl->funcs; func_decl; func_decl = func_decl->next) {
917         for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) {
918             if(func_prop_decl->type == FUNC_DEFGET)
919                 break;
920         }
921         if(!func_prop_decl)
922             class_desc->func_cnt++;
923     }
924
925     class_desc->funcs = compiler_alloc(ctx->code, class_desc->func_cnt*sizeof(*class_desc->funcs));
926     if(!class_desc->funcs)
927         return E_OUTOFMEMORY;
928     memset(class_desc->funcs, 0, class_desc->func_cnt*sizeof(*class_desc->funcs));
929
930     for(func_decl = class_decl->funcs, i=1; func_decl; func_decl = func_decl->next, i++) {
931         for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) {
932             if(func_prop_decl->type == FUNC_DEFGET) {
933                 i--;
934                 break;
935             }
936         }
937
938         if(!strcmpiW(class_initializeW, func_decl->name)) {
939             if(func_decl->type != FUNC_SUB) {
940                 FIXME("class initializer is not sub\n");
941                 return E_FAIL;
942             }
943
944             class_desc->class_initialize_id = i;
945         }
946
947         hres = create_class_funcprop(ctx, func_decl, class_desc->funcs + (func_prop_decl ? 0 : i));
948         if(FAILED(hres))
949             return hres;
950     }
951
952     for(prop_decl = class_decl->props; prop_decl; prop_decl = prop_decl->next)
953         class_desc->prop_cnt++;
954
955     class_desc->props = compiler_alloc(ctx->code, class_desc->prop_cnt*sizeof(*class_desc->props));
956     if(!class_desc->props)
957         return E_OUTOFMEMORY;
958
959     for(prop_decl = class_decl->props, i=0; prop_decl; prop_decl = prop_decl->next, i++) {
960         if(lookup_class_funcs(class_desc, prop_decl->name)) {
961             FIXME("Property %s redefined\n", debugstr_w(prop_decl->name));
962             return E_FAIL;
963         }
964
965         class_desc->props[i].name = compiler_alloc_string(ctx->code, prop_decl->name);
966         if(!class_desc->props[i].name)
967             return E_OUTOFMEMORY;
968
969         class_desc->props[i].is_public = prop_decl->is_public;
970     }
971
972     class_desc->next = ctx->classes;
973     ctx->classes = class_desc;
974     return S_OK;
975 }
976
977 static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifier)
978 {
979     class_desc_t *class;
980     dynamic_var_t *var;
981     function_t *func;
982
983     for(var = script->global_vars; var; var = var->next) {
984         if(!strcmpiW(var->name, identifier))
985             return TRUE;
986     }
987
988     for(func = script->global_funcs; func; func = func->next) {
989         if(!strcmpiW(func->name, identifier))
990             return TRUE;
991     }
992
993     for(class = script->classes; class; class = class->next) {
994         if(!strcmpiW(class->name, identifier))
995             return TRUE;
996     }
997
998     return FALSE;
999 }
1000
1001 static HRESULT check_script_collisions(compile_ctx_t *ctx, script_ctx_t *script)
1002 {
1003     class_desc_t *class;
1004     dynamic_var_t *var;
1005     function_t *func;
1006
1007     for(var = ctx->global_vars; var; var = var->next) {
1008         if(lookup_script_identifier(script, var->name)) {
1009             FIXME("%s: redefined\n", debugstr_w(var->name));
1010             return E_FAIL;
1011         }
1012     }
1013
1014     for(func = ctx->funcs; func; func = func->next) {
1015         if(lookup_script_identifier(script, func->name)) {
1016             FIXME("%s: redefined\n", debugstr_w(func->name));
1017             return E_FAIL;
1018         }
1019     }
1020
1021     for(class = ctx->classes; class; class = class->next) {
1022         if(lookup_script_identifier(script, class->name)) {
1023             FIXME("%s: redefined\n", debugstr_w(class->name));
1024             return E_FAIL;
1025         }
1026     }
1027
1028     return S_OK;
1029 }
1030
1031 void release_vbscode(vbscode_t *code)
1032 {
1033     unsigned i;
1034
1035     list_remove(&code->entry);
1036
1037     for(i=0; i < code->bstr_cnt; i++)
1038         SysFreeString(code->bstr_pool[i]);
1039
1040     vbsheap_free(&code->heap);
1041
1042     heap_free(code->bstr_pool);
1043     heap_free(code->source);
1044     heap_free(code->instrs);
1045     heap_free(code);
1046 }
1047
1048 static vbscode_t *alloc_vbscode(compile_ctx_t *ctx, const WCHAR *source)
1049 {
1050     vbscode_t *ret;
1051
1052     ret = heap_alloc(sizeof(*ret));
1053     if(!ret)
1054         return NULL;
1055
1056     ret->source = heap_strdupW(source);
1057     if(!ret->source) {
1058         heap_free(ret);
1059         return NULL;
1060     }
1061
1062     ret->instrs = heap_alloc(32*sizeof(instr_t));
1063     if(!ret->instrs) {
1064         release_vbscode(ret);
1065         return NULL;
1066     }
1067
1068     ctx->instr_cnt = 0;
1069     ctx->instr_size = 32;
1070     vbsheap_init(&ret->heap);
1071
1072     ret->option_explicit = ctx->parser.option_explicit;
1073
1074     ret->bstr_pool = NULL;
1075     ret->bstr_pool_size = 0;
1076     ret->bstr_cnt = 0;
1077     ret->global_executed = FALSE;
1078
1079     ret->global_code.type = FUNC_GLOBAL;
1080     ret->global_code.name = NULL;
1081     ret->global_code.code_ctx = ret;
1082     ret->global_code.vars = NULL;
1083     ret->global_code.var_cnt = 0;
1084     ret->global_code.arg_cnt = 0;
1085     ret->global_code.args = NULL;
1086
1087     list_init(&ret->entry);
1088     return ret;
1089 }
1090
1091 static void release_compiler(compile_ctx_t *ctx)
1092 {
1093     parser_release(&ctx->parser);
1094     heap_free(ctx->labels);
1095     if(ctx->code)
1096         release_vbscode(ctx->code);
1097 }
1098
1099 HRESULT compile_script(script_ctx_t *script, const WCHAR *src, vbscode_t **ret)
1100 {
1101     function_t *new_func;
1102     function_decl_t *func_decl;
1103     class_decl_t *class_decl;
1104     compile_ctx_t ctx;
1105     vbscode_t *code;
1106     HRESULT hres;
1107
1108     hres = parse_script(&ctx.parser, src);
1109     if(FAILED(hres))
1110         return hres;
1111
1112     code = ctx.code = alloc_vbscode(&ctx, src);
1113     if(!ctx.code)
1114         return E_OUTOFMEMORY;
1115
1116     ctx.funcs = NULL;
1117     ctx.func_decls = NULL;
1118     ctx.global_vars = NULL;
1119     ctx.dim_decls = NULL;
1120     ctx.classes = NULL;
1121     ctx.labels = NULL;
1122     ctx.labels_cnt = ctx.labels_size = 0;
1123
1124     hres = compile_func(&ctx, ctx.parser.stats, &ctx.code->global_code);
1125     if(FAILED(hres)) {
1126         release_compiler(&ctx);
1127         return hres;
1128     }
1129
1130     for(func_decl = ctx.func_decls; func_decl; func_decl = func_decl->next) {
1131         hres = create_function(&ctx, func_decl, &new_func);
1132         if(FAILED(hres)) {
1133             release_compiler(&ctx);
1134             return hres;
1135         }
1136
1137         new_func->next = ctx.funcs;
1138         ctx.funcs = new_func;
1139     }
1140
1141     for(class_decl = ctx.parser.class_decls; class_decl; class_decl = class_decl->next) {
1142         hres = compile_class(&ctx, class_decl);
1143         if(FAILED(hres)) {
1144             release_compiler(&ctx);
1145             return hres;
1146         }
1147     }
1148
1149     hres = check_script_collisions(&ctx, script);
1150     if(FAILED(hres)) {
1151         release_compiler(&ctx);
1152         return hres;
1153     }
1154
1155     if(ctx.global_vars) {
1156         dynamic_var_t *var;
1157
1158         for(var = ctx.global_vars; var->next; var = var->next);
1159
1160         var->next = script->global_vars;
1161         script->global_vars = ctx.global_vars;
1162     }
1163
1164     if(ctx.funcs) {
1165         for(new_func = ctx.funcs; new_func->next; new_func = new_func->next);
1166
1167         new_func->next = script->global_funcs;
1168         script->global_funcs = ctx.funcs;
1169     }
1170
1171     if(ctx.classes) {
1172         class_desc_t *class = ctx.classes;
1173
1174         while(1) {
1175             class->ctx = script;
1176             if(!class->next)
1177                 break;
1178             class = class->next;
1179         }
1180
1181         class->next = script->classes;
1182         script->classes = ctx.classes;
1183     }
1184
1185     if(TRACE_ON(vbscript_disas))
1186         dump_code(&ctx);
1187
1188     ctx.code = NULL;
1189     release_compiler(&ctx);
1190
1191     list_add_tail(&script->code_list, &code->entry);
1192     *ret = code;
1193     return S_OK;
1194 }