From 31e7f84484d227206f3bbb33a8b9be8a9acecfe5 Mon Sep 17 00:00:00 2001 From: Yong He Date: Sat, 4 Nov 2017 15:20:21 -0400 Subject: Passing both assoctype-simple and assoctype-complex test cases. --- source/slang/syntax.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) (limited to 'source/slang/syntax.cpp') 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(declRef.getDecl())) { + auto thisSubst = getThisTypeSubst(declRef, false); + auto oldSubstSrc = thisSubst ? thisSubst->sourceType : nullptr; + bool restore = false; + if (thisSubst && thisSubst->sourceType.Ptr() == dynamic_cast(this)) + thisSubst->sourceType = nullptr; auto newSubst = declRef.substitutions->SubstituteImpl(subst, ioDiff); + if (restore) + thisSubst->sourceType = oldSubstSrc; if (auto thisTypeSubst = newSubst.As()) { 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(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(); if (!substitutions->Equals(declRef.substitutions.Ptr())) return false; @@ -1634,4 +1643,77 @@ void Type::accept(IValVisitor* visitor, void* extra) + void insertSubstAtTop(DeclRefBase & declRef, RefPtr substToInsert) + { + substToInsert->outer = declRef.substitutions; + declRef.substitutions = substToInsert; + } + + RefPtr getThisTypeSubst(DeclRefBase & declRef, bool insertSubstEntry) + { + RefPtr thisSubst; + auto subst = declRef.substitutions; + while (subst) + { + if (auto s = subst.As()) + { + thisSubst = s; + break; + } + subst = subst->outer; + } + if (!thisSubst) + { + thisSubst = new ThisTypeSubstitution(); + if (insertSubstEntry) + { + insertSubstAtTop(declRef, thisSubst); + } + } + return thisSubst; + } + + RefPtr getNewThisTypeSubst(DeclRefBase & declRef) + { + auto oldSubst = getThisTypeSubst(declRef, false); + if (oldSubst) + removeSubstitution(declRef, oldSubst); + return getThisTypeSubst(declRef, true); + } + + void removeSubstitution(DeclRefBase & declRef, RefPtr 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 subst) + { + auto p = subst.Ptr(); + while (p) + { + if (dynamic_cast(p)) + return true; + p = p->outer.Ptr(); + } + return false; + } + } -- cgit v1.2.3