diff options
| author | Yong He <yonghe@outlook.com> | 2017-11-04 15:20:21 -0400 |
|---|---|---|
| committer | Yong He <yonghe@outlook.com> | 2017-11-04 15:20:21 -0400 |
| commit | 31e7f84484d227206f3bbb33a8b9be8a9acecfe5 (patch) | |
| tree | eb06912348d3fd39a671308d80db999d144ae024 /source/slang/syntax.cpp | |
| parent | d803bf74eee7842ce8a358e145b2546c03308dfc (diff) | |
Passing both assoctype-simple and assoctype-complex test cases.
Diffstat (limited to 'source/slang/syntax.cpp')
| -rw-r--r-- | source/slang/syntax.cpp | 84 |
1 files changed, 83 insertions, 1 deletions
diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index 24d508ed5..161f9cc26 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -530,7 +530,14 @@ void Type::accept(IValVisitor* visitor, void* extra) // we want to replace it with the actual associated type else if (auto assocTypeDecl = dynamic_cast<AssocTypeDecl*>(declRef.getDecl())) { + auto thisSubst = getThisTypeSubst(declRef, false); + auto oldSubstSrc = thisSubst ? thisSubst->sourceType : nullptr; + bool restore = false; + if (thisSubst && thisSubst->sourceType.Ptr() == dynamic_cast<Val*>(this)) + thisSubst->sourceType = nullptr; auto newSubst = declRef.substitutions->SubstituteImpl(subst, ioDiff); + if (restore) + thisSubst->sourceType = oldSubstSrc; if (auto thisTypeSubst = newSubst.As<ThisTypeSubstitution>()) { if (thisTypeSubst->sourceType) @@ -1258,6 +1265,8 @@ void Type::accept(IValVisitor* visitor, void* extra) bool ThisTypeSubstitution::Equals(Substitutions* subst) { + if (!subst) + return true; if (subst && dynamic_cast<ThisTypeSubstitution*>(subst)) return true; return false; @@ -1323,7 +1332,7 @@ void Type::accept(IValVisitor* visitor, void* extra) if (decl != declRef.decl) return false; if (!substitutions) - return !declRef.substitutions; + return !declRef.substitutions || declRef.substitutions.As<ThisTypeSubstitution>(); if (!substitutions->Equals(declRef.substitutions.Ptr())) return false; @@ -1634,4 +1643,77 @@ void Type::accept(IValVisitor* visitor, void* extra) + void insertSubstAtTop(DeclRefBase & declRef, RefPtr<Substitutions> substToInsert) + { + substToInsert->outer = declRef.substitutions; + declRef.substitutions = substToInsert; + } + + RefPtr<ThisTypeSubstitution> getThisTypeSubst(DeclRefBase & declRef, bool insertSubstEntry) + { + RefPtr<ThisTypeSubstitution> thisSubst; + auto subst = declRef.substitutions; + while (subst) + { + if (auto s = subst.As<ThisTypeSubstitution>()) + { + thisSubst = s; + break; + } + subst = subst->outer; + } + if (!thisSubst) + { + thisSubst = new ThisTypeSubstitution(); + if (insertSubstEntry) + { + insertSubstAtTop(declRef, thisSubst); + } + } + return thisSubst; + } + + RefPtr<ThisTypeSubstitution> getNewThisTypeSubst(DeclRefBase & declRef) + { + auto oldSubst = getThisTypeSubst(declRef, false); + if (oldSubst) + removeSubstitution(declRef, oldSubst); + return getThisTypeSubst(declRef, true); + } + + void removeSubstitution(DeclRefBase & declRef, RefPtr<Substitutions> toRemove) + { + if (!declRef.substitutions) + return; + if (toRemove == declRef.substitutions) + { + declRef.substitutions = declRef.substitutions->outer; + return; + } + auto prev = declRef.substitutions; + auto subst = prev->outer; + while (subst) + { + if (subst == toRemove) + { + prev->outer = subst->outer; + break; + } + prev = subst; + subst = subst->outer; + } + } + + bool hasGenericSubstitutions(RefPtr<Substitutions> subst) + { + auto p = subst.Ptr(); + while (p) + { + if (dynamic_cast<GenericSubstitution*>(p)) + return true; + p = p->outer.Ptr(); + } + return false; + } + } |
