summaryrefslogtreecommitdiffstats
path: root/source/slang/syntax.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2017-11-24 11:55:54 -0500
committerTim Foley <tfoleyNV@users.noreply.github.com>2017-11-24 08:55:54 -0800
commit109ee8aae399042fba6ea71e43e5ee2d441288dd (patch)
tree3ece48c6b575f14500666d9f808022eda846a517 /source/slang/syntax.cpp
parent83d49ce376185f7dc3f40eb531f01ee350220959 (diff)
Fix substitution mechanism to remove special cases for global params (#297)
Add a new function: `substituteSubstitutions(Substitutions * substHead, Substitutions subst, int * ioDiff)` This function substitutes the type arguments referenced in a linked list of substitutions headed at `substHead` using the substitutions specified by `subst`. If the linked list `substHead` does not contain `GlobalGenericParamSubstitution` entries, they will be added to the bottom (outter most) of the linked list. Note that this function should be called when `substHead` is known to be the head of substitution linked list because the existance of `GlobalGenericPaaramSubstitution` is detected assuming the linked lists starts at `substHead`. If a substitution that is not the head of a substitution linked list is passed in, duplicate `GlobalGenericParamSubstitution`s could be appended to the linked list. This means that this function should *not* be called in places like `GenericSubstitution::SubstitutionImpl()` for its outer substitutions, because `outer` is obviously not the head of the linked list. Instead, use this function to substitution the substitution lists of `DeclRef` etc. instead of calling `declRef.substitutions->SubstituteImpl()` where the head to the linked list is known as a member of that class. With this function, IRSpecContext::maybeCloneType() is simplified down to `originalType->Substitute(subst)` Updates `DeclRefBase::SubstituteImpl` and `DeclRefType::SubstituteImpl` to call `substituteSubstitutions` instead of making direct `substitutions->SubstituteImpl` call. Providing actual implementation of `GlobalGenericParamSubstitution::SubstituteImpl` instead of just returning `this` to deal with potential situations where a true substitution is needed.
Diffstat (limited to 'source/slang/syntax.cpp')
-rw-r--r--source/slang/syntax.cpp57
1 files changed, 46 insertions, 11 deletions
diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp
index 2c214a332..f8237359d 100644
--- a/source/slang/syntax.cpp
+++ b/source/slang/syntax.cpp
@@ -489,7 +489,7 @@ void Type::accept(IValVisitor* visitor, void* extra)
bool restore = false;
if (thisSubst && thisSubst->sourceType.Ptr() == dynamic_cast<Val*>(this))
thisSubst->sourceType = nullptr;
- auto newSubst = declRef.substitutions->SubstituteImpl(subst, ioDiff);
+ auto newSubst = substituteSubstitutions(declRef.substitutions, subst, ioDiff);
if (restore)
thisSubst->sourceType = oldSubstSrc;
if (auto thisTypeSubst = newSubst.As<ThisTypeSubstitution>())
@@ -1205,9 +1205,7 @@ void Type::accept(IValVisitor* visitor, void* extra)
if (!this) return nullptr;
int diff = 0;
- RefPtr<Substitutions> outerSubst;
- if (outer)
- outerSubst = outer->SubstituteImpl(subst, &diff);
+ RefPtr<Substitutions> outerSubst = outer ? outer->SubstituteImpl(subst, &diff) : nullptr;
RefPtr<Val> newSourceType;
if (sourceType)
newSourceType = sourceType->SubstituteImpl(subst, &diff);
@@ -1244,9 +1242,36 @@ void Type::accept(IValVisitor* visitor, void* extra)
return false;
}
- RefPtr<Substitutions> GlobalGenericParamSubstitution::SubstituteImpl(Substitutions* /*subst*/, int* /*ioDiff*/)
+ RefPtr<Substitutions> GlobalGenericParamSubstitution::SubstituteImpl(Substitutions* subst, int* ioDiff)
{
- // we will never replace values for this type of substitution
+ // if we find a GlobalGenericParamSubstitution in subst that references the same __generic_param decl
+ // return a copy of that GlobalGenericParamSubstitution
+ int diff = 0;
+ RefPtr<Substitutions> outerSubst = outer ? outer->SubstituteImpl(subst, &diff) : nullptr;
+ while (subst)
+ {
+ if (auto gSubst = dynamic_cast<GlobalGenericParamSubstitution*>(subst))
+ {
+ if (gSubst->paramDecl == paramDecl)
+ {
+ // substitute only if we are really different
+ if (!gSubst->actualType->EqualsVal(actualType))
+ {
+ RefPtr<GlobalGenericParamSubstitution> rs = new GlobalGenericParamSubstitution(*gSubst);
+ rs->outer = outerSubst;
+ return rs;
+ }
+ }
+ }
+ subst = subst->outer;
+ }
+ if (diff)
+ {
+ *ioDiff++;
+ RefPtr<GlobalGenericParamSubstitution> rs = new GlobalGenericParamSubstitution(*this);
+ rs->outer = outerSubst;
+ return rs;
+ }
return this;
}
@@ -1322,8 +1347,9 @@ void Type::accept(IValVisitor* visitor, void* extra)
}
return false;
}
- void insertGlobalGenericSubstitutions(RefPtr<Substitutions> & destSubst, Substitutions * srcSubst)
+ void insertGlobalGenericSubstitutions(RefPtr<Substitutions> & destSubst, Substitutions * srcSubst, int * ioDiff)
{
+ int diff = 0;
while (srcSubst)
{
if (auto globalGenSubst = dynamic_cast<GlobalGenericParamSubstitution*>(srcSubst))
@@ -1333,19 +1359,18 @@ void Type::accept(IValVisitor* visitor, void* extra)
RefPtr<GlobalGenericParamSubstitution> cpyGlobalGenSubst = new GlobalGenericParamSubstitution(*globalGenSubst);
cpyGlobalGenSubst->outer = nullptr;
insertSubstAtBottom(destSubst, cpyGlobalGenSubst);
+ diff = 1;
}
}
srcSubst = srcSubst->outer;
}
+ *ioDiff += diff;
}
DeclRefBase DeclRefBase::SubstituteImpl(Substitutions* subst, int* ioDiff)
{
- insertGlobalGenericSubstitutions(substitutions, subst);
- if (!substitutions) return *this;
-
int diff = 0;
- RefPtr<Substitutions> substSubst = substitutions->SubstituteImpl(subst, &diff);
+ RefPtr<Substitutions> substSubst = substituteSubstitutions(substitutions, subst, &diff);
if (!diff)
return *this;
@@ -1841,6 +1866,16 @@ void Type::accept(IValVisitor* visitor, void* extra)
return nullptr;
}
+ RefPtr<Substitutions> substituteSubstitutions(RefPtr<Substitutions> oldSubst, Substitutions * subst, int * ioDiff)
+ {
+ if (oldSubst)
+ oldSubst = oldSubst->SubstituteImpl(subst, ioDiff);
+
+ RefPtr<Substitutions> newSubst = oldSubst;
+ insertGlobalGenericSubstitutions(newSubst, subst, ioDiff);
+ return newSubst;
+ }
+
// FilteredTupleType
String FilteredTupleType::ToString()