diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index 6bacaa01cb3..814d9ea9409 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -483,6 +483,34 @@ static HRESULT compile_if_statement(compile_ctx_t *ctx, if_statement_t *stat) return S_OK; } +static HRESULT compile_while_statement(compile_ctx_t *ctx, while_statement_t *stat) +{ + unsigned start_addr; + unsigned jmp_end; + HRESULT hres; + + start_addr = ctx->instr_cnt; + + hres = compile_expression(ctx, stat->expr); + if(FAILED(hres)) + return hres; + + jmp_end = push_instr(ctx, OP_jmp_false); + if(jmp_end == -1) + return E_OUTOFMEMORY; + + hres = compile_statement(ctx, stat->body); + if(FAILED(hres)) + return hres; + + hres = push_instr_addr(ctx, OP_jmp, start_addr); + if(FAILED(hres)) + return hres; + + instr_ptr(ctx, jmp_end)->arg1.uint = ctx->instr_cnt; + return S_OK; +} + static HRESULT compile_assign_statement(compile_ctx_t *ctx, assign_statement_t *stat, BOOL is_set) { HRESULT hres; @@ -632,6 +660,9 @@ 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_WHILE: + hres = compile_while_statement(ctx, (while_statement_t*)stat); + break; default: FIXME("Unimplemented statement type %d\n", stat->type); hres = E_NOTIMPL; diff --git a/dlls/vbscript/parse.h b/dlls/vbscript/parse.h index 245badc2ba7..efd3d67714a 100644 --- a/dlls/vbscript/parse.h +++ b/dlls/vbscript/parse.h @@ -99,7 +99,8 @@ typedef enum { STAT_FUNC, STAT_IF, STAT_SET, - STAT_STOP + STAT_STOP, + STAT_WHILE } statement_type_t; typedef struct _statement_t { @@ -176,6 +177,12 @@ typedef struct { statement_t *else_stat; } if_statement_t; +typedef struct { + statement_t stat; + expression_t *expr; + statement_t *body; +} while_statement_t; + typedef struct { const WCHAR *code; const WCHAR *ptr; diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index adf1aba837d..d06c84f404d 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -52,6 +52,7 @@ 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_set_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_while_statement(parser_ctx_t*,statement_type_t,expression_t*,statement_t*); static statement_t *new_if_statement(parser_ctx_t*,expression_t*,statement_t*,elseif_decl_t*,statement_t*); static statement_t *new_function_statement(parser_ctx_t*,function_decl_t*); @@ -153,6 +154,8 @@ Statement { $1->args = $2; $$ = new_assign_statement(ctx, $1, $4); CHECK_ERROR; } | tDIM DimDeclList { $$ = new_dim_statement(ctx, $2); CHECK_ERROR; } | IfStatement { $$ = $1; } + | tWHILE Expression tNL StatementsNl_opt tWEND + { $$ = new_while_statement(ctx, STAT_WHILE, $2, $4); CHECK_ERROR; } | FunctionDecl { $$ = new_function_statement(ctx, $1); CHECK_ERROR; } | tEXIT tFUNCTION { $$ = new_statement(ctx, STAT_EXITFUNC, 0); CHECK_ERROR; } | tEXIT tPROPERTY { $$ = new_statement(ctx, STAT_EXITPROP, 0); CHECK_ERROR; } @@ -565,6 +568,19 @@ static elseif_decl_t *new_elseif_decl(parser_ctx_t *ctx, expression_t *expr, sta return decl; } +static statement_t *new_while_statement(parser_ctx_t *ctx, statement_type_t type, expression_t *expr, statement_t *body) +{ + while_statement_t *stat; + + stat = new_statement(ctx, type, sizeof(*stat)); + if(!stat) + return NULL; + + stat->expr = expr; + stat->body = body; + return &stat->stat; +} + static statement_t *new_if_statement(parser_ctx_t *ctx, expression_t *expr, statement_t *if_stat, elseif_decl_t *elseif_decl, statement_t *else_stat) { diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 961eea27d53..d3886d66748 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -199,6 +199,19 @@ ElseIf not False Then End If Call ok(x, "elseif not called?") +x = false +y = false +while not (x and y) + if x then + y = true + end if + x = true +wend +call ok((x and y), "x or y is false after while") + +while false +wend + if false then Sub testsub x = true