[PATCH v10 0/1] MR10362: vbscript: Support chained call syntax like dict.Keys()(i).
Treat '(' after tEMPTYBRACKETS as an argument list opener in the lexer, so that expressions like GetArr()(0) or dict.Keys()(i) parse correctly. Also dereference VT_BYREF|VT_VARIANT results in vcall so chained indexing on call results works at runtime. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58051 This includes some of the work done in !10308, preferably that one is merged first. -- v10: vbscript: Support chained call syntax like dict.Keys()(i). https://gitlab.winehq.org/wine/wine/-/merge_requests/10362
From: Francis De Brabandere <francisdb@gmail.com> Treat '(' after tEMPTYBRACKETS as an argument list opener in the lexer, so that expressions like GetArr()(0) or dict.Keys()(i) parse correctly. Also dereference VT_BYREF|VT_VARIANT results in vcall so chained indexing on call results works at runtime. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58051 --- dlls/vbscript/lex.c | 3 ++- dlls/vbscript/tests/lang.vbs | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/dlls/vbscript/lex.c b/dlls/vbscript/lex.c index 12305ab671b..076320e8917 100644 --- a/dlls/vbscript/lex.c +++ b/dlls/vbscript/lex.c @@ -491,7 +491,8 @@ static int parse_next_token(void *lval, unsigned *loc, parser_ctx_t *ctx) * Parser can't predict if bracket is part of argument expression or an argument * in call expression. We predict it here instead. */ - if(ctx->last_token == tIdentifier || ctx->last_token == ')' || ctx->last_token == tME) + if(ctx->last_token == tIdentifier || ctx->last_token == ')' || ctx->last_token == tME + || ctx->last_token == tEMPTYBRACKETS) return '('; return tEXPRLBRACKET; case '"': diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 39f1d08e27b..04ffbd9311a 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -1841,6 +1841,38 @@ call ok(containerObj("Key")(1)(0) = "SubValue1", "containerObj(Key)(1)(0) = " & call ok(Split("1;2", ";")(0) = "1", "Split(""1;2"", "";"")(0) = " & Split("1;2", ";")(0)) call ok(Split("1;2", ";")(1) = "2", "Split(""1;2"", "";"")(1) = " & Split("1;2", ";")(1)) +Function GetABC() + GetABC = Array("a", "b", "c") +End Function +call ok(GetABC()(0) = "a", "GetABC()(0) = " & GetABC()(0)) +call ok(GetABC()(1) = "b", "GetABC()(1) = " & GetABC()(1)) +call ok(GetABC()(2) = "c", "GetABC()(2) = " & GetABC()(2)) + +Function GetNested() + GetNested = Array(Array(1, 2), Array(3, 4)) +End Function +call ok(GetNested()(0)(0) = 1, "GetNested()(0)(0) = " & GetNested()(0)(0)) +call ok(GetNested()(0)(1) = 2, "GetNested()(0)(1) = " & GetNested()(0)(1)) +call ok(GetNested()(1)(0) = 3, "GetNested()(1)(0) = " & GetNested()(1)(0)) +call ok(GetNested()(1)(1) = 4, "GetNested()(1)(1) = " & GetNested()(1)(1)) + +x = GetABC()(0) & GetABC()(2) +call ok(x = "ac", "GetABC()(0) & GetABC()(2) = " & x) + +call ok(Array(10,20,30)(1) = 20, "Array(10,20,30)(1) = " & Array(10,20,30)(1)) + +' Chained call with dot accessor: dict.Keys()(0) +Dim chainDict +Set chainDict = CreateObject("Scripting.Dictionary") +chainDict.Add "first", 1 +chainDict.Add "second", 2 +call ok(chainDict.Keys()(0) = "first", "dict.Keys()(0) = " & chainDict.Keys()(0)) +call ok(chainDict.Keys()(1) = "second", "dict.Keys()(1) = " & chainDict.Keys()(1)) +call ok(chainDict.Items()(0) = 1, "dict.Items()(0) = " & chainDict.Items()(0)) + +' Chained call as argument to function: Len(GetABC()(0)) +call ok(Len(GetABC()(0)) = 1, "Len(GetABC()(0)) = " & Len(GetABC()(0))) +call ok(UBound(GetABC()) = 2, "UBound(GetABC()) = " & UBound(GetABC())) function seta0(arr) arr(0) = 2 -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10362
participants (2)
-
Francis De Brabandere -
Francis De Brabandere (@francisdb)