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

vbscript: Added exit for statement support.

parent cbb735e2
...@@ -39,6 +39,7 @@ typedef struct { ...@@ -39,6 +39,7 @@ typedef struct {
unsigned labels_cnt; unsigned labels_cnt;
unsigned while_end_label; unsigned while_end_label;
unsigned for_end_label;
unsigned sub_end_label; unsigned sub_end_label;
unsigned func_end_label; unsigned func_end_label;
unsigned prop_end_label; unsigned prop_end_label;
...@@ -617,7 +618,7 @@ static HRESULT compile_dowhile_statement(compile_ctx_t *ctx, while_statement_t * ...@@ -617,7 +618,7 @@ static HRESULT compile_dowhile_statement(compile_ctx_t *ctx, while_statement_t *
static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *stat) static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *stat)
{ {
unsigned step_instr, instr; unsigned step_instr, instr, prev_label;
BSTR identifier; BSTR identifier;
HRESULT hres; HRESULT hres;
...@@ -654,10 +655,16 @@ static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *st ...@@ -654,10 +655,16 @@ static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *st
return hres; return hres;
} }
prev_label = ctx->for_end_label;
ctx->for_end_label = alloc_label(ctx);
if(ctx->for_end_label == -1)
return E_OUTOFMEMORY;
step_instr = push_instr(ctx, OP_step); step_instr = push_instr(ctx, OP_step);
if(step_instr == -1) if(step_instr == -1)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
instr_ptr(ctx, step_instr)->arg2.bstr = identifier; instr_ptr(ctx, step_instr)->arg2.bstr = identifier;
instr_ptr(ctx, step_instr)->arg1.uint = ctx->for_end_label;
hres = compile_statement(ctx, stat->body); hres = compile_statement(ctx, stat->body);
if(FAILED(hres)) if(FAILED(hres))
...@@ -672,7 +679,8 @@ static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *st ...@@ -672,7 +679,8 @@ static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *st
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
instr_ptr(ctx, step_instr)->arg1.uint = ctx->instr_cnt; label_set_addr(ctx, ctx->for_end_label);
ctx->for_end_label = prev_label;
return push_instr_uint(ctx, OP_pop, 2); return push_instr_uint(ctx, OP_pop, 2);
} }
...@@ -804,6 +812,16 @@ static HRESULT compile_exitdo_statement(compile_ctx_t *ctx) ...@@ -804,6 +812,16 @@ static HRESULT compile_exitdo_statement(compile_ctx_t *ctx)
return push_instr_addr(ctx, OP_jmp, ctx->while_end_label); return push_instr_addr(ctx, OP_jmp, ctx->while_end_label);
} }
static HRESULT compile_exitfor_statement(compile_ctx_t *ctx)
{
if(ctx->for_end_label == -1) {
FIXME("Exit For outside For Loop\n");
return E_FAIL;
}
return push_instr_addr(ctx, OP_jmp, ctx->for_end_label);
}
static HRESULT compile_exitsub_statement(compile_ctx_t *ctx) static HRESULT compile_exitsub_statement(compile_ctx_t *ctx)
{ {
if(ctx->sub_end_label == -1) { if(ctx->sub_end_label == -1) {
...@@ -864,6 +882,9 @@ static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat) ...@@ -864,6 +882,9 @@ static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat)
case STAT_EXITDO: case STAT_EXITDO:
hres = compile_exitdo_statement(ctx); hres = compile_exitdo_statement(ctx);
break; break;
case STAT_EXITFOR:
hres = compile_exitfor_statement(ctx);
break;
case STAT_EXITFUNC: case STAT_EXITFUNC:
hres = compile_exitfunc_statement(ctx); hres = compile_exitfunc_statement(ctx);
break; break;
...@@ -931,6 +952,7 @@ static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *f ...@@ -931,6 +952,7 @@ 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->while_end_label = -1; ctx->while_end_label = -1;
ctx->for_end_label = -1;
ctx->sub_end_label = -1; ctx->sub_end_label = -1;
ctx->func_end_label = -1; ctx->func_end_label = -1;
ctx->prop_end_label = -1; ctx->prop_end_label = -1;
...@@ -967,6 +989,7 @@ static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *f ...@@ -967,6 +989,7 @@ static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *f
return hres; return hres;
assert(ctx->while_end_label == -1); assert(ctx->while_end_label == -1);
assert(ctx->for_end_label == -1);
if(ctx->sub_end_label != -1) if(ctx->sub_end_label != -1)
label_set_addr(ctx, ctx->sub_end_label); label_set_addr(ctx, ctx->sub_end_label);
......
...@@ -103,6 +103,7 @@ typedef enum { ...@@ -103,6 +103,7 @@ typedef enum {
STAT_DOUNTIL, STAT_DOUNTIL,
STAT_DOWHILE, STAT_DOWHILE,
STAT_EXITDO, STAT_EXITDO,
STAT_EXITFOR,
STAT_EXITFUNC, STAT_EXITFUNC,
STAT_EXITPROP, STAT_EXITPROP,
STAT_EXITSUB, STAT_EXITSUB,
......
...@@ -178,6 +178,7 @@ SimpleStatement ...@@ -178,6 +178,7 @@ SimpleStatement
CHECK_ERROR; } CHECK_ERROR; }
| FunctionDecl { $$ = new_function_statement(ctx, $1); CHECK_ERROR; } | FunctionDecl { $$ = new_function_statement(ctx, $1); CHECK_ERROR; }
| tEXIT tDO { $$ = new_statement(ctx, STAT_EXITDO, 0); CHECK_ERROR; } | tEXIT tDO { $$ = new_statement(ctx, STAT_EXITDO, 0); CHECK_ERROR; }
| tEXIT tFOR { $$ = new_statement(ctx, STAT_EXITFOR, 0); CHECK_ERROR; }
| tEXIT tFUNCTION { $$ = new_statement(ctx, STAT_EXITFUNC, 0); CHECK_ERROR; } | tEXIT tFUNCTION { $$ = new_statement(ctx, STAT_EXITFUNC, 0); CHECK_ERROR; }
| tEXIT tPROPERTY { $$ = new_statement(ctx, STAT_EXITPROP, 0); CHECK_ERROR; } | tEXIT tPROPERTY { $$ = new_statement(ctx, STAT_EXITPROP, 0); CHECK_ERROR; }
| tEXIT tSUB { $$ = new_statement(ctx, STAT_EXITSUB, 0); CHECK_ERROR; } | tEXIT tSUB { $$ = new_statement(ctx, STAT_EXITSUB, 0); CHECK_ERROR; }
......
...@@ -387,6 +387,15 @@ for x = 5 to 8 ...@@ -387,6 +387,15 @@ for x = 5 to 8
next next
Call ok(y = "for8: 5 7", "y = " & y) Call ok(y = "for8: 5 7", "y = " & y)
for x = 1.5 to 1
Call ok(false, "for..to called when unexpected")
next
for x = 1 to 100
exit for
Call ok(false, "exit for not escaped the loop?")
next
if false then if false then
Sub testsub Sub testsub
x = true x = true
......
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