summaryrefslogtreecommitdiffstats
path: root/source/slang/syntax.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2017-11-04 15:20:21 -0400
committerYong He <yonghe@outlook.com>2017-11-04 15:20:21 -0400
commit31e7f84484d227206f3bbb33a8b9be8a9acecfe5 (patch)
treeeb06912348d3fd39a671308d80db999d144ae024 /source/slang/syntax.cpp
parentd803bf74eee7842ce8a358e145b2546c03308dfc (diff)
Passing both assoctype-simple and assoctype-complex test cases.
Diffstat (limited to 'source/slang/syntax.cpp')
-rw-r--r--source/slang/syntax.cpp84
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;
+ }
+
}