summaryrefslogtreecommitdiffstats
path: root/source/slang/syntax.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/syntax.cpp')
-rw-r--r--source/slang/syntax.cpp312
1 files changed, 243 insertions, 69 deletions
diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp
index 149e0b811..9acdadad6 100644
--- a/source/slang/syntax.cpp
+++ b/source/slang/syntax.cpp
@@ -91,6 +91,8 @@ ABSTRACT_SYNTAX_CLASS(Modifier, SyntaxNodeBase);
ABSTRACT_SYNTAX_CLASS(Expr, SyntaxNode);
ABSTRACT_SYNTAX_CLASS(Substitutions, SyntaxNode);
+ABSTRACT_SYNTAX_CLASS(GenericSubstitution, Substitutions);
+ABSTRACT_SYNTAX_CLASS(ThisTypeSubstitution, Substitutions);
#include "expr-defs.h"
#include "decl-defs.h"
@@ -98,8 +100,6 @@ ABSTRACT_SYNTAX_CLASS(Substitutions, SyntaxNode);
#include "stmt-defs.h"
#include "type-defs.h"
#include "val-defs.h"
-
-
#include "object-meta-end.h"
bool SyntaxClassBase::isSubClassOfImpl(SyntaxClassBase const& super) const
@@ -283,7 +283,7 @@ void Type::accept(IValVisitor* visitor, void* extra)
this, "PtrType").As<GenericDecl>();
auto typeDecl = genericDecl->inner;
- auto substitutions = new Substitutions();
+ auto substitutions = new GenericSubstitution();
substitutions->genericDecl = genericDecl.Ptr();
substitutions->args.Add(valueType);
@@ -414,38 +414,69 @@ void Type::accept(IValVisitor* visitor, void* extra)
// search for a substitution that might apply to us
for (auto s = subst; s; s = s->outer.Ptr())
{
- // the generic decl associated with the substitution list must be
- // the generic decl that declared this parameter
- auto genericDecl = s->genericDecl;
- if (genericDecl != genericTypeParamDecl->ParentDecl)
- continue;
-
- int index = 0;
- for (auto m : genericDecl->Members)
+ if (auto genericSubst = dynamic_cast<GenericSubstitution*>(s))
{
- if (m.Ptr() == genericTypeParamDecl)
- {
- // We've found it, so return the corresponding specialization argument
- (*ioDiff)++;
- return s->args[index];
- }
- else if(auto typeParam = m.As<GenericTypeParamDecl>())
- {
- index++;
- }
- else if(auto valParam = m.As<GenericValueParamDecl>())
+ // the generic decl associated with the substitution list must be
+ // the generic decl that declared this parameter
+ auto genericDecl = genericSubst->genericDecl;
+ if (genericDecl != genericTypeParamDecl->ParentDecl)
+ continue;
+
+ int index = 0;
+ for (auto m : genericDecl->Members)
{
- index++;
+ if (m.Ptr() == genericTypeParamDecl)
+ {
+ // We've found it, so return the corresponding specialization argument
+ (*ioDiff)++;
+ return genericSubst->args[index];
+ }
+ else if (auto typeParam = m.As<GenericTypeParamDecl>())
+ {
+ index++;
+ }
+ else if (auto valParam = m.As<GenericValueParamDecl>())
+ {
+ index++;
+ }
+ else
+ {
+ }
}
- else
+ }
+
+ }
+ }
+ // the second case we care about is when this decl type refers to an associatedtype decl
+ // 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)
+ {
+ if (auto aggTypeDeclRef = thisTypeSubst->sourceType.As<DeclRefType>()->declRef.As<AggTypeDecl>())
{
+ Decl * targetType = nullptr;
+ if (aggTypeDeclRef.getDecl()->memberDictionary.TryGetValue(assocTypeDecl->getName(), targetType))
+ {
+ if (auto typeDefDecl = dynamic_cast<TypeDefDecl*>(targetType))
+ return typeDefDecl->type.type;
+ else
+ return DeclRefType::Create(getSession(), DeclRef<Decl>(targetType, aggTypeDeclRef.substitutions));
+ }
}
}
-
}
}
-
-
int diff = 0;
DeclRef<Decl> substDeclRef = declRef.SubstituteImpl(subst, &diff);
@@ -486,10 +517,25 @@ void Type::accept(IValVisitor* visitor, void* extra)
// we will construct a default specialization at the use
// site if needed.
- if( auto genericParent = declRef.GetParent().As<GenericDecl>() )
+ if (auto genericParent = declRef.GetParent().As<GenericDecl>())
{
auto subst = declRef.substitutions;
- if( !subst || subst->genericDecl != genericParent.decl )
+ // try find a substitution targeting this generic decl
+ bool substFound = false;
+ while (subst)
+ {
+ if (auto genSubst = dynamic_cast<GenericSubstitution*>(subst.Ptr()))
+ {
+ if (genSubst->genericDecl == genericParent.decl)
+ {
+ substFound = true;
+ break;
+ }
+ }
+ subst = subst->outer;
+ }
+ // we did not find an existing substituion, create a default one
+ if (!substFound)
{
declRef.substitutions = createDefaultSubstitutions(
session,
@@ -507,7 +553,7 @@ void Type::accept(IValVisitor* visitor, void* extra)
}
else if (auto magicMod = declRef.getDecl()->FindModifier<MagicTypeModifier>())
{
- Substitutions* subst = declRef.substitutions.Ptr();
+ GenericSubstitution* subst = declRef.substitutions.As<GenericSubstitution>().Ptr();
if (magicMod->name == "SamplerState")
{
@@ -972,24 +1018,24 @@ void Type::accept(IValVisitor* visitor, void* extra)
Type* MatrixExpressionType::getElementType()
{
- return this->declRef.substitutions->args[0].As<Type>().Ptr();
+ return this->declRef.substitutions.As<GenericSubstitution>()->args[0].As<Type>().Ptr();
}
IntVal* MatrixExpressionType::getRowCount()
{
- return this->declRef.substitutions->args[1].As<IntVal>().Ptr();
+ return this->declRef.substitutions.As<GenericSubstitution>()->args[1].As<IntVal>().Ptr();
}
IntVal* MatrixExpressionType::getColumnCount()
{
- return this->declRef.substitutions->args[2].As<IntVal>().Ptr();
+ return this->declRef.substitutions.As<GenericSubstitution>()->args[2].As<IntVal>().Ptr();
}
// PtrTypeBase
Type* PtrTypeBase::getValueType()
{
- return this->declRef.substitutions->args[0].As<Type>().Ptr();
+ return this->declRef.substitutions.As<GenericSubstitution>()->args[0].As<Type>().Ptr();
}
// GenericParamIntVal
@@ -1018,31 +1064,34 @@ void Type::accept(IValVisitor* visitor, void* extra)
// search for a substitution that might apply to us
for (auto s = subst; s; s = s->outer.Ptr())
{
- // the generic decl associated with the substitution list must be
- // the generic decl that declared this parameter
- auto genericDecl = s->genericDecl;
- if (genericDecl != declRef.getDecl()->ParentDecl)
- continue;
-
- int index = 0;
- for (auto m : genericDecl->Members)
+ if (auto genSubst = dynamic_cast<GenericSubstitution*>(s))
{
- if (m.Ptr() == declRef.getDecl())
- {
- // We've found it, so return the corresponding specialization argument
- (*ioDiff)++;
- return s->args[index];
- }
- else if(auto typeParam = m.As<GenericTypeParamDecl>())
- {
- index++;
- }
- else if(auto valParam = m.As<GenericValueParamDecl>())
- {
- index++;
- }
- else
+ // the generic decl associated with the substitution list must be
+ // the generic decl that declared this parameter
+ auto genericDecl = genSubst->genericDecl;
+ if (genericDecl != declRef.getDecl()->ParentDecl)
+ continue;
+
+ int index = 0;
+ for (auto m : genericDecl->Members)
{
+ if (m.Ptr() == declRef.getDecl())
+ {
+ // We've found it, so return the corresponding specialization argument
+ (*ioDiff)++;
+ return genSubst->args[index];
+ }
+ else if (auto typeParam = m.As<GenericTypeParamDecl>())
+ {
+ index++;
+ }
+ else if (auto valParam = m.As<GenericValueParamDecl>())
+ {
+ index++;
+ }
+ else
+ {
+ }
}
}
}
@@ -1053,12 +1102,12 @@ void Type::accept(IValVisitor* visitor, void* extra)
// Substitutions
- RefPtr<Substitutions> Substitutions::SubstituteImpl(Substitutions* subst, int* ioDiff)
+ RefPtr<Substitutions> GenericSubstitution::SubstituteImpl(Substitutions* subst, int* ioDiff)
{
if (!this) return nullptr;
int diff = 0;
- auto outerSubst = outer->SubstituteImpl(subst, &diff);
+ auto outerSubst = outer ? outer->SubstituteImpl(subst, &diff) : nullptr;
List<RefPtr<Val>> substArgs;
for (auto a : args)
@@ -1069,35 +1118,85 @@ void Type::accept(IValVisitor* visitor, void* extra)
if (!diff) return this;
(*ioDiff)++;
- auto substSubst = new Substitutions();
+ auto substSubst = new GenericSubstitution();
substSubst->genericDecl = genericDecl;
substSubst->args = substArgs;
return substSubst;
}
- bool Substitutions::Equals(Substitutions* subst)
+ bool GenericSubstitution::Equals(Substitutions* subst)
{
// both must be NULL, or non-NULL
if (!this || !subst)
return !this && !subst;
-
- if (genericDecl != subst->genericDecl)
+ auto genericSubst = dynamic_cast<GenericSubstitution*>(subst);
+ if (!genericSubst)
+ return false;
+ if (genericDecl != genericSubst->genericDecl)
return false;
UInt argCount = args.Count();
- SLANG_RELEASE_ASSERT(args.Count() == subst->args.Count());
+ SLANG_RELEASE_ASSERT(args.Count() == genericSubst->args.Count());
for (UInt aa = 0; aa < argCount; ++aa)
{
- if (!args[aa]->EqualsVal(subst->args[aa].Ptr()))
+ if (!args[aa]->EqualsVal(genericSubst->args[aa].Ptr()))
return false;
}
+ if (!outer)
+ return !subst->outer || subst->outer.As<ThisTypeSubstitution>();
+
if (!outer->Equals(subst->outer.Ptr()))
return false;
return true;
}
+ RefPtr<Substitutions> ThisTypeSubstitution::SubstituteImpl(Substitutions* subst, int* ioDiff)
+ {
+ if (!this) return nullptr;
+
+ int diff = 0;
+ RefPtr<Substitutions> outerSubst;
+ if (outer)
+ outerSubst = outer->SubstituteImpl(subst, &diff);
+ RefPtr<Val> newSourceType;
+ if (sourceType)
+ newSourceType = sourceType->SubstituteImpl(subst, &diff);
+ else
+ {
+ // this_type is a free variable, use this_type from subst
+ auto psubst = subst;
+ while (psubst)
+ {
+ if (auto pthisSubst = dynamic_cast<ThisTypeSubstitution*>(subst))
+ {
+ diff++;
+ newSourceType = pthisSubst->sourceType;
+ break;
+ }
+ psubst = psubst->outer;
+ }
+ }
+ if (!diff) return this;
+
+ (*ioDiff)++;
+ auto substSubst = new ThisTypeSubstitution();
+ substSubst->sourceType = newSourceType;
+ substSubst->outer = outerSubst;
+ return substSubst;
+ }
+
+ bool ThisTypeSubstitution::Equals(Substitutions* subst)
+ {
+ if (!subst)
+ return true;
+ if (subst && dynamic_cast<ThisTypeSubstitution*>(subst))
+ return true;
+ return false;
+ }
+
+
// DeclRefBase
@@ -1158,7 +1257,8 @@ void Type::accept(IValVisitor* visitor, void* extra)
{
if (decl != declRef.decl)
return false;
-
+ if (!substitutions)
+ return !declRef.substitutions || declRef.substitutions.As<ThisTypeSubstitution>();
if (!substitutions->Equals(declRef.substitutions.Ptr()))
return false;
@@ -1179,7 +1279,8 @@ void Type::accept(IValVisitor* visitor, void* extra)
if (auto parentGeneric = dynamic_cast<GenericDecl*>(parentDecl))
{
- if (substitutions && substitutions->genericDecl == parentDecl)
+ auto genSubst = substitutions.As<GenericSubstitution>();
+ if (genSubst && genSubst->genericDecl == parentDecl)
{
// We strip away the specializations that were applied to
// the parent, since we were asked for a reference *to* the parent.
@@ -1318,12 +1419,12 @@ void Type::accept(IValVisitor* visitor, void* extra)
Type* HLSLPatchType::getElementType()
{
- return this->declRef.substitutions->args[0].As<Type>().Ptr();
+ return this->declRef.substitutions.As<GenericSubstitution>()->args[0].As<Type>().Ptr();
}
IntVal* HLSLPatchType::getElementCount()
{
- return this->declRef.substitutions->args[1].As<IntVal>().Ptr();
+ return this->declRef.substitutions.As<GenericSubstitution>()->args[1].As<IntVal>().Ptr();
}
// Constructors for types
@@ -1469,4 +1570,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;
+ }
+
}