xref: /reactos/dll/win32/vbscript/compile.c (revision 9a0ddc13)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Copyright 2011 Jacek Caban for CodeWeavers
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
5c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
6c2c66affSColin Finck  * License as published by the Free Software Foundation; either
7c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
8c2c66affSColin Finck  *
9c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
10c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12c2c66affSColin Finck  * Lesser General Public License for more details.
13c2c66affSColin Finck  *
14c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
15c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
16c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17c2c66affSColin Finck  */
18c2c66affSColin Finck 
199f8faabaSAmine Khaldi #include <assert.h>
20c2c66affSColin Finck 
219f8faabaSAmine Khaldi #include "vbscript.h"
229f8faabaSAmine Khaldi #include "parse.h"
239f8faabaSAmine Khaldi #include "parser.tab.h"
249f8faabaSAmine Khaldi 
259f8faabaSAmine Khaldi #include "wine/debug.h"
269f8faabaSAmine Khaldi 
279f8faabaSAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
28c2c66affSColin Finck WINE_DECLARE_DEBUG_CHANNEL(vbscript_disas);
29c2c66affSColin Finck 
30c2c66affSColin Finck typedef struct _statement_ctx_t {
31c2c66affSColin Finck     unsigned stack_use;
32c2c66affSColin Finck 
33c2c66affSColin Finck     unsigned while_end_label;
34c2c66affSColin Finck     unsigned for_end_label;
35c2c66affSColin Finck 
36c2c66affSColin Finck     struct _statement_ctx_t *next;
37c2c66affSColin Finck } statement_ctx_t;
38c2c66affSColin Finck 
39c2c66affSColin Finck typedef struct {
40c2c66affSColin Finck     parser_ctx_t parser;
41c2c66affSColin Finck 
42c2c66affSColin Finck     unsigned instr_cnt;
43c2c66affSColin Finck     unsigned instr_size;
44c2c66affSColin Finck     vbscode_t *code;
45c2c66affSColin Finck 
46c2c66affSColin Finck     statement_ctx_t *stat_ctx;
47c2c66affSColin Finck 
48c2c66affSColin Finck     unsigned *labels;
49c2c66affSColin Finck     unsigned labels_size;
50c2c66affSColin Finck     unsigned labels_cnt;
51c2c66affSColin Finck 
52c2c66affSColin Finck     unsigned sub_end_label;
53c2c66affSColin Finck     unsigned func_end_label;
54c2c66affSColin Finck     unsigned prop_end_label;
55c2c66affSColin Finck 
56c2c66affSColin Finck     dim_decl_t *dim_decls;
57c2c66affSColin Finck     dim_decl_t *dim_decls_tail;
58c2c66affSColin Finck     dynamic_var_t *global_vars;
59c2c66affSColin Finck 
60c2c66affSColin Finck     const_decl_t *const_decls;
61c2c66affSColin Finck     const_decl_t *global_consts;
62c2c66affSColin Finck 
63c2c66affSColin Finck     function_t *func;
64c2c66affSColin Finck     function_t *funcs;
65c2c66affSColin Finck     function_decl_t *func_decls;
66c2c66affSColin Finck 
67c2c66affSColin Finck     class_desc_t *classes;
68c2c66affSColin Finck } compile_ctx_t;
69c2c66affSColin Finck 
70c2c66affSColin Finck static HRESULT compile_expression(compile_ctx_t*,expression_t*);
71c2c66affSColin Finck static HRESULT compile_statement(compile_ctx_t*,statement_ctx_t*,statement_t*);
72c2c66affSColin Finck 
73c2c66affSColin Finck static const struct {
74c2c66affSColin Finck     const char *op_str;
75c2c66affSColin Finck     instr_arg_type_t arg1_type;
76c2c66affSColin Finck     instr_arg_type_t arg2_type;
77c2c66affSColin Finck } instr_info[] = {
78c2c66affSColin Finck #define X(n,a,b,c) {#n,b,c},
79c2c66affSColin Finck OP_LIST
80c2c66affSColin Finck #undef X
81c2c66affSColin Finck };
82c2c66affSColin Finck 
dump_instr_arg(instr_arg_type_t type,instr_arg_t * arg)83c2c66affSColin Finck static void dump_instr_arg(instr_arg_type_t type, instr_arg_t *arg)
84c2c66affSColin Finck {
85c2c66affSColin Finck     switch(type) {
86c2c66affSColin Finck     case ARG_STR:
87c2c66affSColin Finck     case ARG_BSTR:
88c2c66affSColin Finck         TRACE_(vbscript_disas)("\t%s", debugstr_w(arg->str));
89c2c66affSColin Finck         break;
90c2c66affSColin Finck     case ARG_INT:
91c2c66affSColin Finck         TRACE_(vbscript_disas)("\t%d", arg->uint);
92c2c66affSColin Finck         break;
93c2c66affSColin Finck     case ARG_UINT:
94c2c66affSColin Finck     case ARG_ADDR:
95c2c66affSColin Finck         TRACE_(vbscript_disas)("\t%u", arg->uint);
96c2c66affSColin Finck         break;
97c2c66affSColin Finck     case ARG_DOUBLE:
98c2c66affSColin Finck         TRACE_(vbscript_disas)("\t%lf", *arg->dbl);
99c2c66affSColin Finck         break;
100c2c66affSColin Finck     case ARG_NONE:
101c2c66affSColin Finck         break;
102c2c66affSColin Finck     DEFAULT_UNREACHABLE;
103c2c66affSColin Finck     }
104c2c66affSColin Finck }
105c2c66affSColin Finck 
dump_code(compile_ctx_t * ctx)106c2c66affSColin Finck static void dump_code(compile_ctx_t *ctx)
107c2c66affSColin Finck {
108c2c66affSColin Finck     instr_t *instr;
109c2c66affSColin Finck 
110c2c66affSColin Finck     for(instr = ctx->code->instrs+1; instr < ctx->code->instrs+ctx->instr_cnt; instr++) {
111c2c66affSColin Finck         assert(instr->op < OP_LAST);
112c2c66affSColin Finck         TRACE_(vbscript_disas)("%d:\t%s", (int)(instr-ctx->code->instrs), instr_info[instr->op].op_str);
113c2c66affSColin Finck         dump_instr_arg(instr_info[instr->op].arg1_type, &instr->arg1);
114c2c66affSColin Finck         dump_instr_arg(instr_info[instr->op].arg2_type, &instr->arg2);
115c2c66affSColin Finck         TRACE_(vbscript_disas)("\n");
116c2c66affSColin Finck     }
117c2c66affSColin Finck }
118c2c66affSColin Finck 
compiler_alloc(vbscode_t * vbscode,size_t size)119c2c66affSColin Finck static inline void *compiler_alloc(vbscode_t *vbscode, size_t size)
120c2c66affSColin Finck {
121c2c66affSColin Finck     return heap_pool_alloc(&vbscode->heap, size);
122c2c66affSColin Finck }
123c2c66affSColin Finck 
compiler_alloc_zero(vbscode_t * vbscode,size_t size)124c2c66affSColin Finck static inline void *compiler_alloc_zero(vbscode_t *vbscode, size_t size)
125c2c66affSColin Finck {
126c2c66affSColin Finck     void *ret;
127c2c66affSColin Finck 
128c2c66affSColin Finck     ret = heap_pool_alloc(&vbscode->heap, size);
129c2c66affSColin Finck     if(ret)
130c2c66affSColin Finck         memset(ret, 0, size);
131c2c66affSColin Finck     return ret;
132c2c66affSColin Finck }
133c2c66affSColin Finck 
compiler_alloc_string(vbscode_t * vbscode,const WCHAR * str)134c2c66affSColin Finck static WCHAR *compiler_alloc_string(vbscode_t *vbscode, const WCHAR *str)
135c2c66affSColin Finck {
136c2c66affSColin Finck     size_t size;
137c2c66affSColin Finck     WCHAR *ret;
138c2c66affSColin Finck 
139*9a0ddc13SAmine Khaldi     size = (lstrlenW(str)+1)*sizeof(WCHAR);
140c2c66affSColin Finck     ret = compiler_alloc(vbscode, size);
141c2c66affSColin Finck     if(ret)
142c2c66affSColin Finck         memcpy(ret, str, size);
143c2c66affSColin Finck     return ret;
144c2c66affSColin Finck }
145c2c66affSColin Finck 
instr_ptr(compile_ctx_t * ctx,unsigned id)146c2c66affSColin Finck static inline instr_t *instr_ptr(compile_ctx_t *ctx, unsigned id)
147c2c66affSColin Finck {
148c2c66affSColin Finck     assert(id < ctx->instr_cnt);
149c2c66affSColin Finck     return ctx->code->instrs + id;
150c2c66affSColin Finck }
151c2c66affSColin Finck 
push_instr(compile_ctx_t * ctx,vbsop_t op)152c2c66affSColin Finck static unsigned push_instr(compile_ctx_t *ctx, vbsop_t op)
153c2c66affSColin Finck {
154c2c66affSColin Finck     assert(ctx->instr_size && ctx->instr_size >= ctx->instr_cnt);
155c2c66affSColin Finck 
156c2c66affSColin Finck     if(ctx->instr_size == ctx->instr_cnt) {
157c2c66affSColin Finck         instr_t *new_instr;
158c2c66affSColin Finck 
159c2c66affSColin Finck         new_instr = heap_realloc(ctx->code->instrs, ctx->instr_size*2*sizeof(instr_t));
160c2c66affSColin Finck         if(!new_instr)
161c2c66affSColin Finck             return 0;
162c2c66affSColin Finck 
163c2c66affSColin Finck         ctx->code->instrs = new_instr;
164c2c66affSColin Finck         ctx->instr_size *= 2;
165c2c66affSColin Finck     }
166c2c66affSColin Finck 
167c2c66affSColin Finck     ctx->code->instrs[ctx->instr_cnt].op = op;
168c2c66affSColin Finck     return ctx->instr_cnt++;
169c2c66affSColin Finck }
170c2c66affSColin Finck 
push_instr_int(compile_ctx_t * ctx,vbsop_t op,LONG arg)171c2c66affSColin Finck static HRESULT push_instr_int(compile_ctx_t *ctx, vbsop_t op, LONG arg)
172c2c66affSColin Finck {
173c2c66affSColin Finck     unsigned ret;
174c2c66affSColin Finck 
175c2c66affSColin Finck     ret = push_instr(ctx, op);
176c2c66affSColin Finck     if(!ret)
177c2c66affSColin Finck         return E_OUTOFMEMORY;
178c2c66affSColin Finck 
179c2c66affSColin Finck     instr_ptr(ctx, ret)->arg1.lng = arg;
180c2c66affSColin Finck     return S_OK;
181c2c66affSColin Finck }
182c2c66affSColin Finck 
push_instr_uint(compile_ctx_t * ctx,vbsop_t op,unsigned arg)183c2c66affSColin Finck static HRESULT push_instr_uint(compile_ctx_t *ctx, vbsop_t op, unsigned arg)
184c2c66affSColin Finck {
185c2c66affSColin Finck     unsigned ret;
186c2c66affSColin Finck 
187c2c66affSColin Finck     ret = push_instr(ctx, op);
188c2c66affSColin Finck     if(!ret)
189c2c66affSColin Finck         return E_OUTOFMEMORY;
190c2c66affSColin Finck 
191c2c66affSColin Finck     instr_ptr(ctx, ret)->arg1.uint = arg;
192c2c66affSColin Finck     return S_OK;
193c2c66affSColin Finck }
194c2c66affSColin Finck 
push_instr_addr(compile_ctx_t * ctx,vbsop_t op,unsigned arg)195c2c66affSColin Finck static HRESULT push_instr_addr(compile_ctx_t *ctx, vbsop_t op, unsigned arg)
196c2c66affSColin Finck {
197c2c66affSColin Finck     unsigned ret;
198c2c66affSColin Finck 
199c2c66affSColin Finck     ret = push_instr(ctx, op);
200c2c66affSColin Finck     if(!ret)
201c2c66affSColin Finck         return E_OUTOFMEMORY;
202c2c66affSColin Finck 
203c2c66affSColin Finck     instr_ptr(ctx, ret)->arg1.uint = arg;
204c2c66affSColin Finck     return S_OK;
205c2c66affSColin Finck }
206c2c66affSColin Finck 
push_instr_str(compile_ctx_t * ctx,vbsop_t op,const WCHAR * arg)207c2c66affSColin Finck static HRESULT push_instr_str(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg)
208c2c66affSColin Finck {
209c2c66affSColin Finck     unsigned instr;
210c2c66affSColin Finck     WCHAR *str;
211c2c66affSColin Finck 
212c2c66affSColin Finck     str = compiler_alloc_string(ctx->code, arg);
213c2c66affSColin Finck     if(!str)
214c2c66affSColin Finck         return E_OUTOFMEMORY;
215c2c66affSColin Finck 
216c2c66affSColin Finck     instr = push_instr(ctx, op);
217c2c66affSColin Finck     if(!instr)
218c2c66affSColin Finck         return E_OUTOFMEMORY;
219c2c66affSColin Finck 
220c2c66affSColin Finck     instr_ptr(ctx, instr)->arg1.str = str;
221c2c66affSColin Finck     return S_OK;
222c2c66affSColin Finck }
223c2c66affSColin Finck 
push_instr_double(compile_ctx_t * ctx,vbsop_t op,double arg)224c2c66affSColin Finck static HRESULT push_instr_double(compile_ctx_t *ctx, vbsop_t op, double arg)
225c2c66affSColin Finck {
226c2c66affSColin Finck     unsigned instr;
227c2c66affSColin Finck     double *d;
228c2c66affSColin Finck 
229c2c66affSColin Finck     d = compiler_alloc(ctx->code, sizeof(double));
230c2c66affSColin Finck     if(!d)
231c2c66affSColin Finck         return E_OUTOFMEMORY;
232c2c66affSColin Finck 
233c2c66affSColin Finck     instr = push_instr(ctx, op);
234c2c66affSColin Finck     if(!instr)
235c2c66affSColin Finck         return E_OUTOFMEMORY;
236c2c66affSColin Finck 
237c2c66affSColin Finck     *d = arg;
238c2c66affSColin Finck     instr_ptr(ctx, instr)->arg1.dbl = d;
239c2c66affSColin Finck     return S_OK;
240c2c66affSColin Finck }
241c2c66affSColin Finck 
alloc_bstr_arg(compile_ctx_t * ctx,const WCHAR * str)242c2c66affSColin Finck static BSTR alloc_bstr_arg(compile_ctx_t *ctx, const WCHAR *str)
243c2c66affSColin Finck {
244c2c66affSColin Finck     if(!ctx->code->bstr_pool_size) {
245c2c66affSColin Finck         ctx->code->bstr_pool = heap_alloc(8 * sizeof(BSTR));
246c2c66affSColin Finck         if(!ctx->code->bstr_pool)
247c2c66affSColin Finck             return NULL;
248c2c66affSColin Finck         ctx->code->bstr_pool_size = 8;
249c2c66affSColin Finck     }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) {
250c2c66affSColin Finck         BSTR *new_pool;
251c2c66affSColin Finck 
252c2c66affSColin Finck         new_pool = heap_realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR));
253c2c66affSColin Finck         if(!new_pool)
254c2c66affSColin Finck             return NULL;
255c2c66affSColin Finck 
256c2c66affSColin Finck         ctx->code->bstr_pool = new_pool;
257c2c66affSColin Finck         ctx->code->bstr_pool_size *= 2;
258c2c66affSColin Finck     }
259c2c66affSColin Finck 
260c2c66affSColin Finck     ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocString(str);
261c2c66affSColin Finck     if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
262c2c66affSColin Finck         return NULL;
263c2c66affSColin Finck 
264c2c66affSColin Finck     return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
265c2c66affSColin Finck }
266c2c66affSColin Finck 
push_instr_bstr(compile_ctx_t * ctx,vbsop_t op,const WCHAR * arg)267c2c66affSColin Finck static HRESULT push_instr_bstr(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg)
268c2c66affSColin Finck {
269c2c66affSColin Finck     unsigned instr;
270c2c66affSColin Finck     BSTR bstr;
271c2c66affSColin Finck 
272c2c66affSColin Finck     bstr = alloc_bstr_arg(ctx, arg);
273c2c66affSColin Finck     if(!bstr)
274c2c66affSColin Finck         return E_OUTOFMEMORY;
275c2c66affSColin Finck 
276c2c66affSColin Finck     instr = push_instr(ctx, op);
277c2c66affSColin Finck     if(!instr)
278c2c66affSColin Finck         return E_OUTOFMEMORY;
279c2c66affSColin Finck 
280c2c66affSColin Finck     instr_ptr(ctx, instr)->arg1.bstr = bstr;
281c2c66affSColin Finck     return S_OK;
282c2c66affSColin Finck }
283c2c66affSColin Finck 
push_instr_bstr_uint(compile_ctx_t * ctx,vbsop_t op,const WCHAR * arg1,unsigned arg2)284c2c66affSColin Finck static HRESULT push_instr_bstr_uint(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg1, unsigned arg2)
285c2c66affSColin Finck {
286c2c66affSColin Finck     unsigned instr;
287c2c66affSColin Finck     BSTR bstr;
288c2c66affSColin Finck 
289c2c66affSColin Finck     bstr = alloc_bstr_arg(ctx, arg1);
290c2c66affSColin Finck     if(!bstr)
291c2c66affSColin Finck         return E_OUTOFMEMORY;
292c2c66affSColin Finck 
293c2c66affSColin Finck     instr = push_instr(ctx, op);
294c2c66affSColin Finck     if(!instr)
295c2c66affSColin Finck         return E_OUTOFMEMORY;
296c2c66affSColin Finck 
297c2c66affSColin Finck     instr_ptr(ctx, instr)->arg1.bstr = bstr;
298c2c66affSColin Finck     instr_ptr(ctx, instr)->arg2.uint = arg2;
299c2c66affSColin Finck     return S_OK;
300c2c66affSColin Finck }
301c2c66affSColin Finck 
push_instr_uint_bstr(compile_ctx_t * ctx,vbsop_t op,unsigned arg1,const WCHAR * arg2)302c2c66affSColin Finck static HRESULT push_instr_uint_bstr(compile_ctx_t *ctx, vbsop_t op, unsigned arg1, const WCHAR *arg2)
303c2c66affSColin Finck {
304c2c66affSColin Finck     unsigned instr;
305c2c66affSColin Finck     BSTR bstr;
306c2c66affSColin Finck 
307c2c66affSColin Finck     bstr = alloc_bstr_arg(ctx, arg2);
308c2c66affSColin Finck     if(!bstr)
309c2c66affSColin Finck         return E_OUTOFMEMORY;
310c2c66affSColin Finck 
311c2c66affSColin Finck     instr = push_instr(ctx, op);
312c2c66affSColin Finck     if(!instr)
313c2c66affSColin Finck         return E_OUTOFMEMORY;
314c2c66affSColin Finck 
315c2c66affSColin Finck     instr_ptr(ctx, instr)->arg1.uint = arg1;
316c2c66affSColin Finck     instr_ptr(ctx, instr)->arg2.bstr = bstr;
317c2c66affSColin Finck     return S_OK;
318c2c66affSColin Finck }
319c2c66affSColin Finck 
320c2c66affSColin Finck #define LABEL_FLAG 0x80000000
321c2c66affSColin Finck 
alloc_label(compile_ctx_t * ctx)322c2c66affSColin Finck static unsigned alloc_label(compile_ctx_t *ctx)
323c2c66affSColin Finck {
324c2c66affSColin Finck     if(!ctx->labels_size) {
325c2c66affSColin Finck         ctx->labels = heap_alloc(8 * sizeof(*ctx->labels));
326c2c66affSColin Finck         if(!ctx->labels)
327c2c66affSColin Finck             return 0;
328c2c66affSColin Finck         ctx->labels_size = 8;
329c2c66affSColin Finck     }else if(ctx->labels_size == ctx->labels_cnt) {
330c2c66affSColin Finck         unsigned *new_labels;
331c2c66affSColin Finck 
332c2c66affSColin Finck         new_labels = heap_realloc(ctx->labels, 2*ctx->labels_size*sizeof(*ctx->labels));
333c2c66affSColin Finck         if(!new_labels)
334c2c66affSColin Finck             return 0;
335c2c66affSColin Finck 
336c2c66affSColin Finck         ctx->labels = new_labels;
337c2c66affSColin Finck         ctx->labels_size *= 2;
338c2c66affSColin Finck     }
339c2c66affSColin Finck 
340c2c66affSColin Finck     return ctx->labels_cnt++ | LABEL_FLAG;
341c2c66affSColin Finck }
342c2c66affSColin Finck 
label_set_addr(compile_ctx_t * ctx,unsigned label)343c2c66affSColin Finck static inline void label_set_addr(compile_ctx_t *ctx, unsigned label)
344c2c66affSColin Finck {
345c2c66affSColin Finck     assert(label & LABEL_FLAG);
346c2c66affSColin Finck     ctx->labels[label & ~LABEL_FLAG] = ctx->instr_cnt;
347c2c66affSColin Finck }
348c2c66affSColin Finck 
stack_offset(compile_ctx_t * ctx)349c2c66affSColin Finck static inline unsigned stack_offset(compile_ctx_t *ctx)
350c2c66affSColin Finck {
351c2c66affSColin Finck     statement_ctx_t *iter;
352c2c66affSColin Finck     unsigned ret = 0;
353c2c66affSColin Finck 
354c2c66affSColin Finck     for(iter = ctx->stat_ctx; iter; iter = iter->next)
355c2c66affSColin Finck         ret += iter->stack_use;
356c2c66affSColin Finck 
357c2c66affSColin Finck     return ret;
358c2c66affSColin Finck }
359c2c66affSColin Finck 
emit_catch_jmp(compile_ctx_t * ctx,unsigned stack_off,unsigned code_off)360c2c66affSColin Finck static BOOL emit_catch_jmp(compile_ctx_t *ctx, unsigned stack_off, unsigned code_off)
361c2c66affSColin Finck {
362c2c66affSColin Finck     unsigned code;
363c2c66affSColin Finck 
364c2c66affSColin Finck     code = push_instr(ctx, OP_catch);
365c2c66affSColin Finck     if(!code)
366c2c66affSColin Finck         return FALSE;
367c2c66affSColin Finck 
368c2c66affSColin Finck     instr_ptr(ctx, code)->arg1.uint = code_off;
369c2c66affSColin Finck     instr_ptr(ctx, code)->arg2.uint = stack_off + stack_offset(ctx);
370c2c66affSColin Finck     return TRUE;
371c2c66affSColin Finck }
372c2c66affSColin Finck 
emit_catch(compile_ctx_t * ctx,unsigned off)373c2c66affSColin Finck static inline BOOL emit_catch(compile_ctx_t *ctx, unsigned off)
374c2c66affSColin Finck {
375c2c66affSColin Finck     return emit_catch_jmp(ctx, off, ctx->instr_cnt);
376c2c66affSColin Finck }
377c2c66affSColin Finck 
compile_error(script_ctx_t * ctx,HRESULT error)378*9a0ddc13SAmine Khaldi static HRESULT compile_error(script_ctx_t *ctx, HRESULT error)
379*9a0ddc13SAmine Khaldi {
380*9a0ddc13SAmine Khaldi     if(error == SCRIPT_E_REPORTED)
381*9a0ddc13SAmine Khaldi         return error;
382*9a0ddc13SAmine Khaldi 
383*9a0ddc13SAmine Khaldi     clear_ei(&ctx->ei);
384*9a0ddc13SAmine Khaldi     ctx->ei.scode = error = map_hres(error);
385*9a0ddc13SAmine Khaldi     ctx->ei.bstrSource = get_vbscript_string(VBS_COMPILE_ERROR);
386*9a0ddc13SAmine Khaldi     ctx->ei.bstrDescription = get_vbscript_error_string(error);
387*9a0ddc13SAmine Khaldi     return report_script_error(ctx);
388*9a0ddc13SAmine Khaldi }
389*9a0ddc13SAmine Khaldi 
lookup_const_decls(compile_ctx_t * ctx,const WCHAR * name,BOOL lookup_global)390c2c66affSColin Finck static expression_t *lookup_const_decls(compile_ctx_t *ctx, const WCHAR *name, BOOL lookup_global)
391c2c66affSColin Finck {
392c2c66affSColin Finck     const_decl_t *decl;
393c2c66affSColin Finck 
394c2c66affSColin Finck     for(decl = ctx->const_decls; decl; decl = decl->next) {
395*9a0ddc13SAmine Khaldi         if(!wcsicmp(decl->name, name))
396c2c66affSColin Finck             return decl->value_expr;
397c2c66affSColin Finck     }
398c2c66affSColin Finck 
399c2c66affSColin Finck     if(!lookup_global)
400c2c66affSColin Finck         return NULL;
401c2c66affSColin Finck 
402c2c66affSColin Finck     for(decl = ctx->global_consts; decl; decl = decl->next) {
403*9a0ddc13SAmine Khaldi         if(!wcsicmp(decl->name, name))
404c2c66affSColin Finck             return decl->value_expr;
405c2c66affSColin Finck     }
406c2c66affSColin Finck 
407c2c66affSColin Finck     return NULL;
408c2c66affSColin Finck }
409c2c66affSColin Finck 
compile_args(compile_ctx_t * ctx,expression_t * args,unsigned * ret)410c2c66affSColin Finck static HRESULT compile_args(compile_ctx_t *ctx, expression_t *args, unsigned *ret)
411c2c66affSColin Finck {
412c2c66affSColin Finck     unsigned arg_cnt = 0;
413c2c66affSColin Finck     HRESULT hres;
414c2c66affSColin Finck 
415c2c66affSColin Finck     while(args) {
416c2c66affSColin Finck         hres = compile_expression(ctx, args);
417c2c66affSColin Finck         if(FAILED(hres))
418c2c66affSColin Finck             return hres;
419c2c66affSColin Finck 
420c2c66affSColin Finck         arg_cnt++;
421c2c66affSColin Finck         args = args->next;
422c2c66affSColin Finck     }
423c2c66affSColin Finck 
424c2c66affSColin Finck     *ret = arg_cnt;
425c2c66affSColin Finck     return S_OK;
426c2c66affSColin Finck }
427c2c66affSColin Finck 
compile_member_expression(compile_ctx_t * ctx,member_expression_t * expr,BOOL ret_val)428c2c66affSColin Finck static HRESULT compile_member_expression(compile_ctx_t *ctx, member_expression_t *expr, BOOL ret_val)
429c2c66affSColin Finck {
430c2c66affSColin Finck     unsigned arg_cnt = 0;
431c2c66affSColin Finck     HRESULT hres;
432c2c66affSColin Finck 
433c2c66affSColin Finck     if(ret_val && !expr->args) {
434c2c66affSColin Finck         expression_t *const_expr;
435c2c66affSColin Finck 
436c2c66affSColin Finck         const_expr = lookup_const_decls(ctx, expr->identifier, TRUE);
437c2c66affSColin Finck         if(const_expr)
438c2c66affSColin Finck             return compile_expression(ctx, const_expr);
439c2c66affSColin Finck     }
440c2c66affSColin Finck 
441c2c66affSColin Finck     hres = compile_args(ctx, expr->args, &arg_cnt);
442c2c66affSColin Finck     if(FAILED(hres))
443c2c66affSColin Finck         return hres;
444c2c66affSColin Finck 
445c2c66affSColin Finck     if(expr->obj_expr) {
446c2c66affSColin Finck         hres = compile_expression(ctx, expr->obj_expr);
447c2c66affSColin Finck         if(FAILED(hres))
448c2c66affSColin Finck             return hres;
449c2c66affSColin Finck 
450c2c66affSColin Finck         hres = push_instr_bstr_uint(ctx, ret_val ? OP_mcall : OP_mcallv, expr->identifier, arg_cnt);
451c2c66affSColin Finck     }else {
452c2c66affSColin Finck         hres = push_instr_bstr_uint(ctx, ret_val ? OP_icall : OP_icallv, expr->identifier, arg_cnt);
453c2c66affSColin Finck     }
454c2c66affSColin Finck 
455c2c66affSColin Finck     return hres;
456c2c66affSColin Finck }
457c2c66affSColin Finck 
compile_unary_expression(compile_ctx_t * ctx,unary_expression_t * expr,vbsop_t op)458c2c66affSColin Finck static HRESULT compile_unary_expression(compile_ctx_t *ctx, unary_expression_t *expr, vbsop_t op)
459c2c66affSColin Finck {
460c2c66affSColin Finck     HRESULT hres;
461c2c66affSColin Finck 
462c2c66affSColin Finck     hres = compile_expression(ctx, expr->subexpr);
463c2c66affSColin Finck     if(FAILED(hres))
464c2c66affSColin Finck         return hres;
465c2c66affSColin Finck 
466c2c66affSColin Finck     return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
467c2c66affSColin Finck }
468c2c66affSColin Finck 
compile_binary_expression(compile_ctx_t * ctx,binary_expression_t * expr,vbsop_t op)469c2c66affSColin Finck static HRESULT compile_binary_expression(compile_ctx_t *ctx, binary_expression_t *expr, vbsop_t op)
470c2c66affSColin Finck {
471c2c66affSColin Finck     HRESULT hres;
472c2c66affSColin Finck 
473c2c66affSColin Finck     hres = compile_expression(ctx, expr->left);
474c2c66affSColin Finck     if(FAILED(hres))
475c2c66affSColin Finck         return hres;
476c2c66affSColin Finck 
477c2c66affSColin Finck     hres = compile_expression(ctx, expr->right);
478c2c66affSColin Finck     if(FAILED(hres))
479c2c66affSColin Finck         return hres;
480c2c66affSColin Finck 
481c2c66affSColin Finck     return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
482c2c66affSColin Finck }
483c2c66affSColin Finck 
compile_expression(compile_ctx_t * ctx,expression_t * expr)484c2c66affSColin Finck static HRESULT compile_expression(compile_ctx_t *ctx, expression_t *expr)
485c2c66affSColin Finck {
486c2c66affSColin Finck     switch(expr->type) {
487c2c66affSColin Finck     case EXPR_ADD:
488c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add);
489c2c66affSColin Finck     case EXPR_AND:
490c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_and);
491c2c66affSColin Finck     case EXPR_BOOL:
492c2c66affSColin Finck         return push_instr_int(ctx, OP_bool, ((bool_expression_t*)expr)->value);
493c2c66affSColin Finck     case EXPR_BRACKETS:
494c2c66affSColin Finck         return compile_expression(ctx, ((unary_expression_t*)expr)->subexpr);
495c2c66affSColin Finck     case EXPR_CONCAT:
496c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_concat);
497c2c66affSColin Finck     case EXPR_DIV:
498c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div);
499c2c66affSColin Finck     case EXPR_DOUBLE:
500c2c66affSColin Finck         return push_instr_double(ctx, OP_double, ((double_expression_t*)expr)->value);
501c2c66affSColin Finck     case EXPR_EMPTY:
502c2c66affSColin Finck         return push_instr(ctx, OP_empty) ? S_OK : E_OUTOFMEMORY;
503c2c66affSColin Finck     case EXPR_EQUAL:
504c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_equal);
505c2c66affSColin Finck     case EXPR_EQV:
506c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eqv);
507c2c66affSColin Finck     case EXPR_EXP:
508c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_exp);
509c2c66affSColin Finck     case EXPR_GT:
510c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gt);
511c2c66affSColin Finck     case EXPR_GTEQ:
512c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gteq);
513c2c66affSColin Finck     case EXPR_IDIV:
514c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_idiv);
515c2c66affSColin Finck     case EXPR_IS:
516c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_is);
517c2c66affSColin Finck     case EXPR_IMP:
518c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_imp);
519c2c66affSColin Finck     case EXPR_LT:
520c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lt);
521c2c66affSColin Finck     case EXPR_LTEQ:
522c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lteq);
523c2c66affSColin Finck     case EXPR_ME:
524c2c66affSColin Finck         return push_instr(ctx, OP_me) ? S_OK : E_OUTOFMEMORY;
525c2c66affSColin Finck     case EXPR_MEMBER:
526c2c66affSColin Finck         return compile_member_expression(ctx, (member_expression_t*)expr, TRUE);
527c2c66affSColin Finck     case EXPR_MOD:
528c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod);
529c2c66affSColin Finck     case EXPR_MUL:
530c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul);
531c2c66affSColin Finck     case EXPR_NEG:
532c2c66affSColin Finck         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg);
533c2c66affSColin Finck     case EXPR_NEQUAL:
534c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_nequal);
535c2c66affSColin Finck     case EXPR_NEW:
536c2c66affSColin Finck         return push_instr_str(ctx, OP_new, ((string_expression_t*)expr)->value);
537c2c66affSColin Finck     case EXPR_NOARG:
538c2c66affSColin Finck         return push_instr_int(ctx, OP_hres, DISP_E_PARAMNOTFOUND);
539c2c66affSColin Finck     case EXPR_NOT:
540c2c66affSColin Finck         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_not);
541c2c66affSColin Finck     case EXPR_NOTHING:
542c2c66affSColin Finck         return push_instr(ctx, OP_nothing) ? S_OK : E_OUTOFMEMORY;
543c2c66affSColin Finck     case EXPR_NULL:
544c2c66affSColin Finck         return push_instr(ctx, OP_null) ? S_OK : E_OUTOFMEMORY;
545c2c66affSColin Finck     case EXPR_OR:
546c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_or);
547c2c66affSColin Finck     case EXPR_STRING:
548c2c66affSColin Finck         return push_instr_str(ctx, OP_string, ((string_expression_t*)expr)->value);
549c2c66affSColin Finck     case EXPR_SUB:
550c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
551*9a0ddc13SAmine Khaldi     case EXPR_INT:
552*9a0ddc13SAmine Khaldi         return push_instr_int(ctx, OP_int, ((int_expression_t*)expr)->value);
553c2c66affSColin Finck     case EXPR_XOR:
554c2c66affSColin Finck         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor);
555c2c66affSColin Finck     default:
556c2c66affSColin Finck         FIXME("Unimplemented expression type %d\n", expr->type);
557c2c66affSColin Finck         return E_NOTIMPL;
558c2c66affSColin Finck     }
559c2c66affSColin Finck 
560c2c66affSColin Finck     return S_OK;
561c2c66affSColin Finck }
562c2c66affSColin Finck 
compile_if_statement(compile_ctx_t * ctx,if_statement_t * stat)563c2c66affSColin Finck static HRESULT compile_if_statement(compile_ctx_t *ctx, if_statement_t *stat)
564c2c66affSColin Finck {
565c2c66affSColin Finck     unsigned cnd_jmp, endif_label = 0;
566c2c66affSColin Finck     elseif_decl_t *elseif_decl;
567c2c66affSColin Finck     HRESULT hres;
568c2c66affSColin Finck 
569c2c66affSColin Finck     hres = compile_expression(ctx, stat->expr);
570c2c66affSColin Finck     if(FAILED(hres))
571c2c66affSColin Finck         return hres;
572c2c66affSColin Finck 
573c2c66affSColin Finck     cnd_jmp = push_instr(ctx, OP_jmp_false);
574c2c66affSColin Finck     if(!cnd_jmp)
575c2c66affSColin Finck         return E_OUTOFMEMORY;
576c2c66affSColin Finck 
577c2c66affSColin Finck     if(!emit_catch(ctx, 0))
578c2c66affSColin Finck         return E_OUTOFMEMORY;
579c2c66affSColin Finck 
580c2c66affSColin Finck     hres = compile_statement(ctx, NULL, stat->if_stat);
581c2c66affSColin Finck     if(FAILED(hres))
582c2c66affSColin Finck         return hres;
583c2c66affSColin Finck 
584c2c66affSColin Finck     if(stat->else_stat || stat->elseifs) {
585c2c66affSColin Finck         endif_label = alloc_label(ctx);
586c2c66affSColin Finck         if(!endif_label)
587c2c66affSColin Finck             return E_OUTOFMEMORY;
588c2c66affSColin Finck 
589c2c66affSColin Finck         hres = push_instr_addr(ctx, OP_jmp, endif_label);
590c2c66affSColin Finck         if(FAILED(hres))
591c2c66affSColin Finck             return hres;
592c2c66affSColin Finck     }
593c2c66affSColin Finck 
594c2c66affSColin Finck     for(elseif_decl = stat->elseifs; elseif_decl; elseif_decl = elseif_decl->next) {
595c2c66affSColin Finck         instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;
596c2c66affSColin Finck 
597c2c66affSColin Finck         hres = compile_expression(ctx, elseif_decl->expr);
598c2c66affSColin Finck         if(FAILED(hres))
599c2c66affSColin Finck             return hres;
600c2c66affSColin Finck 
601c2c66affSColin Finck         cnd_jmp = push_instr(ctx, OP_jmp_false);
602c2c66affSColin Finck         if(!cnd_jmp)
603c2c66affSColin Finck             return E_OUTOFMEMORY;
604c2c66affSColin Finck 
605c2c66affSColin Finck         if(!emit_catch(ctx, 0))
606c2c66affSColin Finck             return E_OUTOFMEMORY;
607c2c66affSColin Finck 
608c2c66affSColin Finck         hres = compile_statement(ctx, NULL, elseif_decl->stat);
609c2c66affSColin Finck         if(FAILED(hres))
610c2c66affSColin Finck             return hres;
611c2c66affSColin Finck 
612c2c66affSColin Finck         hres = push_instr_addr(ctx, OP_jmp, endif_label);
613c2c66affSColin Finck         if(FAILED(hres))
614c2c66affSColin Finck             return hres;
615c2c66affSColin Finck     }
616c2c66affSColin Finck 
617c2c66affSColin Finck     instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;
618c2c66affSColin Finck 
619c2c66affSColin Finck     if(stat->else_stat) {
620c2c66affSColin Finck         hres = compile_statement(ctx, NULL, stat->else_stat);
621c2c66affSColin Finck         if(FAILED(hres))
622c2c66affSColin Finck             return hres;
623c2c66affSColin Finck     }
624c2c66affSColin Finck 
625c2c66affSColin Finck     if(endif_label)
626c2c66affSColin Finck         label_set_addr(ctx, endif_label);
627c2c66affSColin Finck     return S_OK;
628c2c66affSColin Finck }
629c2c66affSColin Finck 
compile_while_statement(compile_ctx_t * ctx,while_statement_t * stat)630c2c66affSColin Finck static HRESULT compile_while_statement(compile_ctx_t *ctx, while_statement_t *stat)
631c2c66affSColin Finck {
632c2c66affSColin Finck     statement_ctx_t stat_ctx = {0}, *loop_ctx;
633c2c66affSColin Finck     unsigned start_addr;
634c2c66affSColin Finck     unsigned jmp_end;
635c2c66affSColin Finck     HRESULT hres;
636c2c66affSColin Finck 
637c2c66affSColin Finck     start_addr = ctx->instr_cnt;
638c2c66affSColin Finck 
639c2c66affSColin Finck     hres = compile_expression(ctx, stat->expr);
640c2c66affSColin Finck     if(FAILED(hres))
641c2c66affSColin Finck         return hres;
642c2c66affSColin Finck 
643c2c66affSColin Finck     jmp_end = push_instr(ctx, stat->stat.type == STAT_UNTIL ? OP_jmp_true : OP_jmp_false);
644c2c66affSColin Finck     if(!jmp_end)
645c2c66affSColin Finck         return E_OUTOFMEMORY;
646c2c66affSColin Finck 
647c2c66affSColin Finck     if(!emit_catch(ctx, 0))
648c2c66affSColin Finck         return E_OUTOFMEMORY;
649c2c66affSColin Finck 
650c2c66affSColin Finck     if(stat->stat.type == STAT_WHILE) {
651c2c66affSColin Finck         loop_ctx = NULL;
652c2c66affSColin Finck     }else {
653c2c66affSColin Finck         if(!(stat_ctx.while_end_label = alloc_label(ctx)))
654c2c66affSColin Finck             return E_OUTOFMEMORY;
655c2c66affSColin Finck         loop_ctx = &stat_ctx;
656c2c66affSColin Finck     }
657c2c66affSColin Finck 
658c2c66affSColin Finck     hres = compile_statement(ctx, loop_ctx, stat->body);
659c2c66affSColin Finck     if(FAILED(hres))
660c2c66affSColin Finck         return hres;
661c2c66affSColin Finck 
662c2c66affSColin Finck     hres = push_instr_addr(ctx, OP_jmp, start_addr);
663c2c66affSColin Finck     if(FAILED(hres))
664c2c66affSColin Finck         return hres;
665c2c66affSColin Finck 
666c2c66affSColin Finck     instr_ptr(ctx, jmp_end)->arg1.uint = ctx->instr_cnt;
667c2c66affSColin Finck 
668c2c66affSColin Finck     if(loop_ctx)
669c2c66affSColin Finck         label_set_addr(ctx, stat_ctx.while_end_label);
670c2c66affSColin Finck 
671c2c66affSColin Finck     return S_OK;
672c2c66affSColin Finck }
673c2c66affSColin Finck 
compile_dowhile_statement(compile_ctx_t * ctx,while_statement_t * stat)674c2c66affSColin Finck static HRESULT compile_dowhile_statement(compile_ctx_t *ctx, while_statement_t *stat)
675c2c66affSColin Finck {
676c2c66affSColin Finck     statement_ctx_t loop_ctx = {0};
677c2c66affSColin Finck     unsigned start_addr;
678c2c66affSColin Finck     vbsop_t jmp_op;
679c2c66affSColin Finck     HRESULT hres;
680c2c66affSColin Finck 
681c2c66affSColin Finck     start_addr = ctx->instr_cnt;
682c2c66affSColin Finck 
683c2c66affSColin Finck     if(!(loop_ctx.while_end_label = alloc_label(ctx)))
684c2c66affSColin Finck         return E_OUTOFMEMORY;
685c2c66affSColin Finck 
686c2c66affSColin Finck     hres = compile_statement(ctx, &loop_ctx, stat->body);
687c2c66affSColin Finck     if(FAILED(hres))
688c2c66affSColin Finck         return hres;
689c2c66affSColin Finck 
690c2c66affSColin Finck     if(stat->expr) {
691c2c66affSColin Finck         hres = compile_expression(ctx, stat->expr);
692c2c66affSColin Finck         if(FAILED(hres))
693c2c66affSColin Finck             return hres;
694c2c66affSColin Finck 
695c2c66affSColin Finck         jmp_op = stat->stat.type == STAT_DOUNTIL ? OP_jmp_false : OP_jmp_true;
696c2c66affSColin Finck     }else {
697c2c66affSColin Finck         jmp_op = OP_jmp;
698c2c66affSColin Finck     }
699c2c66affSColin Finck 
700c2c66affSColin Finck     hres = push_instr_addr(ctx, jmp_op, start_addr);
701c2c66affSColin Finck     if(FAILED(hres))
702c2c66affSColin Finck         return hres;
703c2c66affSColin Finck 
704c2c66affSColin Finck     label_set_addr(ctx, loop_ctx.while_end_label);
705c2c66affSColin Finck 
706c2c66affSColin Finck     if(!emit_catch(ctx, 0))
707c2c66affSColin Finck         return E_OUTOFMEMORY;
708c2c66affSColin Finck 
709c2c66affSColin Finck     return S_OK;
710c2c66affSColin Finck }
711c2c66affSColin Finck 
compile_foreach_statement(compile_ctx_t * ctx,foreach_statement_t * stat)712c2c66affSColin Finck static HRESULT compile_foreach_statement(compile_ctx_t *ctx, foreach_statement_t *stat)
713c2c66affSColin Finck {
714c2c66affSColin Finck     statement_ctx_t loop_ctx = {1};
715c2c66affSColin Finck     unsigned loop_start;
716c2c66affSColin Finck     HRESULT hres;
717c2c66affSColin Finck 
718c2c66affSColin Finck     /* Preserve a place on the stack in case we throw before having proper enum collection. */
719c2c66affSColin Finck     if(!push_instr(ctx, OP_empty))
720c2c66affSColin Finck         return E_OUTOFMEMORY;
721c2c66affSColin Finck 
722c2c66affSColin Finck     hres = compile_expression(ctx, stat->group_expr);
723c2c66affSColin Finck     if(FAILED(hres))
724c2c66affSColin Finck         return hres;
725c2c66affSColin Finck 
726c2c66affSColin Finck     if(!push_instr(ctx, OP_newenum))
727c2c66affSColin Finck         return E_OUTOFMEMORY;
728c2c66affSColin Finck 
729c2c66affSColin Finck     if(!(loop_ctx.for_end_label = alloc_label(ctx)))
730c2c66affSColin Finck         return E_OUTOFMEMORY;
731c2c66affSColin Finck 
732c2c66affSColin Finck     hres = push_instr_uint_bstr(ctx, OP_enumnext, loop_ctx.for_end_label, stat->identifier);
733c2c66affSColin Finck     if(FAILED(hres))
734c2c66affSColin Finck         return hres;
735c2c66affSColin Finck 
736c2c66affSColin Finck     if(!emit_catch(ctx, 1))
737c2c66affSColin Finck         return E_OUTOFMEMORY;
738c2c66affSColin Finck 
739c2c66affSColin Finck     loop_start = ctx->instr_cnt;
740c2c66affSColin Finck     hres = compile_statement(ctx, &loop_ctx, stat->body);
741c2c66affSColin Finck     if(FAILED(hres))
742c2c66affSColin Finck         return hres;
743c2c66affSColin Finck 
744c2c66affSColin Finck     /* We need a separated enumnext here, because we need to jump out of the loop on exception. */
745c2c66affSColin Finck     hres = push_instr_uint_bstr(ctx, OP_enumnext, loop_ctx.for_end_label, stat->identifier);
746c2c66affSColin Finck     if(FAILED(hres))
747c2c66affSColin Finck         return hres;
748c2c66affSColin Finck 
749c2c66affSColin Finck     hres = push_instr_addr(ctx, OP_jmp, loop_start);
750c2c66affSColin Finck     if(FAILED(hres))
751c2c66affSColin Finck         return hres;
752c2c66affSColin Finck 
753c2c66affSColin Finck     label_set_addr(ctx, loop_ctx.for_end_label);
754c2c66affSColin Finck     return S_OK;
755c2c66affSColin Finck }
756c2c66affSColin Finck 
compile_forto_statement(compile_ctx_t * ctx,forto_statement_t * stat)757c2c66affSColin Finck static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *stat)
758c2c66affSColin Finck {
759c2c66affSColin Finck     statement_ctx_t loop_ctx = {2};
760c2c66affSColin Finck     unsigned step_instr, instr;
761c2c66affSColin Finck     BSTR identifier;
762c2c66affSColin Finck     HRESULT hres;
763c2c66affSColin Finck 
764c2c66affSColin Finck     identifier = alloc_bstr_arg(ctx, stat->identifier);
765c2c66affSColin Finck     if(!identifier)
766c2c66affSColin Finck         return E_OUTOFMEMORY;
767c2c66affSColin Finck 
768c2c66affSColin Finck     hres = compile_expression(ctx, stat->from_expr);
769c2c66affSColin Finck     if(FAILED(hres))
770c2c66affSColin Finck         return hres;
771c2c66affSColin Finck 
772c2c66affSColin Finck     /* FIXME: Assign should happen after both expressions evaluation. */
773c2c66affSColin Finck     instr = push_instr(ctx, OP_assign_ident);
774c2c66affSColin Finck     if(!instr)
775c2c66affSColin Finck         return E_OUTOFMEMORY;
776c2c66affSColin Finck     instr_ptr(ctx, instr)->arg1.bstr = identifier;
777c2c66affSColin Finck     instr_ptr(ctx, instr)->arg2.uint = 0;
778c2c66affSColin Finck 
779c2c66affSColin Finck     hres = compile_expression(ctx, stat->to_expr);
780c2c66affSColin Finck     if(FAILED(hres))
781c2c66affSColin Finck         return hres;
782c2c66affSColin Finck 
783c2c66affSColin Finck     if(!push_instr(ctx, OP_val))
784c2c66affSColin Finck         return E_OUTOFMEMORY;
785c2c66affSColin Finck 
786c2c66affSColin Finck     if(stat->step_expr) {
787c2c66affSColin Finck         hres = compile_expression(ctx, stat->step_expr);
788c2c66affSColin Finck         if(FAILED(hres))
789c2c66affSColin Finck             return hres;
790c2c66affSColin Finck 
791c2c66affSColin Finck         if(!push_instr(ctx, OP_val))
792c2c66affSColin Finck             return E_OUTOFMEMORY;
793c2c66affSColin Finck     }else {
794*9a0ddc13SAmine Khaldi         hres = push_instr_int(ctx, OP_int, 1);
795c2c66affSColin Finck         if(FAILED(hres))
796c2c66affSColin Finck             return hres;
797c2c66affSColin Finck     }
798c2c66affSColin Finck 
799c2c66affSColin Finck     loop_ctx.for_end_label = alloc_label(ctx);
800c2c66affSColin Finck     if(!loop_ctx.for_end_label)
801c2c66affSColin Finck         return E_OUTOFMEMORY;
802c2c66affSColin Finck 
803c2c66affSColin Finck     step_instr = push_instr(ctx, OP_step);
804c2c66affSColin Finck     if(!step_instr)
805c2c66affSColin Finck         return E_OUTOFMEMORY;
806c2c66affSColin Finck     instr_ptr(ctx, step_instr)->arg2.bstr = identifier;
807c2c66affSColin Finck     instr_ptr(ctx, step_instr)->arg1.uint = loop_ctx.for_end_label;
808c2c66affSColin Finck 
809c2c66affSColin Finck     if(!emit_catch(ctx, 2))
810c2c66affSColin Finck         return E_OUTOFMEMORY;
811c2c66affSColin Finck 
812c2c66affSColin Finck     hres = compile_statement(ctx, &loop_ctx, stat->body);
813c2c66affSColin Finck     if(FAILED(hres))
814c2c66affSColin Finck         return hres;
815c2c66affSColin Finck 
816c2c66affSColin Finck     /* FIXME: Error handling can't be done compatible with native using OP_incc here. */
817c2c66affSColin Finck     instr = push_instr(ctx, OP_incc);
818c2c66affSColin Finck     if(!instr)
819c2c66affSColin Finck         return E_OUTOFMEMORY;
820c2c66affSColin Finck     instr_ptr(ctx, instr)->arg1.bstr = identifier;
821c2c66affSColin Finck 
822c2c66affSColin Finck     hres = push_instr_addr(ctx, OP_jmp, step_instr);
823c2c66affSColin Finck     if(FAILED(hres))
824c2c66affSColin Finck         return hres;
825c2c66affSColin Finck 
826c2c66affSColin Finck     hres = push_instr_uint(ctx, OP_pop, 2);
827c2c66affSColin Finck     if(FAILED(hres))
828c2c66affSColin Finck         return hres;
829c2c66affSColin Finck 
830c2c66affSColin Finck     label_set_addr(ctx, loop_ctx.for_end_label);
831c2c66affSColin Finck 
832c2c66affSColin Finck     /* FIXME: reconsider after OP_incc fixup. */
833c2c66affSColin Finck     if(!emit_catch(ctx, 0))
834c2c66affSColin Finck         return E_OUTOFMEMORY;
835c2c66affSColin Finck 
836c2c66affSColin Finck     return S_OK;
837c2c66affSColin Finck }
838c2c66affSColin Finck 
compile_select_statement(compile_ctx_t * ctx,select_statement_t * stat)839c2c66affSColin Finck static HRESULT compile_select_statement(compile_ctx_t *ctx, select_statement_t *stat)
840c2c66affSColin Finck {
841c2c66affSColin Finck     unsigned end_label, case_cnt = 0, *case_labels = NULL, i;
842c2c66affSColin Finck     case_clausule_t *case_iter;
843c2c66affSColin Finck     expression_t *expr_iter;
844c2c66affSColin Finck     HRESULT hres;
845c2c66affSColin Finck 
846c2c66affSColin Finck     hres = compile_expression(ctx, stat->expr);
847c2c66affSColin Finck     if(FAILED(hres))
848c2c66affSColin Finck         return hres;
849c2c66affSColin Finck 
850c2c66affSColin Finck     if(!push_instr(ctx, OP_val))
851c2c66affSColin Finck         return E_OUTOFMEMORY;
852c2c66affSColin Finck 
853c2c66affSColin Finck     end_label = alloc_label(ctx);
854c2c66affSColin Finck     if(!end_label)
855c2c66affSColin Finck         return E_OUTOFMEMORY;
856c2c66affSColin Finck 
857c2c66affSColin Finck     if(!emit_catch_jmp(ctx, 0, end_label))
858c2c66affSColin Finck         return E_OUTOFMEMORY;
859c2c66affSColin Finck 
860c2c66affSColin Finck     for(case_iter = stat->case_clausules; case_iter; case_iter = case_iter->next)
861c2c66affSColin Finck         case_cnt++;
862c2c66affSColin Finck 
863c2c66affSColin Finck     if(case_cnt) {
864c2c66affSColin Finck         case_labels = heap_alloc(case_cnt*sizeof(*case_labels));
865c2c66affSColin Finck         if(!case_labels)
866c2c66affSColin Finck             return E_OUTOFMEMORY;
867c2c66affSColin Finck     }
868c2c66affSColin Finck 
869c2c66affSColin Finck     for(case_iter = stat->case_clausules, i=0; case_iter; case_iter = case_iter->next, i++) {
870c2c66affSColin Finck         case_labels[i] = alloc_label(ctx);
871c2c66affSColin Finck         if(!case_labels[i]) {
872c2c66affSColin Finck             hres = E_OUTOFMEMORY;
873c2c66affSColin Finck             break;
874c2c66affSColin Finck         }
875c2c66affSColin Finck 
876c2c66affSColin Finck         if(!case_iter->expr)
877c2c66affSColin Finck             break;
878c2c66affSColin Finck 
879c2c66affSColin Finck         for(expr_iter = case_iter->expr; expr_iter; expr_iter = expr_iter->next) {
880c2c66affSColin Finck             hres = compile_expression(ctx, expr_iter);
881c2c66affSColin Finck             if(FAILED(hres))
882c2c66affSColin Finck                 break;
883c2c66affSColin Finck 
884c2c66affSColin Finck             hres = push_instr_addr(ctx, OP_case, case_labels[i]);
885c2c66affSColin Finck             if(FAILED(hres))
886c2c66affSColin Finck                 break;
887c2c66affSColin Finck 
888c2c66affSColin Finck             if(!emit_catch_jmp(ctx, 0, case_labels[i])) {
889c2c66affSColin Finck                 hres = E_OUTOFMEMORY;
890c2c66affSColin Finck                 break;
891c2c66affSColin Finck             }
892c2c66affSColin Finck         }
893c2c66affSColin Finck     }
894c2c66affSColin Finck 
895c2c66affSColin Finck     if(FAILED(hres)) {
896c2c66affSColin Finck         heap_free(case_labels);
897c2c66affSColin Finck         return hres;
898c2c66affSColin Finck     }
899c2c66affSColin Finck 
900c2c66affSColin Finck     hres = push_instr_uint(ctx, OP_pop, 1);
901c2c66affSColin Finck     if(FAILED(hres)) {
902c2c66affSColin Finck         heap_free(case_labels);
903c2c66affSColin Finck         return hres;
904c2c66affSColin Finck     }
905c2c66affSColin Finck 
906c2c66affSColin Finck     hres = push_instr_addr(ctx, OP_jmp, case_iter ? case_labels[i] : end_label);
907c2c66affSColin Finck     if(FAILED(hres)) {
908c2c66affSColin Finck         heap_free(case_labels);
909c2c66affSColin Finck         return hres;
910c2c66affSColin Finck     }
911c2c66affSColin Finck 
912c2c66affSColin Finck     for(case_iter = stat->case_clausules, i=0; case_iter; case_iter = case_iter->next, i++) {
913c2c66affSColin Finck         label_set_addr(ctx, case_labels[i]);
914c2c66affSColin Finck         hres = compile_statement(ctx, NULL, case_iter->stat);
915c2c66affSColin Finck         if(FAILED(hres))
916c2c66affSColin Finck             break;
917c2c66affSColin Finck 
918c2c66affSColin Finck         if(!case_iter->next)
919c2c66affSColin Finck             break;
920c2c66affSColin Finck 
921c2c66affSColin Finck         hres = push_instr_addr(ctx, OP_jmp, end_label);
922c2c66affSColin Finck         if(FAILED(hres))
923c2c66affSColin Finck             break;
924c2c66affSColin Finck     }
925c2c66affSColin Finck 
926c2c66affSColin Finck     heap_free(case_labels);
927c2c66affSColin Finck     if(FAILED(hres))
928c2c66affSColin Finck         return hres;
929c2c66affSColin Finck 
930c2c66affSColin Finck     label_set_addr(ctx, end_label);
931c2c66affSColin Finck     return S_OK;
932c2c66affSColin Finck }
933c2c66affSColin Finck 
compile_assignment(compile_ctx_t * ctx,member_expression_t * member_expr,expression_t * value_expr,BOOL is_set)934c2c66affSColin Finck static HRESULT compile_assignment(compile_ctx_t *ctx, member_expression_t *member_expr, expression_t *value_expr, BOOL is_set)
935c2c66affSColin Finck {
936c2c66affSColin Finck     unsigned args_cnt;
937c2c66affSColin Finck     vbsop_t op;
938c2c66affSColin Finck     HRESULT hres;
939c2c66affSColin Finck 
940c2c66affSColin Finck     if(member_expr->obj_expr) {
941c2c66affSColin Finck         hres = compile_expression(ctx, member_expr->obj_expr);
942c2c66affSColin Finck         if(FAILED(hres))
943c2c66affSColin Finck             return hres;
944c2c66affSColin Finck 
945c2c66affSColin Finck         op = is_set ? OP_set_member : OP_assign_member;
946c2c66affSColin Finck     }else {
947c2c66affSColin Finck         op = is_set ? OP_set_ident : OP_assign_ident;
948c2c66affSColin Finck     }
949c2c66affSColin Finck 
950c2c66affSColin Finck     hres = compile_expression(ctx, value_expr);
951c2c66affSColin Finck     if(FAILED(hres))
952c2c66affSColin Finck         return hres;
953c2c66affSColin Finck 
954c2c66affSColin Finck     hres = compile_args(ctx, member_expr->args, &args_cnt);
955c2c66affSColin Finck     if(FAILED(hres))
956c2c66affSColin Finck         return hres;
957c2c66affSColin Finck 
958c2c66affSColin Finck     hres = push_instr_bstr_uint(ctx, op, member_expr->identifier, args_cnt);
959c2c66affSColin Finck     if(FAILED(hres))
960c2c66affSColin Finck         return hres;
961c2c66affSColin Finck 
962c2c66affSColin Finck     if(!emit_catch(ctx, 0))
963c2c66affSColin Finck         return E_OUTOFMEMORY;
964c2c66affSColin Finck 
965c2c66affSColin Finck     return S_OK;
966c2c66affSColin Finck }
967c2c66affSColin Finck 
compile_assign_statement(compile_ctx_t * ctx,assign_statement_t * stat,BOOL is_set)968c2c66affSColin Finck static HRESULT compile_assign_statement(compile_ctx_t *ctx, assign_statement_t *stat, BOOL is_set)
969c2c66affSColin Finck {
970c2c66affSColin Finck     return compile_assignment(ctx, stat->member_expr, stat->value_expr, is_set);
971c2c66affSColin Finck }
972c2c66affSColin Finck 
compile_call_statement(compile_ctx_t * ctx,call_statement_t * stat)973c2c66affSColin Finck static HRESULT compile_call_statement(compile_ctx_t *ctx, call_statement_t *stat)
974c2c66affSColin Finck {
975c2c66affSColin Finck     HRESULT hres;
976c2c66affSColin Finck 
977c2c66affSColin Finck     /* It's challenging for parser to distinguish parameterized assignment with one argument from call
978c2c66affSColin Finck      * with equality expression argument, so we do it in compiler. */
979c2c66affSColin Finck     if(!stat->is_strict && stat->expr->args && !stat->expr->args->next && stat->expr->args->type == EXPR_EQUAL) {
980c2c66affSColin Finck         binary_expression_t *eqexpr = (binary_expression_t*)stat->expr->args;
981c2c66affSColin Finck 
982c2c66affSColin Finck         if(eqexpr->left->type == EXPR_BRACKETS) {
983c2c66affSColin Finck             member_expression_t new_member = *stat->expr;
984c2c66affSColin Finck 
985c2c66affSColin Finck             WARN("converting call expr to assign expr\n");
986c2c66affSColin Finck 
987c2c66affSColin Finck             new_member.args = ((unary_expression_t*)eqexpr->left)->subexpr;
988c2c66affSColin Finck             return compile_assignment(ctx, &new_member, eqexpr->right, FALSE);
989c2c66affSColin Finck         }
990c2c66affSColin Finck     }
991c2c66affSColin Finck 
992c2c66affSColin Finck     hres = compile_member_expression(ctx, stat->expr, FALSE);
993c2c66affSColin Finck     if(FAILED(hres))
994c2c66affSColin Finck         return hres;
995c2c66affSColin Finck 
996c2c66affSColin Finck     if(!emit_catch(ctx, 0))
997c2c66affSColin Finck         return E_OUTOFMEMORY;
998c2c66affSColin Finck 
999c2c66affSColin Finck     return S_OK;
1000c2c66affSColin Finck }
1001c2c66affSColin Finck 
lookup_dim_decls(compile_ctx_t * ctx,const WCHAR * name)1002c2c66affSColin Finck static BOOL lookup_dim_decls(compile_ctx_t *ctx, const WCHAR *name)
1003c2c66affSColin Finck {
1004c2c66affSColin Finck     dim_decl_t *dim_decl;
1005c2c66affSColin Finck 
1006c2c66affSColin Finck     for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
1007*9a0ddc13SAmine Khaldi         if(!wcsicmp(dim_decl->name, name))
1008c2c66affSColin Finck             return TRUE;
1009c2c66affSColin Finck     }
1010c2c66affSColin Finck 
1011c2c66affSColin Finck     return FALSE;
1012c2c66affSColin Finck }
1013c2c66affSColin Finck 
lookup_args_name(compile_ctx_t * ctx,const WCHAR * name)1014c2c66affSColin Finck static BOOL lookup_args_name(compile_ctx_t *ctx, const WCHAR *name)
1015c2c66affSColin Finck {
1016c2c66affSColin Finck     unsigned i;
1017c2c66affSColin Finck 
1018c2c66affSColin Finck     for(i = 0; i < ctx->func->arg_cnt; i++) {
1019*9a0ddc13SAmine Khaldi         if(!wcsicmp(ctx->func->args[i].name, name))
1020c2c66affSColin Finck             return TRUE;
1021c2c66affSColin Finck     }
1022c2c66affSColin Finck 
1023c2c66affSColin Finck     return FALSE;
1024c2c66affSColin Finck }
1025c2c66affSColin Finck 
compile_dim_statement(compile_ctx_t * ctx,dim_statement_t * stat)1026c2c66affSColin Finck static HRESULT compile_dim_statement(compile_ctx_t *ctx, dim_statement_t *stat)
1027c2c66affSColin Finck {
1028c2c66affSColin Finck     dim_decl_t *dim_decl = stat->dim_decls;
1029c2c66affSColin Finck 
1030c2c66affSColin Finck     while(1) {
1031c2c66affSColin Finck         if(lookup_dim_decls(ctx, dim_decl->name) || lookup_args_name(ctx, dim_decl->name)
1032c2c66affSColin Finck            || lookup_const_decls(ctx, dim_decl->name, FALSE)) {
1033c2c66affSColin Finck             FIXME("dim %s name redefined\n", debugstr_w(dim_decl->name));
1034c2c66affSColin Finck             return E_FAIL;
1035c2c66affSColin Finck         }
1036c2c66affSColin Finck 
1037c2c66affSColin Finck         ctx->func->var_cnt++;
1038c2c66affSColin Finck 
1039c2c66affSColin Finck         if(dim_decl->is_array) {
1040c2c66affSColin Finck             HRESULT hres = push_instr_bstr_uint(ctx, OP_dim, dim_decl->name, ctx->func->array_cnt++);
1041c2c66affSColin Finck             if(FAILED(hres))
1042c2c66affSColin Finck                 return hres;
1043c2c66affSColin Finck 
1044c2c66affSColin Finck             if(!emit_catch(ctx, 0))
1045c2c66affSColin Finck                 return E_OUTOFMEMORY;
1046c2c66affSColin Finck         }
1047c2c66affSColin Finck 
1048c2c66affSColin Finck         if(!dim_decl->next)
1049c2c66affSColin Finck             break;
1050c2c66affSColin Finck         dim_decl = dim_decl->next;
1051c2c66affSColin Finck     }
1052c2c66affSColin Finck 
1053c2c66affSColin Finck     if(ctx->dim_decls_tail)
1054c2c66affSColin Finck         ctx->dim_decls_tail->next = stat->dim_decls;
1055c2c66affSColin Finck     else
1056c2c66affSColin Finck         ctx->dim_decls = stat->dim_decls;
1057c2c66affSColin Finck     ctx->dim_decls_tail = dim_decl;
1058c2c66affSColin Finck     return S_OK;
1059c2c66affSColin Finck }
1060c2c66affSColin Finck 
compile_const_statement(compile_ctx_t * ctx,const_statement_t * stat)1061c2c66affSColin Finck static HRESULT compile_const_statement(compile_ctx_t *ctx, const_statement_t *stat)
1062c2c66affSColin Finck {
1063c2c66affSColin Finck     const_decl_t *decl, *next_decl = stat->decls;
1064c2c66affSColin Finck 
1065c2c66affSColin Finck     do {
1066c2c66affSColin Finck         decl = next_decl;
1067c2c66affSColin Finck 
1068c2c66affSColin Finck         if(lookup_const_decls(ctx, decl->name, FALSE) || lookup_args_name(ctx, decl->name)
1069c2c66affSColin Finck                 || lookup_dim_decls(ctx, decl->name)) {
1070c2c66affSColin Finck             FIXME("%s redefined\n", debugstr_w(decl->name));
1071c2c66affSColin Finck             return E_FAIL;
1072c2c66affSColin Finck         }
1073c2c66affSColin Finck 
1074c2c66affSColin Finck         if(ctx->func->type == FUNC_GLOBAL) {
1075c2c66affSColin Finck             HRESULT hres;
1076c2c66affSColin Finck 
1077c2c66affSColin Finck             hres = compile_expression(ctx, decl->value_expr);
1078c2c66affSColin Finck             if(FAILED(hres))
1079c2c66affSColin Finck                 return hres;
1080c2c66affSColin Finck 
1081c2c66affSColin Finck             hres = push_instr_bstr(ctx, OP_const, decl->name);
1082c2c66affSColin Finck             if(FAILED(hres))
1083c2c66affSColin Finck                 return hres;
1084c2c66affSColin Finck 
1085c2c66affSColin Finck             if(!emit_catch(ctx, 0))
1086c2c66affSColin Finck                 return E_OUTOFMEMORY;
1087c2c66affSColin Finck         }
1088c2c66affSColin Finck 
1089c2c66affSColin Finck         next_decl = decl->next;
1090c2c66affSColin Finck         decl->next = ctx->const_decls;
1091c2c66affSColin Finck         ctx->const_decls = decl;
1092c2c66affSColin Finck     } while(next_decl);
1093c2c66affSColin Finck 
1094c2c66affSColin Finck     return S_OK;
1095c2c66affSColin Finck }
1096c2c66affSColin Finck 
compile_function_statement(compile_ctx_t * ctx,function_statement_t * stat)1097c2c66affSColin Finck static HRESULT compile_function_statement(compile_ctx_t *ctx, function_statement_t *stat)
1098c2c66affSColin Finck {
1099c2c66affSColin Finck     if(ctx->func != &ctx->code->main_code) {
1100c2c66affSColin Finck         FIXME("Function is not in the global code\n");
1101c2c66affSColin Finck         return E_FAIL;
1102c2c66affSColin Finck     }
1103c2c66affSColin Finck 
1104c2c66affSColin Finck     stat->func_decl->next = ctx->func_decls;
1105c2c66affSColin Finck     ctx->func_decls = stat->func_decl;
1106c2c66affSColin Finck     return S_OK;
1107c2c66affSColin Finck }
1108c2c66affSColin Finck 
compile_exitdo_statement(compile_ctx_t * ctx)1109c2c66affSColin Finck static HRESULT compile_exitdo_statement(compile_ctx_t *ctx)
1110c2c66affSColin Finck {
1111c2c66affSColin Finck     statement_ctx_t *iter;
1112c2c66affSColin Finck     unsigned pop_cnt = 0;
1113c2c66affSColin Finck 
1114c2c66affSColin Finck     for(iter = ctx->stat_ctx; iter; iter = iter->next) {
1115c2c66affSColin Finck         pop_cnt += iter->stack_use;
1116c2c66affSColin Finck         if(iter->while_end_label)
1117c2c66affSColin Finck             break;
1118c2c66affSColin Finck     }
1119c2c66affSColin Finck     if(!iter) {
1120c2c66affSColin Finck         FIXME("Exit Do outside Do Loop\n");
1121c2c66affSColin Finck         return E_FAIL;
1122c2c66affSColin Finck     }
1123c2c66affSColin Finck 
1124c2c66affSColin Finck     if(pop_cnt) {
1125c2c66affSColin Finck         HRESULT hres;
1126c2c66affSColin Finck 
1127c2c66affSColin Finck         hres = push_instr_uint(ctx, OP_pop, pop_cnt);
1128c2c66affSColin Finck         if(FAILED(hres))
1129c2c66affSColin Finck             return hres;
1130c2c66affSColin Finck     }
1131c2c66affSColin Finck 
1132c2c66affSColin Finck     return push_instr_addr(ctx, OP_jmp, iter->while_end_label);
1133c2c66affSColin Finck }
1134c2c66affSColin Finck 
compile_exitfor_statement(compile_ctx_t * ctx)1135c2c66affSColin Finck static HRESULT compile_exitfor_statement(compile_ctx_t *ctx)
1136c2c66affSColin Finck {
1137c2c66affSColin Finck     statement_ctx_t *iter;
1138c2c66affSColin Finck     unsigned pop_cnt = 0;
1139c2c66affSColin Finck 
1140c2c66affSColin Finck     for(iter = ctx->stat_ctx; iter; iter = iter->next) {
1141c2c66affSColin Finck         pop_cnt += iter->stack_use;
1142c2c66affSColin Finck         if(iter->for_end_label)
1143c2c66affSColin Finck             break;
1144c2c66affSColin Finck     }
1145c2c66affSColin Finck     if(!iter) {
1146c2c66affSColin Finck         FIXME("Exit For outside For loop\n");
1147c2c66affSColin Finck         return E_FAIL;
1148c2c66affSColin Finck     }
1149c2c66affSColin Finck 
1150c2c66affSColin Finck     if(pop_cnt) {
1151c2c66affSColin Finck         HRESULT hres;
1152c2c66affSColin Finck 
1153c2c66affSColin Finck         hres = push_instr_uint(ctx, OP_pop, pop_cnt);
1154c2c66affSColin Finck         if(FAILED(hres))
1155c2c66affSColin Finck             return hres;
1156c2c66affSColin Finck     }
1157c2c66affSColin Finck 
1158c2c66affSColin Finck     return push_instr_addr(ctx, OP_jmp, iter->for_end_label);
1159c2c66affSColin Finck }
1160c2c66affSColin Finck 
exit_label(compile_ctx_t * ctx,unsigned jmp_label)1161c2c66affSColin Finck static HRESULT exit_label(compile_ctx_t *ctx, unsigned jmp_label)
1162c2c66affSColin Finck {
1163c2c66affSColin Finck     unsigned pop_cnt = stack_offset(ctx);
1164c2c66affSColin Finck 
1165c2c66affSColin Finck     if(pop_cnt) {
1166c2c66affSColin Finck         HRESULT hres;
1167c2c66affSColin Finck 
1168c2c66affSColin Finck         hres = push_instr_uint(ctx, OP_pop, pop_cnt);
1169c2c66affSColin Finck         if(FAILED(hres))
1170c2c66affSColin Finck             return hres;
1171c2c66affSColin Finck     }
1172c2c66affSColin Finck 
1173c2c66affSColin Finck     return push_instr_addr(ctx, OP_jmp, jmp_label);
1174c2c66affSColin Finck }
1175c2c66affSColin Finck 
compile_exitsub_statement(compile_ctx_t * ctx)1176c2c66affSColin Finck static HRESULT compile_exitsub_statement(compile_ctx_t *ctx)
1177c2c66affSColin Finck {
1178c2c66affSColin Finck     if(!ctx->sub_end_label) {
1179c2c66affSColin Finck         FIXME("Exit Sub outside Sub?\n");
1180c2c66affSColin Finck         return E_FAIL;
1181c2c66affSColin Finck     }
1182c2c66affSColin Finck 
1183c2c66affSColin Finck     return exit_label(ctx, ctx->sub_end_label);
1184c2c66affSColin Finck }
1185c2c66affSColin Finck 
compile_exitfunc_statement(compile_ctx_t * ctx)1186c2c66affSColin Finck static HRESULT compile_exitfunc_statement(compile_ctx_t *ctx)
1187c2c66affSColin Finck {
1188c2c66affSColin Finck     if(!ctx->func_end_label) {
1189c2c66affSColin Finck         FIXME("Exit Function outside Function?\n");
1190c2c66affSColin Finck         return E_FAIL;
1191c2c66affSColin Finck     }
1192c2c66affSColin Finck 
1193c2c66affSColin Finck     return exit_label(ctx, ctx->func_end_label);
1194c2c66affSColin Finck }
1195c2c66affSColin Finck 
compile_exitprop_statement(compile_ctx_t * ctx)1196c2c66affSColin Finck static HRESULT compile_exitprop_statement(compile_ctx_t *ctx)
1197c2c66affSColin Finck {
1198c2c66affSColin Finck     if(!ctx->prop_end_label) {
1199c2c66affSColin Finck         FIXME("Exit Property outside Property?\n");
1200c2c66affSColin Finck         return E_FAIL;
1201c2c66affSColin Finck     }
1202c2c66affSColin Finck 
1203c2c66affSColin Finck     return exit_label(ctx, ctx->prop_end_label);
1204c2c66affSColin Finck }
1205c2c66affSColin Finck 
compile_onerror_statement(compile_ctx_t * ctx,onerror_statement_t * stat)1206c2c66affSColin Finck static HRESULT compile_onerror_statement(compile_ctx_t *ctx, onerror_statement_t *stat)
1207c2c66affSColin Finck {
1208c2c66affSColin Finck     return push_instr_int(ctx, OP_errmode, stat->resume_next);
1209c2c66affSColin Finck }
1210c2c66affSColin Finck 
compile_retval_statement(compile_ctx_t * ctx,retval_statement_t * stat)1211*9a0ddc13SAmine Khaldi static HRESULT compile_retval_statement(compile_ctx_t *ctx, retval_statement_t *stat)
1212*9a0ddc13SAmine Khaldi {
1213*9a0ddc13SAmine Khaldi     HRESULT hres;
1214*9a0ddc13SAmine Khaldi 
1215*9a0ddc13SAmine Khaldi     hres = compile_expression(ctx, stat->expr);
1216*9a0ddc13SAmine Khaldi     if(FAILED(hres))
1217*9a0ddc13SAmine Khaldi         return hres;
1218*9a0ddc13SAmine Khaldi 
1219*9a0ddc13SAmine Khaldi     hres = push_instr(ctx, OP_retval);
1220*9a0ddc13SAmine Khaldi     if(FAILED(hres))
1221*9a0ddc13SAmine Khaldi         return hres;
1222*9a0ddc13SAmine Khaldi 
1223*9a0ddc13SAmine Khaldi     return S_OK;
1224*9a0ddc13SAmine Khaldi }
1225*9a0ddc13SAmine Khaldi 
compile_statement(compile_ctx_t * ctx,statement_ctx_t * stat_ctx,statement_t * stat)1226c2c66affSColin Finck static HRESULT compile_statement(compile_ctx_t *ctx, statement_ctx_t *stat_ctx, statement_t *stat)
1227c2c66affSColin Finck {
1228c2c66affSColin Finck     HRESULT hres;
1229c2c66affSColin Finck 
1230c2c66affSColin Finck     if(stat_ctx) {
1231c2c66affSColin Finck         stat_ctx->next = ctx->stat_ctx;
1232c2c66affSColin Finck         ctx->stat_ctx = stat_ctx;
1233c2c66affSColin Finck     }
1234c2c66affSColin Finck 
1235c2c66affSColin Finck     while(stat) {
1236c2c66affSColin Finck         switch(stat->type) {
1237c2c66affSColin Finck         case STAT_ASSIGN:
1238c2c66affSColin Finck             hres = compile_assign_statement(ctx, (assign_statement_t*)stat, FALSE);
1239c2c66affSColin Finck             break;
1240c2c66affSColin Finck         case STAT_CALL:
1241c2c66affSColin Finck             hres = compile_call_statement(ctx, (call_statement_t*)stat);
1242c2c66affSColin Finck             break;
1243c2c66affSColin Finck         case STAT_CONST:
1244c2c66affSColin Finck             hres = compile_const_statement(ctx, (const_statement_t*)stat);
1245c2c66affSColin Finck             break;
1246c2c66affSColin Finck         case STAT_DIM:
1247c2c66affSColin Finck             hres = compile_dim_statement(ctx, (dim_statement_t*)stat);
1248c2c66affSColin Finck             break;
1249c2c66affSColin Finck         case STAT_DOWHILE:
1250c2c66affSColin Finck         case STAT_DOUNTIL:
1251c2c66affSColin Finck             hres = compile_dowhile_statement(ctx, (while_statement_t*)stat);
1252c2c66affSColin Finck             break;
1253c2c66affSColin Finck         case STAT_EXITDO:
1254c2c66affSColin Finck             hres = compile_exitdo_statement(ctx);
1255c2c66affSColin Finck             break;
1256c2c66affSColin Finck         case STAT_EXITFOR:
1257c2c66affSColin Finck             hres = compile_exitfor_statement(ctx);
1258c2c66affSColin Finck             break;
1259c2c66affSColin Finck         case STAT_EXITFUNC:
1260c2c66affSColin Finck             hres = compile_exitfunc_statement(ctx);
1261c2c66affSColin Finck             break;
1262c2c66affSColin Finck         case STAT_EXITPROP:
1263c2c66affSColin Finck             hres = compile_exitprop_statement(ctx);
1264c2c66affSColin Finck             break;
1265c2c66affSColin Finck         case STAT_EXITSUB:
1266c2c66affSColin Finck             hres = compile_exitsub_statement(ctx);
1267c2c66affSColin Finck             break;
1268c2c66affSColin Finck         case STAT_FOREACH:
1269c2c66affSColin Finck             hres = compile_foreach_statement(ctx, (foreach_statement_t*)stat);
1270c2c66affSColin Finck             break;
1271c2c66affSColin Finck         case STAT_FORTO:
1272c2c66affSColin Finck             hres = compile_forto_statement(ctx, (forto_statement_t*)stat);
1273c2c66affSColin Finck             break;
1274c2c66affSColin Finck         case STAT_FUNC:
1275c2c66affSColin Finck             hres = compile_function_statement(ctx, (function_statement_t*)stat);
1276c2c66affSColin Finck             break;
1277c2c66affSColin Finck         case STAT_IF:
1278c2c66affSColin Finck             hres = compile_if_statement(ctx, (if_statement_t*)stat);
1279c2c66affSColin Finck             break;
1280c2c66affSColin Finck         case STAT_ONERROR:
1281c2c66affSColin Finck             hres = compile_onerror_statement(ctx, (onerror_statement_t*)stat);
1282c2c66affSColin Finck             break;
1283c2c66affSColin Finck         case STAT_SELECT:
1284c2c66affSColin Finck             hres = compile_select_statement(ctx, (select_statement_t*)stat);
1285c2c66affSColin Finck             break;
1286c2c66affSColin Finck         case STAT_SET:
1287c2c66affSColin Finck             hres = compile_assign_statement(ctx, (assign_statement_t*)stat, TRUE);
1288c2c66affSColin Finck             break;
1289c2c66affSColin Finck         case STAT_STOP:
1290c2c66affSColin Finck             hres = push_instr(ctx, OP_stop) ? S_OK : E_OUTOFMEMORY;
1291c2c66affSColin Finck             break;
1292c2c66affSColin Finck         case STAT_UNTIL:
1293c2c66affSColin Finck         case STAT_WHILE:
1294c2c66affSColin Finck         case STAT_WHILELOOP:
1295c2c66affSColin Finck             hres = compile_while_statement(ctx, (while_statement_t*)stat);
1296c2c66affSColin Finck             break;
1297*9a0ddc13SAmine Khaldi         case STAT_RETVAL:
1298*9a0ddc13SAmine Khaldi             hres = compile_retval_statement(ctx, (retval_statement_t*)stat);
1299*9a0ddc13SAmine Khaldi             break;
1300c2c66affSColin Finck         default:
1301c2c66affSColin Finck             FIXME("Unimplemented statement type %d\n", stat->type);
1302c2c66affSColin Finck             hres = E_NOTIMPL;
1303c2c66affSColin Finck         }
1304c2c66affSColin Finck 
1305c2c66affSColin Finck         if(FAILED(hres))
1306c2c66affSColin Finck             return hres;
1307c2c66affSColin Finck         stat = stat->next;
1308c2c66affSColin Finck     }
1309c2c66affSColin Finck 
1310c2c66affSColin Finck     if(stat_ctx) {
1311c2c66affSColin Finck         assert(ctx->stat_ctx == stat_ctx);
1312c2c66affSColin Finck         ctx->stat_ctx = stat_ctx->next;
1313c2c66affSColin Finck     }
1314c2c66affSColin Finck 
1315c2c66affSColin Finck     return S_OK;
1316c2c66affSColin Finck }
1317c2c66affSColin Finck 
resolve_labels(compile_ctx_t * ctx,unsigned off)1318c2c66affSColin Finck static void resolve_labels(compile_ctx_t *ctx, unsigned off)
1319c2c66affSColin Finck {
1320c2c66affSColin Finck     instr_t *instr;
1321c2c66affSColin Finck 
1322c2c66affSColin Finck     for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->instr_cnt; instr++) {
1323c2c66affSColin Finck         if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->arg1.uint & LABEL_FLAG)) {
1324c2c66affSColin Finck             assert((instr->arg1.uint & ~LABEL_FLAG) < ctx->labels_cnt);
1325c2c66affSColin Finck             instr->arg1.uint = ctx->labels[instr->arg1.uint & ~LABEL_FLAG];
1326c2c66affSColin Finck         }
1327c2c66affSColin Finck         assert(instr_info[instr->op].arg2_type != ARG_ADDR);
1328c2c66affSColin Finck     }
1329c2c66affSColin Finck 
1330c2c66affSColin Finck     ctx->labels_cnt = 0;
1331c2c66affSColin Finck }
1332c2c66affSColin Finck 
fill_array_desc(compile_ctx_t * ctx,dim_decl_t * dim_decl,array_desc_t * array_desc)1333c2c66affSColin Finck static HRESULT fill_array_desc(compile_ctx_t *ctx, dim_decl_t *dim_decl, array_desc_t *array_desc)
1334c2c66affSColin Finck {
1335c2c66affSColin Finck     unsigned dim_cnt = 0, i;
1336c2c66affSColin Finck     dim_list_t *iter;
1337c2c66affSColin Finck 
1338c2c66affSColin Finck     for(iter = dim_decl->dims; iter; iter = iter->next)
1339c2c66affSColin Finck         dim_cnt++;
1340c2c66affSColin Finck 
1341c2c66affSColin Finck     array_desc->bounds = compiler_alloc(ctx->code, dim_cnt * sizeof(SAFEARRAYBOUND));
1342c2c66affSColin Finck     if(!array_desc->bounds)
1343c2c66affSColin Finck         return E_OUTOFMEMORY;
1344c2c66affSColin Finck 
1345c2c66affSColin Finck     array_desc->dim_cnt = dim_cnt;
1346c2c66affSColin Finck 
1347c2c66affSColin Finck     for(iter = dim_decl->dims, i=0; iter; iter = iter->next, i++) {
1348c2c66affSColin Finck         array_desc->bounds[i].cElements = iter->val+1;
1349c2c66affSColin Finck         array_desc->bounds[i].lLbound = 0;
1350c2c66affSColin Finck     }
1351c2c66affSColin Finck 
1352c2c66affSColin Finck     return S_OK;
1353c2c66affSColin Finck }
1354c2c66affSColin Finck 
compile_func(compile_ctx_t * ctx,statement_t * stat,function_t * func)1355c2c66affSColin Finck static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *func)
1356c2c66affSColin Finck {
1357c2c66affSColin Finck     HRESULT hres;
1358c2c66affSColin Finck 
1359c2c66affSColin Finck     func->code_off = ctx->instr_cnt;
1360c2c66affSColin Finck 
1361c2c66affSColin Finck     ctx->sub_end_label = 0;
1362c2c66affSColin Finck     ctx->func_end_label = 0;
1363c2c66affSColin Finck     ctx->prop_end_label = 0;
1364c2c66affSColin Finck 
1365c2c66affSColin Finck     switch(func->type) {
1366c2c66affSColin Finck     case FUNC_FUNCTION:
1367c2c66affSColin Finck         ctx->func_end_label = alloc_label(ctx);
1368c2c66affSColin Finck         if(!ctx->func_end_label)
1369c2c66affSColin Finck             return E_OUTOFMEMORY;
1370c2c66affSColin Finck         break;
1371c2c66affSColin Finck     case FUNC_SUB:
1372c2c66affSColin Finck         ctx->sub_end_label = alloc_label(ctx);
1373c2c66affSColin Finck         if(!ctx->sub_end_label)
1374c2c66affSColin Finck             return E_OUTOFMEMORY;
1375c2c66affSColin Finck         break;
1376c2c66affSColin Finck     case FUNC_PROPGET:
1377c2c66affSColin Finck     case FUNC_PROPLET:
1378c2c66affSColin Finck     case FUNC_PROPSET:
1379c2c66affSColin Finck     case FUNC_DEFGET:
1380c2c66affSColin Finck         ctx->prop_end_label = alloc_label(ctx);
1381c2c66affSColin Finck         if(!ctx->prop_end_label)
1382c2c66affSColin Finck             return E_OUTOFMEMORY;
1383c2c66affSColin Finck         break;
1384c2c66affSColin Finck     case FUNC_GLOBAL:
1385c2c66affSColin Finck         break;
1386c2c66affSColin Finck     }
1387c2c66affSColin Finck 
1388c2c66affSColin Finck     ctx->func = func;
1389c2c66affSColin Finck     ctx->dim_decls = ctx->dim_decls_tail = NULL;
1390c2c66affSColin Finck     ctx->const_decls = NULL;
1391c2c66affSColin Finck     hres = compile_statement(ctx, NULL, stat);
1392c2c66affSColin Finck     ctx->func = NULL;
1393c2c66affSColin Finck     if(FAILED(hres))
1394c2c66affSColin Finck         return hres;
1395c2c66affSColin Finck 
1396c2c66affSColin Finck     if(ctx->sub_end_label)
1397c2c66affSColin Finck         label_set_addr(ctx, ctx->sub_end_label);
1398c2c66affSColin Finck     if(ctx->func_end_label)
1399c2c66affSColin Finck         label_set_addr(ctx, ctx->func_end_label);
1400c2c66affSColin Finck     if(ctx->prop_end_label)
1401c2c66affSColin Finck         label_set_addr(ctx, ctx->prop_end_label);
1402c2c66affSColin Finck 
1403c2c66affSColin Finck     if(!push_instr(ctx, OP_ret))
1404c2c66affSColin Finck         return E_OUTOFMEMORY;
1405c2c66affSColin Finck 
1406c2c66affSColin Finck     resolve_labels(ctx, func->code_off);
1407c2c66affSColin Finck 
1408c2c66affSColin Finck     if(func->var_cnt) {
1409c2c66affSColin Finck         dim_decl_t *dim_decl;
1410c2c66affSColin Finck 
1411c2c66affSColin Finck         if(func->type == FUNC_GLOBAL) {
1412c2c66affSColin Finck             dynamic_var_t *new_var;
1413c2c66affSColin Finck 
1414c2c66affSColin Finck             func->var_cnt = 0;
1415c2c66affSColin Finck 
1416c2c66affSColin Finck             for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
1417c2c66affSColin Finck                 new_var = compiler_alloc(ctx->code, sizeof(*new_var));
1418c2c66affSColin Finck                 if(!new_var)
1419c2c66affSColin Finck                     return E_OUTOFMEMORY;
1420c2c66affSColin Finck 
1421c2c66affSColin Finck                 new_var->name = compiler_alloc_string(ctx->code, dim_decl->name);
1422c2c66affSColin Finck                 if(!new_var->name)
1423c2c66affSColin Finck                     return E_OUTOFMEMORY;
1424c2c66affSColin Finck 
1425c2c66affSColin Finck                 V_VT(&new_var->v) = VT_EMPTY;
1426c2c66affSColin Finck                 new_var->is_const = FALSE;
1427c2c66affSColin Finck 
1428c2c66affSColin Finck                 new_var->next = ctx->global_vars;
1429c2c66affSColin Finck                 ctx->global_vars = new_var;
1430c2c66affSColin Finck             }
1431c2c66affSColin Finck         }else {
1432c2c66affSColin Finck             unsigned i;
1433c2c66affSColin Finck 
1434c2c66affSColin Finck             func->vars = compiler_alloc(ctx->code, func->var_cnt * sizeof(var_desc_t));
1435c2c66affSColin Finck             if(!func->vars)
1436c2c66affSColin Finck                 return E_OUTOFMEMORY;
1437c2c66affSColin Finck 
1438c2c66affSColin Finck             for(dim_decl = ctx->dim_decls, i=0; dim_decl; dim_decl = dim_decl->next, i++) {
1439c2c66affSColin Finck                 func->vars[i].name = compiler_alloc_string(ctx->code, dim_decl->name);
1440c2c66affSColin Finck                 if(!func->vars[i].name)
1441c2c66affSColin Finck                     return E_OUTOFMEMORY;
1442c2c66affSColin Finck             }
1443c2c66affSColin Finck 
1444c2c66affSColin Finck             assert(i == func->var_cnt);
1445c2c66affSColin Finck         }
1446c2c66affSColin Finck     }
1447c2c66affSColin Finck 
1448c2c66affSColin Finck     if(func->array_cnt) {
1449c2c66affSColin Finck         unsigned array_id = 0;
1450c2c66affSColin Finck         dim_decl_t *dim_decl;
1451c2c66affSColin Finck 
1452c2c66affSColin Finck         func->array_descs = compiler_alloc(ctx->code, func->array_cnt * sizeof(array_desc_t));
1453c2c66affSColin Finck         if(!func->array_descs)
1454c2c66affSColin Finck             return E_OUTOFMEMORY;
1455c2c66affSColin Finck 
1456c2c66affSColin Finck         for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
1457c2c66affSColin Finck             if(dim_decl->is_array) {
1458c2c66affSColin Finck                 hres = fill_array_desc(ctx, dim_decl, func->array_descs + array_id++);
1459c2c66affSColin Finck                 if(FAILED(hres))
1460c2c66affSColin Finck                     return hres;
1461c2c66affSColin Finck             }
1462c2c66affSColin Finck         }
1463c2c66affSColin Finck 
1464c2c66affSColin Finck         assert(array_id == func->array_cnt);
1465c2c66affSColin Finck     }
1466c2c66affSColin Finck 
1467c2c66affSColin Finck     return S_OK;
1468c2c66affSColin Finck }
1469c2c66affSColin Finck 
lookup_funcs_name(compile_ctx_t * ctx,const WCHAR * name)1470c2c66affSColin Finck static BOOL lookup_funcs_name(compile_ctx_t *ctx, const WCHAR *name)
1471c2c66affSColin Finck {
1472c2c66affSColin Finck     function_t *iter;
1473c2c66affSColin Finck 
1474c2c66affSColin Finck     for(iter = ctx->funcs; iter; iter = iter->next) {
1475*9a0ddc13SAmine Khaldi         if(!wcsicmp(iter->name, name))
1476c2c66affSColin Finck             return TRUE;
1477c2c66affSColin Finck     }
1478c2c66affSColin Finck 
1479c2c66affSColin Finck     return FALSE;
1480c2c66affSColin Finck }
1481c2c66affSColin Finck 
create_function(compile_ctx_t * ctx,function_decl_t * decl,function_t ** ret)1482c2c66affSColin Finck static HRESULT create_function(compile_ctx_t *ctx, function_decl_t *decl, function_t **ret)
1483c2c66affSColin Finck {
1484c2c66affSColin Finck     function_t *func;
1485c2c66affSColin Finck     HRESULT hres;
1486c2c66affSColin Finck 
1487c2c66affSColin Finck     if(lookup_dim_decls(ctx, decl->name) || lookup_funcs_name(ctx, decl->name) || lookup_const_decls(ctx, decl->name, FALSE)) {
1488c2c66affSColin Finck         FIXME("%s: redefinition\n", debugstr_w(decl->name));
1489c2c66affSColin Finck         return E_FAIL;
1490c2c66affSColin Finck     }
1491c2c66affSColin Finck 
1492c2c66affSColin Finck     func = compiler_alloc(ctx->code, sizeof(*func));
1493c2c66affSColin Finck     if(!func)
1494c2c66affSColin Finck         return E_OUTOFMEMORY;
1495c2c66affSColin Finck 
1496c2c66affSColin Finck     func->name = compiler_alloc_string(ctx->code, decl->name);
1497c2c66affSColin Finck     if(!func->name)
1498c2c66affSColin Finck         return E_OUTOFMEMORY;
1499c2c66affSColin Finck 
1500c2c66affSColin Finck     func->vars = NULL;
1501c2c66affSColin Finck     func->var_cnt = 0;
1502c2c66affSColin Finck     func->array_cnt = 0;
1503c2c66affSColin Finck     func->code_ctx = ctx->code;
1504c2c66affSColin Finck     func->type = decl->type;
1505c2c66affSColin Finck     func->is_public = decl->is_public;
1506c2c66affSColin Finck 
1507c2c66affSColin Finck     func->arg_cnt = 0;
1508c2c66affSColin Finck     if(decl->args) {
1509c2c66affSColin Finck         arg_decl_t *arg;
1510c2c66affSColin Finck         unsigned i;
1511c2c66affSColin Finck 
1512c2c66affSColin Finck         for(arg = decl->args; arg; arg = arg->next)
1513c2c66affSColin Finck             func->arg_cnt++;
1514c2c66affSColin Finck 
1515c2c66affSColin Finck         func->args = compiler_alloc(ctx->code, func->arg_cnt * sizeof(arg_desc_t));
1516c2c66affSColin Finck         if(!func->args)
1517c2c66affSColin Finck             return E_OUTOFMEMORY;
1518c2c66affSColin Finck 
1519c2c66affSColin Finck         for(i = 0, arg = decl->args; arg; arg = arg->next, i++) {
1520c2c66affSColin Finck             func->args[i].name = compiler_alloc_string(ctx->code, arg->name);
1521c2c66affSColin Finck             if(!func->args[i].name)
1522c2c66affSColin Finck                 return E_OUTOFMEMORY;
1523c2c66affSColin Finck             func->args[i].by_ref = arg->by_ref;
1524c2c66affSColin Finck         }
1525c2c66affSColin Finck     }else {
1526c2c66affSColin Finck         func->args = NULL;
1527c2c66affSColin Finck     }
1528c2c66affSColin Finck 
1529c2c66affSColin Finck     hres = compile_func(ctx, decl->body, func);
1530c2c66affSColin Finck     if(FAILED(hres))
1531c2c66affSColin Finck         return hres;
1532c2c66affSColin Finck 
1533c2c66affSColin Finck     *ret = func;
1534c2c66affSColin Finck     return S_OK;
1535c2c66affSColin Finck }
1536c2c66affSColin Finck 
lookup_class_name(compile_ctx_t * ctx,const WCHAR * name)1537c2c66affSColin Finck static BOOL lookup_class_name(compile_ctx_t *ctx, const WCHAR *name)
1538c2c66affSColin Finck {
1539c2c66affSColin Finck     class_desc_t *iter;
1540c2c66affSColin Finck 
1541c2c66affSColin Finck     for(iter = ctx->classes; iter; iter = iter->next) {
1542*9a0ddc13SAmine Khaldi         if(!wcsicmp(iter->name, name))
1543c2c66affSColin Finck             return TRUE;
1544c2c66affSColin Finck     }
1545c2c66affSColin Finck 
1546c2c66affSColin Finck     return FALSE;
1547c2c66affSColin Finck }
1548c2c66affSColin Finck 
create_class_funcprop(compile_ctx_t * ctx,function_decl_t * func_decl,vbdisp_funcprop_desc_t * desc)1549c2c66affSColin Finck static HRESULT create_class_funcprop(compile_ctx_t *ctx, function_decl_t *func_decl, vbdisp_funcprop_desc_t *desc)
1550c2c66affSColin Finck {
1551c2c66affSColin Finck     vbdisp_invoke_type_t invoke_type;
1552c2c66affSColin Finck     function_decl_t *funcprop_decl;
1553c2c66affSColin Finck     HRESULT hres;
1554c2c66affSColin Finck 
1555c2c66affSColin Finck     desc->name = compiler_alloc_string(ctx->code, func_decl->name);
1556c2c66affSColin Finck     if(!desc->name)
1557c2c66affSColin Finck         return E_OUTOFMEMORY;
1558c2c66affSColin Finck 
1559c2c66affSColin Finck     for(funcprop_decl = func_decl; funcprop_decl; funcprop_decl = funcprop_decl->next_prop_func) {
1560c2c66affSColin Finck         switch(funcprop_decl->type) {
1561c2c66affSColin Finck         case FUNC_FUNCTION:
1562c2c66affSColin Finck         case FUNC_SUB:
1563c2c66affSColin Finck         case FUNC_PROPGET:
1564c2c66affSColin Finck         case FUNC_DEFGET:
1565c2c66affSColin Finck             invoke_type = VBDISP_CALLGET;
1566c2c66affSColin Finck             break;
1567c2c66affSColin Finck         case FUNC_PROPLET:
1568c2c66affSColin Finck             invoke_type = VBDISP_LET;
1569c2c66affSColin Finck             break;
1570c2c66affSColin Finck         case FUNC_PROPSET:
1571c2c66affSColin Finck             invoke_type = VBDISP_SET;
1572c2c66affSColin Finck             break;
1573c2c66affSColin Finck         DEFAULT_UNREACHABLE;
1574c2c66affSColin Finck         }
1575c2c66affSColin Finck 
1576c2c66affSColin Finck         assert(!desc->entries[invoke_type]);
1577c2c66affSColin Finck 
1578c2c66affSColin Finck         if(funcprop_decl->is_public)
1579c2c66affSColin Finck             desc->is_public = TRUE;
1580c2c66affSColin Finck 
1581c2c66affSColin Finck         hres = create_function(ctx, funcprop_decl, desc->entries+invoke_type);
1582c2c66affSColin Finck         if(FAILED(hres))
1583c2c66affSColin Finck             return hres;
1584c2c66affSColin Finck     }
1585c2c66affSColin Finck 
1586c2c66affSColin Finck     return S_OK;
1587c2c66affSColin Finck }
1588c2c66affSColin Finck 
lookup_class_funcs(class_desc_t * class_desc,const WCHAR * name)1589c2c66affSColin Finck static BOOL lookup_class_funcs(class_desc_t *class_desc, const WCHAR *name)
1590c2c66affSColin Finck {
1591c2c66affSColin Finck     unsigned i;
1592c2c66affSColin Finck 
1593c2c66affSColin Finck     for(i=0; i < class_desc->func_cnt; i++) {
1594*9a0ddc13SAmine Khaldi         if(class_desc->funcs[i].name && !wcsicmp(class_desc->funcs[i].name, name))
1595c2c66affSColin Finck             return TRUE;
1596c2c66affSColin Finck     }
1597c2c66affSColin Finck 
1598c2c66affSColin Finck     return FALSE;
1599c2c66affSColin Finck }
1600c2c66affSColin Finck 
compile_class(compile_ctx_t * ctx,class_decl_t * class_decl)1601c2c66affSColin Finck static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl)
1602c2c66affSColin Finck {
1603c2c66affSColin Finck     function_decl_t *func_decl, *func_prop_decl;
1604c2c66affSColin Finck     class_desc_t *class_desc;
1605c2c66affSColin Finck     dim_decl_t *prop_decl;
1606c2c66affSColin Finck     unsigned i;
1607c2c66affSColin Finck     HRESULT hres;
1608c2c66affSColin Finck 
1609c2c66affSColin Finck     static const WCHAR class_initializeW[] = {'c','l','a','s','s','_','i','n','i','t','i','a','l','i','z','e',0};
1610c2c66affSColin Finck     static const WCHAR class_terminateW[] = {'c','l','a','s','s','_','t','e','r','m','i','n','a','t','e',0};
1611c2c66affSColin Finck 
1612c2c66affSColin Finck     if(lookup_dim_decls(ctx, class_decl->name) || lookup_funcs_name(ctx, class_decl->name)
1613c2c66affSColin Finck             || lookup_const_decls(ctx, class_decl->name, FALSE) || lookup_class_name(ctx, class_decl->name)) {
1614c2c66affSColin Finck         FIXME("%s: redefinition\n", debugstr_w(class_decl->name));
1615c2c66affSColin Finck         return E_FAIL;
1616c2c66affSColin Finck     }
1617c2c66affSColin Finck 
1618c2c66affSColin Finck     class_desc = compiler_alloc_zero(ctx->code, sizeof(*class_desc));
1619c2c66affSColin Finck     if(!class_desc)
1620c2c66affSColin Finck         return E_OUTOFMEMORY;
1621c2c66affSColin Finck 
1622c2c66affSColin Finck     class_desc->name = compiler_alloc_string(ctx->code, class_decl->name);
1623c2c66affSColin Finck     if(!class_desc->name)
1624c2c66affSColin Finck         return E_OUTOFMEMORY;
1625c2c66affSColin Finck 
1626c2c66affSColin Finck     class_desc->func_cnt = 1; /* always allocate slot for default getter */
1627c2c66affSColin Finck 
1628c2c66affSColin Finck     for(func_decl = class_decl->funcs; func_decl; func_decl = func_decl->next) {
1629c2c66affSColin Finck         for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) {
1630c2c66affSColin Finck             if(func_prop_decl->type == FUNC_DEFGET)
1631c2c66affSColin Finck                 break;
1632c2c66affSColin Finck         }
1633c2c66affSColin Finck         if(!func_prop_decl)
1634c2c66affSColin Finck             class_desc->func_cnt++;
1635c2c66affSColin Finck     }
1636c2c66affSColin Finck 
1637c2c66affSColin Finck     class_desc->funcs = compiler_alloc(ctx->code, class_desc->func_cnt*sizeof(*class_desc->funcs));
1638c2c66affSColin Finck     if(!class_desc->funcs)
1639c2c66affSColin Finck         return E_OUTOFMEMORY;
1640c2c66affSColin Finck     memset(class_desc->funcs, 0, class_desc->func_cnt*sizeof(*class_desc->funcs));
1641c2c66affSColin Finck 
1642c2c66affSColin Finck     for(func_decl = class_decl->funcs, i=1; func_decl; func_decl = func_decl->next, i++) {
1643c2c66affSColin Finck         for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) {
1644c2c66affSColin Finck             if(func_prop_decl->type == FUNC_DEFGET) {
1645c2c66affSColin Finck                 i--;
1646c2c66affSColin Finck                 break;
1647c2c66affSColin Finck             }
1648c2c66affSColin Finck         }
1649c2c66affSColin Finck 
1650*9a0ddc13SAmine Khaldi         if(!wcsicmp(class_initializeW, func_decl->name)) {
1651c2c66affSColin Finck             if(func_decl->type != FUNC_SUB) {
1652c2c66affSColin Finck                 FIXME("class initializer is not sub\n");
1653c2c66affSColin Finck                 return E_FAIL;
1654c2c66affSColin Finck             }
1655c2c66affSColin Finck 
1656c2c66affSColin Finck             class_desc->class_initialize_id = i;
1657*9a0ddc13SAmine Khaldi         }else  if(!wcsicmp(class_terminateW, func_decl->name)) {
1658c2c66affSColin Finck             if(func_decl->type != FUNC_SUB) {
1659c2c66affSColin Finck                 FIXME("class terminator is not sub\n");
1660c2c66affSColin Finck                 return E_FAIL;
1661c2c66affSColin Finck             }
1662c2c66affSColin Finck 
1663c2c66affSColin Finck             class_desc->class_terminate_id = i;
1664c2c66affSColin Finck         }
1665c2c66affSColin Finck 
1666c2c66affSColin Finck         hres = create_class_funcprop(ctx, func_decl, class_desc->funcs + (func_prop_decl ? 0 : i));
1667c2c66affSColin Finck         if(FAILED(hres))
1668c2c66affSColin Finck             return hres;
1669c2c66affSColin Finck     }
1670c2c66affSColin Finck 
1671c2c66affSColin Finck     for(prop_decl = class_decl->props; prop_decl; prop_decl = prop_decl->next)
1672c2c66affSColin Finck         class_desc->prop_cnt++;
1673c2c66affSColin Finck 
1674c2c66affSColin Finck     class_desc->props = compiler_alloc(ctx->code, class_desc->prop_cnt*sizeof(*class_desc->props));
1675c2c66affSColin Finck     if(!class_desc->props)
1676c2c66affSColin Finck         return E_OUTOFMEMORY;
1677c2c66affSColin Finck 
1678c2c66affSColin Finck     for(prop_decl = class_decl->props, i=0; prop_decl; prop_decl = prop_decl->next, i++) {
1679c2c66affSColin Finck         if(lookup_class_funcs(class_desc, prop_decl->name)) {
1680c2c66affSColin Finck             FIXME("Property %s redefined\n", debugstr_w(prop_decl->name));
1681c2c66affSColin Finck             return E_FAIL;
1682c2c66affSColin Finck         }
1683c2c66affSColin Finck 
1684c2c66affSColin Finck         class_desc->props[i].name = compiler_alloc_string(ctx->code, prop_decl->name);
1685c2c66affSColin Finck         if(!class_desc->props[i].name)
1686c2c66affSColin Finck             return E_OUTOFMEMORY;
1687c2c66affSColin Finck 
1688c2c66affSColin Finck         class_desc->props[i].is_public = prop_decl->is_public;
1689c2c66affSColin Finck         class_desc->props[i].is_array = prop_decl->is_array;
1690c2c66affSColin Finck 
1691c2c66affSColin Finck         if(prop_decl->is_array)
1692c2c66affSColin Finck             class_desc->array_cnt++;
1693c2c66affSColin Finck     }
1694c2c66affSColin Finck 
1695c2c66affSColin Finck     if(class_desc->array_cnt) {
1696c2c66affSColin Finck         class_desc->array_descs = compiler_alloc(ctx->code, class_desc->array_cnt*sizeof(*class_desc->array_descs));
1697c2c66affSColin Finck         if(!class_desc->array_descs)
1698c2c66affSColin Finck             return E_OUTOFMEMORY;
1699c2c66affSColin Finck 
1700c2c66affSColin Finck         for(prop_decl = class_decl->props, i=0; prop_decl; prop_decl = prop_decl->next) {
1701c2c66affSColin Finck             if(prop_decl->is_array) {
1702c2c66affSColin Finck                 hres = fill_array_desc(ctx, prop_decl, class_desc->array_descs + i++);
1703c2c66affSColin Finck                 if(FAILED(hres))
1704c2c66affSColin Finck                     return hres;
1705c2c66affSColin Finck             }
1706c2c66affSColin Finck         }
1707c2c66affSColin Finck     }
1708c2c66affSColin Finck 
1709c2c66affSColin Finck     class_desc->next = ctx->classes;
1710c2c66affSColin Finck     ctx->classes = class_desc;
1711c2c66affSColin Finck     return S_OK;
1712c2c66affSColin Finck }
1713c2c66affSColin Finck 
lookup_script_identifier(script_ctx_t * script,const WCHAR * identifier)1714c2c66affSColin Finck static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifier)
1715c2c66affSColin Finck {
1716c2c66affSColin Finck     class_desc_t *class;
1717c2c66affSColin Finck     dynamic_var_t *var;
1718c2c66affSColin Finck     function_t *func;
1719c2c66affSColin Finck 
1720c2c66affSColin Finck     for(var = script->global_vars; var; var = var->next) {
1721*9a0ddc13SAmine Khaldi         if(!wcsicmp(var->name, identifier))
1722c2c66affSColin Finck             return TRUE;
1723c2c66affSColin Finck     }
1724c2c66affSColin Finck 
1725c2c66affSColin Finck     for(func = script->global_funcs; func; func = func->next) {
1726*9a0ddc13SAmine Khaldi         if(!wcsicmp(func->name, identifier))
1727c2c66affSColin Finck             return TRUE;
1728c2c66affSColin Finck     }
1729c2c66affSColin Finck 
1730c2c66affSColin Finck     for(class = script->classes; class; class = class->next) {
1731*9a0ddc13SAmine Khaldi         if(!wcsicmp(class->name, identifier))
1732c2c66affSColin Finck             return TRUE;
1733c2c66affSColin Finck     }
1734c2c66affSColin Finck 
1735c2c66affSColin Finck     return FALSE;
1736c2c66affSColin Finck }
1737c2c66affSColin Finck 
check_script_collisions(compile_ctx_t * ctx,script_ctx_t * script)1738c2c66affSColin Finck static HRESULT check_script_collisions(compile_ctx_t *ctx, script_ctx_t *script)
1739c2c66affSColin Finck {
1740c2c66affSColin Finck     class_desc_t *class;
1741c2c66affSColin Finck     dynamic_var_t *var;
1742c2c66affSColin Finck     function_t *func;
1743c2c66affSColin Finck 
1744c2c66affSColin Finck     for(var = ctx->global_vars; var; var = var->next) {
1745c2c66affSColin Finck         if(lookup_script_identifier(script, var->name)) {
1746c2c66affSColin Finck             FIXME("%s: redefined\n", debugstr_w(var->name));
1747c2c66affSColin Finck             return E_FAIL;
1748c2c66affSColin Finck         }
1749c2c66affSColin Finck     }
1750c2c66affSColin Finck 
1751c2c66affSColin Finck     for(func = ctx->funcs; func; func = func->next) {
1752c2c66affSColin Finck         if(lookup_script_identifier(script, func->name)) {
1753c2c66affSColin Finck             FIXME("%s: redefined\n", debugstr_w(func->name));
1754c2c66affSColin Finck             return E_FAIL;
1755c2c66affSColin Finck         }
1756c2c66affSColin Finck     }
1757c2c66affSColin Finck 
1758c2c66affSColin Finck     for(class = ctx->classes; class; class = class->next) {
1759c2c66affSColin Finck         if(lookup_script_identifier(script, class->name)) {
1760c2c66affSColin Finck             FIXME("%s: redefined\n", debugstr_w(class->name));
1761c2c66affSColin Finck             return E_FAIL;
1762c2c66affSColin Finck         }
1763c2c66affSColin Finck     }
1764c2c66affSColin Finck 
1765c2c66affSColin Finck     return S_OK;
1766c2c66affSColin Finck }
1767c2c66affSColin Finck 
release_vbscode(vbscode_t * code)1768c2c66affSColin Finck void release_vbscode(vbscode_t *code)
1769c2c66affSColin Finck {
1770c2c66affSColin Finck     unsigned i;
1771c2c66affSColin Finck 
1772c2c66affSColin Finck     list_remove(&code->entry);
1773c2c66affSColin Finck 
1774c2c66affSColin Finck     for(i=0; i < code->bstr_cnt; i++)
1775c2c66affSColin Finck         SysFreeString(code->bstr_pool[i]);
1776c2c66affSColin Finck 
1777bcea8c65SAmine Khaldi     if(code->context)
1778bcea8c65SAmine Khaldi         IDispatch_Release(code->context);
1779c2c66affSColin Finck     heap_pool_free(&code->heap);
1780c2c66affSColin Finck 
1781c2c66affSColin Finck     heap_free(code->bstr_pool);
1782c2c66affSColin Finck     heap_free(code->source);
1783c2c66affSColin Finck     heap_free(code->instrs);
1784c2c66affSColin Finck     heap_free(code);
1785c2c66affSColin Finck }
1786c2c66affSColin Finck 
alloc_vbscode(compile_ctx_t * ctx,const WCHAR * source)1787c2c66affSColin Finck static vbscode_t *alloc_vbscode(compile_ctx_t *ctx, const WCHAR *source)
1788c2c66affSColin Finck {
1789c2c66affSColin Finck     vbscode_t *ret;
1790c2c66affSColin Finck 
1791bcea8c65SAmine Khaldi     ret = heap_alloc_zero(sizeof(*ret));
1792c2c66affSColin Finck     if(!ret)
1793c2c66affSColin Finck         return NULL;
1794c2c66affSColin Finck 
1795c2c66affSColin Finck     ret->source = heap_strdupW(source);
1796c2c66affSColin Finck     if(!ret->source) {
1797c2c66affSColin Finck         heap_free(ret);
1798c2c66affSColin Finck         return NULL;
1799c2c66affSColin Finck     }
1800c2c66affSColin Finck 
1801c2c66affSColin Finck     ret->instrs = heap_alloc(32*sizeof(instr_t));
1802c2c66affSColin Finck     if(!ret->instrs) {
1803c2c66affSColin Finck         release_vbscode(ret);
1804c2c66affSColin Finck         return NULL;
1805c2c66affSColin Finck     }
1806c2c66affSColin Finck 
1807c2c66affSColin Finck     ctx->instr_cnt = 1;
1808c2c66affSColin Finck     ctx->instr_size = 32;
1809c2c66affSColin Finck     heap_pool_init(&ret->heap);
1810c2c66affSColin Finck 
1811c2c66affSColin Finck     ret->option_explicit = ctx->parser.option_explicit;
1812c2c66affSColin Finck 
1813c2c66affSColin Finck     ret->main_code.type = FUNC_GLOBAL;
1814c2c66affSColin Finck     ret->main_code.code_ctx = ret;
1815c2c66affSColin Finck 
1816c2c66affSColin Finck     list_init(&ret->entry);
1817c2c66affSColin Finck     return ret;
1818c2c66affSColin Finck }
1819c2c66affSColin Finck 
release_compiler(compile_ctx_t * ctx)1820c2c66affSColin Finck static void release_compiler(compile_ctx_t *ctx)
1821c2c66affSColin Finck {
1822c2c66affSColin Finck     parser_release(&ctx->parser);
1823c2c66affSColin Finck     heap_free(ctx->labels);
1824c2c66affSColin Finck     if(ctx->code)
1825c2c66affSColin Finck         release_vbscode(ctx->code);
1826c2c66affSColin Finck }
1827c2c66affSColin Finck 
compile_script(script_ctx_t * script,const WCHAR * src,const WCHAR * delimiter,DWORD flags,vbscode_t ** ret)1828*9a0ddc13SAmine Khaldi HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *delimiter, DWORD flags, vbscode_t **ret)
1829c2c66affSColin Finck {
1830c2c66affSColin Finck     function_t *new_func;
1831c2c66affSColin Finck     function_decl_t *func_decl;
1832c2c66affSColin Finck     class_decl_t *class_decl;
1833c2c66affSColin Finck     compile_ctx_t ctx;
1834c2c66affSColin Finck     vbscode_t *code;
1835c2c66affSColin Finck     HRESULT hres;
1836c2c66affSColin Finck 
1837*9a0ddc13SAmine Khaldi     if (!src) src = L"";
1838*9a0ddc13SAmine Khaldi 
1839*9a0ddc13SAmine Khaldi     hres = parse_script(&ctx.parser, src, delimiter, flags);
1840c2c66affSColin Finck     if(FAILED(hres))
1841*9a0ddc13SAmine Khaldi         return compile_error(script, hres);
1842c2c66affSColin Finck 
1843c2c66affSColin Finck     code = ctx.code = alloc_vbscode(&ctx, src);
1844c2c66affSColin Finck     if(!ctx.code)
1845*9a0ddc13SAmine Khaldi         return compile_error(script, E_OUTOFMEMORY);
1846c2c66affSColin Finck 
1847c2c66affSColin Finck     ctx.funcs = NULL;
1848c2c66affSColin Finck     ctx.func_decls = NULL;
1849c2c66affSColin Finck     ctx.global_vars = NULL;
1850c2c66affSColin Finck     ctx.classes = NULL;
1851c2c66affSColin Finck     ctx.labels = NULL;
1852c2c66affSColin Finck     ctx.global_consts = NULL;
1853c2c66affSColin Finck     ctx.stat_ctx = NULL;
1854c2c66affSColin Finck     ctx.labels_cnt = ctx.labels_size = 0;
1855c2c66affSColin Finck 
1856c2c66affSColin Finck     hres = compile_func(&ctx, ctx.parser.stats, &ctx.code->main_code);
1857c2c66affSColin Finck     if(FAILED(hres)) {
1858c2c66affSColin Finck         release_compiler(&ctx);
1859*9a0ddc13SAmine Khaldi         return compile_error(script, hres);
1860c2c66affSColin Finck     }
1861c2c66affSColin Finck 
1862c2c66affSColin Finck     ctx.global_consts = ctx.const_decls;
1863c2c66affSColin Finck 
1864c2c66affSColin Finck     for(func_decl = ctx.func_decls; func_decl; func_decl = func_decl->next) {
1865c2c66affSColin Finck         hres = create_function(&ctx, func_decl, &new_func);
1866c2c66affSColin Finck         if(FAILED(hres)) {
1867c2c66affSColin Finck             release_compiler(&ctx);
1868*9a0ddc13SAmine Khaldi             return compile_error(script, hres);
1869c2c66affSColin Finck         }
1870c2c66affSColin Finck 
1871c2c66affSColin Finck         new_func->next = ctx.funcs;
1872c2c66affSColin Finck         ctx.funcs = new_func;
1873c2c66affSColin Finck     }
1874c2c66affSColin Finck 
1875c2c66affSColin Finck     for(class_decl = ctx.parser.class_decls; class_decl; class_decl = class_decl->next) {
1876c2c66affSColin Finck         hres = compile_class(&ctx, class_decl);
1877c2c66affSColin Finck         if(FAILED(hres)) {
1878c2c66affSColin Finck             release_compiler(&ctx);
1879*9a0ddc13SAmine Khaldi             return compile_error(script, hres);
1880c2c66affSColin Finck         }
1881c2c66affSColin Finck     }
1882c2c66affSColin Finck 
1883c2c66affSColin Finck     hres = check_script_collisions(&ctx, script);
1884c2c66affSColin Finck     if(FAILED(hres)) {
1885c2c66affSColin Finck         release_compiler(&ctx);
1886*9a0ddc13SAmine Khaldi         return compile_error(script, hres);
1887c2c66affSColin Finck     }
1888c2c66affSColin Finck 
1889c2c66affSColin Finck     if(ctx.global_vars) {
1890c2c66affSColin Finck         dynamic_var_t *var;
1891c2c66affSColin Finck 
1892c2c66affSColin Finck         for(var = ctx.global_vars; var->next; var = var->next);
1893c2c66affSColin Finck 
1894c2c66affSColin Finck         var->next = script->global_vars;
1895c2c66affSColin Finck         script->global_vars = ctx.global_vars;
1896c2c66affSColin Finck     }
1897c2c66affSColin Finck 
1898c2c66affSColin Finck     if(ctx.funcs) {
1899c2c66affSColin Finck         for(new_func = ctx.funcs; new_func->next; new_func = new_func->next);
1900c2c66affSColin Finck 
1901c2c66affSColin Finck         new_func->next = script->global_funcs;
1902c2c66affSColin Finck         script->global_funcs = ctx.funcs;
1903c2c66affSColin Finck     }
1904c2c66affSColin Finck 
1905c2c66affSColin Finck     if(ctx.classes) {
1906c2c66affSColin Finck         class_desc_t *class = ctx.classes;
1907c2c66affSColin Finck 
1908c2c66affSColin Finck         while(1) {
1909c2c66affSColin Finck             class->ctx = script;
1910c2c66affSColin Finck             if(!class->next)
1911c2c66affSColin Finck                 break;
1912c2c66affSColin Finck             class = class->next;
1913c2c66affSColin Finck         }
1914c2c66affSColin Finck 
1915c2c66affSColin Finck         class->next = script->classes;
1916c2c66affSColin Finck         script->classes = ctx.classes;
1917c2c66affSColin Finck     }
1918c2c66affSColin Finck 
1919c2c66affSColin Finck     if(TRACE_ON(vbscript_disas))
1920c2c66affSColin Finck         dump_code(&ctx);
1921c2c66affSColin Finck 
1922c2c66affSColin Finck     ctx.code = NULL;
1923c2c66affSColin Finck     release_compiler(&ctx);
1924c2c66affSColin Finck 
1925c2c66affSColin Finck     list_add_tail(&script->code_list, &code->entry);
1926c2c66affSColin Finck     *ret = code;
1927c2c66affSColin Finck     return S_OK;
1928c2c66affSColin Finck }
1929*9a0ddc13SAmine Khaldi 
compile_procedure(script_ctx_t * script,const WCHAR * src,const WCHAR * delimiter,DWORD flags,class_desc_t ** ret)1930*9a0ddc13SAmine Khaldi HRESULT compile_procedure(script_ctx_t *script, const WCHAR *src, const WCHAR *delimiter, DWORD flags, class_desc_t **ret)
1931*9a0ddc13SAmine Khaldi {
1932*9a0ddc13SAmine Khaldi     class_desc_t *desc;
1933*9a0ddc13SAmine Khaldi     vbscode_t *code;
1934*9a0ddc13SAmine Khaldi     HRESULT hres;
1935*9a0ddc13SAmine Khaldi 
1936*9a0ddc13SAmine Khaldi     hres = compile_script(script, src, delimiter, flags, &code);
1937*9a0ddc13SAmine Khaldi     if(FAILED(hres))
1938*9a0ddc13SAmine Khaldi         return hres;
1939*9a0ddc13SAmine Khaldi 
1940*9a0ddc13SAmine Khaldi     if(!(desc = compiler_alloc_zero(code, sizeof(*desc))))
1941*9a0ddc13SAmine Khaldi         return E_OUTOFMEMORY;
1942*9a0ddc13SAmine Khaldi     if(!(desc->funcs = compiler_alloc_zero(code, sizeof(*desc->funcs))))
1943*9a0ddc13SAmine Khaldi         return E_OUTOFMEMORY;
1944*9a0ddc13SAmine Khaldi 
1945*9a0ddc13SAmine Khaldi     desc->ctx = script;
1946*9a0ddc13SAmine Khaldi     desc->func_cnt = 1;
1947*9a0ddc13SAmine Khaldi     desc->funcs->entries[VBDISP_CALLGET] = &code->main_code;
1948*9a0ddc13SAmine Khaldi 
1949*9a0ddc13SAmine Khaldi     desc->next = script->procs;
1950*9a0ddc13SAmine Khaldi     script->procs = desc;
1951*9a0ddc13SAmine Khaldi 
1952*9a0ddc13SAmine Khaldi     *ret = desc;
1953*9a0ddc13SAmine Khaldi     return S_OK;
1954*9a0ddc13SAmine Khaldi }
1955