From 5dc3c2f57963de93ad03724a01ea48b8585dc15a Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 25 Oct 2023 07:50:14 -0700 Subject: Add `IArray`. (#3281) * Initial support for generic interfaces. * Cleanup. * Add generic syntax for interfaces. * Add `IArray`. * Fix. * Fix. * Fix. --------- Co-authored-by: Yong He --- source/slang/slang-check-decl.cpp | 92 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) (limited to 'source/slang/slang-check-decl.cpp') 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 satisfyingMemberDeclRef, + DeclRef requiredMemberDeclRef, + RefPtr 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> mapRequiredToSatisfyingAccessorDeclRef; + for (auto requiredAccessorDeclRef : getMembersOfType(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(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 satisfyingMemberDeclRef, DeclRef requiredMemberDeclRef, @@ -2514,6 +2598,14 @@ namespace Slang return doesVarMatchRequirement(varDeclRef, requiredVarDeclRef, witnessTable); } } + else if (auto subscriptDeclRef = memberDeclRef.as()) + { + if (auto requiredSubscriptDeclRef = requiredMemberDeclRef.as()) + { + ensureDecl(subscriptDeclRef, DeclCheckState::CanUseFuncSignature); + return doesSubscriptMatchRequirement(subscriptDeclRef, requiredSubscriptDeclRef, witnessTable); + } + } // Default: just assume that thing aren't being satisfied. return false; } -- cgit v1.2.3