Module: wine Branch: master Commit: 413bc99044e75a9cd9aafcfd14f259627aaca3a4 URL: http://source.winehq.org/git/wine.git/?a=commit;h=413bc99044e75a9cd9aafcfd14...
Author: Jacek Caban jacek@codeweavers.com Date: Wed Sep 14 12:55:07 2011 +0200
vbscript: Added function compiler implementation.
---
dlls/vbscript/compile.c | 142 +++++++++++++++++++++++++++++++++++------ dlls/vbscript/tests/lang.vbs | 6 ++ dlls/vbscript/vbscript.h | 3 + 3 files changed, 130 insertions(+), 21 deletions(-)
diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index d39b94e..4e8cd06 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -40,6 +40,10 @@ typedef struct {
dim_decl_t *dim_decls; dynamic_var_t *global_vars; + + function_t *func; + function_t *funcs; + function_decl_t *func_decls; } compile_ctx_t;
static HRESULT compile_expression(compile_ctx_t*,expression_t*); @@ -514,6 +518,18 @@ static HRESULT compile_dim_statement(compile_ctx_t *ctx, dim_statement_t *stat) return S_OK; }
+static HRESULT compile_function_statement(compile_ctx_t *ctx, function_statement_t *stat) +{ + if(ctx->func != &ctx->code->global_code) { + FIXME("Function is not in the global code\n"); + return E_FAIL; + } + + stat->func_decl->next = ctx->func_decls; + ctx->func_decls = stat->func_decl; + return S_OK; +} + static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat) { HRESULT hres; @@ -529,6 +545,9 @@ static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat) case STAT_DIM: hres = compile_dim_statement(ctx, (dim_statement_t*)stat); break; + case STAT_FUNC: + hres = compile_function_statement(ctx, (function_statement_t*)stat); + break; case STAT_IF: hres = compile_if_statement(ctx, (if_statement_t*)stat); break; @@ -545,11 +564,11 @@ static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat) return S_OK; }
-static void resolve_labels(compile_ctx_t *ctx) +static void resolve_labels(compile_ctx_t *ctx, unsigned off) { instr_t *instr;
- for(instr = ctx->code->instrs; instr < ctx->code->instrs+ctx->instr_cnt; instr++) { + for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->instr_cnt; instr++) { if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->arg1.uint & LABEL_FLAG)) { assert((instr->arg1.uint & ~LABEL_FLAG) < ctx->labels_cnt); instr->arg1.uint = ctx->labels[instr->arg1.uint & ~LABEL_FLAG]; @@ -566,38 +585,92 @@ static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *f
func->code_off = ctx->instr_cnt;
+ ctx->func = func; + ctx->dim_decls = NULL; hres = compile_statement(ctx, stat); + ctx->func = NULL; if(FAILED(hres)) return hres;
if(push_instr(ctx, OP_ret) == -1) return E_OUTOFMEMORY;
- resolve_labels(ctx); + resolve_labels(ctx, func->code_off);
if(ctx->dim_decls) { dim_decl_t *dim_decl; - dynamic_var_t *new_var;
- for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) { - new_var = compiler_alloc(ctx->code, sizeof(*new_var)); - if(!new_var) - return E_OUTOFMEMORY; + if(func->type == FUNC_GLOBAL) { + dynamic_var_t *new_var;
- new_var->name = compiler_alloc_string(ctx->code, dim_decl->name); - if(!new_var->name) - return E_OUTOFMEMORY; + for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) { + new_var = compiler_alloc(ctx->code, sizeof(*new_var)); + if(!new_var) + return E_OUTOFMEMORY;
- V_VT(&new_var->v) = VT_EMPTY; + new_var->name = compiler_alloc_string(ctx->code, dim_decl->name); + if(!new_var->name) + return E_OUTOFMEMORY;
- new_var->next = ctx->global_vars; - ctx->global_vars = new_var; + V_VT(&new_var->v) = VT_EMPTY; + + new_var->next = ctx->global_vars; + ctx->global_vars = new_var; + } + }else { + FIXME("var not implemented for functions\n"); } }
return S_OK; }
+static BOOL lookup_funcs_name(compile_ctx_t *ctx, const WCHAR *name) +{ + function_t *iter; + + for(iter = ctx->funcs; iter; iter = iter->next) { + if(!strcmpiW(iter->name, name)) + return TRUE; + } + + return FALSE; +} + +static HRESULT create_function(compile_ctx_t *ctx, function_decl_t *decl, function_t **ret) +{ + function_t *func; + HRESULT hres; + + if(lookup_dim_decls(ctx, decl->name) || lookup_funcs_name(ctx, decl->name)) { + FIXME("%s: redefinition\n", debugstr_w(decl->name)); + return E_FAIL; + } + + func = compiler_alloc(ctx->code, sizeof(*func)); + if(!func) + return E_OUTOFMEMORY; + + func->name = compiler_alloc_string(ctx->code, decl->name); + if(!func->name) + return E_OUTOFMEMORY; + + func->code_ctx = ctx->code; + func->type = decl->type; + + if(decl->args) { + FIXME("arguments not implemented\n"); + return E_NOTIMPL; + } + + hres = compile_func(ctx, decl->body, func); + if(FAILED(hres)) + return hres; + + *ret = func; + return S_OK; +} + static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifier) { dynamic_var_t *var; @@ -671,25 +744,40 @@ static vbscode_t *alloc_vbscode(compile_ctx_t *ctx, const WCHAR *source) ret->bstr_pool_size = 0; ret->bstr_cnt = 0;
+ ret->global_code.type = FUNC_GLOBAL; + ret->global_code.name = NULL; ret->global_code.code_ctx = ret;
list_init(&ret->entry); return ret; }
+static void release_compiler(compile_ctx_t *ctx) +{ + parser_release(&ctx->parser); + heap_free(ctx->labels); + if(ctx->code) + release_vbscode(ctx->code); +} + HRESULT compile_script(script_ctx_t *script, const WCHAR *src, vbscode_t **ret) { + function_t *new_func; + function_decl_t *func_decl; compile_ctx_t ctx; + vbscode_t *code; HRESULT hres;
hres = parse_script(&ctx.parser, src); if(FAILED(hres)) return hres;
- ctx.code = alloc_vbscode(&ctx, src); + code = ctx.code = alloc_vbscode(&ctx, src); if(!ctx.code) return E_OUTOFMEMORY;
+ ctx.funcs = NULL; + ctx.func_decls = NULL; ctx.global_vars = NULL; ctx.dim_decls = NULL; ctx.labels = NULL; @@ -697,13 +785,24 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, vbscode_t **ret)
hres = compile_func(&ctx, ctx.parser.stats, &ctx.code->global_code); if(FAILED(hres)) { - release_vbscode(ctx.code); + release_compiler(&ctx); return hres; }
+ for(func_decl = ctx.func_decls; func_decl; func_decl = func_decl->next) { + hres = create_function(&ctx, func_decl, &new_func); + if(FAILED(hres)) { + release_compiler(&ctx); + return hres; + } + + new_func->next = ctx.funcs; + ctx.funcs = new_func; + } + hres = check_script_collisions(&ctx, script); if(FAILED(hres)) { - release_vbscode(ctx.code); + release_compiler(&ctx); return hres; }
@@ -716,12 +815,13 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, vbscode_t **ret) script->global_vars = ctx.global_vars; }
- parser_release(&ctx.parser); - if(TRACE_ON(vbscript_disas)) dump_code(&ctx);
- list_add_tail(&script->code_list, &ctx.code->entry); - *ret = ctx.code; + ctx.code = NULL; + release_compiler(&ctx); + + list_add_tail(&script->code_list, &code->entry); + *ret = code; return S_OK; } diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 12bdaf5..60ca988 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -169,4 +169,10 @@ ElseIf not False Then End If Call ok(x, "elseif not called?")
+if false then +Sub testsub + x = true +End Sub +end if + reportSuccess() diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index b52aa09..41dea38 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -152,8 +152,11 @@ typedef enum { } function_type_t;
struct _function_t { + function_type_t type; + const WCHAR *name; unsigned code_off; vbscode_t *code_ctx; + function_t *next; };
struct _vbscode_t {