vbscript: Added do until..loop statement implementation.

This commit is contained in:
Jacek Caban 2011-09-16 13:30:31 +02:00 committed by Alexandre Julliard
parent 9701bdb563
commit 223a407a7f
6 changed files with 55 additions and 4 deletions

View File

@ -496,7 +496,7 @@ static HRESULT compile_while_statement(compile_ctx_t *ctx, while_statement_t *st
if(FAILED(hres)) if(FAILED(hres))
return 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) if(jmp_end == -1)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
@ -686,6 +686,7 @@ static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat)
case STAT_STOP: case STAT_STOP:
hres = push_instr(ctx, OP_stop) == -1 ? E_OUTOFMEMORY : S_OK; hres = push_instr(ctx, OP_stop) == -1 ? E_OUTOFMEMORY : S_OK;
break; break;
case STAT_UNTIL:
case STAT_WHILE: case STAT_WHILE:
case STAT_WHILELOOP: case STAT_WHILELOOP:
hres = compile_while_statement(ctx, (while_statement_t*)stat); hres = compile_while_statement(ctx, (while_statement_t*)stat);

View File

@ -611,6 +611,31 @@ static HRESULT interp_jmp_false(exec_ctx_t *ctx)
return S_OK; 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) static HRESULT interp_ret(exec_ctx_t *ctx)
{ {
TRACE("\n"); TRACE("\n");

View File

@ -101,6 +101,7 @@ typedef enum {
STAT_IF, STAT_IF,
STAT_SET, STAT_SET,
STAT_STOP, STAT_STOP,
STAT_UNTIL,
STAT_WHILE, STAT_WHILE,
STAT_WHILELOOP STAT_WHILELOOP
} statement_type_t; } statement_type_t;

View File

@ -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 <expression> NotExpression UnaryExpression AndExpression OrExpression XorExpression EqvExpression
%type <member> MemberExpression %type <member> MemberExpression
%type <expression> Arguments_opt ArgumentList_opt ArgumentList %type <expression> Arguments_opt ArgumentList_opt ArgumentList
%type <bool> OptionExplicit_opt %type <bool> OptionExplicit_opt DoType
%type <arg_decl> ArgumentsDecl_opt ArgumentDeclList ArgumentDecl %type <arg_decl> ArgumentsDecl_opt ArgumentDeclList ArgumentDecl
%type <func_decl> FunctionDecl PropertyDecl %type <func_decl> FunctionDecl PropertyDecl
%type <elseif> ElseIfs_opt ElseIfs ElseIf %type <elseif> ElseIfs_opt ElseIfs ElseIf
@ -156,8 +156,9 @@ Statement
| IfStatement { $$ = $1; } | IfStatement { $$ = $1; }
| tWHILE Expression tNL StatementsNl_opt tWEND | tWHILE Expression tNL StatementsNl_opt tWEND
{ $$ = new_while_statement(ctx, STAT_WHILE, $2, $4); CHECK_ERROR; } { $$ = new_while_statement(ctx, STAT_WHILE, $2, $4); CHECK_ERROR; }
| tDO tWHILE Expression tNL StatementsNl_opt tLOOP | tDO DoType Expression tNL StatementsNl_opt tLOOP
{ $$ = new_while_statement(ctx, STAT_WHILELOOP, $3, $5); CHECK_ERROR; } { $$ = new_while_statement(ctx, $2 ? STAT_WHILELOOP : STAT_UNTIL, $3, $5);
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 tFUNCTION { $$ = new_statement(ctx, STAT_EXITFUNC, 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 { $$ = new_dim_decl(ctx, $1, NULL); CHECK_ERROR; }
| tIdentifier ',' DimDeclList { $$ = new_dim_decl(ctx, $1, $3); CHECK_ERROR; } | tIdentifier ',' DimDeclList { $$ = new_dim_decl(ctx, $1, $3); CHECK_ERROR; }
DoType
: tWHILE { $$ = TRUE; }
| tUNTIL { $$ = FALSE; }
IfStatement IfStatement
: tIF Expression tTHEN tNL StatementsNl ElseIfs_opt Else_opt tEND tIF : tIF Expression tTHEN tNL StatementsNl ElseIfs_opt Else_opt tEND tIF
{ $$ = new_if_statement(ctx, $2, $5, $6, $7); CHECK_ERROR; } { $$ = new_if_statement(ctx, $2, $5, $6, $7); CHECK_ERROR; }

View File

@ -230,6 +230,24 @@ do while true
ok false, "exit do didn't work" ok false, "exit do didn't work"
loop 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 if false then
Sub testsub Sub testsub
x = true x = true

View File

@ -167,6 +167,7 @@ typedef enum {
X(imp, 1, 0, 0) \ X(imp, 1, 0, 0) \
X(jmp, 0, ARG_ADDR, 0) \ X(jmp, 0, ARG_ADDR, 0) \
X(jmp_false, 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(long, 1, ARG_INT, 0) \
X(mcall, 1, ARG_BSTR, ARG_UINT) \ X(mcall, 1, ARG_BSTR, ARG_UINT) \
X(mcallv, 1, ARG_BSTR, ARG_UINT) \ X(mcallv, 1, ARG_BSTR, ARG_UINT) \