vbscript: Added 'and' expression parser/compiler implementation.
[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
44     dim_decl_t *dim_decls;
45     dynamic_var_t *global_vars;
46
47     function_t *func;
48     function_t *funcs;
49     function_decl_t *func_decls;
50 } compile_ctx_t;
51
52 static HRESULT compile_expression(compile_ctx_t*,expression_t*);
53 static HRESULT compile_statement(compile_ctx_t*,statement_t*);
54
55 static const struct {
56     const char *op_str;
57     instr_arg_type_t arg1_type;
58     instr_arg_type_t arg2_type;
59 } instr_info[] = {
60 #define X(n,a,b,c) {#n,b,c},
61 OP_LIST
62 #undef X
63 };
64
65 static void dump_instr_arg(instr_arg_type_t type, instr_arg_t *arg)
66 {
67     switch(type) {
68     case ARG_STR:
69     case ARG_BSTR:
70         TRACE_(vbscript_disas)("\t%s", debugstr_w(arg->str));
71         break;
72     case ARG_INT:
73         TRACE_(vbscript_disas)("\t%d", arg->uint);
74         break;
75     case ARG_UINT:
76     case ARG_ADDR:
77         TRACE_(vbscript_disas)("\t%u", arg->uint);
78         break;
79     case ARG_DOUBLE:
80         TRACE_(vbscript_disas)("\t%lf", *arg->dbl);
81         break;
82     case ARG_NONE:
83         break;
84     default:
85         assert(0);
86     }
87 }
88
89 static void dump_code(compile_ctx_t *ctx)
90 {
91     instr_t *instr;
92
93     for(instr = ctx->code->instrs; instr < ctx->code->instrs+ctx->instr_cnt; instr++) {
94         TRACE_(vbscript_disas)("%d:\t%s", instr-ctx->code->instrs, instr_info[instr->op].op_str);
95         dump_instr_arg(instr_info[instr->op].arg1_type, &instr->arg1);
96         dump_instr_arg(instr_info[instr->op].arg2_type, &instr->arg2);
97         TRACE_(vbscript_disas)("\n");
98     }
99 }
100
101 static inline void *compiler_alloc(vbscode_t *vbscode, size_t size)
102 {
103     return vbsheap_alloc(&vbscode->heap, size);
104 }
105
106 static WCHAR *compiler_alloc_string(vbscode_t *vbscode, const WCHAR *str)
107 {
108     size_t size;
109     WCHAR *ret;
110
111     size = (strlenW(str)+1)*sizeof(WCHAR);
112     ret = compiler_alloc(vbscode, size);
113     if(ret)
114         memcpy(ret, str, size);
115     return ret;
116 }
117
118 static inline instr_t *instr_ptr(compile_ctx_t *ctx, unsigned id)
119 {
120     assert(id < ctx->instr_cnt);
121     return ctx->code->instrs + id;
122 }
123
124 static unsigned push_instr(compile_ctx_t *ctx, vbsop_t op)
125 {
126     assert(ctx->instr_size && ctx->instr_size >= ctx->instr_cnt);
127
128     if(ctx->instr_size == ctx->instr_cnt) {
129         instr_t *new_instr;
130
131         new_instr = heap_realloc(ctx->code->instrs, ctx->instr_size*2*sizeof(instr_t));
132         if(!new_instr)
133             return -1;
134
135         ctx->code->instrs = new_instr;
136         ctx->instr_size *= 2;
137     }
138
139     ctx->code->instrs[ctx->instr_cnt].op = op;
140     return ctx->instr_cnt++;
141 }
142
143 static HRESULT push_instr_int(compile_ctx_t *ctx, vbsop_t op, LONG arg)
144 {
145     unsigned ret;
146
147     ret = push_instr(ctx, op);
148     if(ret == -1)
149         return E_OUTOFMEMORY;
150
151     instr_ptr(ctx, ret)->arg1.lng = arg;
152     return S_OK;
153 }
154
155 static HRESULT push_instr_addr(compile_ctx_t *ctx, vbsop_t op, unsigned arg)
156 {
157     unsigned ret;
158
159     ret = push_instr(ctx, op);
160     if(ret == -1)
161         return E_OUTOFMEMORY;
162
163     instr_ptr(ctx, ret)->arg1.uint = arg;
164     return S_OK;
165 }
166
167 static HRESULT push_instr_str(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg)
168 {
169     unsigned instr;
170     WCHAR *str;
171
172     str = compiler_alloc_string(ctx->code, arg);
173     if(!str)
174         return E_OUTOFMEMORY;
175
176     instr = push_instr(ctx, op);
177     if(instr == -1)
178         return E_OUTOFMEMORY;
179
180     instr_ptr(ctx, instr)->arg1.str = str;
181     return S_OK;
182 }
183
184 static HRESULT push_instr_double(compile_ctx_t *ctx, vbsop_t op, double arg)
185 {
186     unsigned instr;
187     double *d;
188
189     d = compiler_alloc(ctx->code, sizeof(double));
190     if(!d)
191         return E_OUTOFMEMORY;
192
193     instr = push_instr(ctx, op);
194     if(instr == -1)
195         return E_OUTOFMEMORY;
196
197     *d = arg;
198     instr_ptr(ctx, instr)->arg1.dbl = d;
199     return S_OK;
200 }
201
202 static BSTR alloc_bstr_arg(compile_ctx_t *ctx, const WCHAR *str)
203 {
204     if(!ctx->code->bstr_pool_size) {
205         ctx->code->bstr_pool = heap_alloc(8 * sizeof(BSTR));
206         if(!ctx->code->bstr_pool)
207             return NULL;
208         ctx->code->bstr_pool_size = 8;
209     }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) {
210        BSTR *new_pool;
211
212         new_pool = heap_realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR));
213         if(!new_pool)
214             return NULL;
215
216         ctx->code->bstr_pool = new_pool;
217         ctx->code->bstr_pool_size *= 2;
218     }
219
220     ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocString(str);
221     if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
222         return NULL;
223
224     return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
225 }
226
227 static HRESULT push_instr_bstr(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg)
228 {
229     unsigned instr;
230     BSTR bstr;
231
232     bstr = alloc_bstr_arg(ctx, arg);
233     if(!bstr)
234         return E_OUTOFMEMORY;
235
236     instr = push_instr(ctx, op);
237     if(instr == -1)
238         return E_OUTOFMEMORY;
239
240     instr_ptr(ctx, instr)->arg1.bstr = bstr;
241     return S_OK;
242 }
243
244 static HRESULT push_instr_bstr_uint(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg1, unsigned arg2)
245 {
246     unsigned instr;
247     BSTR bstr;
248
249     bstr = alloc_bstr_arg(ctx, arg1);
250     if(!bstr)
251         return E_OUTOFMEMORY;
252
253     instr = push_instr(ctx, op);
254     if(instr == -1)
255         return E_OUTOFMEMORY;
256
257     instr_ptr(ctx, instr)->arg1.bstr = bstr;
258     instr_ptr(ctx, instr)->arg2.uint = arg2;
259     return S_OK;
260 }
261
262 #define LABEL_FLAG 0x80000000
263
264 static unsigned alloc_label(compile_ctx_t *ctx)
265 {
266     if(!ctx->labels_size) {
267         ctx->labels = heap_alloc(8 * sizeof(*ctx->labels));
268         if(!ctx->labels)
269             return -1;
270         ctx->labels_size = 8;
271     }else if(ctx->labels_size == ctx->labels_cnt) {
272         unsigned *new_labels;
273
274         new_labels = heap_realloc(ctx->labels, 2*ctx->labels_size*sizeof(*ctx->labels));
275         if(!new_labels)
276             return -1;
277
278         ctx->labels = new_labels;
279         ctx->labels_size *= 2;
280     }
281
282     return ctx->labels_cnt++ | LABEL_FLAG;
283 }
284
285 static inline void label_set_addr(compile_ctx_t *ctx, unsigned label)
286 {
287     assert(label & LABEL_FLAG);
288     ctx->labels[label & ~LABEL_FLAG] = ctx->instr_cnt;
289 }
290
291 static HRESULT compile_args(compile_ctx_t *ctx, expression_t *args, unsigned *ret)
292 {
293     unsigned arg_cnt = 0;
294     HRESULT hres;
295
296     while(args) {
297         hres = compile_expression(ctx, args);
298         if(FAILED(hres))
299             return hres;
300
301         arg_cnt++;
302         args = args->next;
303     }
304
305     *ret = arg_cnt;
306     return S_OK;
307 }
308
309 static HRESULT compile_member_expression(compile_ctx_t *ctx, member_expression_t *expr, BOOL ret_val)
310 {
311     unsigned arg_cnt = 0;
312     HRESULT hres;
313
314     hres = compile_args(ctx, expr->args, &arg_cnt);
315     if(FAILED(hres))
316         return hres;
317
318     if(expr->obj_expr) {
319         FIXME("obj_expr not implemented\n");
320         hres = E_NOTIMPL;
321     }else {
322         hres = push_instr_bstr_uint(ctx, ret_val ? OP_icall : OP_icallv, expr->identifier, arg_cnt);
323     }
324
325     return hres;
326 }
327
328 static HRESULT compile_unary_expression(compile_ctx_t *ctx, unary_expression_t *expr, vbsop_t op)
329 {
330     HRESULT hres;
331
332     hres = compile_expression(ctx, expr->subexpr);
333     if(FAILED(hres))
334         return hres;
335
336     return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK;
337 }
338
339 static HRESULT compile_binary_expression(compile_ctx_t *ctx, binary_expression_t *expr, vbsop_t op)
340 {
341     HRESULT hres;
342
343     hres = compile_expression(ctx, expr->left);
344     if(FAILED(hres))
345         return hres;
346
347     hres = compile_expression(ctx, expr->right);
348     if(FAILED(hres))
349         return hres;
350
351     return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK;
352 }
353
354 static HRESULT compile_expression(compile_ctx_t *ctx, expression_t *expr)
355 {
356     switch(expr->type) {
357     case EXPR_ADD:
358         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add);
359     case EXPR_AND:
360         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_and);
361     case EXPR_BOOL:
362         return push_instr_int(ctx, OP_bool, ((bool_expression_t*)expr)->value);
363     case EXPR_CONCAT:
364         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_concat);
365     case EXPR_DIV:
366         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div);
367     case EXPR_DOUBLE:
368         return push_instr_double(ctx, OP_double, ((double_expression_t*)expr)->value);
369     case EXPR_EMPTY:
370         return push_instr(ctx, OP_empty) != -1 ? S_OK : E_OUTOFMEMORY;
371     case EXPR_EQUAL:
372         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_equal);
373     case EXPR_EXP:
374         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_exp);
375     case EXPR_IDIV:
376         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_idiv);
377     case EXPR_MEMBER:
378         return compile_member_expression(ctx, (member_expression_t*)expr, TRUE);
379     case EXPR_MOD:
380         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod);
381     case EXPR_MUL:
382         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul);
383     case EXPR_NEG:
384         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg);
385     case EXPR_NEQUAL:
386         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_nequal);
387     case EXPR_NOT:
388         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_not);
389     case EXPR_NULL:
390         return push_instr(ctx, OP_null) != -1 ? S_OK : E_OUTOFMEMORY;
391     case EXPR_STRING:
392         return push_instr_str(ctx, OP_string, ((string_expression_t*)expr)->value);
393     case EXPR_SUB:
394         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
395     case EXPR_USHORT:
396         return push_instr_int(ctx, OP_short, ((int_expression_t*)expr)->value);
397     case EXPR_ULONG:
398         return push_instr_int(ctx, OP_long, ((int_expression_t*)expr)->value);
399     default:
400         FIXME("Unimplemented expression type %d\n", expr->type);
401         return E_NOTIMPL;
402     }
403
404     return S_OK;
405 }
406
407 static HRESULT compile_if_statement(compile_ctx_t *ctx, if_statement_t *stat)
408 {
409     unsigned cnd_jmp, endif_label = -1;
410     elseif_decl_t *elseif_decl;
411     HRESULT hres;
412
413     hres = compile_expression(ctx, stat->expr);
414     if(FAILED(hres))
415         return hres;
416
417     cnd_jmp = push_instr(ctx, OP_jmp_false);
418     if(cnd_jmp == -1)
419         return E_OUTOFMEMORY;
420
421     hres = compile_statement(ctx, stat->if_stat);
422     if(FAILED(hres))
423         return hres;
424
425     if(stat->else_stat || stat->elseifs) {
426         endif_label = alloc_label(ctx);
427         if(endif_label == -1)
428             return E_OUTOFMEMORY;
429
430         hres = push_instr_addr(ctx, OP_jmp, endif_label);
431         if(FAILED(hres))
432             return hres;
433     }
434
435     for(elseif_decl = stat->elseifs; elseif_decl; elseif_decl = elseif_decl->next) {
436         instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;
437
438         hres = compile_expression(ctx, elseif_decl->expr);
439         if(FAILED(hres))
440             return hres;
441
442         cnd_jmp = push_instr(ctx, OP_jmp_false);
443         if(cnd_jmp == -1)
444             return E_OUTOFMEMORY;
445
446         hres = compile_statement(ctx, elseif_decl->stat);
447         if(FAILED(hres))
448             return hres;
449
450         hres = push_instr_addr(ctx, OP_jmp, endif_label);
451         if(FAILED(hres))
452             return hres;
453     }
454
455     instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;
456
457     if(stat->else_stat) {
458         hres = compile_statement(ctx, stat->else_stat);
459         if(FAILED(hres))
460             return hres;
461     }
462
463     if(endif_label != -1)
464         label_set_addr(ctx, endif_label);
465     return S_OK;
466 }
467
468 static HRESULT compile_assign_statement(compile_ctx_t *ctx, assign_statement_t *stat)
469 {
470     HRESULT hres;
471
472     hres = compile_expression(ctx, stat->value_expr);
473     if(FAILED(hres))
474         return hres;
475
476     if(stat->member_expr->args) {
477         FIXME("arguments support not implemented\n");
478         return E_NOTIMPL;
479     }
480
481     if(stat->member_expr->obj_expr) {
482         hres = compile_expression(ctx, stat->member_expr->obj_expr);
483         if(FAILED(hres))
484             return hres;
485
486         hres = push_instr_bstr(ctx, OP_assign_member, stat->member_expr->identifier);
487     }else {
488         hres = push_instr_bstr(ctx, OP_assign_ident, stat->member_expr->identifier);
489     }
490
491     return hres;
492 }
493
494 static BOOL lookup_dim_decls(compile_ctx_t *ctx, const WCHAR *name)
495 {
496     dim_decl_t *dim_decl;
497
498     for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
499         if(!strcmpiW(dim_decl->name, name))
500             return TRUE;
501     }
502
503     return FALSE;
504 }
505
506 static BOOL lookup_args_name(compile_ctx_t *ctx, const WCHAR *name)
507 {
508     unsigned i;
509
510     for(i = 0; i < ctx->func->arg_cnt; i++) {
511         if(!strcmpiW(ctx->func->args[i].name, name))
512             return TRUE;
513     }
514
515     return FALSE;
516 }
517
518 static HRESULT compile_dim_statement(compile_ctx_t *ctx, dim_statement_t *stat)
519 {
520     dim_decl_t *dim_decl = stat->dim_decls;
521
522     while(1) {
523         if(lookup_dim_decls(ctx, dim_decl->name) || lookup_args_name(ctx, dim_decl->name)) {
524             FIXME("dim %s name redefined\n", debugstr_w(dim_decl->name));
525             return E_FAIL;
526         }
527
528         if(!dim_decl->next)
529             break;
530         dim_decl = dim_decl->next;
531     }
532
533     dim_decl->next = ctx->dim_decls;
534     ctx->dim_decls = stat->dim_decls;
535     ctx->func->var_cnt++;
536     return S_OK;
537 }
538
539 static HRESULT compile_function_statement(compile_ctx_t *ctx, function_statement_t *stat)
540 {
541     if(ctx->func != &ctx->code->global_code) {
542         FIXME("Function is not in the global code\n");
543         return E_FAIL;
544     }
545
546     stat->func_decl->next = ctx->func_decls;
547     ctx->func_decls = stat->func_decl;
548     return S_OK;
549 }
550
551 static HRESULT compile_exitsub_statement(compile_ctx_t *ctx)
552 {
553     if(ctx->sub_end_label == -1) {
554         FIXME("Exit Sub outside Sub?\n");
555         return E_FAIL;
556     }
557
558     return push_instr_addr(ctx, OP_jmp, ctx->sub_end_label);
559 }
560
561 static HRESULT compile_exitfunc_statement(compile_ctx_t *ctx)
562 {
563     if(ctx->func_end_label == -1) {
564         FIXME("Exit Function outside Function?\n");
565         return E_FAIL;
566     }
567
568     return push_instr_addr(ctx, OP_jmp, ctx->func_end_label);
569 }
570
571 static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat)
572 {
573     HRESULT hres;
574
575     while(stat) {
576         switch(stat->type) {
577         case STAT_ASSIGN:
578             hres = compile_assign_statement(ctx, (assign_statement_t*)stat);
579             break;
580         case STAT_CALL:
581             hres = compile_member_expression(ctx, ((call_statement_t*)stat)->expr, FALSE);
582             break;
583         case STAT_DIM:
584             hres = compile_dim_statement(ctx, (dim_statement_t*)stat);
585             break;
586         case STAT_EXITFUNC:
587             hres = compile_exitfunc_statement(ctx);
588             break;
589         case STAT_EXITSUB:
590             hres = compile_exitsub_statement(ctx);
591             break;
592         case STAT_FUNC:
593             hres = compile_function_statement(ctx, (function_statement_t*)stat);
594             break;
595         case STAT_IF:
596             hres = compile_if_statement(ctx, (if_statement_t*)stat);
597             break;
598         default:
599             FIXME("Unimplemented statement type %d\n", stat->type);
600             hres = E_NOTIMPL;
601         }
602
603         if(FAILED(hres))
604             return hres;
605         stat = stat->next;
606     }
607
608     return S_OK;
609 }
610
611 static void resolve_labels(compile_ctx_t *ctx, unsigned off)
612 {
613     instr_t *instr;
614
615     for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->instr_cnt; instr++) {
616         if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->arg1.uint & LABEL_FLAG)) {
617             assert((instr->arg1.uint & ~LABEL_FLAG) < ctx->labels_cnt);
618             instr->arg1.uint = ctx->labels[instr->arg1.uint & ~LABEL_FLAG];
619         }
620         assert(instr_info[instr->op].arg2_type != ARG_ADDR);
621     }
622
623     ctx->labels_cnt = 0;
624 }
625
626 static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *func)
627 {
628     HRESULT hres;
629
630     func->code_off = ctx->instr_cnt;
631
632     ctx->sub_end_label = -1;
633     ctx->func_end_label = -1;
634
635     switch(func->type) {
636     case FUNC_FUNCTION:
637         ctx->func_end_label = alloc_label(ctx);
638         if(ctx->func_end_label == -1)
639             return E_OUTOFMEMORY; /* FIXME ! */
640         break;
641     case FUNC_SUB:
642         ctx->sub_end_label = alloc_label(ctx);
643         if(ctx->sub_end_label == -1)
644             return E_OUTOFMEMORY;
645         break;
646     case FUNC_GLOBAL:
647         break;
648     }
649
650     ctx->func = func;
651     ctx->dim_decls = NULL;
652     hres = compile_statement(ctx, stat);
653     ctx->func = NULL;
654     if(FAILED(hres))
655         return hres;
656
657     if(ctx->sub_end_label != -1)
658         label_set_addr(ctx, ctx->sub_end_label);
659     if(ctx->func_end_label != -1)
660         label_set_addr(ctx, ctx->func_end_label);
661
662     if(push_instr(ctx, OP_ret) == -1)
663         return E_OUTOFMEMORY;
664
665     resolve_labels(ctx, func->code_off);
666
667     if(func->var_cnt) {
668         dim_decl_t *dim_decl;
669
670         if(func->type == FUNC_GLOBAL) {
671             dynamic_var_t *new_var;
672
673             func->var_cnt = 0;
674
675             for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
676                 new_var = compiler_alloc(ctx->code, sizeof(*new_var));
677                 if(!new_var)
678                     return E_OUTOFMEMORY;
679
680                 new_var->name = compiler_alloc_string(ctx->code, dim_decl->name);
681                 if(!new_var->name)
682                     return E_OUTOFMEMORY;
683
684                 V_VT(&new_var->v) = VT_EMPTY;
685
686                 new_var->next = ctx->global_vars;
687                 ctx->global_vars = new_var;
688             }
689         }else {
690             unsigned i;
691
692             func->vars = compiler_alloc(ctx->code, func->var_cnt * sizeof(var_desc_t));
693             if(!func->vars)
694                 return E_OUTOFMEMORY;
695
696             for(dim_decl = ctx->dim_decls, i=0; dim_decl; dim_decl = dim_decl->next, i++) {
697                 func->vars[i].name = compiler_alloc_string(ctx->code, dim_decl->name);
698                 if(!func->vars[i].name)
699                     return E_OUTOFMEMORY;
700             }
701
702             assert(i == func->var_cnt);
703         }
704     }
705
706     return S_OK;
707 }
708
709 static BOOL lookup_funcs_name(compile_ctx_t *ctx, const WCHAR *name)
710 {
711     function_t *iter;
712
713     for(iter = ctx->funcs; iter; iter = iter->next) {
714         if(!strcmpiW(iter->name, name))
715             return TRUE;
716     }
717
718     return FALSE;
719 }
720
721 static HRESULT create_function(compile_ctx_t *ctx, function_decl_t *decl, function_t **ret)
722 {
723     function_t *func;
724     HRESULT hres;
725
726     if(lookup_dim_decls(ctx, decl->name) || lookup_funcs_name(ctx, decl->name)) {
727         FIXME("%s: redefinition\n", debugstr_w(decl->name));
728         return E_FAIL;
729     }
730
731     func = compiler_alloc(ctx->code, sizeof(*func));
732     if(!func)
733         return E_OUTOFMEMORY;
734
735     func->name = compiler_alloc_string(ctx->code, decl->name);
736     if(!func->name)
737         return E_OUTOFMEMORY;
738
739     func->vars = NULL;
740     func->var_cnt = 0;
741     func->code_ctx = ctx->code;
742     func->type = decl->type;
743
744     func->arg_cnt = 0;
745     if(decl->args) {
746         arg_decl_t *arg;
747         unsigned i;
748
749         for(arg = decl->args; arg; arg = arg->next)
750             func->arg_cnt++;
751
752         func->args = compiler_alloc(ctx->code, func->arg_cnt * sizeof(arg_desc_t));
753         if(!func->args)
754             return E_OUTOFMEMORY;
755
756         for(i = 0, arg = decl->args; arg; arg = arg->next, i++) {
757             func->args[i].name = compiler_alloc_string(ctx->code, arg->name);
758             if(!func->args[i].name)
759                 return E_OUTOFMEMORY;
760             func->args[i].by_ref = arg->by_ref;
761         }
762     }else {
763         func->args = NULL;
764     }
765
766     hres = compile_func(ctx, decl->body, func);
767     if(FAILED(hres))
768         return hres;
769
770     *ret = func;
771     return S_OK;
772 }
773
774 static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifier)
775 {
776     dynamic_var_t *var;
777     function_t *func;
778
779     for(var = script->global_vars; var; var = var->next) {
780         if(!strcmpiW(var->name, identifier))
781             return TRUE;
782     }
783
784     for(func = script->global_funcs; func; func = func->next) {
785         if(!strcmpiW(func->name, identifier))
786             return TRUE;
787     }
788
789     return FALSE;
790 }
791
792 static HRESULT check_script_collisions(compile_ctx_t *ctx, script_ctx_t *script)
793 {
794     dynamic_var_t *var;
795     function_t *func;
796
797     for(var = ctx->global_vars; var; var = var->next) {
798         if(lookup_script_identifier(script, var->name)) {
799             FIXME("%s: redefined\n", debugstr_w(var->name));
800             return E_FAIL;
801         }
802     }
803
804     for(func = ctx->funcs; func; func = func->next) {
805         if(lookup_script_identifier(script, func->name)) {
806             FIXME("%s: redefined\n", debugstr_w(func->name));
807             return E_FAIL;
808         }
809     }
810
811     return S_OK;
812 }
813
814 void release_vbscode(vbscode_t *code)
815 {
816     unsigned i;
817
818     list_remove(&code->entry);
819
820     for(i=0; i < code->bstr_cnt; i++)
821         SysFreeString(code->bstr_pool[i]);
822
823     vbsheap_free(&code->heap);
824
825     heap_free(code->bstr_pool);
826     heap_free(code->source);
827     heap_free(code->instrs);
828     heap_free(code);
829 }
830
831 static vbscode_t *alloc_vbscode(compile_ctx_t *ctx, const WCHAR *source)
832 {
833     vbscode_t *ret;
834
835     ret = heap_alloc(sizeof(*ret));
836     if(!ret)
837         return NULL;
838
839     ret->source = heap_strdupW(source);
840     if(!ret->source) {
841         heap_free(ret);
842         return NULL;
843     }
844
845     ret->instrs = heap_alloc(32*sizeof(instr_t));
846     if(!ret->instrs) {
847         release_vbscode(ret);
848         return NULL;
849     }
850
851     ctx->instr_cnt = 0;
852     ctx->instr_size = 32;
853     vbsheap_init(&ret->heap);
854
855     ret->option_explicit = ctx->parser.option_explicit;
856
857     ret->bstr_pool = NULL;
858     ret->bstr_pool_size = 0;
859     ret->bstr_cnt = 0;
860     ret->global_executed = FALSE;
861
862     ret->global_code.type = FUNC_GLOBAL;
863     ret->global_code.name = NULL;
864     ret->global_code.code_ctx = ret;
865     ret->global_code.vars = NULL;
866     ret->global_code.var_cnt = 0;
867     ret->global_code.arg_cnt = 0;
868     ret->global_code.args = NULL;
869
870     list_init(&ret->entry);
871     return ret;
872 }
873
874 static void release_compiler(compile_ctx_t *ctx)
875 {
876     parser_release(&ctx->parser);
877     heap_free(ctx->labels);
878     if(ctx->code)
879         release_vbscode(ctx->code);
880 }
881
882 HRESULT compile_script(script_ctx_t *script, const WCHAR *src, vbscode_t **ret)
883 {
884     function_t *new_func;
885     function_decl_t *func_decl;
886     compile_ctx_t ctx;
887     vbscode_t *code;
888     HRESULT hres;
889
890     hres = parse_script(&ctx.parser, src);
891     if(FAILED(hres))
892         return hres;
893
894     code = ctx.code = alloc_vbscode(&ctx, src);
895     if(!ctx.code)
896         return E_OUTOFMEMORY;
897
898     ctx.funcs = NULL;
899     ctx.func_decls = NULL;
900     ctx.global_vars = NULL;
901     ctx.dim_decls = NULL;
902     ctx.labels = NULL;
903     ctx.labels_cnt = ctx.labels_size = 0;
904
905     hres = compile_func(&ctx, ctx.parser.stats, &ctx.code->global_code);
906     if(FAILED(hres)) {
907         release_compiler(&ctx);
908         return hres;
909     }
910
911     for(func_decl = ctx.func_decls; func_decl; func_decl = func_decl->next) {
912         hres = create_function(&ctx, func_decl, &new_func);
913         if(FAILED(hres)) {
914             release_compiler(&ctx);
915             return hres;
916         }
917
918         new_func->next = ctx.funcs;
919         ctx.funcs = new_func;
920     }
921
922     hres = check_script_collisions(&ctx, script);
923     if(FAILED(hres)) {
924         release_compiler(&ctx);
925         return hres;
926     }
927
928     if(ctx.global_vars) {
929         dynamic_var_t *var;
930
931         for(var = ctx.global_vars; var->next; var = var->next);
932
933         var->next = script->global_vars;
934         script->global_vars = ctx.global_vars;
935     }
936
937     if(ctx.funcs) {
938         for(new_func = ctx.funcs; new_func->next; new_func = new_func->next);
939
940         new_func->next = script->global_funcs;
941         script->global_funcs = ctx.funcs;
942     }
943
944     if(TRACE_ON(vbscript_disas))
945         dump_code(&ctx);
946
947     ctx.code = NULL;
948     release_compiler(&ctx);
949
950     list_add_tail(&script->code_list, &code->entry);
951     *ret = code;
952     return S_OK;
953 }