Jacek Caban : vbscript: Added while..wend statement implementation.

Alexandre Julliard julliard at winehq.org
Fri Sep 16 13:28:33 CDT 2011


Module: wine
Branch: master
Commit: 3d34925802b62238ae9360ac1e210955cf63de91
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=3d34925802b62238ae9360ac1e210955cf63de91

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Sep 16 13:29:59 2011 +0200

vbscript: Added while..wend statement implementation.

---

 dlls/vbscript/compile.c      |   31 +++++++++++++++++++++++++++++++
 dlls/vbscript/parse.h        |    9 ++++++++-
 dlls/vbscript/parser.y       |   16 ++++++++++++++++
 dlls/vbscript/tests/lang.vbs |   13 +++++++++++++
 4 files changed, 68 insertions(+), 1 deletions(-)

diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c
index 6bacaa0..814d9ea 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 245badc..efd3d67 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 {
@@ -177,6 +178,12 @@ typedef struct {
 } 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;
     const WCHAR *end;
diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y
index adf1aba..d06c84f 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 961eea2..d3886d6 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




More information about the wine-cvs mailing list