diff options
| author | Yong He <yonghe@outlook.com> | 2023-10-25 07:50:14 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-10-25 22:50:14 +0800 |
| commit | 5dc3c2f57963de93ad03724a01ea48b8585dc15a (patch) | |
| tree | 072748b952eb03da7950110ed3a8f87da9b5e72f /source/slang/slang-check-decl.cpp | |
| parent | f8bf75cf1ae0aeee155996a917c2925bc500f3e2 (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.cpp | 92 |
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; } |
