closes https://bugs.winehq.org/show_bug.cgi?id=53644
* This applies the patch [provided by](https://bugs.winehq.org/show_bug.cgi?id=53644) @sloper42 and adds tests. * I left a TODO for accessing class variables of type array for a later mr.
-- v4: vbscript: class single line multivar
From: Francis De Brabandere francisdb@gmail.com
--- dlls/vbscript/parser.y | 42 ++++++++++++++++++++++++++---------- dlls/vbscript/tests/lang.vbs | 41 +++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 11 deletions(-)
diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index caeaf25945c..6c1c5e2010c 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -150,11 +150,11 @@ static statement_t *link_statements(statement_t*,statement_t*); %type <elseif> ElseIfs_opt ElseIfs ElseIf %type <class_decl> ClassDeclaration ClassBody %type <uint> Storage Storage_opt IntegerValue -%type <dim_decl> DimDeclList DimDecl +%type <dim_decl> DimDeclList DimDecl MemberDeclList MemberDecl %type <dim_list> DimList %type <redim_decl> ReDimDeclList ReDimDecl %type <const_decl> ConstDecl ConstDeclList -%type <string> Identifier +%type <string> Identifier MemberIdentifier %type <case_clausule> CaseClausules
%% @@ -257,6 +257,15 @@ Preserve_opt : /* empty */ { $$ = FALSE; } | tPRESERVE { $$ = TRUE; }
+MemberDeclList + : MemberDecl { $$ = $1; } + | MemberDecl ',' MemberDeclList { $1->next = $3; $$ = $1; } + +MemberDecl + : MemberIdentifier { $$ = new_dim_decl(ctx, $1, FALSE, NULL); CHECK_ERROR; } + | MemberIdentifier '(' DimList ')' { $$ = new_dim_decl(ctx, $1, TRUE, $3); CHECK_ERROR; } + | MemberIdentifier tEMPTYBRACKETS { $$ = new_dim_decl(ctx, $1, TRUE, NULL); CHECK_ERROR; } + ReDimDecl : tIdentifier '(' ArgumentList ')' { $$ = new_redim_decl(ctx, $1, $3); CHECK_ERROR; }
@@ -458,13 +467,10 @@ ClassBody : /* empty */ { $$ = new_class_decl(ctx); } | FunctionDecl { $$ = add_class_function(ctx, new_class_decl(ctx), $1); CHECK_ERROR; } | FunctionDecl StSep ClassBody { $$ = add_class_function(ctx, $3, $1); CHECK_ERROR; } - /* FIXME: We should use DimDecl here to support arrays, but that conflicts with PropertyDecl. */ - | Storage tIdentifier { dim_decl_t *dim_decl = new_dim_decl(ctx, $2, FALSE, NULL); CHECK_ERROR; - $$ = add_dim_prop(ctx, new_class_decl(ctx), dim_decl, $1); CHECK_ERROR; } - | Storage tIdentifier StSep ClassBody { dim_decl_t *dim_decl = new_dim_decl(ctx, $2, FALSE, NULL); CHECK_ERROR; - $$ = add_dim_prop(ctx, $4, dim_decl, $1); CHECK_ERROR; } - | tDIM DimDecl { $$ = add_dim_prop(ctx, new_class_decl(ctx), $2, 0); CHECK_ERROR; } - | tDIM DimDecl StSep ClassBody { $$ = add_dim_prop(ctx, $4, $2, 0); CHECK_ERROR; } + | Storage MemberDeclList { $$ = add_dim_prop(ctx, new_class_decl(ctx), $2, $1); CHECK_ERROR; } + | Storage MemberDeclList StSep ClassBody { $$ = add_dim_prop(ctx, $4, $2, $1); CHECK_ERROR; } + | tDIM DimDeclList { $$ = add_dim_prop(ctx, new_class_decl(ctx), $2, 0); CHECK_ERROR; } + | tDIM DimDeclList StSep ClassBody { $$ = add_dim_prop(ctx, $4, $2, 0); CHECK_ERROR; } | PropertyDecl { $$ = add_class_function(ctx, new_class_decl(ctx), $1); CHECK_ERROR; } | PropertyDecl StSep ClassBody { $$ = add_class_function(ctx, $3, $1); CHECK_ERROR; }
@@ -513,6 +519,12 @@ ArgumentDecl | tBYVAL Identifier EmptyBrackets_opt { $$ = new_argument_decl(ctx, $2, FALSE); }
/* these keywords may also be an identifier, depending on context */ +MemberIdentifier + : tIdentifier { $$ = $1; } + | tERROR { ctx->last_token = tIdentifier; $$ = $1; } + | tEXPLICIT { ctx->last_token = tIdentifier; $$ = $1; } + | tSTEP { ctx->last_token = tIdentifier; $$ = $1; } + Identifier : tIdentifier { $$ = $1; } | tDEFAULT { ctx->last_token = tIdentifier; $$ = $1; } @@ -1135,14 +1147,22 @@ static class_decl_t *add_class_function(parser_ctx_t *ctx, class_decl_t *class_d
static class_decl_t *add_dim_prop(parser_ctx_t *ctx, class_decl_t *class_decl, dim_decl_t *dim_decl, unsigned storage_flags) { + dim_decl_t *iter; + if(storage_flags & STORAGE_IS_DEFAULT) { FIXME("variant prop can't be default value\n"); ctx->hres = E_FAIL; return NULL; }
- dim_decl->is_public = !(storage_flags & STORAGE_IS_PRIVATE); - dim_decl->next = class_decl->props; + iter = dim_decl; + while(1) { + iter->is_public = !(storage_flags & STORAGE_IS_PRIVATE); + if (!iter->next) break; + iter = iter->next; + } + + iter->next = class_decl->props; class_decl->props = dim_decl; return class_decl; } diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 3c6ce656f1c..b96dfa8a3f6 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -2142,6 +2142,47 @@ call ok(x.getprop.getprop().prop is obj, "x.getprop.getprop().prop is not obj (e ok getVT(x) = "VT_DISPATCH*", "getVT(x) = " & getVT(x) todo_wine_ok getVT(x()) = "VT_BSTR", "getVT(x()) = " & getVT(x())
+Class TestClassVariablesMulti + Public pub1, pub2 + Public pubArray(3), pubArray2(5, 10) + Private priv1, priv2 + Dim dim1, dim2 + + Private Sub Class_Initialize() + pub1 = 1 + pub2 = 2 + pubArray(0) = 3 + pubArray2(0, 0) = 4 + priv1 = 5 + priv2 = 6 + dim1 = 7 + dim2 = 8 + End Sub +End Class + +Set x = new TestClassVariablesMulti +call ok(x.pub1 = 1, "x.pub1 = " & x.pub1) +call ok(x.pub2 = 2, "x.pub2 = " & x.pub2) +call ok(ubound(x.pubArray) = 3, "ubound(x.pubArray) = " & ubound(x.pubArray)) +call ok(ubound(x.pubArray2, 1) = 5, "ubound(x.pubArray2, 1) = " & ubound(x.pubArray2, 1)) +call ok(ubound(x.pubArray2, 2) = 10, "ubound(x.pubArray2, 2) = " & ubound(x.pubArray2, 2)) +' TODO: this does not parse: accessing class variable of array type element directly +' call ok(x.pubArray(0) = 3, "x.pubArray(0) = " & x.pubArray(0)) +call ok(x.dim1 = 7, "x.dim1 = " & x.dim1) +call ok(x.dim2 = 8, "x.dim2 = " & x.dim2) + +on error resume next +x.priv1 = 1 +call ok(err.number = 438, "err.number = " & err.number) +err.clear +x.priv2 = 2 +call ok(err.number = 438, "err.number = " & err.number) +err.clear +' TODO: set class variable of array type element directly +x.pubArray(0) = 1 +call todo_wine_ok(err.number = 0, "set x.pubArray(0) err.number = " & err.number) +on error goto 0 + funcCalled = "" class DefaultSubTest1 Public default Sub init(a)
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=150816
Your paranoid android.
=== debian11b (64 bit WoW report) ===
dnsapi: query.c:142: Test failed: expected record name L"testbot.winehq.org", got L"becky.ns.cloudflare.com"
secur32: schannel.c:1206: Test failed: QueryContextAttributesW(SECPKG_ATTR_ENDPOINT_BINDINGS) failed: 00000057 schannel.c:1284: Test failed: got L"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" schannel.c:1298: Test failed: got L"ECDSA" schannel.c:1307: Test failed: key_info.SignatureAlgorithm = 2203 schannel.c:1309: Test failed: key_info.sSignatureAlgorithmName = ECDSA
wininet: http.c:6917: Test failed: lpszSubjectInfo = test.winehq.org
On Thu Jan 9 14:15:12 2025 +0000, Jacek Caban wrote:
This introduces a new shift/reduce warning. I didn't look at what's native behavior for those reserved names, but removing `MemberIdentifier` and using `tIdentifier` instead fixes it and it seems fine for the initial version.
I think I fixed this one
Jacek Caban (@jacek) commented about dlls/vbscript/parser.y:
| tBYVAL Identifier EmptyBrackets_opt { $$ = new_argument_decl(ctx, $2, FALSE); }
/* these keywords may also be an identifier, depending on context */ +MemberIdentifier
- : tIdentifier { $$ = $1; }
- | tERROR { ctx->last_token = tIdentifier; $$ = $1; }
- | tEXPLICIT { ctx->last_token = tIdentifier; $$ = $1; }
- | tSTEP { ctx->last_token = tIdentifier; $$ = $1; }
The patch looks good to me now. However, please add class variables with those keywords as names to the test.