From 2de6982f46f20895b5f82e9ee602a905f68aa1d5 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 19 Sep 2011 14:08:02 +0200 Subject: [PATCH] vbscript: Added is expression implementation. --- dlls/vbscript/compile.c | 2 + dlls/vbscript/interp.c | 71 ++++++++++++++++++++++++++++++++++++ dlls/vbscript/parse.h | 1 + dlls/vbscript/parser.y | 1 + dlls/vbscript/tests/lang.vbs | 12 ++++++ dlls/vbscript/vbscript.h | 1 + 6 files changed, 88 insertions(+) diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index c939aea2148..df08c2422c6 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -387,6 +387,8 @@ static HRESULT compile_expression(compile_ctx_t *ctx, expression_t *expr) return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gteq); case EXPR_IDIV: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_idiv); + case EXPR_IS: + return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_is); case EXPR_IMP: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_imp); case EXPR_LT: diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index d3c3483e8b2..472d23c4d44 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -1005,6 +1005,77 @@ static HRESULT interp_lteq(exec_ctx_t *ctx) return stack_push(ctx, &v); } +static HRESULT disp_cmp(IDispatch *disp1, IDispatch *disp2, VARIANT_BOOL *ret) +{ + IObjectIdentity *identity; + IUnknown *unk1, *unk2; + HRESULT hres; + + if(disp1 == disp2) { + *ret = VARIANT_TRUE; + return S_OK; + } + + if(!disp1 || !disp2) { + *ret = VARIANT_FALSE; + return S_OK; + } + + hres = IDispatch_QueryInterface(disp1, &IID_IUnknown, (void**)&unk1); + if(FAILED(hres)) + return hres; + + hres = IDispatch_QueryInterface(disp2, &IID_IUnknown, (void**)&unk2); + if(FAILED(hres)) { + IUnknown_Release(unk1); + return hres; + } + + if(unk1 == unk2) { + *ret = VARIANT_TRUE; + }else { + hres = IUnknown_QueryInterface(unk1, &IID_IObjectIdentity, (void**)&identity); + if(SUCCEEDED(hres)) { + hres = IObjectIdentity_IsEqualObject(identity, unk2); + IObjectIdentity_Release(identity); + *ret = hres == S_OK ? VARIANT_TRUE : VARIANT_FALSE; + }else { + *ret = VARIANT_FALSE; + } + } + + IUnknown_Release(unk1); + IUnknown_Release(unk2); + return S_OK; +} + +static HRESULT interp_is(exec_ctx_t *ctx) +{ + IDispatch *l, *r; + VARIANT v; + HRESULT hres; + + TRACE("\n"); + + hres = stack_pop_disp(ctx, &r); + if(FAILED(hres)) + return hres; + + hres = stack_pop_disp(ctx, &l); + if(SUCCEEDED(hres)) { + V_VT(&v) = VT_BOOL; + hres = disp_cmp(l, r, &V_BOOL(&v)); + if(l) + IDispatch_Release(l); + } + if(r) + IDispatch_Release(r); + if(FAILED(hres)) + return hres; + + return stack_push(ctx, &v); +} + static HRESULT interp_concat(exec_ctx_t *ctx) { variant_val_t r, l; diff --git a/dlls/vbscript/parse.h b/dlls/vbscript/parse.h index ef7f1390ed3..b61582b9a71 100644 --- a/dlls/vbscript/parse.h +++ b/dlls/vbscript/parse.h @@ -31,6 +31,7 @@ typedef enum { EXPR_GTEQ, EXPR_IDIV, EXPR_IMP, + EXPR_IS, EXPR_LT, EXPR_LTEQ, EXPR_MEMBER, diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index d0c3f700751..f25d82591c5 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -252,6 +252,7 @@ EqualityExpression | EqualityExpression '<' ConcatExpression { $$ = new_binary_expression(ctx, EXPR_LT, $1, $3); CHECK_ERROR; } | EqualityExpression tGTEQ ConcatExpression { $$ = new_binary_expression(ctx, EXPR_GTEQ, $1, $3); CHECK_ERROR; } | EqualityExpression tLTEQ ConcatExpression { $$ = new_binary_expression(ctx, EXPR_LTEQ, $1, $3); CHECK_ERROR; } + | EqualityExpression tIS ConcatExpression { $$ = new_binary_expression(ctx, EXPR_IS, $1, $3); CHECK_ERROR; } ConcatExpression : AdditiveExpression { $$ = $1; } diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index a63f9cf0161..64230dc1ecf 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -608,4 +608,16 @@ funcCalled = "" Set obj = Nothing Call ok(funcCalled = "terminate", "funcCalled = " & funcCalled) +Set obj = new EmptyClass +Set x = obj +Set y = new EmptyClass + +Call ok(obj is x, "obj is not x") +Call ok(x is obj, "x is not obj") +Call ok(not (obj is y), "obj is not y") +Call ok(not obj is y, "obj is not y") +Call ok(not (x is Nothing), "x is 1") +Call ok(Nothing is Nothing, "Nothing is not Nothing") +Call ok(x is obj and true, "x is obj and true is false") + reportSuccess() diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index c73f11df1a3..60835118961 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -167,6 +167,7 @@ typedef enum { X(icallv, 1, ARG_BSTR, ARG_UINT) \ X(idiv, 1, 0, 0) \ X(imp, 1, 0, 0) \ + X(is, 1, 0, 0) \ X(jmp, 0, ARG_ADDR, 0) \ X(jmp_false, 0, ARG_ADDR, 0) \ X(jmp_true, 0, ARG_ADDR, 0) \