Skip to content

Commit 6cf15f4

Browse files
authored
Allow .member syntax on vector and scalars. (#6424)
* Allow `.member` syntax on vector and scalars. * Fix. * fix. * Fix. * update comment. * Fix tests. * Fix warning. * Add more tests.
1 parent 2ebf955 commit 6cf15f4

13 files changed

+200
-143
lines changed

source/slang/slang-check-expr.cpp

+69-97
Original file line numberDiff line numberDiff line change
@@ -4136,12 +4136,6 @@ Expr* SemanticsVisitor::CheckMatrixSwizzleExpr(
41364136
IntegerLiteralValue baseElementRowCount,
41374137
IntegerLiteralValue baseElementColCount)
41384138
{
4139-
MatrixSwizzleExpr* swizExpr = m_astBuilder->create<MatrixSwizzleExpr>();
4140-
swizExpr->loc = memberRefExpr->loc;
4141-
swizExpr->base = memberRefExpr->baseExpression;
4142-
swizExpr->memberOpLoc = memberRefExpr->memberOperatorLoc;
4143-
swizExpr->checked = true;
4144-
41454139
// We can have up to 4 swizzles of two elements each
41464140
MatrixCoord elementCoords[4];
41474141
int elementCount = 0;
@@ -4170,24 +4164,14 @@ Expr* SemanticsVisitor::CheckMatrixSwizzleExpr(
41704164
// Throw out swizzling with more than 4 output elements
41714165
if (elementCount >= 4)
41724166
{
4173-
getSink()->diagnose(
4174-
swizExpr,
4175-
Diagnostics::invalidSwizzleExpr,
4176-
swizzleText,
4177-
baseElementType->toString());
4178-
return CreateErrorExpr(memberRefExpr);
4167+
return nullptr;
41794168
}
41804169
MatrixCoord elementCoord = {0, 0};
41814170

41824171
// Check for the preceding underscore
41834172
if (*cursor++ != '_')
41844173
{
4185-
getSink()->diagnose(
4186-
swizExpr,
4187-
Diagnostics::invalidSwizzleExpr,
4188-
swizzleText,
4189-
baseElementType->toString());
4190-
return CreateErrorExpr(memberRefExpr);
4174+
return nullptr;
41914175
}
41924176

41934177
// Check for one or zero indexing
@@ -4196,12 +4180,7 @@ Expr* SemanticsVisitor::CheckMatrixSwizzleExpr(
41964180
// Can't mix one and zero indexing
41974181
if (zeroIndexOffset == 1)
41984182
{
4199-
getSink()->diagnose(
4200-
swizExpr,
4201-
Diagnostics::invalidSwizzleExpr,
4202-
swizzleText,
4203-
baseElementType->toString());
4204-
return CreateErrorExpr(memberRefExpr);
4183+
return nullptr;
42054184
}
42064185
zeroIndexOffset = 0;
42074186
// Increment the index since we saw 'm'
@@ -4212,12 +4191,7 @@ Expr* SemanticsVisitor::CheckMatrixSwizzleExpr(
42124191
// Can't mix one and zero indexing
42134192
if (zeroIndexOffset == 0)
42144193
{
4215-
getSink()->diagnose(
4216-
swizExpr,
4217-
Diagnostics::invalidSwizzleExpr,
4218-
swizzleText,
4219-
baseElementType->toString());
4220-
return CreateErrorExpr(memberRefExpr);
4194+
return nullptr;
42214195
}
42224196
zeroIndexOffset = 1;
42234197
}
@@ -4229,13 +4203,7 @@ Expr* SemanticsVisitor::CheckMatrixSwizzleExpr(
42294203

42304204
if (ch < '0' || ch > '4')
42314205
{
4232-
// An invalid character in the swizzle is an error
4233-
getSink()->diagnose(
4234-
swizExpr,
4235-
Diagnostics::invalidSwizzleExpr,
4236-
swizzleText,
4237-
baseElementType->toString());
4238-
return CreateErrorExpr(memberRefExpr);
4206+
return nullptr;
42394207
}
42404208
const int subIndex = ch - '0' - zeroIndexOffset;
42414209

@@ -4255,12 +4223,7 @@ Expr* SemanticsVisitor::CheckMatrixSwizzleExpr(
42554223
// Account for off-by-one and reject 0 if oneIndexed
42564224
if (subIndex >= elementLimit || subIndex < 0)
42574225
{
4258-
getSink()->diagnose(
4259-
swizExpr,
4260-
Diagnostics::invalidSwizzleExpr,
4261-
swizzleText,
4262-
baseElementType->toString());
4263-
return CreateErrorExpr(memberRefExpr);
4226+
return nullptr;
42644227
}
42654228
}
42664229
// Check if we've seen this index before
@@ -4275,6 +4238,12 @@ Expr* SemanticsVisitor::CheckMatrixSwizzleExpr(
42754238
elementCount++;
42764239
}
42774240

4241+
MatrixSwizzleExpr* swizExpr = m_astBuilder->create<MatrixSwizzleExpr>();
4242+
swizExpr->loc = memberRefExpr->loc;
4243+
swizExpr->base = memberRefExpr->baseExpression;
4244+
swizExpr->memberOpLoc = memberRefExpr->memberOperatorLoc;
4245+
swizExpr->checked = true;
4246+
42784247
// Store our list in the actual AST node
42794248
for (int ee = 0; ee < elementCount; ++ee)
42804249
{
@@ -4324,11 +4293,7 @@ Expr* SemanticsVisitor::CheckMatrixSwizzleExpr(
43244293
constantColCount->getValue());
43254294
}
43264295
}
4327-
getSink()->diagnose(
4328-
memberRefExpr,
4329-
Diagnostics::unimplemented,
4330-
"swizzle on matrix of unknown size");
4331-
return CreateErrorExpr(memberRefExpr);
4296+
return nullptr;
43324297
}
43334298

43344299
Expr* SemanticsVisitor::checkTupleSwizzleExpr(MemberExpr* memberExpr, TupleType* baseTupleType)
@@ -4439,26 +4404,13 @@ Expr* SemanticsVisitor::CheckSwizzleExpr(
44394404
Type* baseElementType,
44404405
IntegerLiteralValue baseElementCount)
44414406
{
4442-
SwizzleExpr* swizExpr = m_astBuilder->create<SwizzleExpr>();
4443-
swizExpr->loc = memberRefExpr->loc;
4444-
swizExpr->base = memberRefExpr->baseExpression;
4445-
swizExpr->memberOpLoc = memberRefExpr->memberOperatorLoc;
44464407
IntegerLiteralValue limitElement = baseElementCount;
44474408

44484409
ShortList<uint32_t, 4> elementIndices;
44494410

44504411
bool anyDuplicates = false;
44514412
bool anyError = false;
4452-
if (memberRefExpr->name == getSession()->getCompletionRequestTokenName())
4453-
{
4454-
auto& suggestions = getLinkage()->contentAssistInfo.completionSuggestions;
4455-
suggestions.clear();
4456-
suggestions.scopeKind = CompletionSuggestions::ScopeKind::Swizzle;
4457-
suggestions.swizzleBaseType =
4458-
memberRefExpr->baseExpression ? memberRefExpr->baseExpression->type : nullptr;
4459-
suggestions.elementCount[0] = baseElementCount;
4460-
suggestions.elementCount[1] = 0;
4461-
}
4413+
44624414
auto swizzleText = getText(memberRefExpr->name);
44634415

44644416
for (Index i = 0; i < swizzleText.getLength(); i++)
@@ -4518,18 +4470,18 @@ Expr* SemanticsVisitor::CheckSwizzleExpr(
45184470
elementIndices.add(elementIndex);
45194471
}
45204472

4521-
swizExpr->elementIndices = _Move(elementIndices);
4522-
45234473
if (anyError)
45244474
{
4525-
getSink()->diagnose(
4526-
swizExpr,
4527-
Diagnostics::invalidSwizzleExpr,
4528-
swizzleText,
4529-
baseElementType->toString());
4530-
return CreateErrorExpr(memberRefExpr);
4475+
return nullptr;
45314476
}
4532-
else if (swizExpr->elementIndices.getCount() == 1)
4477+
4478+
SwizzleExpr* swizExpr = m_astBuilder->create<SwizzleExpr>();
4479+
swizExpr->loc = memberRefExpr->loc;
4480+
swizExpr->base = memberRefExpr->baseExpression;
4481+
swizExpr->memberOpLoc = memberRefExpr->memberOperatorLoc;
4482+
swizExpr->elementIndices = _Move(elementIndices);
4483+
4484+
if (swizExpr->elementIndices.getCount() == 1)
45334485
{
45344486
// single-component swizzle produces a scalar
45354487
//
@@ -4568,11 +4520,7 @@ Expr* SemanticsVisitor::CheckSwizzleExpr(
45684520
}
45694521
else
45704522
{
4571-
getSink()->diagnose(
4572-
memberRefExpr,
4573-
Diagnostics::unimplemented,
4574-
"swizzle on vector of unknown size");
4575-
return CreateErrorExpr(memberRefExpr);
4523+
return nullptr;
45764524
}
45774525
}
45784526

@@ -4914,6 +4862,28 @@ Expr* SemanticsVisitor::checkGeneralMemberLookupExpr(MemberExpr* expr, Type* bas
49144862
if (expr->name == getSession()->getCompletionRequestTokenName())
49154863
{
49164864
suggestCompletionItems(CompletionSuggestions::ScopeKind::Member, lookupResult);
4865+
if (expr->baseExpression)
4866+
{
4867+
if (auto vectorType = as<VectorExpressionType>(expr->baseExpression->type))
4868+
{
4869+
auto& suggestions = getLinkage()->contentAssistInfo.completionSuggestions;
4870+
suggestions.scopeKind = CompletionSuggestions::ScopeKind::Swizzle;
4871+
suggestions.elementCount[1] = 0;
4872+
suggestions.swizzleBaseType = vectorType;
4873+
if (auto elementCount = as<ConstantIntVal>(vectorType->getElementCount()))
4874+
suggestions.elementCount[0] = elementCount->getValue();
4875+
else
4876+
suggestions.elementCount[0] = 1;
4877+
}
4878+
else if (auto scalarType = as<BasicExpressionType>(expr->baseExpression->type))
4879+
{
4880+
auto& suggestions = getLinkage()->contentAssistInfo.completionSuggestions;
4881+
suggestions.scopeKind = CompletionSuggestions::ScopeKind::Swizzle;
4882+
suggestions.elementCount[1] = 0;
4883+
suggestions.elementCount[0] = 1;
4884+
suggestions.swizzleBaseType = scalarType;
4885+
}
4886+
}
49174887
}
49184888
return createLookupResultExpr(expr->name, lookupResult, expr->baseExpression, expr->loc, expr);
49194889
}
@@ -4942,34 +4912,36 @@ Expr* SemanticsExprVisitor::visitMemberExpr(MemberExpr* expr)
49424912
if (auto modifiedType = as<ModifiedType>(baseType))
49434913
baseType = modifiedType->getBase();
49444914

4945-
// Note: Checking for vector types before declaration-reference types,
4946-
// because vectors are also declaration reference types...
4915+
// Try handle swizzle-able types (scalar,vector,matrix) first.
4916+
// If checking as a swizzle failed for these types,
4917+
// we will fallback to normal member lookup.
49474918
//
4948-
// Also note: the way this is done right now means that the ability
4949-
// to swizzle vectors interferes with any chance of looking up
4950-
// members via extension, for vector or scalar types.
4951-
//
4952-
if (auto baseMatrixType = as<MatrixExpressionType>(baseType))
4919+
if (auto baseScalarType = as<BasicExpressionType>(baseType))
49534920
{
4954-
return CheckMatrixSwizzleExpr(
4955-
expr,
4956-
baseMatrixType->getElementType(),
4957-
baseMatrixType->getRowCount(),
4958-
baseMatrixType->getColumnCount());
4921+
// Treat scalar like a 1-element vector when swizzling
4922+
auto swizzle = CheckSwizzleExpr(expr, baseScalarType, 1);
4923+
if (swizzle)
4924+
return swizzle;
49594925
}
4960-
if (auto baseVecType = as<VectorExpressionType>(baseType))
4926+
else if (auto baseVecType = as<VectorExpressionType>(baseType))
49614927
{
4962-
return CheckSwizzleExpr(
4963-
expr,
4964-
baseVecType->getElementType(),
4965-
baseVecType->getElementCount());
4928+
auto swizzle =
4929+
CheckSwizzleExpr(expr, baseVecType->getElementType(), baseVecType->getElementCount());
4930+
if (swizzle)
4931+
return swizzle;
49664932
}
4967-
else if (auto baseScalarType = as<BasicExpressionType>(baseType))
4933+
else if (auto baseMatrixType = as<MatrixExpressionType>(baseType))
49684934
{
4969-
// Treat scalar like a 1-element vector when swizzling
4970-
return CheckSwizzleExpr(expr, baseScalarType, 1);
4935+
auto swizzle = CheckMatrixSwizzleExpr(
4936+
expr,
4937+
baseMatrixType->getElementType(),
4938+
baseMatrixType->getRowCount(),
4939+
baseMatrixType->getColumnCount());
4940+
if (swizzle)
4941+
return swizzle;
49714942
}
4972-
else if (as<NamespaceType>(baseType))
4943+
4944+
if (as<NamespaceType>(baseType))
49734945
{
49744946
return _lookupStaticMember(expr, expr->baseExpression);
49754947
}

source/slang/slang-check-overload.cpp

+10-8
Original file line numberDiff line numberDiff line change
@@ -1316,15 +1316,17 @@ int SemanticsVisitor::CompareLookupResultItems(
13161316
// Add a special case for constructors, where we prefer the one that is not synthesized,
13171317
if (auto leftCtor = as<ConstructorDecl>(left.declRef.getDecl()))
13181318
{
1319-
auto rightCtor = as<ConstructorDecl>(right.declRef.getDecl());
1320-
bool leftIsSynthesized =
1321-
leftCtor->containsFlavor(ConstructorDecl::ConstructorFlavor::SynthesizedDefault);
1322-
bool rightIsSynthesized =
1323-
rightCtor->containsFlavor(ConstructorDecl::ConstructorFlavor::SynthesizedDefault);
1324-
1325-
if (leftIsSynthesized != rightIsSynthesized)
1319+
if (auto rightCtor = as<ConstructorDecl>(right.declRef.getDecl()))
13261320
{
1327-
return int(leftIsSynthesized) - int(rightIsSynthesized);
1321+
bool leftIsSynthesized = leftCtor->containsFlavor(
1322+
ConstructorDecl::ConstructorFlavor::SynthesizedDefault);
1323+
bool rightIsSynthesized = rightCtor->containsFlavor(
1324+
ConstructorDecl::ConstructorFlavor::SynthesizedDefault);
1325+
1326+
if (leftIsSynthesized != rightIsSynthesized)
1327+
{
1328+
return int(leftIsSynthesized) - int(rightIsSynthesized);
1329+
}
13281330
}
13291331
}
13301332

source/slang/slang-language-server-completion.cpp

+18-11
Original file line numberDiff line numberDiff line change
@@ -512,11 +512,14 @@ LanguageServerResult<CompletionResult> CompletionContext::tryCompleteMemberAndSy
512512

513513
CompletionResult CompletionContext::collectMembersAndSymbols()
514514
{
515+
List<LanguageServerProtocol::CompletionItem> result;
516+
515517
auto linkage = version->linkage;
516518
if (linkage->contentAssistInfo.completionSuggestions.scopeKind ==
517519
CompletionSuggestions::ScopeKind::Swizzle)
518520
{
519-
return createSwizzleCandidates(
521+
createSwizzleCandidates(
522+
result,
520523
linkage->contentAssistInfo.completionSuggestions.swizzleBaseType,
521524
linkage->contentAssistInfo.completionSuggestions.elementCount);
522525
}
@@ -526,12 +529,12 @@ CompletionResult CompletionContext::collectMembersAndSymbols()
526529
{
527530
return createCapabilityCandidates();
528531
}
529-
List<LanguageServerProtocol::CompletionItem> result;
530532
bool useCommitChars = true;
531533
bool addKeywords = false;
532534
switch (linkage->contentAssistInfo.completionSuggestions.scopeKind)
533535
{
534536
case CompletionSuggestions::ScopeKind::Member:
537+
case CompletionSuggestions::ScopeKind::Swizzle:
535538
useCommitChars =
536539
(commitCharacterBehavior == CommitCharacterBehavior::MembersOnly ||
537540
commitCharacterBehavior == CommitCharacterBehavior::All);
@@ -698,13 +701,12 @@ CompletionResult CompletionContext::createCapabilityCandidates()
698701
return result;
699702
}
700703

701-
CompletionResult CompletionContext::createSwizzleCandidates(
704+
void CompletionContext::createSwizzleCandidates(
705+
List<LanguageServerProtocol::CompletionItem>& result,
702706
Type* type,
703707
IntegerLiteralValue elementCount[2])
704708
{
705-
List<LanguageServerProtocol::CompletionItem> result;
706709
// Hard code members for vector and matrix types.
707-
result.clear();
708710
if (auto vectorType = as<VectorExpressionType>(type))
709711
{
710712
const char* memberNames[4] = {"x", "y", "z", "w"};
@@ -724,6 +726,17 @@ CompletionResult CompletionContext::createSwizzleCandidates(
724726
result.add(item);
725727
}
726728
}
729+
else if (auto scalarType = as<BasicExpressionType>(type))
730+
{
731+
String typeStr;
732+
typeStr = scalarType->toString();
733+
LanguageServerProtocol::CompletionItem item;
734+
item.data = 0;
735+
item.detail = typeStr;
736+
item.kind = LanguageServerProtocol::kCompletionItemKindVariable;
737+
item.label = "x";
738+
result.add(item);
739+
}
727740
else if (auto matrixType = as<MatrixExpressionType>(type))
728741
{
729742
Type* elementType = nullptr;
@@ -769,12 +782,6 @@ CompletionResult CompletionContext::createSwizzleCandidates(
769782
result.add(item);
770783
}
771784
}
772-
for (auto& item : result)
773-
{
774-
for (auto ch : getCommitChars())
775-
item.commitCharacters.add(ch);
776-
}
777-
return result;
778785
}
779786

780787
LanguageServerProtocol::CompletionItem CompletionContext::generateGUIDCompletionItem()

source/slang/slang-language-server-completion.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ struct CompletionContext
5555

5656

5757
CompletionResult collectMembersAndSymbols();
58-
CompletionResult createSwizzleCandidates(Type* baseType, IntegerLiteralValue elementCount[2]);
58+
void createSwizzleCandidates(
59+
List<LanguageServerProtocol::CompletionItem>& result,
60+
Type* type,
61+
IntegerLiteralValue elementCount[2]);
5962
CompletionResult createCapabilityCandidates();
6063
CompletionResult collectAttributes();
6164
LanguageServerProtocol::CompletionItem generateGUIDCompletionItem();

0 commit comments

Comments
 (0)