summaryrefslogtreecommitdiff
path: root/source/slang/slang-check-decl.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2023-10-25 07:50:14 -0700
committerGitHub <noreply@github.com>2023-10-25 22:50:14 +0800
commit5dc3c2f57963de93ad03724a01ea48b8585dc15a (patch)
tree072748b952eb03da7950110ed3a8f87da9b5e72f /source/slang/slang-check-decl.cpp
parentf8bf75cf1ae0aeee155996a917c2925bc500f3e2 (diff)
Add `IArray`. (#3281)
* Initial support for generic interfaces. * Cleanup. * Add generic syntax for interfaces. * Add `IArray`. * Fix. * Fix. * Fix. --------- Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source/slang/slang-check-decl.cpp')
-rw-r--r--source/slang/slang-check-decl.cpp92
1 files changed, 92 insertions, 0 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 8df5ae618..f75f84e21 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -2058,6 +2058,90 @@ namespace Slang
return true;
}
+ bool SemanticsVisitor::doesSubscriptMatchRequirement(
+ DeclRef<SubscriptDecl> satisfyingMemberDeclRef,
+ DeclRef<SubscriptDecl> requiredMemberDeclRef,
+ RefPtr<WitnessTable> witnessTable)
+ {
+ // The result type and parameters of the satisfying member must match the type of the required member.
+ //
+ auto requiredParams = getParameters(m_astBuilder, requiredMemberDeclRef).toArray();
+ auto satisfyingParams = getParameters(m_astBuilder, satisfyingMemberDeclRef).toArray();
+ auto paramCount = requiredParams.getCount();
+ if (satisfyingParams.getCount() != paramCount)
+ return false;
+
+ for (Index paramIndex = 0; paramIndex < paramCount; ++paramIndex)
+ {
+ auto requiredParam = requiredParams[paramIndex];
+ auto satisfyingParam = satisfyingParams[paramIndex];
+
+ auto requiredParamType = getType(m_astBuilder, requiredParam);
+ auto satisfyingParamType = getType(m_astBuilder, satisfyingParam);
+
+ if (!requiredParamType->equals(satisfyingParamType))
+ return false;
+ }
+
+ auto requiredResultType = getResultType(m_astBuilder, requiredMemberDeclRef);
+ auto satisfyingResultType = getResultType(m_astBuilder, satisfyingMemberDeclRef);
+ if (!requiredResultType->equals(satisfyingResultType))
+ return false;
+
+ // Each accessor in the requirement must be accounted for by an accessor
+ // in the satisfying member.
+ //
+ // Note: it is fine for the satisfying member to provide *more* accessors
+ // than the original declaration.
+ //
+ Dictionary<DeclRef<AccessorDecl>, DeclRef<AccessorDecl>> mapRequiredToSatisfyingAccessorDeclRef;
+ for (auto requiredAccessorDeclRef : getMembersOfType<AccessorDecl>(m_astBuilder, requiredMemberDeclRef))
+ {
+ // We need to search for an accessor that can satisfy the requirement.
+ //
+ // For now we will do the simplest (and slowest) thing of a linear search,
+ // which is mostly fine because the number of accessors is bounded.
+ //
+ bool found = false;
+ for (auto satisfyingAccessorDeclRef : getMembersOfType<AccessorDecl>(m_astBuilder, satisfyingMemberDeclRef))
+ {
+ if (doesAccessorMatchRequirement(satisfyingAccessorDeclRef, requiredAccessorDeclRef))
+ {
+ // When we find a match on an accessor, we record it so that
+ // we can set up the witness values later, but we do *not*
+ // record it into the actual witness table yet, in case
+ // a later accessor comes along that doesn't find a match.
+ //
+ mapRequiredToSatisfyingAccessorDeclRef.add(requiredAccessorDeclRef, satisfyingAccessorDeclRef);
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return false;
+ }
+
+ // Once things are done, we will install the satisfying values
+ // into the witness table for the requirements.
+ //
+ for (const auto& [key, value] : mapRequiredToSatisfyingAccessorDeclRef)
+ {
+ witnessTable->add(
+ key.getDecl(),
+ RequirementWitness(value));
+ }
+ //
+ // Note: the subscript declaration itself isn't something that
+ // has a useful value/representation in downstream passes, so
+ // we are mostly just installing it into the witness table
+ // as a way to mark this requirement as being satisfied.
+ //
+ witnessTable->add(
+ requiredMemberDeclRef.getDecl(),
+ RequirementWitness(satisfyingMemberDeclRef));
+ return true;
+ }
+
bool SemanticsVisitor::doesVarMatchRequirement(
DeclRef<VarDeclBase> satisfyingMemberDeclRef,
DeclRef<VarDeclBase> requiredMemberDeclRef,
@@ -2514,6 +2598,14 @@ namespace Slang
return doesVarMatchRequirement(varDeclRef, requiredVarDeclRef, witnessTable);
}
}
+ else if (auto subscriptDeclRef = memberDeclRef.as<SubscriptDecl>())
+ {
+ if (auto requiredSubscriptDeclRef = requiredMemberDeclRef.as<SubscriptDecl>())
+ {
+ ensureDecl(subscriptDeclRef, DeclCheckState::CanUseFuncSignature);
+ return doesSubscriptMatchRequirement(subscriptDeclRef, requiredSubscriptDeclRef, witnessTable);
+ }
+ }
// Default: just assume that thing aren't being satisfied.
return false;
}