diff options
| author | Yong He <yonghe@outlook.com> | 2017-11-24 11:55:54 -0500 |
|---|---|---|
| committer | Tim Foley <tfoleyNV@users.noreply.github.com> | 2017-11-24 08:55:54 -0800 |
| commit | 109ee8aae399042fba6ea71e43e5ee2d441288dd (patch) | |
| tree | 3ece48c6b575f14500666d9f808022eda846a517 /source/slang/syntax.cpp | |
| parent | 83d49ce376185f7dc3f40eb531f01ee350220959 (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.cpp | 57 |
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() |
