summaryrefslogtreecommitdiffstats
path: root/source/slang/syntax.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-05-31 17:20:37 -0400
committerGitHub <noreply@github.com>2019-05-31 17:20:37 -0400
commit6cbc3929a54d37bd23cb5efa8e3320ba02f78b2f (patch)
tree5a23cb47782e9e2a77762c90dd35da1005eba8d0 /source/slang/syntax.cpp
parentb81ff3ef968d1cc4e954b31a1812b3c391d17b02 (diff)
Use slang- prefix on slang compiler and core source (#973)
* Prefixing source files in source/slang with slang- * Prefix source in source/slang with slang- prefix. * Rename core source files with slang- prefix. * Update project files. * Fix problems from automatic merge.
Diffstat (limited to 'source/slang/syntax.cpp')
-rw-r--r--source/slang/syntax.cpp2865
1 files changed, 0 insertions, 2865 deletions
diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp
deleted file mode 100644
index 17c85175d..000000000
--- a/source/slang/syntax.cpp
+++ /dev/null
@@ -1,2865 +0,0 @@
-#include "syntax.h"
-
-#include "compiler.h"
-#include "visitor.h"
-
-#include <typeinfo>
-#include <assert.h>
-
-namespace Slang
-{
- // BasicExpressionType
-
- bool BasicExpressionType::EqualsImpl(Type * type)
- {
- auto basicType = dynamicCast<const BasicExpressionType>(type);
- return basicType && basicType->baseType == this->baseType;
- }
-
- RefPtr<Type> BasicExpressionType::CreateCanonicalType()
- {
- // A basic type is already canonical, in our setup
- return this;
- }
-
- // Generate dispatch logic and other definitions for all syntax classes
-#define SYNTAX_CLASS(NAME, BASE) /* empty */
-#include "object-meta-begin.h"
-
-#include "syntax-base-defs.h"
-#undef SYNTAX_CLASS
-#undef ABSTRACT_SYNTAX_CLASS
-
-#define ABSTRACT_SYNTAX_CLASS(NAME, BASE) \
- template<> \
- SyntaxClassBase::ClassInfo const SyntaxClassBase::Impl<NAME>::kClassInfo = { #NAME, &SyntaxClassBase::Impl<BASE>::kClassInfo, nullptr };
-
-#define SYNTAX_CLASS(NAME, BASE) \
- void NAME::accept(NAME::Visitor* visitor, void* extra) \
- { visitor->dispatch_##NAME(this, extra); } \
- template<> \
- void* SyntaxClassBase::Impl<NAME>::createFunc() { return new NAME(); } \
- SyntaxClass<NodeBase> NAME::getClass() { return Slang::getClass<NAME>(); } \
- template<> \
- SyntaxClassBase::ClassInfo const SyntaxClassBase::Impl<NAME>::kClassInfo = { #NAME, &SyntaxClassBase::Impl<BASE>::kClassInfo, &SyntaxClassBase::Impl<NAME>::createFunc };
-
-template<>
-SyntaxClassBase::ClassInfo const SyntaxClassBase::Impl<RefObject>::kClassInfo = { "RefObject", nullptr, nullptr };
-
-ABSTRACT_SYNTAX_CLASS(NodeBase, RefObject);
-ABSTRACT_SYNTAX_CLASS(SyntaxNodeBase, NodeBase);
-ABSTRACT_SYNTAX_CLASS(SyntaxNode, SyntaxNodeBase);
-ABSTRACT_SYNTAX_CLASS(ModifiableSyntaxNode, SyntaxNode);
-ABSTRACT_SYNTAX_CLASS(DeclBase, ModifiableSyntaxNode);
-ABSTRACT_SYNTAX_CLASS(Decl, DeclBase);
-ABSTRACT_SYNTAX_CLASS(Stmt, ModifiableSyntaxNode);
-ABSTRACT_SYNTAX_CLASS(Val, NodeBase);
-ABSTRACT_SYNTAX_CLASS(Type, Val);
-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);
-ABSTRACT_SYNTAX_CLASS(GlobalGenericParamSubstitution, Substitutions);
-
-#include "expr-defs.h"
-#include "decl-defs.h"
-#include "modifier-defs.h"
-#include "stmt-defs.h"
-#include "type-defs.h"
-#include "val-defs.h"
-#include "object-meta-end.h"
-
-bool SyntaxClassBase::isSubClassOfImpl(SyntaxClassBase const& super) const
-{
- SyntaxClassBase::ClassInfo const* info = classInfo;
- while (info)
- {
- if (info == super.classInfo)
- return true;
-
- info = info->baseClass;
- }
-
- return false;
-}
-
-void Type::accept(IValVisitor* visitor, void* extra)
-{
- accept((ITypeVisitor*)visitor, extra);
-}
-
- // TypeExp
-
- bool TypeExp::Equals(Type* other)
- {
- return type->Equals(other);
- }
-
- bool TypeExp::Equals(RefPtr<Type> other)
- {
- return type->Equals(other.Ptr());
- }
-
- // BasicExpressionType
-
- BasicExpressionType* BasicExpressionType::GetScalarType()
- {
- return this;
- }
-
- //
-
- Type::~Type()
- {
- // If the canonicalType !=nullptr AND it is not set to this (ie the canonicalType is another object)
- // then it needs to be released because it's owned by this object.
- if (canonicalType && canonicalType != this)
- {
- canonicalType->releaseReference();
- }
- }
-
- bool Type::Equals(Type * type)
- {
- return GetCanonicalType()->EqualsImpl(type->GetCanonicalType());
- }
-
- bool Type::EqualsVal(Val* val)
- {
- if (auto type = dynamicCast<Type>(val))
- return const_cast<Type*>(this)->Equals(type);
- return false;
- }
-
- RefPtr<Val> Type::SubstituteImpl(SubstitutionSet subst, int* ioDiff)
- {
- int diff = 0;
- auto canSubst = GetCanonicalType()->SubstituteImpl(subst, &diff);
-
- // If nothing changed, then don't drop any sugar that is applied
- if (!diff)
- return this;
-
- // If the canonical type changed, then we return a canonical type,
- // rather than try to re-construct any amount of sugar
- (*ioDiff)++;
- return canSubst;
- }
-
- Type* Type::GetCanonicalType()
- {
- Type* et = const_cast<Type*>(this);
- if (!et->canonicalType)
- {
- // TODO(tfoley): worry about thread safety here?
- auto canType = et->CreateCanonicalType();
- et->canonicalType = canType;
-
- // TODO(js): That this detachs when canType == this is a little surprising. It would seem
- // as if this would create a circular reference on the object, but in practice there are
- // no leaks so appears correct.
- // That the dtor only releases if != this, also makes it surprising.
- canType.detach();
-
- SLANG_ASSERT(et->canonicalType);
- }
- return et->canonicalType;
- }
-
- void Session::initializeTypes()
- {
- errorType = new ErrorType();
- errorType->setSession(this);
-
- initializerListType = new InitializerListType();
- initializerListType->setSession(this);
-
- overloadedType = new OverloadGroupType();
- overloadedType->setSession(this);
- }
-
- Type* Session::getBoolType()
- {
- return getBuiltinType(BaseType::Bool);
- }
-
- Type* Session::getHalfType()
- {
- return getBuiltinType(BaseType::Half);
- }
-
- Type* Session::getFloatType()
- {
- return getBuiltinType(BaseType::Float);
- }
-
- Type* Session::getDoubleType()
- {
- return getBuiltinType(BaseType::Double);
- }
-
- Type* Session::getIntType()
- {
- return getBuiltinType(BaseType::Int);
- }
-
- Type* Session::getInt64Type()
- {
- return getBuiltinType(BaseType::Int64);
- }
-
- Type* Session::getUIntType()
- {
- return getBuiltinType(BaseType::UInt);
- }
-
- Type* Session::getUInt64Type()
- {
- return getBuiltinType(BaseType::UInt64);
- }
-
- Type* Session::getVoidType()
- {
- return getBuiltinType(BaseType::Void);
- }
-
- Type* Session::getBuiltinType(BaseType flavor)
- {
- return RefPtr<Type>(builtinTypes[(int)flavor]);
- }
-
- Type* Session::getInitializerListType()
- {
- return initializerListType;
- }
-
- Type* Session::getOverloadedType()
- {
- return overloadedType;
- }
-
- Type* Session::getErrorType()
- {
- return errorType;
- }
-
- Type* Session::getStringType()
- {
- if (stringType == nullptr)
- {
- auto stringTypeDecl = findMagicDecl(this, "StringType");
- stringType = DeclRefType::Create(this, makeDeclRef<Decl>(stringTypeDecl));
- }
- return stringType;
- }
-
- Type* Session::getEnumTypeType()
- {
- if (enumTypeType == nullptr)
- {
- auto enumTypeTypeDecl = findMagicDecl(this, "EnumTypeType");
- enumTypeType = DeclRefType::Create(this, makeDeclRef<Decl>(enumTypeTypeDecl));
- }
- return enumTypeType;
- }
-
- RefPtr<PtrType> Session::getPtrType(
- RefPtr<Type> valueType)
- {
- return getPtrType(valueType, "PtrType").dynamicCast<PtrType>();
- }
-
- // Construct the type `Out<valueType>`
- RefPtr<OutType> Session::getOutType(RefPtr<Type> valueType)
- {
- return getPtrType(valueType, "OutType").dynamicCast<OutType>();
- }
-
- RefPtr<InOutType> Session::getInOutType(RefPtr<Type> valueType)
- {
- return getPtrType(valueType, "InOutType").dynamicCast<InOutType>();
- }
-
- RefPtr<RefType> Session::getRefType(RefPtr<Type> valueType)
- {
- return getPtrType(valueType, "RefType").dynamicCast<RefType>();
- }
-
- RefPtr<PtrTypeBase> Session::getPtrType(RefPtr<Type> valueType, char const* ptrTypeName)
- {
- auto genericDecl = findMagicDecl(this, ptrTypeName).dynamicCast<GenericDecl>();
- return getPtrType(valueType, genericDecl);
- }
-
- RefPtr<PtrTypeBase> Session::getPtrType(RefPtr<Type> valueType, GenericDecl* genericDecl)
- {
- auto typeDecl = genericDecl->inner;
-
- auto substitutions = new GenericSubstitution();
- substitutions->genericDecl = genericDecl;
- substitutions->args.add(valueType);
-
- auto declRef = DeclRef<Decl>(typeDecl.Ptr(), substitutions);
- auto rsType = DeclRefType::Create(
- this,
- declRef);
- return as<PtrTypeBase>( rsType);
- }
-
- RefPtr<ArrayExpressionType> Session::getArrayType(
- Type* elementType,
- IntVal* elementCount)
- {
- RefPtr<ArrayExpressionType> arrayType = new ArrayExpressionType();
- arrayType->setSession(this);
- arrayType->baseType = elementType;
- arrayType->ArrayLength = elementCount;
- return arrayType;
- }
-
- SyntaxClass<RefObject> Session::findSyntaxClass(Name* name)
- {
- SyntaxClass<RefObject> syntaxClass;
- if (mapNameToSyntaxClass.TryGetValue(name, syntaxClass))
- return syntaxClass;
-
- return SyntaxClass<RefObject>();
- }
-
-
-
- bool ArrayExpressionType::EqualsImpl(Type* type)
- {
- auto arrType = as<ArrayExpressionType>(type);
- if (!arrType)
- return false;
- return (areValsEqual(ArrayLength, arrType->ArrayLength) && baseType->Equals(arrType->baseType.Ptr()));
- }
-
- RefPtr<Val> ArrayExpressionType::SubstituteImpl(SubstitutionSet subst, int* ioDiff)
- {
- int diff = 0;
- auto elementType = baseType->SubstituteImpl(subst, &diff).as<Type>();
- auto arrlen = ArrayLength->SubstituteImpl(subst, &diff).as<IntVal>();
- SLANG_ASSERT(arrlen);
- if (diff)
- {
- *ioDiff = 1;
- auto rsType = getArrayType(
- elementType,
- arrlen);
- return rsType;
- }
- return this;
- }
-
- RefPtr<Type> ArrayExpressionType::CreateCanonicalType()
- {
- auto canonicalElementType = baseType->GetCanonicalType();
- auto canonicalArrayType = getArrayType(
- canonicalElementType,
- ArrayLength);
- return canonicalArrayType;
- }
- int ArrayExpressionType::GetHashCode()
- {
- if (ArrayLength)
- return (baseType->GetHashCode() * 16777619) ^ ArrayLength->GetHashCode();
- else
- return baseType->GetHashCode();
- }
- Slang::String ArrayExpressionType::ToString()
- {
- if (ArrayLength)
- return baseType->ToString() + "[" + ArrayLength->ToString() + "]";
- else
- return baseType->ToString() + "[]";
- }
-
- // DeclRefType
-
- String DeclRefType::ToString()
- {
- return declRef.toString();
- }
-
- int DeclRefType::GetHashCode()
- {
- return (declRef.GetHashCode() * 16777619) ^ (int)(typeid(this).hash_code());
- }
-
- bool DeclRefType::EqualsImpl(Type * type)
- {
- if (auto declRefType = as<DeclRefType>(type))
- {
- return declRef.Equals(declRefType->declRef);
- }
- return false;
- }
-
- RefPtr<Type> DeclRefType::CreateCanonicalType()
- {
- // A declaration reference is already canonical
- return this;
- }
-
- //
- // RequirementWitness
- //
-
- RequirementWitness::RequirementWitness(RefPtr<Val> val)
- : m_flavor(Flavor::val)
- , m_obj(val)
- {}
-
-
- RequirementWitness::RequirementWitness(RefPtr<WitnessTable> witnessTable)
- : m_flavor(Flavor::witnessTable)
- , m_obj(witnessTable)
- {}
-
- RefPtr<WitnessTable> RequirementWitness::getWitnessTable()
- {
- SLANG_ASSERT(getFlavor() == Flavor::witnessTable);
- return m_obj.as<WitnessTable>();
- }
-
-
- RequirementWitness RequirementWitness::specialize(SubstitutionSet const& subst)
- {
- switch(getFlavor())
- {
- default:
- SLANG_UNEXPECTED("unknown requirement witness flavor");
- case RequirementWitness::Flavor::none:
- return RequirementWitness();
-
- case RequirementWitness::Flavor::declRef:
- {
- int diff = 0;
- return RequirementWitness(
- getDeclRef().SubstituteImpl(subst, &diff));
- }
-
- case RequirementWitness::Flavor::val:
- {
- auto val = getVal();
- SLANG_ASSERT(val);
-
- return RequirementWitness(
- val->Substitute(subst));
- }
- }
- }
-
- RequirementWitness tryLookUpRequirementWitness(
- SubtypeWitness* subtypeWitness,
- Decl* requirementKey)
- {
- if(auto declaredSubtypeWitness = as<DeclaredSubtypeWitness>(subtypeWitness))
- {
- if(auto inheritanceDeclRef = declaredSubtypeWitness->declRef.as<InheritanceDecl>())
- {
- // A conformance that was declared as part of an inheritance clause
- // will have built up a dictionary of the satisfying declarations
- // for each of its requirements.
- RequirementWitness requirementWitness;
- auto witnessTable = inheritanceDeclRef.getDecl()->witnessTable;
- if(witnessTable && witnessTable->requirementDictionary.TryGetValue(requirementKey, requirementWitness))
- {
- // The `inheritanceDeclRef` has substitutions applied to it that
- // *aren't* present in the `requirementWitness`, because it was
- // derived by the front-end when looking at the `InheritanceDecl` alone.
- //
- // We need to apply these substitutions here for the result to make sense.
- //
- // E.g., if we have a case like:
- //
- // interface ISidekick { associatedtype Hero; void follow(Hero hero); }
- // struct Sidekick<H> : ISidekick { typedef H Hero; void follow(H hero) {} };
- //
- // void followHero<S : ISidekick>(S s, S.Hero h)
- // {
- // s.follow(h);
- // }
- //
- // Batman batman;
- // Sidekick<Batman> robin;
- // followHero<Sidekick<Batman>>(robin, batman);
- //
- // The second argument to `followHero` is `batman`, which has type `Batman`.
- // The parameter declaration lists the type `S.Hero`, which is a reference
- // to an associated type. The front end will expand this into something
- // like `S.{S:ISidekick}.Hero` - that is, we'll end up with a declaration
- // reference to `ISidekick.Hero` with a this-type substitution that references
- // the `{S:ISidekick}` declaration as a witness.
- //
- // The front-end will expand the generic application `followHero<Sidekick<Batman>>`
- // to `followHero<Sidekick<Batman>, {Sidekick<H>:ISidekick}[H->Batman]>`
- // (that is, the hidden second parameter will reference the inheritance
- // clause on `Sidekick<H>`, with a substitution to map `H` to `Batman`.
- //
- // This step should map the `{S:ISidekick}` declaration over to the
- // concrete `{Sidekick<H>:ISidekick}[H->Batman]` inheritance declaration.
- // At that point `tryLookupRequirementWitness` might be called, because
- // we want to look up the witness for the key `ISidekick.Hero` in the
- // inheritance decl-ref that is `{Sidekick<H>:ISidekick}[H->Batman]`.
- //
- // That lookup will yield us a reference to the typedef `Sidekick<H>.Hero`,
- // *without* any substitution for `H` (or rather, with a default one that
- // maps `H` to `H`.
- //
- // So, in order to get the *right* end result, we need to apply
- // the substitutions from the inheritance decl-ref to the witness.
- //
- requirementWitness = requirementWitness.specialize(inheritanceDeclRef.substitutions);
-
- return requirementWitness;
- }
- }
- }
-
- // TODO: should handle the transitive case here too
-
- return RequirementWitness();
- }
-
- RefPtr<Val> DeclRefType::SubstituteImpl(SubstitutionSet subst, int* ioDiff)
- {
- if (!subst) return this;
-
- // the case we especially care about is when this type references a declaration
- // of a generic parameter, since that is what we might be substituting...
- if (auto genericTypeParamDecl = as<GenericTypeParamDecl>(declRef.getDecl()))
- {
- // search for a substitution that might apply to us
- for(auto s = subst.substitutions; s; s = s->outer)
- {
- auto genericSubst = s.as<GenericSubstitution>();
- if(!genericSubst)
- continue;
-
- // 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)
- {
- if (m.Ptr() == genericTypeParamDecl)
- {
- // We've found it, so return the corresponding specialization argument
- (*ioDiff)++;
- return genericSubst->args[index];
- }
- else if (auto typeParam = as<GenericTypeParamDecl>(m))
- {
- index++;
- }
- else if (auto valParam = as<GenericValueParamDecl>(m))
- {
- index++;
- }
- else
- {
- }
- }
- }
- }
- else if (auto globalGenParam = as<GlobalGenericParamDecl>(declRef.getDecl()))
- {
- // search for a substitution that might apply to us
- for(auto s = subst.substitutions; s; s = s->outer)
- {
- auto genericSubst = as<GlobalGenericParamSubstitution>(s);
- if(!genericSubst)
- continue;
-
- if (genericSubst->paramDecl == globalGenParam)
- {
- (*ioDiff)++;
- return genericSubst->actualType;
- }
- }
- }
- int diff = 0;
- DeclRef<Decl> substDeclRef = declRef.SubstituteImpl(subst, &diff);
-
- if (!diff)
- return this;
-
- // Make sure to record the difference!
- *ioDiff += diff;
-
- // If this type is a reference to an associated type declaration,
- // and the substitutions provide a "this type" substitution for
- // the outer interface, then try to replace the type with the
- // actual value of the associated type for the given implementation.
- //
- if(auto substAssocTypeDecl = as<AssocTypeDecl>(substDeclRef.decl))
- {
- for(auto s = substDeclRef.substitutions.substitutions; s; s = s->outer)
- {
- auto thisSubst = s.as<ThisTypeSubstitution>();
- if(!thisSubst)
- continue;
-
- if(auto interfaceDecl = as<InterfaceDecl>(substAssocTypeDecl->ParentDecl))
- {
- if(thisSubst->interfaceDecl == interfaceDecl)
- {
- // We need to look up the declaration that satisfies
- // the requirement named by the associated type.
- Decl* requirementKey = substAssocTypeDecl;
- RequirementWitness requirementWitness = tryLookUpRequirementWitness(thisSubst->witness, requirementKey);
- switch(requirementWitness.getFlavor())
- {
- default:
- // No usable value was found, so there is nothing we can do.
- break;
-
- case RequirementWitness::Flavor::val:
- {
- auto satisfyingVal = requirementWitness.getVal();
- return satisfyingVal;
- }
- break;
- }
- }
- }
- }
- }
-
- // Re-construct the type in case we are using a specialized sub-class
- return DeclRefType::Create(getSession(), substDeclRef);
- }
-
- static RefPtr<Type> ExtractGenericArgType(RefPtr<Val> val)
- {
- auto type = val.as<Type>();
- SLANG_RELEASE_ASSERT(type.Ptr());
- return type;
- }
-
- static RefPtr<IntVal> ExtractGenericArgInteger(RefPtr<Val> val)
- {
- auto intVal = val.as<IntVal>();
- SLANG_RELEASE_ASSERT(intVal.Ptr());
- return intVal;
- }
-
- DeclRef<Decl> createDefaultSubstitutionsIfNeeded(
- Session* session,
- DeclRef<Decl> declRef)
- {
- // It is possible that `declRef` refers to a generic type,
- // but does not specify arguments for its generic parameters.
- // (E.g., this happens when referring to a generic type from
- // within its own member functions). To handle this case,
- // we will construct a default specialization at the use
- // site if needed.
- //
- // This same logic should also apply to declarations nested
- // more than one level inside of a generic (e.g., a `typdef`
- // inside of a generic `struct`).
- //
- // Similarly, it needs to work for multiple levels of
- // nested generics.
- //
-
- // We are going to build up a list of substitutions that need
- // to be applied to the decl-ref to make it specialized.
- RefPtr<Substitutions> substsToApply;
- RefPtr<Substitutions>* link = &substsToApply;
-
- RefPtr<Decl> dd = declRef.getDecl();
- for(;;)
- {
- RefPtr<Decl> childDecl = dd;
- RefPtr<Decl> parentDecl = dd->ParentDecl;
- if(!parentDecl)
- break;
-
- dd = parentDecl;
-
- if(auto genericParentDecl = parentDecl.as<GenericDecl>())
- {
- // Don't specialize any parameters of a generic.
- if(childDecl != genericParentDecl->inner)
- break;
-
- // We have a generic ancestor, but do we have an substitutions for it?
- RefPtr<GenericSubstitution> foundSubst;
- for(auto s = declRef.substitutions.substitutions; s; s = s->outer)
- {
- auto genSubst = s.as<GenericSubstitution>();
- if(!genSubst)
- continue;
-
- if(genSubst->genericDecl != genericParentDecl)
- continue;
-
- // Okay, we found a matching substitution,
- // so there is nothing to be done.
- foundSubst = genSubst;
- break;
- }
-
- if(!foundSubst)
- {
- RefPtr<Substitutions> newSubst = createDefaultSubsitutionsForGeneric(
- session,
- genericParentDecl,
- nullptr);
-
- *link = newSubst;
- link = &newSubst->outer;
- }
- }
- }
-
- if(!substsToApply)
- return declRef;
-
- int diff = 0;
- return declRef.SubstituteImpl(substsToApply, &diff);
- }
-
- // TODO: need to figure out how to unify this with the logic
- // in the generic case...
- RefPtr<DeclRefType> DeclRefType::Create(
- Session* session,
- DeclRef<Decl> declRef)
- {
- declRef = createDefaultSubstitutionsIfNeeded(session, declRef);
-
- if (auto builtinMod = declRef.getDecl()->FindModifier<BuiltinTypeModifier>())
- {
- auto type = new BasicExpressionType(builtinMod->tag);
- type->setSession(session);
- type->declRef = declRef;
- return type;
- }
- else if (auto magicMod = declRef.getDecl()->FindModifier<MagicTypeModifier>())
- {
- GenericSubstitution* subst = nullptr;
- for(auto s = declRef.substitutions.substitutions; s; s = s->outer)
- {
- if(auto genericSubst = s.as<GenericSubstitution>())
- {
- subst = genericSubst;
- break;
- }
- }
-
- if (magicMod->name == "SamplerState")
- {
- auto type = new SamplerStateType();
- type->setSession(session);
- type->declRef = declRef;
- type->flavor = SamplerStateFlavor(magicMod->tag);
- return type;
- }
- else if (magicMod->name == "Vector")
- {
- SLANG_ASSERT(subst && subst->args.getCount() == 2);
- auto vecType = new VectorExpressionType();
- vecType->setSession(session);
- vecType->declRef = declRef;
- vecType->elementType = ExtractGenericArgType(subst->args[0]);
- vecType->elementCount = ExtractGenericArgInteger(subst->args[1]);
- return vecType;
- }
- else if (magicMod->name == "Matrix")
- {
- SLANG_ASSERT(subst && subst->args.getCount() == 3);
- auto matType = new MatrixExpressionType();
- matType->setSession(session);
- matType->declRef = declRef;
- return matType;
- }
- else if (magicMod->name == "Texture")
- {
- SLANG_ASSERT(subst && subst->args.getCount() >= 1);
- auto textureType = new TextureType(
- TextureFlavor(magicMod->tag),
- ExtractGenericArgType(subst->args[0]));
- textureType->setSession(session);
- textureType->declRef = declRef;
- return textureType;
- }
- else if (magicMod->name == "TextureSampler")
- {
- SLANG_ASSERT(subst && subst->args.getCount() >= 1);
- auto textureType = new TextureSamplerType(
- TextureFlavor(magicMod->tag),
- ExtractGenericArgType(subst->args[0]));
- textureType->setSession(session);
- textureType->declRef = declRef;
- return textureType;
- }
- else if (magicMod->name == "GLSLImageType")
- {
- SLANG_ASSERT(subst && subst->args.getCount() >= 1);
- auto textureType = new GLSLImageType(
- TextureFlavor(magicMod->tag),
- ExtractGenericArgType(subst->args[0]));
- textureType->setSession(session);
- textureType->declRef = declRef;
- return textureType;
- }
-
- // TODO: eventually everything should follow this pattern,
- // and we can drive the dispatch with a table instead
- // of this ridiculously slow `if` cascade.
-
- #define CASE(n,T) \
- else if(magicMod->name == #n) { \
- auto type = new T(); \
- type->setSession(session); \
- type->declRef = declRef; \
- return type; \
- }
-
- CASE(HLSLInputPatchType, HLSLInputPatchType)
- CASE(HLSLOutputPatchType, HLSLOutputPatchType)
-
- #undef CASE
-
- #define CASE(n,T) \
- else if(magicMod->name == #n) { \
- SLANG_ASSERT(subst && subst->args.getCount() == 1); \
- auto type = new T(); \
- type->setSession(session); \
- type->elementType = ExtractGenericArgType(subst->args[0]); \
- type->declRef = declRef; \
- return type; \
- }
-
- CASE(ConstantBuffer, ConstantBufferType)
- CASE(TextureBuffer, TextureBufferType)
- CASE(ParameterBlockType, ParameterBlockType)
- CASE(GLSLInputParameterGroupType, GLSLInputParameterGroupType)
- CASE(GLSLOutputParameterGroupType, GLSLOutputParameterGroupType)
- CASE(GLSLShaderStorageBufferType, GLSLShaderStorageBufferType)
-
- CASE(HLSLStructuredBufferType, HLSLStructuredBufferType)
- CASE(HLSLRWStructuredBufferType, HLSLRWStructuredBufferType)
- CASE(HLSLRasterizerOrderedStructuredBufferType, HLSLRasterizerOrderedStructuredBufferType)
- CASE(HLSLAppendStructuredBufferType, HLSLAppendStructuredBufferType)
- CASE(HLSLConsumeStructuredBufferType, HLSLConsumeStructuredBufferType)
-
- CASE(HLSLPointStreamType, HLSLPointStreamType)
- CASE(HLSLLineStreamType, HLSLLineStreamType)
- CASE(HLSLTriangleStreamType, HLSLTriangleStreamType)
-
- #undef CASE
-
- // "magic" builtin types which have no generic parameters
- #define CASE(n,T) \
- else if(magicMod->name == #n) { \
- auto type = new T(); \
- type->setSession(session); \
- type->declRef = declRef; \
- return type; \
- }
-
- CASE(HLSLByteAddressBufferType, HLSLByteAddressBufferType)
- CASE(HLSLRWByteAddressBufferType, HLSLRWByteAddressBufferType)
- CASE(HLSLRasterizerOrderedByteAddressBufferType, HLSLRasterizerOrderedByteAddressBufferType)
- CASE(UntypedBufferResourceType, UntypedBufferResourceType)
-
- CASE(GLSLInputAttachmentType, GLSLInputAttachmentType)
-
- #undef CASE
-
- else
- {
- auto classInfo = session->findSyntaxClass(
- session->getNamePool()->getName(magicMod->name));
- if (!classInfo.classInfo)
- {
- SLANG_UNEXPECTED("unhandled type");
- }
-
- RefPtr<RefObject> type = classInfo.createInstance();
- if (!type)
- {
- SLANG_UNEXPECTED("constructor failure");
- }
-
- auto declRefType = dynamicCast<DeclRefType>(type);
- if (!declRefType)
- {
- SLANG_UNEXPECTED("expected a declaration reference type");
- }
- declRefType->session = session;
- declRefType->declRef = declRef;
- return declRefType;
- }
- }
- else
- {
- auto type = new DeclRefType(declRef);
- type->setSession(session);
- return type;
- }
- }
-
- // OverloadGroupType
-
- String OverloadGroupType::ToString()
- {
- return "overload group";
- }
-
- bool OverloadGroupType::EqualsImpl(Type * /*type*/)
- {
- return false;
- }
-
- RefPtr<Type> OverloadGroupType::CreateCanonicalType()
- {
- return this;
- }
-
- int OverloadGroupType::GetHashCode()
- {
- return (int)(int64_t)(void*)this;
- }
-
- // InitializerListType
-
- String InitializerListType::ToString()
- {
- return "initializer list";
- }
-
- bool InitializerListType::EqualsImpl(Type * /*type*/)
- {
- return false;
- }
-
- RefPtr<Type> InitializerListType::CreateCanonicalType()
- {
- return this;
- }
-
- int InitializerListType::GetHashCode()
- {
- return (int)(int64_t)(void*)this;
- }
-
- // ErrorType
-
- String ErrorType::ToString()
- {
- return "error";
- }
-
- bool ErrorType::EqualsImpl(Type* type)
- {
- if (auto errorType = as<ErrorType>(type))
- return true;
- return false;
- }
-
- RefPtr<Type> ErrorType::CreateCanonicalType()
- {
- return this;
- }
-
- RefPtr<Val> ErrorType::SubstituteImpl(SubstitutionSet /*subst*/, int* /*ioDiff*/)
- {
- return this;
- }
-
- int ErrorType::GetHashCode()
- {
- return (int)(int64_t)(void*)this;
- }
-
-
- // NamedExpressionType
-
- String NamedExpressionType::ToString()
- {
- return getText(declRef.GetName());
- }
-
- bool NamedExpressionType::EqualsImpl(Type * /*type*/)
- {
- SLANG_UNEXPECTED("unreachable");
- UNREACHABLE_RETURN(false);
- }
-
- RefPtr<Type> NamedExpressionType::CreateCanonicalType()
- {
- if (!innerType)
- innerType = GetType(declRef);
- return innerType->GetCanonicalType();
- }
-
- int NamedExpressionType::GetHashCode()
- {
- // Type equality is based on comparing canonical types,
- // so the hash code for a type needs to come from the
- // canonical version of the type. This really means
- // that `Type::GetHashCode()` should dispatch out to
- // something like `Type::GetHashCodeImpl()` on the
- // canonical version of a type, but it is less invasive
- // for now (and hopefully equivalent) to just have any
- // named types automaticlaly route hash-code requests
- // to their canonical type.
- return GetCanonicalType()->GetHashCode();
- }
-
- // FuncType
-
- String FuncType::ToString()
- {
- StringBuilder sb;
- sb << "(";
- UInt paramCount = getParamCount();
- for (UInt pp = 0; pp < paramCount; ++pp)
- {
- if (pp != 0) sb << ", ";
- sb << getParamType(pp)->ToString();
- }
- sb << ") -> ";
- sb << getResultType()->ToString();
- return sb.ProduceString();
- }
-
- bool FuncType::EqualsImpl(Type * type)
- {
- if (auto funcType = as<FuncType>(type))
- {
- auto paramCount = getParamCount();
- auto otherParamCount = funcType->getParamCount();
- if (paramCount != otherParamCount)
- return false;
-
- for (UInt pp = 0; pp < paramCount; ++pp)
- {
- auto paramType = getParamType(pp);
- auto otherParamType = funcType->getParamType(pp);
- if (!paramType->Equals(otherParamType))
- return false;
- }
-
- if(!resultType->Equals(funcType->resultType))
- return false;
-
- // TODO: if we ever introduce other kinds
- // of qualification on function types, we'd
- // want to consider it here.
- return true;
- }
- return false;
- }
-
- RefPtr<Val> FuncType::SubstituteImpl(SubstitutionSet subst, int* ioDiff)
- {
- int diff = 0;
-
- // result type
- RefPtr<Type> substResultType = resultType->SubstituteImpl(subst, &diff).as<Type>();
-
- // parameter types
- List<RefPtr<Type>> substParamTypes;
- for( auto pp : paramTypes )
- {
- substParamTypes.add(pp->SubstituteImpl(subst, &diff).as<Type>());
- }
-
- // early exit for no change...
- if(!diff)
- return this;
-
- (*ioDiff)++;
- RefPtr<FuncType> substType = new FuncType();
- substType->session = session;
- substType->resultType = substResultType;
- substType->paramTypes = substParamTypes;
- return substType;
- }
-
- RefPtr<Type> FuncType::CreateCanonicalType()
- {
- // result type
- RefPtr<Type> canResultType = resultType->GetCanonicalType();
-
- // parameter types
- List<RefPtr<Type>> canParamTypes;
- for( auto pp : paramTypes )
- {
- canParamTypes.add(pp->GetCanonicalType());
- }
-
- RefPtr<FuncType> canType = new FuncType();
- canType->session = session;
- canType->resultType = resultType;
- canType->paramTypes = canParamTypes;
-
- return canType;
- }
-
- int FuncType::GetHashCode()
- {
- int hashCode = getResultType()->GetHashCode();
- UInt paramCount = getParamCount();
- hashCode = combineHash(hashCode, Slang::GetHashCode(paramCount));
- for (UInt pp = 0; pp < paramCount; ++pp)
- {
- hashCode = combineHash(
- hashCode,
- getParamType(pp)->GetHashCode());
- }
- return hashCode;
- }
-
- // TypeType
-
- String TypeType::ToString()
- {
- StringBuilder sb;
- sb << "typeof(" << type->ToString() << ")";
- return sb.ProduceString();
- }
-
- bool TypeType::EqualsImpl(Type * t)
- {
- if (auto typeType = as<TypeType>(t))
- {
- return t->Equals(typeType->type);
- }
- return false;
- }
-
- RefPtr<Type> TypeType::CreateCanonicalType()
- {
- auto canType = getTypeType(type->GetCanonicalType());
- return canType;
- }
-
- int TypeType::GetHashCode()
- {
- SLANG_UNEXPECTED("unreachable");
- UNREACHABLE_RETURN(0);
- }
-
- // GenericDeclRefType
-
- String GenericDeclRefType::ToString()
- {
- // TODO: what is appropriate here?
- return "<DeclRef<GenericDecl>>";
- }
-
- bool GenericDeclRefType::EqualsImpl(Type * type)
- {
- if (auto genericDeclRefType = as<GenericDeclRefType>(type))
- {
- return declRef.Equals(genericDeclRefType->declRef);
- }
- return false;
- }
-
- int GenericDeclRefType::GetHashCode()
- {
- return declRef.GetHashCode();
- }
-
- RefPtr<Type> GenericDeclRefType::CreateCanonicalType()
- {
- return this;
- }
-
- // ArithmeticExpressionType
-
- // VectorExpressionType
-
- String VectorExpressionType::ToString()
- {
- StringBuilder sb;
- sb << "vector<" << elementType->ToString() << "," << elementCount->ToString() << ">";
- return sb.ProduceString();
- }
-
- BasicExpressionType* VectorExpressionType::GetScalarType()
- {
- return as<BasicExpressionType>(elementType);
- }
-
- //
-
- RefPtr<GenericSubstitution> findInnerMostGenericSubstitution(Substitutions* subst)
- {
- for(RefPtr<Substitutions> s = subst; s; s = s->outer)
- {
- if(auto genericSubst = as<GenericSubstitution>(s))
- return genericSubst;
- }
- return nullptr;
- }
-
- // MatrixExpressionType
-
- String MatrixExpressionType::ToString()
- {
- StringBuilder sb;
- sb << "matrix<" << getElementType()->ToString() << "," << getRowCount()->ToString() << "," << getColumnCount()->ToString() << ">";
- return sb.ProduceString();
- }
-
- BasicExpressionType* MatrixExpressionType::GetScalarType()
- {
- return as<BasicExpressionType>(getElementType());
- }
-
- Type* MatrixExpressionType::getElementType()
- {
- return as<Type>(findInnerMostGenericSubstitution(declRef.substitutions)->args[0]);
- }
-
- IntVal* MatrixExpressionType::getRowCount()
- {
- return as<IntVal>(findInnerMostGenericSubstitution(declRef.substitutions)->args[1]);
- }
-
- IntVal* MatrixExpressionType::getColumnCount()
- {
- return as<IntVal>(findInnerMostGenericSubstitution(declRef.substitutions)->args[2]);
- }
-
- RefPtr<Type> MatrixExpressionType::getRowType()
- {
- if( !mRowType )
- {
- mRowType = getSession()->getVectorType(getElementType(), getColumnCount());
- }
- return mRowType;
- }
-
- RefPtr<VectorExpressionType> Session::getVectorType(
- RefPtr<Type> elementType,
- RefPtr<IntVal> elementCount)
- {
- auto vectorGenericDecl = findMagicDecl(
- this, "Vector").as<GenericDecl>();
- auto vectorTypeDecl = vectorGenericDecl->inner;
-
- auto substitutions = new GenericSubstitution();
- substitutions->genericDecl = vectorGenericDecl.Ptr();
- substitutions->args.add(elementType);
- substitutions->args.add(elementCount);
-
- auto declRef = DeclRef<Decl>(vectorTypeDecl.Ptr(), substitutions);
-
- return DeclRefType::Create(
- this,
- declRef).as<VectorExpressionType>();
- }
-
-
- // PtrTypeBase
-
- Type* PtrTypeBase::getValueType()
- {
- return as<Type>(findInnerMostGenericSubstitution(declRef.substitutions)->args[0]);
- }
-
- // GenericParamIntVal
-
- bool GenericParamIntVal::EqualsVal(Val* val)
- {
- if (auto genericParamVal = as<GenericParamIntVal>(val))
- {
- return declRef.Equals(genericParamVal->declRef);
- }
- return false;
- }
-
- String GenericParamIntVal::ToString()
- {
- return getText(declRef.GetName());
- }
-
- int GenericParamIntVal::GetHashCode()
- {
- return declRef.GetHashCode() ^ 0xFFFF;
- }
-
- RefPtr<Val> GenericParamIntVal::SubstituteImpl(SubstitutionSet subst, int* ioDiff)
- {
- // search for a substitution that might apply to us
- for(auto s = subst.substitutions; s; s = s->outer)
- {
- auto genSubst = s.as<GenericSubstitution>();
- if(!genSubst)
- continue;
-
- // 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 = as<GenericTypeParamDecl>(m))
- {
- index++;
- }
- else if (auto valParam = as<GenericValueParamDecl>(m))
- {
- index++;
- }
- else
- {
- }
- }
- }
-
- // Nothing found: don't substitute.
- return this;
- }
-
- // Substitutions
-
- RefPtr<Substitutions> GenericSubstitution::applySubstitutionsShallow(SubstitutionSet substSet, RefPtr<Substitutions> substOuter, int* ioDiff)
- {
- int diff = 0;
-
- if(substOuter != outer) diff++;
-
- List<RefPtr<Val>> substArgs;
- for (auto a : args)
- {
- substArgs.add(a->SubstituteImpl(substSet, &diff));
- }
-
- if (!diff) return this;
-
- (*ioDiff)++;
- auto substSubst = new GenericSubstitution();
- substSubst->genericDecl = genericDecl;
- substSubst->args = substArgs;
- substSubst->outer = substOuter;
- return substSubst;
- }
-
- bool GenericSubstitution::Equals(Substitutions* subst)
- {
- // both must be NULL, or non-NULL
- if (subst == nullptr)
- return false;
- if (this == subst)
- return true;
-
- auto genericSubst = as<GenericSubstitution>(subst);
- if (!genericSubst)
- return false;
- if (genericDecl != genericSubst->genericDecl)
- return false;
-
- Index argCount = args.getCount();
- SLANG_RELEASE_ASSERT(args.getCount() == genericSubst->args.getCount());
- for (Index aa = 0; aa < argCount; ++aa)
- {
- if (!args[aa]->EqualsVal(genericSubst->args[aa].Ptr()))
- return false;
- }
-
- if (!outer)
- return !genericSubst->outer;
-
- if (!outer->Equals(genericSubst->outer.Ptr()))
- return false;
-
- return true;
- }
-
- RefPtr<Substitutions> ThisTypeSubstitution::applySubstitutionsShallow(SubstitutionSet substSet, RefPtr<Substitutions> substOuter, int* ioDiff)
- {
- int diff = 0;
-
- if(substOuter != outer) diff++;
-
- // NOTE: Must use .as because we must have a smart pointer here to keep in scope.
- auto substWitness = witness->SubstituteImpl(substSet, &diff).as<SubtypeWitness>();
-
- if (!diff) return this;
-
- (*ioDiff)++;
- auto substSubst = new ThisTypeSubstitution();
- substSubst->interfaceDecl = interfaceDecl;
- substSubst->witness = substWitness;
- substSubst->outer = substOuter;
- return substSubst;
- }
-
- bool ThisTypeSubstitution::Equals(Substitutions* subst)
- {
- if (!subst)
- return false;
- if (subst == this)
- return true;
-
- if (auto thisTypeSubst = as<ThisTypeSubstitution>(subst))
- {
- return witness->EqualsVal(thisTypeSubst->witness);
- }
- return false;
- }
-
- int ThisTypeSubstitution::GetHashCode() const
- {
- return witness->GetHashCode();
- }
-
- RefPtr<Substitutions> GlobalGenericParamSubstitution::applySubstitutionsShallow(SubstitutionSet substSet, RefPtr<Substitutions> substOuter, int* ioDiff)
- {
- // if we find a GlobalGenericParamSubstitution in subst that references the same type_param decl
- // return a copy of that GlobalGenericParamSubstitution
- int diff = 0;
-
- if(substOuter != outer) diff++;
-
- auto substActualType = actualType->SubstituteImpl(substSet, &diff).as<Type>();
-
- List<ConstraintArg> substConstraintArgs;
- for(auto constraintArg : constraintArgs)
- {
- ConstraintArg substConstraintArg;
- substConstraintArg.decl = constraintArg.decl;
- substConstraintArg.val = constraintArg.val->SubstituteImpl(substSet, &diff);
-
- substConstraintArgs.add(substConstraintArg);
- }
-
- if(!diff)
- return this;
-
- (*ioDiff)++;
-
- RefPtr<GlobalGenericParamSubstitution> substSubst = new GlobalGenericParamSubstitution();
- substSubst->paramDecl = paramDecl;
- substSubst->actualType = substActualType;
- substSubst->constraintArgs = substConstraintArgs;
- substSubst->outer = substOuter;
- return substSubst;
- }
-
- bool GlobalGenericParamSubstitution::Equals(Substitutions* subst)
- {
- if (!subst)
- return false;
- if (subst == this)
- return true;
-
- if (auto genSubst = as<GlobalGenericParamSubstitution>(subst))
- {
- if (paramDecl != genSubst->paramDecl)
- return false;
- if (!actualType->EqualsVal(genSubst->actualType))
- return false;
- if (constraintArgs.getCount() != genSubst->constraintArgs.getCount())
- return false;
- for (Index i = 0; i < constraintArgs.getCount(); i++)
- {
- if (!constraintArgs[i].val->EqualsVal(genSubst->constraintArgs[i].val))
- return false;
- }
- return true;
- }
- return false;
- }
-
-
- // DeclRefBase
-
- RefPtr<Type> DeclRefBase::Substitute(RefPtr<Type> type) const
- {
- // Note that type can be nullptr, and so this function can return nullptr (although only correctly when no substitutions)
-
- // No substitutions? Easy.
- if (!substitutions)
- return type;
-
- SLANG_ASSERT(type);
-
- // Otherwise we need to recurse on the type structure
- // and apply substitutions where it makes sense
- return type->Substitute(substitutions).as<Type>();
- }
-
- DeclRefBase DeclRefBase::Substitute(DeclRefBase declRef) const
- {
- if(!substitutions)
- return declRef;
-
- int diff = 0;
- return declRef.SubstituteImpl(substitutions, &diff);
- }
-
- RefPtr<Expr> DeclRefBase::Substitute(RefPtr<Expr> expr) const
- {
- // No substitutions? Easy.
- if (!substitutions)
- return expr;
-
- SLANG_UNIMPLEMENTED_X("generic substitution into expressions");
-
- UNREACHABLE_RETURN(expr);
- }
-
- void buildMemberDictionary(ContainerDecl* decl);
-
- InterfaceDecl* findOuterInterfaceDecl(Decl* decl)
- {
- Decl* dd = decl;
- while(dd)
- {
- if(auto interfaceDecl = as<InterfaceDecl>(dd))
- return interfaceDecl;
-
- dd = dd->ParentDecl;
- }
- return nullptr;
- }
-
- RefPtr<GlobalGenericParamSubstitution> findGlobalGenericSubst(
- RefPtr<Substitutions> substs,
- GlobalGenericParamDecl* paramDecl)
- {
- for(auto s = substs; s; s = s->outer)
- {
- auto gSubst = s.as<GlobalGenericParamSubstitution>();
- if(!gSubst)
- continue;
-
- if(gSubst->paramDecl != paramDecl)
- continue;
-
- return gSubst;
- }
-
- return nullptr;
- }
-
- RefPtr<Substitutions> specializeSubstitutionsShallow(
- RefPtr<Substitutions> substToSpecialize,
- RefPtr<Substitutions> substsToApply,
- RefPtr<Substitutions> restSubst,
- int* ioDiff)
- {
- SLANG_ASSERT(substToSpecialize);
- return substToSpecialize->applySubstitutionsShallow(substsToApply, restSubst, ioDiff);
- }
-
- RefPtr<Substitutions> specializeGlobalGenericSubstitutions(
- Decl* declToSpecialize,
- RefPtr<Substitutions> substsToSpecialize,
- RefPtr<Substitutions> substsToApply,
- int* ioDiff,
- HashSet<GlobalGenericParamDecl*>& ioParametersFound)
- {
- // Any existing global-generic substitutions will trigger
- // a recursive case that skips the rest of the function.
- for(auto specSubst = substsToSpecialize; specSubst; specSubst = specSubst->outer)
- {
- auto specGlobalGenericSubst = specSubst.as<GlobalGenericParamSubstitution>();
- if(!specGlobalGenericSubst)
- continue;
-
- ioParametersFound.Add(specGlobalGenericSubst->paramDecl);
-
- int diff = 0;
- auto restSubst = specializeGlobalGenericSubstitutions(
- declToSpecialize,
- specSubst->outer,
- substsToApply,
- &diff,
- ioParametersFound);
-
- auto firstSubst = specializeSubstitutionsShallow(
- specGlobalGenericSubst,
- substsToApply,
- restSubst,
- &diff);
-
- *ioDiff += diff;
- return firstSubst;
- }
-
- // No more existing substitutions, so we know we can apply
- // our global generic substitutions without any special work.
-
- // We expect global generic substitutions to come at
- // the end of the list in all cases, so lets advance
- // until we see them.
- RefPtr<Substitutions> appGlobalGenericSubsts = substsToApply;
- while(appGlobalGenericSubsts && !appGlobalGenericSubsts.as<GlobalGenericParamSubstitution>())
- appGlobalGenericSubsts = appGlobalGenericSubsts->outer;
-
-
- // If there is nothing to apply, then we are done
- if(!appGlobalGenericSubsts)
- return nullptr;
-
- // Otherwise, it seems like something has to change.
- (*ioDiff)++;
-
- // If there were no parameters bound by the existing substitution,
- // then we can safely use the global generics from the to-apply set.
- if(ioParametersFound.Count() == 0)
- return appGlobalGenericSubsts;
-
- RefPtr<Substitutions> resultSubst;
- RefPtr<Substitutions>* link = &resultSubst;
- for(auto appSubst = appGlobalGenericSubsts; appSubst; appSubst = appSubst->outer)
- {
- auto appGlobalGenericSubst = appSubst.as<GlobalGenericParamSubstitution>();
- if(!appSubst)
- continue;
-
- // Don't include substitutions for parameters already handled.
- if(ioParametersFound.Contains(appGlobalGenericSubst->paramDecl))
- continue;
-
- RefPtr<GlobalGenericParamSubstitution> newSubst = new GlobalGenericParamSubstitution();
- newSubst->paramDecl = appGlobalGenericSubst->paramDecl;
- newSubst->actualType = appGlobalGenericSubst->actualType;
- newSubst->constraintArgs = appGlobalGenericSubst->constraintArgs;
-
- *link = newSubst;
- link = &newSubst->outer;
- }
-
- return resultSubst;
- }
-
- RefPtr<Substitutions> specializeGlobalGenericSubstitutions(
- Decl* declToSpecialize,
- RefPtr<Substitutions> substsToSpecialize,
- RefPtr<Substitutions> substsToApply,
- int* ioDiff)
- {
- // Keep track of any parameters already present in the
- // existing substitution.
- HashSet<GlobalGenericParamDecl*> parametersFound;
- return specializeGlobalGenericSubstitutions(declToSpecialize, substsToSpecialize, substsToApply, ioDiff, parametersFound);
- }
-
-
- // Construct new substitutions to apply to a declaration,
- // based on a provided substitution set to be applied
- RefPtr<Substitutions> specializeSubstitutions(
- Decl* declToSpecialize,
- RefPtr<Substitutions> substsToSpecialize,
- RefPtr<Substitutions> substsToApply,
- int* ioDiff)
- {
- // No declaration? Then nothing to specialize.
- if(!declToSpecialize)
- return nullptr;
-
- // No (remaining) substitutions to apply? Then we are done.
- if(!substsToApply)
- return substsToSpecialize;
-
- // Walk the hierarchy of the declaration to determine what specializations might apply.
- // We assume that the `substsToSpecialize` must be aligned with the ancestor
- // hierarchy of `declToSpecialize` such that if, e.g., the `declToSpecialize` is
- // nested directly in a generic, then `substToSpecialize` will either start with
- // the corresponding `GenericSubstitution` or there will be *no* generic substitutions
- // corresponding to that decl.
- for(Decl* ancestorDecl = declToSpecialize; ancestorDecl; ancestorDecl = ancestorDecl->ParentDecl)
- {
- if(auto ancestorGenericDecl = as<GenericDecl>(ancestorDecl))
- {
- // The declaration is nested inside a generic.
- // Does it already have a specialization for that generic?
- if(auto specGenericSubst = as<GenericSubstitution>(substsToSpecialize))
- {
- if(specGenericSubst->genericDecl == ancestorGenericDecl)
- {
- // Yes. We have an existing specialization, so we will
- // keep one matching it in place.
- int diff = 0;
- auto restSubst = specializeSubstitutions(
- ancestorGenericDecl->ParentDecl,
- specGenericSubst->outer,
- substsToApply,
- &diff);
-
- auto firstSubst = specializeSubstitutionsShallow(
- specGenericSubst,
- substsToApply,
- restSubst,
- &diff);
-
- *ioDiff += diff;
- return firstSubst;
- }
- }
-
- // If the declaration is not already specialized
- // for the given generic, then see if we are trying
- // to *apply* such specializations to it.
- //
- // TODO: The way we handle things right now with
- // "default" specializations, this case shouldn't
- // actually come up.
- //
- for(auto s = substsToApply; s; s = s->outer)
- {
- auto appGenericSubst = as<GenericSubstitution>(s);
- if(!appGenericSubst)
- continue;
-
- if(appGenericSubst->genericDecl != ancestorGenericDecl)
- continue;
-
- // The substitutions we are applying are trying
- // to specialize this generic, but we don't already
- // have a generic substitution in place.
- // We will need to create one.
-
- int diff = 0;
- auto restSubst = specializeSubstitutions(
- ancestorGenericDecl->ParentDecl,
- substsToSpecialize,
- substsToApply,
- &diff);
-
- RefPtr<GenericSubstitution> firstSubst = new GenericSubstitution();
- firstSubst->genericDecl = ancestorGenericDecl;
- firstSubst->args = appGenericSubst->args;
- firstSubst->outer = restSubst;
-
- (*ioDiff)++;
- return firstSubst;
- }
- }
- else if(auto ancestorInterfaceDecl = as<InterfaceDecl>(ancestorDecl))
- {
- // The task is basically the same as for the generic case:
- // We want to see if there is any existing substitution that
- // applies to this declaration, and use that if possible.
-
- // The declaration is nested inside a generic.
- // Does it already have a specialization for that generic?
- if(auto specThisTypeSubst = as<ThisTypeSubstitution>(substsToSpecialize))
- {
- if(specThisTypeSubst->interfaceDecl == ancestorInterfaceDecl)
- {
- // Yes. We have an existing specialization, so we will
- // keep one matching it in place.
- int diff = 0;
- auto restSubst = specializeSubstitutions(
- ancestorInterfaceDecl->ParentDecl,
- specThisTypeSubst->outer,
- substsToApply,
- &diff);
-
- auto firstSubst = specializeSubstitutionsShallow(
- specThisTypeSubst,
- substsToApply,
- restSubst,
- &diff);
-
- *ioDiff += diff;
- return firstSubst;
- }
- }
-
- // Otherwise, check if we are trying to apply
- // a this-type substitution to the given interface
- //
- for(auto s = substsToApply; s; s = s->outer)
- {
- auto appThisTypeSubst = s.as<ThisTypeSubstitution>();
- if(!appThisTypeSubst)
- continue;
-
- if(appThisTypeSubst->interfaceDecl != ancestorInterfaceDecl)
- continue;
-
- int diff = 0;
- auto restSubst = specializeSubstitutions(
- ancestorInterfaceDecl->ParentDecl,
- substsToSpecialize,
- substsToApply,
- &diff);
-
- RefPtr<ThisTypeSubstitution> firstSubst = new ThisTypeSubstitution();
- firstSubst->interfaceDecl = ancestorInterfaceDecl;
- firstSubst->witness = appThisTypeSubst->witness;
- firstSubst->outer = restSubst;
-
- (*ioDiff)++;
- return firstSubst;
- }
- }
- }
-
- // If we reach here then we've walked the full hierarchy up from
- // `declToSpecialize` and either didn't run into an generic/interface
- // declarations, or we didn't find any attempt to specialize them
- // in either substitution.
- //
- // As an invariant, there should *not* be any generic or this-type
- // substitutions in `substToSpecialize`, because otherwise they
- // would be specializations that don't actually apply to the given
- // declaration.
- //
- // The remaining substitutions to apply, if any, should thus be
- // global-generic substitutions. And similarly, those are the
- // only remaining substitutions we really care about in
- // `substsToApply`.
- //
- // Note: this does *not* mean that `substsToApply` doesn't have
- // any generic or this-type substitutions; it just means that none
- // of them were applicable.
- //
- return specializeGlobalGenericSubstitutions(
- declToSpecialize,
- substsToSpecialize,
- substsToApply,
- ioDiff);
- }
-
- DeclRefBase DeclRefBase::SubstituteImpl(SubstitutionSet substSet, int* ioDiff)
- {
- // Nothing to do when we have no declaration.
- if(!decl)
- return *this;
-
- // Apply the given substitutions to any specializations
- // that have already been applied to this declaration.
- int diff = 0;
-
- auto substSubst = specializeSubstitutions(
- decl,
- substitutions.substitutions,
- substSet.substitutions,
- &diff);
-
- if (!diff)
- return *this;
-
- *ioDiff += diff;
-
- DeclRefBase substDeclRef;
- substDeclRef.decl = decl;
- substDeclRef.substitutions = substSubst;
-
- // TODO: The old code here used to try to translate a decl-ref
- // to an associated type in a decl-ref for the concrete type
- // in a particular implementation.
- //
- // I have only kept that logic in `DeclRefType::SubstituteImpl`,
- // but it may turn out it is needed here too.
-
- return substDeclRef;
- }
-
-
- // Check if this is an equivalent declaration reference to another
- bool DeclRefBase::Equals(DeclRefBase const& declRef) const
- {
- if (decl != declRef.decl)
- return false;
- if (!substitutions.Equals(declRef.substitutions))
- return false;
-
- return true;
- }
-
- // Convenience accessors for common properties of declarations
- Name* DeclRefBase::GetName() const
- {
- return decl->nameAndLoc.name;
- }
-
- SourceLoc DeclRefBase::getLoc() const
- {
- return decl->loc;
- }
-
- DeclRefBase DeclRefBase::GetParent() const
- {
- // Want access to the free function (the 'as' method by default gets priority)
- // Can access as method with this->as because it removes any ambiguity.
- using Slang::as;
-
- auto parentDecl = decl->ParentDecl;
- if (!parentDecl)
- return DeclRefBase();
-
- // Default is to apply the same set of substitutions/specializations
- // to the parent declaration as were applied to the child.
- RefPtr<Substitutions> substToApply = substitutions.substitutions;
-
- if(auto interfaceDecl = as<InterfaceDecl>(decl))
- {
- // The declaration being referenced is an `interface` declaration,
- // and there might be a this-type substitution in place.
- // A reference to the parent of the interface declaration
- // should not include that substitution.
- if(auto thisTypeSubst = as<ThisTypeSubstitution>(substToApply))
- {
- if(thisTypeSubst->interfaceDecl == interfaceDecl)
- {
- // Strip away that specializations that apply to the interface.
- substToApply = thisTypeSubst->outer;
- }
- }
- }
-
- if (auto parentGenericDecl = as<GenericDecl>(parentDecl))
- {
- // The parent of this declaration is a generic, which means
- // that the decl-ref to the current declaration might include
- // substitutions that specialize the generic parameters.
- // A decl-ref to the parent generic should *not* include
- // those substitutions.
- //
- if(auto genericSubst = as<GenericSubstitution>(substToApply))
- {
- if(genericSubst->genericDecl == parentGenericDecl)
- {
- // Strip away the specializations that were applied to the parent.
- substToApply = genericSubst->outer;
- }
- }
- }
-
- return DeclRefBase(parentDecl, substToApply);
- }
-
- int DeclRefBase::GetHashCode() const
- {
- return combineHash(PointerHash<1>::GetHashCode(decl), substitutions.GetHashCode());
- }
-
- // Val
-
- RefPtr<Val> Val::Substitute(SubstitutionSet subst)
- {
- if (!subst) return this;
- int diff = 0;
- return SubstituteImpl(subst, &diff);
- }
-
- RefPtr<Val> Val::SubstituteImpl(SubstitutionSet /*subst*/, int* /*ioDiff*/)
- {
- // Default behavior is to not substitute at all
- return this;
- }
-
- // IntVal
-
- IntegerLiteralValue GetIntVal(RefPtr<IntVal> val)
- {
- if (auto constantVal = as<ConstantIntVal>(val))
- {
- return constantVal->value;
- }
- SLANG_UNEXPECTED("needed a known integer value");
- return 0;
- }
-
- // ConstantIntVal
-
- bool ConstantIntVal::EqualsVal(Val* val)
- {
- if (auto intVal = as<ConstantIntVal>(val))
- return value == intVal->value;
- return false;
- }
-
- String ConstantIntVal::ToString()
- {
- return String(value);
- }
-
- int ConstantIntVal::GetHashCode()
- {
- return (int) value;
- }
-
- //
-
- void registerBuiltinDecl(
- Session* session,
- RefPtr<Decl> decl,
- RefPtr<BuiltinTypeModifier> modifier)
- {
- auto type = DeclRefType::Create(
- session,
- DeclRef<Decl>(decl.Ptr(), nullptr));
- session->builtinTypes[(int)modifier->tag] = type;
- }
-
- void registerMagicDecl(
- Session* session,
- RefPtr<Decl> decl,
- RefPtr<MagicTypeModifier> modifier)
- {
- session->magicDecls[modifier->name] = decl.Ptr();
- }
-
- RefPtr<Decl> findMagicDecl(
- Session* session,
- String const& name)
- {
- return session->magicDecls[name].GetValue();
- }
-
- //
-
- SyntaxNodeBase* createInstanceOfSyntaxClassByName(
- String const& name)
- {
- if(0) {}
- #define CASE(NAME) \
- else if(name == #NAME) return new NAME()
-
- CASE(GLSLBufferModifier);
- CASE(GLSLWriteOnlyModifier);
- CASE(GLSLReadOnlyModifier);
- CASE(GLSLPatchModifier);
- CASE(SimpleModifier);
-
- #undef CASE
- else
- {
- SLANG_UNEXPECTED("unhandled syntax class name");
- UNREACHABLE_RETURN(nullptr);
- }
- }
-
- //
-
- // HLSLPatchType
-
- Type* HLSLPatchType::getElementType()
- {
- return as<Type>(findInnerMostGenericSubstitution(declRef.substitutions)->args[0]);
- }
-
- IntVal* HLSLPatchType::getElementCount()
- {
- return as<IntVal>(findInnerMostGenericSubstitution(declRef.substitutions)->args[1]);
- }
-
- // Constructors for types
-
- RefPtr<ArrayExpressionType> getArrayType(
- Type* elementType,
- IntVal* elementCount)
- {
- auto session = elementType->getSession();
- auto arrayType = new ArrayExpressionType();
- arrayType->setSession(session);
- arrayType->baseType = elementType;
- arrayType->ArrayLength = elementCount;
- return arrayType;
- }
-
- RefPtr<ArrayExpressionType> getArrayType(
- Type* elementType)
- {
- auto session = elementType->getSession();
- auto arrayType = new ArrayExpressionType();
- arrayType->setSession(session);
- arrayType->baseType = elementType;
- return arrayType;
- }
-
- RefPtr<NamedExpressionType> getNamedType(
- Session* session,
- DeclRef<TypeDefDecl> const& declRef)
- {
- DeclRef<TypeDefDecl> specializedDeclRef = createDefaultSubstitutionsIfNeeded(session, declRef).as<TypeDefDecl>();
-
- auto namedType = new NamedExpressionType(specializedDeclRef);
- namedType->setSession(session);
- return namedType;
- }
-
- RefPtr<TypeType> getTypeType(
- Type* type)
- {
- auto session = type->getSession();
- auto typeType = new TypeType(type);
- typeType->setSession(session);
- return typeType;
- }
-
- RefPtr<FuncType> getFuncType(
- Session* session,
- DeclRef<CallableDecl> const& declRef)
- {
- RefPtr<FuncType> funcType = new FuncType();
- funcType->setSession(session);
-
- funcType->resultType = GetResultType(declRef);
- for (auto paramDeclRef : GetParameters(declRef))
- {
- auto paramDecl = paramDeclRef.getDecl();
- auto paramType = GetType(paramDeclRef);
- if( paramDecl->FindModifier<RefModifier>() )
- {
- paramType = session->getRefType(paramType);
- }
- else if( paramDecl->FindModifier<OutModifier>() )
- {
- if(paramDecl->FindModifier<InOutModifier>() || paramDecl->FindModifier<InModifier>())
- {
- paramType = session->getInOutType(paramType);
- }
- else
- {
- paramType = session->getOutType(paramType);
- }
- }
- funcType->paramTypes.add(paramType);
- }
-
- return funcType;
- }
-
- RefPtr<GenericDeclRefType> getGenericDeclRefType(
- Session* session,
- DeclRef<GenericDecl> const& declRef)
- {
- auto genericDeclRefType = new GenericDeclRefType(declRef);
- genericDeclRefType->setSession(session);
- return genericDeclRefType;
- }
-
- RefPtr<SamplerStateType> getSamplerStateType(
- Session* session)
- {
- auto samplerStateType = new SamplerStateType();
- samplerStateType->setSession(session);
- return samplerStateType;
- }
-
- // TODO: should really have a `type.cpp` and a `witness.cpp`
-
- bool TypeEqualityWitness::EqualsVal(Val* val)
- {
- auto otherWitness = as<TypeEqualityWitness>(val);
- if (!otherWitness)
- return false;
- return sub->Equals(otherWitness->sub);
- }
-
- RefPtr<Val> TypeEqualityWitness::SubstituteImpl(SubstitutionSet subst, int * ioDiff)
- {
- RefPtr<TypeEqualityWitness> rs = new TypeEqualityWitness();
- rs->sub = sub->SubstituteImpl(subst, ioDiff).as<Type>();
- rs->sup = sup->SubstituteImpl(subst, ioDiff).as<Type>();
- return rs;
- }
-
- String TypeEqualityWitness::ToString()
- {
- return "TypeEqualityWitness(" + sub->ToString() + ")";
- }
-
- int TypeEqualityWitness::GetHashCode()
- {
- return sub->GetHashCode();
- }
-
- bool DeclaredSubtypeWitness::EqualsVal(Val* val)
- {
- auto otherWitness = as<DeclaredSubtypeWitness>(val);
- if(!otherWitness)
- return false;
-
- return sub->Equals(otherWitness->sub)
- && sup->Equals(otherWitness->sup)
- && declRef.Equals(otherWitness->declRef);
- }
-
- RefPtr<ThisTypeSubstitution> findThisTypeSubstitution(
- Substitutions* substs,
- InterfaceDecl* interfaceDecl)
- {
- for(RefPtr<Substitutions> s = substs; s; s = s->outer)
- {
- auto thisTypeSubst = as<ThisTypeSubstitution>(s);
- if(!thisTypeSubst)
- continue;
-
- if(thisTypeSubst->interfaceDecl != interfaceDecl)
- continue;
-
- return thisTypeSubst;
- }
-
- return nullptr;
- }
-
- RefPtr<Val> DeclaredSubtypeWitness::SubstituteImpl(SubstitutionSet subst, int * ioDiff)
- {
- if (auto genConstraintDeclRef = declRef.as<GenericTypeConstraintDecl>())
- {
- auto genConstraintDecl = genConstraintDeclRef.getDecl();
-
- // search for a substitution that might apply to us
- for(auto s = subst.substitutions; s; s = s->outer)
- {
- if(auto genericSubst = as<GenericSubstitution>(s))
- {
- // the generic decl associated with the substitution list must be
- // the generic decl that declared this parameter
- auto genericDecl = genericSubst->genericDecl;
- if (genericDecl != genConstraintDecl->ParentDecl)
- continue;
-
- bool found = false;
- Index index = 0;
- for (auto m : genericDecl->Members)
- {
- if (auto constraintParam = as<GenericTypeConstraintDecl>(m))
- {
- if (constraintParam == declRef.getDecl())
- {
- found = true;
- break;
- }
- index++;
- }
- }
- if (found)
- {
- (*ioDiff)++;
- auto ordinaryParamCount = genericDecl->getMembersOfType<GenericTypeParamDecl>().getCount() +
- genericDecl->getMembersOfType<GenericValueParamDecl>().getCount();
- SLANG_ASSERT(index + ordinaryParamCount < genericSubst->args.getCount());
- return genericSubst->args[index + ordinaryParamCount];
- }
- }
- else if(auto globalGenericSubst = s.as<GlobalGenericParamSubstitution>())
- {
- // check if the substitution is really about this global generic type parameter
- if (globalGenericSubst->paramDecl != genConstraintDecl->ParentDecl)
- continue;
-
- for(auto constraintArg : globalGenericSubst->constraintArgs)
- {
- if(constraintArg.decl.Ptr() != genConstraintDecl)
- continue;
-
- (*ioDiff)++;
- return constraintArg.val;
- }
- }
- }
- }
-
- // Perform substitution on the constituent elements.
- int diff = 0;
- auto substSub = sub->SubstituteImpl(subst, &diff).as<Type>();
- auto substSup = sup->SubstituteImpl(subst, &diff).as<Type>();
- auto substDeclRef = declRef.SubstituteImpl(subst, &diff);
- if (!diff)
- return this;
-
- (*ioDiff)++;
-
- // If we have a reference to a type constraint for an
- // associated type declaration, then we can replace it
- // with the concrete conformance witness for a concrete
- // type implementing the outer interface.
- //
- // TODO: It is a bit gross that we use `GenericTypeConstraintDecl` for
- // associated types, when they aren't really generic type *parameters*,
- // so we'll need to change this location in the code if we ever clean
- // up the hierarchy.
- //
- if (auto substTypeConstraintDecl = as<GenericTypeConstraintDecl>(substDeclRef.decl))
- {
- if (auto substAssocTypeDecl = as<AssocTypeDecl>(substTypeConstraintDecl->ParentDecl))
- {
- if (auto interfaceDecl = as<InterfaceDecl>(substAssocTypeDecl->ParentDecl))
- {
- // At this point we have a constraint decl for an associated type,
- // and we nee to see if we are dealing with a concrete substitution
- // for the interface around that associated type.
- if(auto thisTypeSubst = findThisTypeSubstitution(substDeclRef.substitutions, interfaceDecl))
- {
- // We need to look up the declaration that satisfies
- // the requirement named by the associated type.
- Decl* requirementKey = substTypeConstraintDecl;
- RequirementWitness requirementWitness = tryLookUpRequirementWitness(thisTypeSubst->witness, requirementKey);
- switch(requirementWitness.getFlavor())
- {
- default:
- break;
-
- case RequirementWitness::Flavor::val:
- {
- auto satisfyingVal = requirementWitness.getVal();
- return satisfyingVal;
- }
- }
- }
- }
- }
- }
-
-
-
-
- RefPtr<DeclaredSubtypeWitness> rs = new DeclaredSubtypeWitness();
- rs->sub = substSub;
- rs->sup = substSup;
- rs->declRef = substDeclRef;
- return rs;
- }
-
- String DeclaredSubtypeWitness::ToString()
- {
- StringBuilder sb;
- sb << "DeclaredSubtypeWitness(";
- sb << this->sub->ToString();
- sb << ", ";
- sb << this->sup->ToString();
- sb << ", ";
- sb << this->declRef.toString();
- sb << ")";
- return sb.ProduceString();
- }
-
- int DeclaredSubtypeWitness::GetHashCode()
- {
- return declRef.GetHashCode();
- }
-
- // TransitiveSubtypeWitness
-
- bool TransitiveSubtypeWitness::EqualsVal(Val* val)
- {
- auto otherWitness = as<TransitiveSubtypeWitness>(val);
- if(!otherWitness)
- return false;
-
- return sub->Equals(otherWitness->sub)
- && sup->Equals(otherWitness->sup)
- && subToMid->EqualsVal(otherWitness->subToMid)
- && midToSup.Equals(otherWitness->midToSup);
- }
-
- RefPtr<Val> TransitiveSubtypeWitness::SubstituteImpl(SubstitutionSet subst, int * ioDiff)
- {
- int diff = 0;
-
- RefPtr<Type> substSub = sub->SubstituteImpl(subst, &diff).as<Type>();
- RefPtr<Type> substSup = sup->SubstituteImpl(subst, &diff).as<Type>();
- RefPtr<SubtypeWitness> substSubToMid = subToMid->SubstituteImpl(subst, &diff).as<SubtypeWitness>();
- DeclRef<Decl> substMidToSup = midToSup.SubstituteImpl(subst, &diff);
-
- // If nothing changed, then we can bail out early.
- if (!diff)
- return this;
-
- // Something changes, so let the caller know.
- (*ioDiff)++;
-
- // TODO: are there cases where we can simplify?
- //
- // In principle, if either `subToMid` or `midToSub` turns into
- // a reflexive subtype witness, then we could drop that side,
- // and just return the other one (this would imply that `sub == mid`
- // or `mid == sup` after substitutions).
- //
- // In the long run, is it also possible that if `sub` gets resolved
- // to a concrete type *and* we decide to flatten out the inheritance
- // graph into a linearized "class precedence list" stored in any
- // aggregate type, then we could potentially just redirect to point
- // to the appropriate inheritance decl in the original type.
- //
- // For now I'm going to ignore those possibilities and hope for the best.
-
- // In the simple case, we just construct a new transitive subtype
- // witness, and we move on with life.
- RefPtr<TransitiveSubtypeWitness> result = new TransitiveSubtypeWitness();
- result->sub = substSub;
- result->sup = substSup;
- result->subToMid = substSubToMid;
- result->midToSup = substMidToSup;
- return result;
- }
-
- String TransitiveSubtypeWitness::ToString()
- {
- // Note: we only print the constituent
- // witnesses, and rely on them to print
- // the starting and ending types.
- StringBuilder sb;
- sb << "TransitiveSubtypeWitness(";
- sb << this->subToMid->ToString();
- sb << ", ";
- sb << this->midToSup.toString();
- sb << ")";
- return sb.ProduceString();
- }
-
- int TransitiveSubtypeWitness::GetHashCode()
- {
- auto hash = sub->GetHashCode();
- hash = combineHash(hash, sup->GetHashCode());
- hash = combineHash(hash, subToMid->GetHashCode());
- hash = combineHash(hash, midToSup.GetHashCode());
- return hash;
- }
-
- //
-
- String DeclRefBase::toString() const
- {
- if (!decl) return "";
-
- auto name = decl->getName();
- if (!name) return "";
-
- // TODO: need to print out substitutions too!
- return name->text;
- }
-
- bool SubstitutionSet::Equals(const SubstitutionSet& substSet) const
- {
- if (substitutions == substSet.substitutions)
- {
- return true;
- }
- if (substitutions == nullptr || substSet.substitutions == nullptr)
- {
- return false;
- }
- return substitutions->Equals(substSet.substitutions);
- }
-
- int SubstitutionSet::GetHashCode() const
- {
- int rs = 0;
- if (substitutions)
- rs = combineHash(rs, substitutions->GetHashCode());
- return rs;
- }
-
- // ExtractExistentialType
-
- String ExtractExistentialType::ToString()
- {
- String result;
- result.append(declRef.toString());
- result.append(".This");
- return result;
- }
-
- bool ExtractExistentialType::EqualsImpl(Type* type)
- {
- if( auto extractExistential = as<ExtractExistentialType>(type) )
- {
- return declRef.Equals(extractExistential->declRef);
- }
- return false;
- }
-
- int ExtractExistentialType::GetHashCode()
- {
- return declRef.GetHashCode();
- }
-
- RefPtr<Type> ExtractExistentialType::CreateCanonicalType()
- {
- return this;
- }
-
- RefPtr<Val> ExtractExistentialType::SubstituteImpl(SubstitutionSet subst, int* ioDiff)
- {
- int diff = 0;
- auto substDeclRef = declRef.SubstituteImpl(subst, &diff);
- if(!diff)
- return this;
-
- (*ioDiff)++;
-
- RefPtr<ExtractExistentialType> substValue = new ExtractExistentialType();
- substValue->declRef = declRef;
- return substValue;
- }
-
- // ExtractExistentialSubtypeWitness
-
- bool ExtractExistentialSubtypeWitness::EqualsVal(Val* val)
- {
- if( auto extractWitness = as<ExtractExistentialSubtypeWitness>(val) )
- {
- return declRef.Equals(extractWitness->declRef);
- }
- return false;
- }
-
- String ExtractExistentialSubtypeWitness::ToString()
- {
- String result;
- result.append("extractExistentialValue(");
- result.append(declRef.toString());
- result.append(")");
- return result;
- }
-
- int ExtractExistentialSubtypeWitness::GetHashCode()
- {
- return declRef.GetHashCode();
- }
-
- RefPtr<Val> ExtractExistentialSubtypeWitness::SubstituteImpl(SubstitutionSet subst, int* ioDiff)
- {
- int diff = 0;
-
- auto substDeclRef = declRef.SubstituteImpl(subst, &diff);
- auto substSub = sub->SubstituteImpl(subst, &diff).as<Type>();
- auto substSup = sup->SubstituteImpl(subst, &diff).as<Type>();
-
- if(!diff)
- return this;
-
- (*ioDiff)++;
-
- RefPtr<ExtractExistentialSubtypeWitness> substValue = new ExtractExistentialSubtypeWitness();
- substValue->declRef = declRef;
- substValue->sub = substSub;
- substValue->sup = substSup;
- return substValue;
- }
-
- //
- // TaggedUnionType
- //
-
- String TaggedUnionType::ToString()
- {
- String result;
- result.append("__TaggedUnion(");
- bool first = true;
- for( auto caseType : caseTypes )
- {
- if(!first) result.append(", ");
- first = false;
-
- result.append(caseType->ToString());
- }
- result.append(")");
- return result;
- }
-
- bool TaggedUnionType::EqualsImpl(Type* type)
- {
- auto taggedUnion = as<TaggedUnionType>(type);
- if(!taggedUnion)
- return false;
-
- auto caseCount = caseTypes.getCount();
- if(caseCount != taggedUnion->caseTypes.getCount())
- return false;
-
- for( Index ii = 0; ii < caseCount; ++ii )
- {
- if(!caseTypes[ii]->Equals(taggedUnion->caseTypes[ii]))
- return false;
- }
- return true;
- }
-
- int TaggedUnionType::GetHashCode()
- {
- int hashCode = 0;
- for( auto caseType : caseTypes )
- {
- hashCode = combineHash(hashCode, caseType->GetHashCode());
- }
- return hashCode;
- }
-
- RefPtr<Type> TaggedUnionType::CreateCanonicalType()
- {
- RefPtr<TaggedUnionType> canType = new TaggedUnionType();
- canType->setSession(getSession());
-
- for( auto caseType : caseTypes )
- {
- auto canCaseType = caseType->GetCanonicalType();
- canType->caseTypes.add(canCaseType);
- }
-
- return canType;
- }
-
- RefPtr<Val> TaggedUnionType::SubstituteImpl(SubstitutionSet subst, int* ioDiff)
- {
- int diff = 0;
-
- List<RefPtr<Type>> substCaseTypes;
- for( auto caseType : caseTypes )
- {
- substCaseTypes.add(caseType->SubstituteImpl(subst, &diff).as<Type>());
- }
- if(!diff)
- return this;
-
- (*ioDiff)++;
-
- RefPtr<TaggedUnionType> substType = new TaggedUnionType();
- substType->setSession(getSession());
- substType->caseTypes.swapWith(substCaseTypes);
- return substType;
- }
-
-//
-// TaggedUnionSubtypeWitness
-//
-
-
-bool TaggedUnionSubtypeWitness::EqualsVal(Val* val)
-{
- auto taggedUnionWitness = as<TaggedUnionSubtypeWitness>(val);
- if(!taggedUnionWitness)
- return false;
-
- auto caseCount = caseWitnesses.getCount();
- if(caseCount != taggedUnionWitness->caseWitnesses.getCount())
- return false;
-
- for(Index ii = 0; ii < caseCount; ++ii)
- {
- if(!caseWitnesses[ii]->EqualsVal(taggedUnionWitness->caseWitnesses[ii]))
- return false;
- }
-
- return true;
-}
-
-String TaggedUnionSubtypeWitness::ToString()
-{
- String result;
- result.append("TaggedUnionSubtypeWitness(");
- bool first = true;
- for( auto caseWitness : caseWitnesses )
- {
- if(!first) result.append(", ");
- first = false;
-
- result.append(caseWitness->ToString());
- }
- return result;
-}
-
-int TaggedUnionSubtypeWitness::GetHashCode()
-{
- int hash = 0;
- for( auto caseWitness : caseWitnesses )
- {
- hash = combineHash(hash, caseWitness->GetHashCode());
- }
- return hash;
-}
-
-RefPtr<Val> TaggedUnionSubtypeWitness::SubstituteImpl(SubstitutionSet subst, int* ioDiff)
-{
- int diff = 0;
-
- auto substSub = sub->SubstituteImpl(subst, &diff).as<Type>();
- auto substSup = sup->SubstituteImpl(subst, &diff).as<Type>();
-
- List<RefPtr<Val>> substCaseWitnesses;
- for( auto caseWitness : caseWitnesses )
- {
- substCaseWitnesses.add(caseWitness->SubstituteImpl(subst, &diff));
- }
-
- if(!diff)
- return this;
-
- (*ioDiff)++;
-
- RefPtr<TaggedUnionSubtypeWitness> substWitness = new TaggedUnionSubtypeWitness();
- substWitness->sub = substSub;
- substWitness->sup = substSup;
- substWitness->caseWitnesses.swapWith(substCaseWitnesses);
- return substWitness;
-}
-
-Module* getModule(Decl* decl)
-{
- for( auto dd = decl; dd; dd = dd->ParentDecl )
- {
- if(auto moduleDecl = as<ModuleDecl>(dd))
- return moduleDecl->module;
- }
- return nullptr;
-}
-
-bool findImageFormatByName(char const* name, ImageFormat* outFormat)
-{
- static const struct
- {
- char const* name;
- ImageFormat format;
- } kFormats[] =
- {
-#define FORMAT(NAME) { #NAME, ImageFormat::NAME },
-#include "image-format-defs.h"
- };
-
- for( auto item : kFormats )
- {
- if( strcmp(item.name, name) == 0 )
- {
- *outFormat = item.format;
- return true;
- }
- }
-
- return false;
-}
-
-char const* getGLSLNameForImageFormat(ImageFormat format)
-{
- switch( format )
- {
- default: return "unhandled";
-#define FORMAT(NAME) case ImageFormat::NAME: return #NAME;
-#include "image-format-defs.h"
- }
-}
-
-//
-// ExistentialSpecializedType
-//
-
-String ExistentialSpecializedType::ToString()
-{
- String result;
- result.append("__ExistentialSpecializedType(");
- result.append(baseType->ToString());
- for( auto arg : slots.args )
- {
- result.append(", ");
- result.append(arg.type->ToString());
- }
- result.append(")");
- return result;
-}
-
-bool ExistentialSpecializedType::EqualsImpl(Type * type)
-{
- auto other = as<ExistentialSpecializedType>(type);
- if(!other)
- return false;
-
- if(!baseType->Equals(other->baseType))
- return false;
-
- auto argCount = slots.args.getCount();
- if(argCount != other->slots.args.getCount())
- return false;
-
- for( Index ii = 0; ii < argCount; ++ii )
- {
- if(!slots.args[ii].type->Equals(other->slots.args[ii].type))
- return false;
-
- if(!slots.args[ii].witness->EqualsVal(other->slots.args[ii].witness))
- return false;
- }
- return true;
-}
-
-int ExistentialSpecializedType::GetHashCode()
-{
- Hasher hasher;
- hasher.hashObject(baseType);
- for(auto arg : slots.args)
- {
- hasher.hashObject(arg.type);
- hasher.hashObject(arg.witness);
- }
- return hasher.getResult();
-}
-
-RefPtr<Type> ExistentialSpecializedType::CreateCanonicalType()
-{
- RefPtr<ExistentialSpecializedType> canType = new ExistentialSpecializedType();
- canType->setSession(getSession());
-
- canType->baseType = baseType->GetCanonicalType();
- for( auto paramType : slots.paramTypes )
- {
- canType->slots.paramTypes.add( paramType->GetCanonicalType() );
- }
- for( auto arg : slots.args )
- {
- ExistentialTypeSlots::Arg canArg;
- canArg.type = arg.type->GetCanonicalType();
- canArg.witness = arg.witness;
- canType->slots.args.add(canArg);
- }
- return canType;
-}
-
-RefPtr<Val> ExistentialSpecializedType::SubstituteImpl(SubstitutionSet subst, int* ioDiff)
-{
- int diff = 0;
-
- auto substBaseType = baseType->SubstituteImpl(subst, &diff).as<Type>();
-
- ExistentialTypeSlots substSlots;
- for( auto paramType : slots.paramTypes )
- {
- substSlots.paramTypes.add( paramType->SubstituteImpl(subst, &diff).as<Type>() );
- }
- for( auto arg : slots.args )
- {
- ExistentialTypeSlots::Arg substArg;
- substArg.type = arg.type->SubstituteImpl(subst, &diff).as<Type>();
- substArg.witness = arg.witness->SubstituteImpl(subst, &diff);
- substSlots.args.add(substArg);
- }
-
- if(!diff)
- return this;
-
- (*ioDiff)++;
-
- RefPtr<ExistentialSpecializedType> substType = new ExistentialSpecializedType();
- substType->setSession(getSession());
- substType->baseType = substBaseType;
- substType->slots = substSlots;
- return substType;
-}
-
-} // namespace Slang