Module: wine Branch: master Commit: 223a407a7fd399a983d93b8ea10da821bb7f24b0 URL: http://source.winehq.org/git/wine.git/?a=commit;h=223a407a7fd399a983d93b8ea1...
Author: Jacek Caban jacek@codeweavers.com Date: Fri Sep 16 13:30:31 2011 +0200
vbscript: Added do until..loop statement implementation.
---
dlls/vbscript/compile.c | 3 ++- dlls/vbscript/interp.c | 25 +++++++++++++++++++++++++ dlls/vbscript/parse.h | 1 + dlls/vbscript/parser.y | 11 ++++++++--- dlls/vbscript/tests/lang.vbs | 18 ++++++++++++++++++ dlls/vbscript/vbscript.h | 1 + 6 files changed, 55 insertions(+), 4 deletions(-)
diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index 61854e3..5737676 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -496,7 +496,7 @@ static HRESULT compile_while_statement(compile_ctx_t *ctx, while_statement_t *st if(FAILED(hres)) return hres;
- jmp_end = push_instr(ctx, OP_jmp_false); + jmp_end = push_instr(ctx, stat->stat.type == STAT_UNTIL ? OP_jmp_true : OP_jmp_false); if(jmp_end == -1) return E_OUTOFMEMORY;
@@ -686,6 +686,7 @@ static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat) case STAT_STOP: hres = push_instr(ctx, OP_stop) == -1 ? E_OUTOFMEMORY : S_OK; break; + case STAT_UNTIL: case STAT_WHILE: case STAT_WHILELOOP: hres = compile_while_statement(ctx, (while_statement_t*)stat); diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index 474957c..c8e0514 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -611,6 +611,31 @@ static HRESULT interp_jmp_false(exec_ctx_t *ctx) return S_OK; }
+static HRESULT interp_jmp_true(exec_ctx_t *ctx) +{ + const unsigned arg = ctx->instr->arg1.uint; + variant_val_t val; + HRESULT hres; + + TRACE("%u\n", arg); + + hres = stack_pop_val(ctx, &val); + if(FAILED(hres)) + return hres; + + if(V_VT(val.v) != VT_BOOL) { + FIXME("unsupported for %s\n", debugstr_variant(val.v)); + release_val(&val); + return E_NOTIMPL; + } + + if(V_BOOL(val.v)) + instr_jmp(ctx, ctx->instr->arg1.uint); + else + ctx->instr++; + return S_OK; +} + static HRESULT interp_ret(exec_ctx_t *ctx) { TRACE("\n"); diff --git a/dlls/vbscript/parse.h b/dlls/vbscript/parse.h index 5e9c9ae..624e49f 100644 --- a/dlls/vbscript/parse.h +++ b/dlls/vbscript/parse.h @@ -101,6 +101,7 @@ typedef enum { STAT_IF, STAT_SET, STAT_STOP, + STAT_UNTIL, STAT_WHILE, STAT_WHILELOOP } statement_type_t; diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index 1bd8f58..820ae6c 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -114,7 +114,7 @@ static class_decl_t *add_variant_prop(parser_ctx_t*,class_decl_t*,const WCHAR*,u %type <expression> NotExpression UnaryExpression AndExpression OrExpression XorExpression EqvExpression %type <member> MemberExpression %type <expression> Arguments_opt ArgumentList_opt ArgumentList -%type <bool> OptionExplicit_opt +%type <bool> OptionExplicit_opt DoType %type <arg_decl> ArgumentsDecl_opt ArgumentDeclList ArgumentDecl %type <func_decl> FunctionDecl PropertyDecl %type <elseif> ElseIfs_opt ElseIfs ElseIf @@ -156,8 +156,9 @@ Statement | IfStatement { $$ = $1; } | tWHILE Expression tNL StatementsNl_opt tWEND { $$ = new_while_statement(ctx, STAT_WHILE, $2, $4); CHECK_ERROR; } - | tDO tWHILE Expression tNL StatementsNl_opt tLOOP - { $$ = new_while_statement(ctx, STAT_WHILELOOP, $3, $5); CHECK_ERROR; } + | tDO DoType Expression tNL StatementsNl_opt tLOOP + { $$ = new_while_statement(ctx, $2 ? STAT_WHILELOOP : STAT_UNTIL, $3, $5); + CHECK_ERROR; } | FunctionDecl { $$ = new_function_statement(ctx, $1); CHECK_ERROR; } | tEXIT tDO { $$ = new_statement(ctx, STAT_EXITDO, 0); CHECK_ERROR; } | tEXIT tFUNCTION { $$ = new_statement(ctx, STAT_EXITFUNC, 0); CHECK_ERROR; } @@ -175,6 +176,10 @@ DimDeclList /* FIXME: Support arrays */ : tIdentifier { $$ = new_dim_decl(ctx, $1, NULL); CHECK_ERROR; } | tIdentifier ',' DimDeclList { $$ = new_dim_decl(ctx, $1, $3); CHECK_ERROR; }
+DoType + : tWHILE { $$ = TRUE; } + | tUNTIL { $$ = FALSE; } + IfStatement : tIF Expression tTHEN tNL StatementsNl ElseIfs_opt Else_opt tEND tIF { $$ = new_if_statement(ctx, $2, $5, $6, $7); CHECK_ERROR; } diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 78083e6..8b1d1c3 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -230,6 +230,24 @@ do while true ok false, "exit do didn't work" loop
+x = false +y = false +do until x and y + if x then + y = true + end if + x = true +loop +call ok((x and y), "x or y is false after do until") + +do until true +loop + +do until false + exit do + ok false, "exit do didn't work" +loop + if false then Sub testsub x = true diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index a2c23ea..12315ae 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -167,6 +167,7 @@ typedef enum { X(imp, 1, 0, 0) \ X(jmp, 0, ARG_ADDR, 0) \ X(jmp_false, 0, ARG_ADDR, 0) \ + X(jmp_true, 0, ARG_ADDR, 0) \ X(long, 1, ARG_INT, 0) \ X(mcall, 1, ARG_BSTR, ARG_UINT) \ X(mcallv, 1, ARG_BSTR, ARG_UINT) \