Commit d04ba41a authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

vbscript: Added exit sub statement implementation.

parent 1936dd7e
...@@ -38,6 +38,8 @@ typedef struct { ...@@ -38,6 +38,8 @@ typedef struct {
unsigned labels_size; unsigned labels_size;
unsigned labels_cnt; unsigned labels_cnt;
unsigned sub_end_label;
dim_decl_t *dim_decls; dim_decl_t *dim_decls;
dynamic_var_t *global_vars; dynamic_var_t *global_vars;
...@@ -530,6 +532,16 @@ static HRESULT compile_function_statement(compile_ctx_t *ctx, function_statement ...@@ -530,6 +532,16 @@ static HRESULT compile_function_statement(compile_ctx_t *ctx, function_statement
return S_OK; return S_OK;
} }
static HRESULT compile_exitsub_statement(compile_ctx_t *ctx)
{
if(ctx->sub_end_label == -1) {
FIXME("Exit Sub outside Sub?\n");
return E_FAIL;
}
return push_instr_addr(ctx, OP_jmp, ctx->sub_end_label);
}
static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat) static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat)
{ {
HRESULT hres; HRESULT hres;
...@@ -545,6 +557,9 @@ static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat) ...@@ -545,6 +557,9 @@ static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat)
case STAT_DIM: case STAT_DIM:
hres = compile_dim_statement(ctx, (dim_statement_t*)stat); hres = compile_dim_statement(ctx, (dim_statement_t*)stat);
break; break;
case STAT_EXITSUB:
hres = compile_exitsub_statement(ctx);
break;
case STAT_FUNC: case STAT_FUNC:
hres = compile_function_statement(ctx, (function_statement_t*)stat); hres = compile_function_statement(ctx, (function_statement_t*)stat);
break; break;
...@@ -585,6 +600,18 @@ static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *f ...@@ -585,6 +600,18 @@ static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *f
func->code_off = ctx->instr_cnt; func->code_off = ctx->instr_cnt;
ctx->sub_end_label = -1;
switch(func->type) {
case FUNC_SUB:
ctx->sub_end_label = alloc_label(ctx);
if(ctx->sub_end_label == -1)
return E_OUTOFMEMORY;
break;
case FUNC_GLOBAL:
break;
}
ctx->func = func; ctx->func = func;
ctx->dim_decls = NULL; ctx->dim_decls = NULL;
hres = compile_statement(ctx, stat); hres = compile_statement(ctx, stat);
...@@ -592,6 +619,9 @@ static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *f ...@@ -592,6 +619,9 @@ static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *f
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
if(ctx->sub_end_label != -1)
label_set_addr(ctx, ctx->sub_end_label);
if(push_instr(ctx, OP_ret) == -1) if(push_instr(ctx, OP_ret) == -1)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
......
...@@ -86,6 +86,7 @@ typedef enum { ...@@ -86,6 +86,7 @@ typedef enum {
STAT_ASSIGN, STAT_ASSIGN,
STAT_CALL, STAT_CALL,
STAT_DIM, STAT_DIM,
STAT_EXITSUB,
STAT_FUNC, STAT_FUNC,
STAT_IF STAT_IF
} statement_type_t; } statement_type_t;
......
...@@ -45,6 +45,7 @@ static expression_t *new_binary_expression(parser_ctx_t*,expression_type_t,expre ...@@ -45,6 +45,7 @@ static expression_t *new_binary_expression(parser_ctx_t*,expression_type_t,expre
static member_expression_t *new_member_expression(parser_ctx_t*,expression_t*,const WCHAR*); static member_expression_t *new_member_expression(parser_ctx_t*,expression_t*,const WCHAR*);
static void *new_statement(parser_ctx_t*,statement_type_t,size_t);
static statement_t *new_call_statement(parser_ctx_t*,member_expression_t*); static statement_t *new_call_statement(parser_ctx_t*,member_expression_t*);
static statement_t *new_assign_statement(parser_ctx_t*,member_expression_t*,expression_t*); static statement_t *new_assign_statement(parser_ctx_t*,member_expression_t*,expression_t*);
static statement_t *new_dim_statement(parser_ctx_t*,dim_decl_t*); static statement_t *new_dim_statement(parser_ctx_t*,dim_decl_t*);
...@@ -138,6 +139,7 @@ Statement ...@@ -138,6 +139,7 @@ Statement
| tDIM DimDeclList { $$ = new_dim_statement(ctx, $2); CHECK_ERROR; } | tDIM DimDeclList { $$ = new_dim_statement(ctx, $2); CHECK_ERROR; }
| IfStatement { $$ = $1; } | IfStatement { $$ = $1; }
| FunctionDecl { $$ = new_function_statement(ctx, $1); CHECK_ERROR; } | FunctionDecl { $$ = new_function_statement(ctx, $1); CHECK_ERROR; }
| tEXIT tSUB { $$ = new_statement(ctx, STAT_EXITSUB, 0); CHECK_ERROR; }
MemberExpression MemberExpression
: tIdentifier { $$ = new_member_expression(ctx, NULL, $1); CHECK_ERROR; } : tIdentifier { $$ = new_member_expression(ctx, NULL, $1); CHECK_ERROR; }
...@@ -388,11 +390,11 @@ static member_expression_t *new_member_expression(parser_ctx_t *ctx, expression_ ...@@ -388,11 +390,11 @@ static member_expression_t *new_member_expression(parser_ctx_t *ctx, expression_
return expr; return expr;
} }
static void *new_statement(parser_ctx_t *ctx, statement_type_t type, unsigned size) static void *new_statement(parser_ctx_t *ctx, statement_type_t type, size_t size)
{ {
statement_t *stat; statement_t *stat;
stat = parser_alloc(ctx, size); stat = parser_alloc(ctx, size ? size : sizeof(*stat));
if(stat) { if(stat) {
stat->type = type; stat->type = type;
stat->next = NULL; stat->next = NULL;
......
...@@ -218,6 +218,15 @@ Sub TestSubMultiArgs(a,b,c,d,e) ...@@ -218,6 +218,15 @@ Sub TestSubMultiArgs(a,b,c,d,e)
Call ok(e=5, "e = " & e) Call ok(e=5, "e = " & e)
End Sub End Sub
Sub TestSubExit(ByRef a)
If a Then
Exit Sub
End If
Call ok(false, "Exit Sub not called?")
End Sub
Call TestSubExit(true)
TestSubMultiArgs 1, 2, 3, 4, 5 TestSubMultiArgs 1, 2, 3, 4, 5
Call TestSubMultiArgs(1, 2, 3, 4, 5) Call TestSubMultiArgs(1, 2, 3, 4, 5)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment