From 8daafcc2e4bf7b2dfb66d7a3b7ac60c86b2d926c Mon Sep 17 00:00:00 2001 From: Yong He Date: Tue, 9 Jan 2018 10:50:44 -0800 Subject: bruteforce implementation of witness table resolution for associated (#358) --- source/slang/syntax.cpp | 80 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 5 deletions(-) (limited to 'source/slang/syntax.cpp') diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index cdc112846..4f043e0a1 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -1275,8 +1275,12 @@ void Type::accept(IValVisitor* visitor, void* extra) { if (!subst) return true; - if (subst && dynamic_cast(subst)) - return true; + if (auto thisTypeSubst = dynamic_cast(subst)) + { + if (!sourceType || !thisTypeSubst->sourceType) + return true; + return sourceType->EqualsVal(thisTypeSubst->sourceType); + } return false; } @@ -1405,19 +1409,48 @@ void Type::accept(IValVisitor* visitor, void* extra) *ioDiff += diff; } + void buildMemberDictionary(ContainerDecl* decl); + DeclRefBase DeclRefBase::SubstituteImpl(Substitutions* subst, int* ioDiff) { int diff = 0; RefPtr substSubst = substituteSubstitutions(substitutions, subst, &diff); - if (!diff) - return *this; + return *this; *ioDiff += diff; DeclRefBase substDeclRef; substDeclRef.decl = decl; substDeclRef.substitutions = substSubst; + + // if this is a AssocTypeDecl, try lookup the actual associated type + if (auto assocTypeDecl = substDeclRef.decl->As()) + { + auto thisSubst = getThisTypeSubst(substDeclRef, false); + if (thisSubst) + { + if (auto declRefType = thisSubst->sourceType.As()) + { + if (auto aggDeclRef = declRefType->declRef.As()) + { + Decl* subTypeDecl = nullptr; + buildMemberDictionary(aggDeclRef.getDecl()); + SLANG_ASSERT(aggDeclRef.getDecl()->memberDictionaryIsValid); + aggDeclRef.getDecl()->memberDictionary.TryGetValue(assocTypeDecl->getName(), subTypeDecl); + if (auto typeDefDecl = subTypeDecl->As()) + { + auto t = GetType(DeclRef(typeDefDecl, aggDeclRef.substitutions)); + auto canonicalType = t->GetCanonicalType()->AsDeclRefType(); + SLANG_ASSERT(canonicalType); + return canonicalType->declRef; + } + SLANG_ASSERT(subTypeDecl); + return DeclRefBase(subTypeDecl, aggDeclRef.substitutions); + } + } + } + } return substDeclRef; } @@ -1428,7 +1461,7 @@ void Type::accept(IValVisitor* visitor, void* extra) if (decl != declRef.decl) return false; if (!substitutions) - return !declRef.substitutions || declRef.substitutions.As(); + return !hasGenericSubstitutions(declRef.substitutions); if (!substitutions->Equals(declRef.substitutions.Ptr())) return false; @@ -1903,6 +1936,17 @@ void Type::accept(IValVisitor* visitor, void* extra) declRef.substitutions = substToInsert; } + ThisTypeSubstitution* findThisTypeSubst(Substitutions* subst) + { + while (subst) + { + if (auto thisSubst = dynamic_cast(subst)) + return thisSubst; + subst = subst->outer.Ptr(); + } + return nullptr; + } + RefPtr getThisTypeSubst(DeclRefBase & declRef, bool insertSubstEntry) { RefPtr thisSubst; @@ -1958,6 +2002,18 @@ void Type::accept(IValVisitor* visitor, void* extra) } } + bool hasThisTypeSubstitutions(RefPtr subst) + { + auto p = subst.Ptr(); + while (p) + { + if (dynamic_cast(p)) + return true; + p = p->outer.Ptr(); + } + return false; + } + bool hasGenericSubstitutions(RefPtr subst) { auto p = subst.Ptr(); @@ -1987,8 +2043,22 @@ void Type::accept(IValVisitor* visitor, void* extra) if (oldSubst) oldSubst = oldSubst->SubstituteImpl(subst, ioDiff); + // if oldSubst does not have ThisTypeSubst (which means `this_type` is free variable) + // and subst has a ThisTypeSubst (which means `this_type` is bound to a type), + // then copy that ThisTypeSubst over (to bind the this_type to the specified type) RefPtr newSubst = oldSubst; insertGlobalGenericSubstitutions(newSubst, subst, ioDiff); + /*if (!hasThisTypeSubstitutions(oldSubst)) + { + auto thisTypeSubst = findThisTypeSubst(subst); + if (thisTypeSubst) + { + auto cpyThisTypeSubst = new ThisTypeSubstitution(); + cpyThisTypeSubst->sourceType = thisTypeSubst->sourceType; + insertSubstAtBottom(newSubst, cpyThisTypeSubst); + *ioDiff = 1; + } + }*/ return newSubst; } } -- cgit v1.2.3