summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-syntax.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2020-06-03 17:22:48 -0400
committerGitHub <noreply@github.com>2020-06-03 17:22:48 -0400
commit1b8731c809761c4e2dbec81dcee207f8a4621903 (patch)
treeb8c67d97a71df2a8ba776b6d1a39bc13138aeaf0 /source/slang/slang-syntax.cpp
parent4e3e7f2a8f032c3f8fc4c530023aa80973598502 (diff)
Devirtualize AST types (#1368)
* Make getSup work with more general non-virtual 'virtual' mechanism. * WIP: Non virtual AST types. * Project change. * Type doesn't implement equalsImpl * Fix macro invocation Make Overridden functions public to make simply accessible by base types. * Use SLANG_UNEXPECTED. * GetScalarType -> getScalarType Use SLANG_UNEXPECTED instead on ASSERT in NamedExpressionType and TypeType
Diffstat (limited to 'source/slang/slang-syntax.cpp')
-rw-r--r--source/slang/slang-syntax.cpp1598
1 files changed, 4 insertions, 1594 deletions
diff --git a/source/slang/slang-syntax.cpp b/source/slang/slang-syntax.cpp
index 1b96aec98..c78de91a5 100644
--- a/source/slang/slang-syntax.cpp
+++ b/source/slang/slang-syntax.cpp
@@ -51,19 +51,6 @@ SourceLoc const& getDiagnosticPos(TypeExp const& typeExp)
return typeExp.exp->loc;
}
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! BasicExpressionType !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-bool BasicExpressionType::equalsImpl(Type * type)
-{
- auto basicType = as<BasicExpressionType>(type);
- return basicType && basicType->baseType == this->baseType;
-}
-
-RefPtr<Type> BasicExpressionType::createCanonicalType()
-{
- // A basic type is already canonical, in our setup
- return this;
-}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! Free functions !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -213,149 +200,6 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt
return type->equals(other);
}
- // 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(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff)
- {
- int diff = 0;
- auto canSubst = getCanonicalType()->substituteImpl(astBuilder, 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;
- }
-
- 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(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff)
- {
- int diff = 0;
- auto elementType = baseType->substituteImpl(astBuilder, subst, &diff).as<Type>();
- auto arrlen = arrayLength->substituteImpl(astBuilder, subst, &diff).as<IntVal>();
- SLANG_ASSERT(arrlen);
- if (diff)
- {
- *ioDiff = 1;
- auto rsType = getArrayType(
- astBuilder,
- elementType,
- arrlen);
- return rsType;
- }
- return this;
- }
-
- RefPtr<Type> ArrayExpressionType::createCanonicalType()
- {
- auto canonicalElementType = baseType->getCanonicalType();
- auto canonicalArrayType = getASTBuilder()->getArrayType(
- canonicalElementType,
- arrayLength);
- return canonicalArrayType;
- }
-
- HashCode 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();
- }
-
- HashCode DeclRefType::getHashCode()
- {
- return (declRef.getHashCode() * 16777619) ^ (HashCode)(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
//
@@ -478,117 +322,7 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt
return RequirementWitness();
}
- RefPtr<Val> DeclRefType::substituteImpl(ASTBuilder* astBuilder, 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(astBuilder, 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(astBuilder, 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(astBuilder, substDeclRef);
- }
+
static RefPtr<Type> ExtractGenericArgType(RefPtr<Val> val)
{
@@ -848,318 +582,6 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt
}
}
- // OverloadGroupType
-
- String OverloadGroupType::toString()
- {
- return "overload group";
- }
-
- bool OverloadGroupType::equalsImpl(Type * /*type*/)
- {
- return false;
- }
-
- RefPtr<Type> OverloadGroupType::createCanonicalType()
- {
- return this;
- }
-
- HashCode OverloadGroupType::getHashCode()
- {
- return (HashCode)(size_t(this));
- }
-
- // InitializerListType
-
- String InitializerListType::toString()
- {
- return "initializer list";
- }
-
- bool InitializerListType::equalsImpl(Type * /*type*/)
- {
- return false;
- }
-
- RefPtr<Type> InitializerListType::createCanonicalType()
- {
- return this;
- }
-
- HashCode InitializerListType::getHashCode()
- {
- return (HashCode)(size_t(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(ASTBuilder* /* astBuilder */, SubstitutionSet /*subst*/, int* /*ioDiff*/)
- {
- return this;
- }
-
- HashCode ErrorType::getHashCode()
- {
- return HashCode(size_t(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(m_astBuilder, declRef);
- return innerType->getCanonicalType();
- }
-
- HashCode 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(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff)
- {
- int diff = 0;
-
- // result type
- RefPtr<Type> substResultType = resultType->substituteImpl(astBuilder, subst, &diff).as<Type>();
-
- // parameter types
- List<RefPtr<Type>> substParamTypes;
- for( auto pp : paramTypes )
- {
- substParamTypes.add(pp->substituteImpl(astBuilder, subst, &diff).as<Type>());
- }
-
- // early exit for no change...
- if(!diff)
- return this;
-
- (*ioDiff)++;
- RefPtr<FuncType> substType = astBuilder->create<FuncType>();
- 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 = getASTBuilder()->create<FuncType>();
- canType->resultType = resultType;
- canType->paramTypes = canParamTypes;
-
- return canType;
- }
-
- HashCode FuncType::getHashCode()
- {
- HashCode 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()
- {
- return getASTBuilder()->getTypeType(type->getCanonicalType());
- }
-
- HashCode 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;
- }
-
- HashCode GenericDeclRefType::getHashCode()
- {
- return declRef.getHashCode();
- }
-
- RefPtr<Type> GenericDeclRefType::createCanonicalType()
- {
- return this;
- }
-
- // NamespaceType
-
- String NamespaceType::toString()
- {
- String result;
- result.append("namespace ");
- result.append(declRef.toString());
- return result;
- }
-
- bool NamespaceType::equalsImpl(Type * type)
- {
- if (auto namespaceType = as<NamespaceType>(type))
- {
- return declRef.equals(namespaceType->declRef);
- }
- return false;
- }
-
- HashCode NamespaceType::getHashCode()
- {
- return declRef.getHashCode();
- }
-
- RefPtr<Type> NamespaceType::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)
@@ -1172,309 +594,7 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt
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( !rowType )
- {
- rowType = m_astBuilder->getVectorType(getElementType(), getColumnCount());
- }
- return rowType;
- }
-
-
-
-
- // 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());
- }
-
- HashCode GenericParamIntVal::getHashCode()
- {
- return declRef.getHashCode() ^ HashCode(0xFFFF);
- }
-
- RefPtr<Val> GenericParamIntVal::substituteImpl(ASTBuilder* /* astBuilder */, 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;
- }
-
- // ErrorIntVal
-
- bool ErrorIntVal::equalsVal(Val* val)
- {
- if( auto errorIntVal = as<ErrorIntVal>(val) )
- {
- return true;
- }
- return false;
- }
-
- String ErrorIntVal::toString()
- {
- return "<error>";
- }
-
- HashCode ErrorIntVal::getHashCode()
- {
- return HashCode(typeid(this).hash_code());
- }
-
- RefPtr<Val> ErrorIntVal::substituteImpl(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff)
- {
- SLANG_UNUSED(astBuilder);
- SLANG_UNUSED(subst);
- SLANG_UNUSED(ioDiff);
- return this;
- }
-
- // Substitutions
-
- RefPtr<Substitutions> GenericSubstitution::applySubstitutionsShallow(ASTBuilder* astBuilder, 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(astBuilder, substSet, &diff));
- }
-
- if (!diff) return this;
-
- (*ioDiff)++;
- auto substSubst = astBuilder->create<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(ASTBuilder* astBuilder, 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(astBuilder, substSet, &diff).as<SubtypeWitness>();
-
- if (!diff) return this;
-
- (*ioDiff)++;
- auto substSubst = astBuilder->create<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))
- {
- // For our purposes, two this-type substitutions are
- // equivalent if they have the same type as `This`,
- // even if the specific witness values they use
- // might differ.
- //
- if(this->interfaceDecl != thisTypeSubst->interfaceDecl)
- return false;
-
- if(!this->witness->sub->equals(thisTypeSubst->witness->sub))
- return false;
-
- return true;
- }
- return false;
- }
-
- HashCode ThisTypeSubstitution::getHashCode() const
- {
- return witness->getHashCode();
- }
-
- RefPtr<Substitutions> GlobalGenericParamSubstitution::applySubstitutionsShallow(ASTBuilder* astBuilder, 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(astBuilder, substSet, &diff).as<Type>();
-
- List<ConstraintArg> substConstraintArgs;
- for(auto constraintArg : constraintArgs)
- {
- ConstraintArg substConstraintArg;
- substConstraintArg.decl = constraintArg.decl;
- substConstraintArg.val = constraintArg.val->substituteImpl(astBuilder, substSet, &diff);
-
- substConstraintArgs.add(substConstraintArg);
- }
-
- if(!diff)
- return this;
-
- (*ioDiff)++;
-
- RefPtr<GlobalGenericParamSubstitution> substSubst = astBuilder->create<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(ASTBuilder* astBuilder, RefPtr<Type> type) const
@@ -1957,21 +1077,6 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt
return combineHash(PointerHash<1>::getHashCode(decl), substitutions.getHashCode());
}
- // Val
-
- RefPtr<Val> Val::substitute(ASTBuilder* astBuilder, SubstitutionSet subst)
- {
- if (!subst) return this;
- int diff = 0;
- return substituteImpl(astBuilder, subst, &diff);
- }
-
- RefPtr<Val> Val::substituteImpl(ASTBuilder* /* astBuilder */, SubstitutionSet /*subst*/, int* /*ioDiff*/)
- {
- // Default behavior is to not substitute at all
- return this;
- }
-
// IntVal
IntegerLiteralValue getIntVal(RefPtr<IntVal> val)
@@ -1984,27 +1089,6 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt
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);
- }
-
- HashCode ConstantIntVal::getHashCode()
- {
- return (HashCode) value;
- }
-
-
-
//
// HLSLPatchType
@@ -2105,45 +1189,6 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt
return astBuilder->create<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(ASTBuilder* astBuilder, SubstitutionSet subst, int * ioDiff)
- {
- RefPtr<TypeEqualityWitness> rs = astBuilder->create<TypeEqualityWitness>();
- rs->sub = sub->substituteImpl(astBuilder, subst, ioDiff).as<Type>();
- rs->sup = sup->substituteImpl(astBuilder, subst, ioDiff).as<Type>();
- return rs;
- }
-
- String TypeEqualityWitness::toString()
- {
- return "TypeEqualityWitness(" + sub->toString() + ")";
- }
-
- HashCode 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)
@@ -2163,221 +1208,6 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt
return nullptr;
}
- RefPtr<Val> DeclaredSubtypeWitness::substituteImpl(ASTBuilder* astBuilder, 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(astBuilder, subst, &diff).as<Type>();
- auto substSup = sup->substituteImpl(astBuilder, subst, &diff).as<Type>();
- auto substDeclRef = declRef.substituteImpl(astBuilder, 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(astBuilder, thisTypeSubst->witness, requirementKey);
- switch(requirementWitness.getFlavor())
- {
- default:
- break;
-
- case RequirementWitness::Flavor::val:
- {
- auto satisfyingVal = requirementWitness.getVal();
- return satisfyingVal;
- }
- }
- }
- }
- }
- }
-
-
-
-
- RefPtr<DeclaredSubtypeWitness> rs = astBuilder->create<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();
- }
-
- HashCode 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(ASTBuilder* astBuilder, SubstitutionSet subst, int * ioDiff)
- {
- int diff = 0;
-
- RefPtr<Type> substSub = sub->substituteImpl(astBuilder, subst, &diff).as<Type>();
- RefPtr<Type> substSup = sup->substituteImpl(astBuilder, subst, &diff).as<Type>();
- RefPtr<SubtypeWitness> substSubToMid = subToMid->substituteImpl(astBuilder, subst, &diff).as<SubtypeWitness>();
- DeclRef<Decl> substMidToSup = midToSup.substituteImpl(astBuilder, 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 = astBuilder->create<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();
- }
-
- HashCode 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
@@ -2412,248 +1242,8 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt
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;
- }
-
- HashCode ExtractExistentialType::getHashCode()
- {
- return declRef.getHashCode();
- }
-
- RefPtr<Type> ExtractExistentialType::createCanonicalType()
- {
- return this;
- }
-
- RefPtr<Val> ExtractExistentialType::substituteImpl(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff)
- {
- int diff = 0;
- auto substDeclRef = declRef.substituteImpl(astBuilder, subst, &diff);
- if(!diff)
- return this;
-
- (*ioDiff)++;
-
- RefPtr<ExtractExistentialType> substValue = astBuilder->create<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;
- }
-
- HashCode ExtractExistentialSubtypeWitness::getHashCode()
- {
- return declRef.getHashCode();
- }
-
- RefPtr<Val> ExtractExistentialSubtypeWitness::substituteImpl(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff)
- {
- int diff = 0;
-
- auto substDeclRef = declRef.substituteImpl(astBuilder, subst, &diff);
- auto substSub = sub->substituteImpl(astBuilder, subst, &diff).as<Type>();
- auto substSup = sup->substituteImpl(astBuilder, subst, &diff).as<Type>();
-
- if(!diff)
- return this;
-
- (*ioDiff)++;
-
- RefPtr<ExtractExistentialSubtypeWitness> substValue = astBuilder->create<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;
- }
-
- HashCode TaggedUnionType::getHashCode()
- {
- HashCode hashCode = 0;
- for( auto caseType : caseTypes )
- {
- hashCode = combineHash(hashCode, caseType->getHashCode());
- }
- return hashCode;
- }
-
- RefPtr<Type> TaggedUnionType::createCanonicalType()
- {
- RefPtr<TaggedUnionType> canType = m_astBuilder->create<TaggedUnionType>();
-
- for( auto caseType : caseTypes )
- {
- auto canCaseType = caseType->getCanonicalType();
- canType->caseTypes.add(canCaseType);
- }
-
- return canType;
- }
-
- RefPtr<Val> TaggedUnionType::substituteImpl(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff)
- {
- int diff = 0;
-
- List<RefPtr<Type>> substCaseTypes;
- for( auto caseType : caseTypes )
- {
- substCaseTypes.add(caseType->substituteImpl(astBuilder, subst, &diff).as<Type>());
- }
- if(!diff)
- return this;
-
- (*ioDiff)++;
-
- RefPtr<TaggedUnionType> substType = astBuilder->create<TaggedUnionType>();
- 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;
-}
-
-HashCode TaggedUnionSubtypeWitness::getHashCode()
-{
- HashCode hash = 0;
- for( auto caseWitness : caseWitnesses )
- {
- hash = combineHash(hash, caseWitness->getHashCode());
- }
- return hash;
-}
-
-RefPtr<Val> TaggedUnionSubtypeWitness::substituteImpl(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff)
-{
- int diff = 0;
-
- auto substSub = sub->substituteImpl(astBuilder, subst, &diff).as<Type>();
- auto substSup = sup->substituteImpl(astBuilder, subst, &diff).as<Type>();
-
- List<RefPtr<Val>> substCaseWitnesses;
- for( auto caseWitness : caseWitnesses )
- {
- substCaseWitnesses.add(caseWitness->substituteImpl(astBuilder, subst, &diff));
- }
-
- if(!diff)
- return this;
-
- (*ioDiff)++;
-
- RefPtr<TaggedUnionSubtypeWitness> substWitness = astBuilder->create<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 )
@@ -2698,184 +1288,4 @@ char const* getGLSLNameForImageFormat(ImageFormat format)
}
}
-//
-// ExistentialSpecializedType
-//
-
-String ExistentialSpecializedType::toString()
-{
- String result;
- result.append("__ExistentialSpecializedType(");
- result.append(baseType->toString());
- for( auto arg : args )
- {
- result.append(", ");
- result.append(arg.val->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 = args.getCount();
- if(argCount != other->args.getCount())
- return false;
-
- for( Index ii = 0; ii < argCount; ++ii )
- {
- auto arg = args[ii];
- auto otherArg = other->args[ii];
-
- if(!arg.val->equalsVal(otherArg.val))
- return false;
-
- if(!areValsEqual(arg.witness, otherArg.witness))
- return false;
- }
- return true;
-}
-
-HashCode ExistentialSpecializedType::getHashCode()
-{
- Hasher hasher;
- hasher.hashObject(baseType);
- for(auto arg : args)
- {
- hasher.hashObject(arg.val);
- if(auto witness = arg.witness)
- hasher.hashObject(witness);
- }
- return hasher.getResult();
-}
-
-RefPtr<Val> getCanonicalValue(Val* val)
-{
- if(!val)
- return nullptr;
- if(auto type = as<Type>(val))
- {
- return type->getCanonicalType();
- }
- // TODO: We may eventually need/want some sort of canonicalization
- // for non-type values, but for now there is nothing to do.
- return val;
-}
-
-RefPtr<Type> ExistentialSpecializedType::createCanonicalType()
-{
- RefPtr<ExistentialSpecializedType> canType = m_astBuilder->create<ExistentialSpecializedType>();
-
- canType->baseType = baseType->getCanonicalType();
- for( auto arg : args )
- {
- ExpandedSpecializationArg canArg;
- canArg.val = getCanonicalValue(arg.val);
- canArg.witness = getCanonicalValue(arg.witness);
- canType->args.add(canArg);
- }
- return canType;
-}
-
-RefPtr<Val> substituteImpl(ASTBuilder* astBuilder, Val* val, SubstitutionSet subst, int* ioDiff)
-{
- if(!val) return nullptr;
- return val->substituteImpl(astBuilder, subst, ioDiff);
-}
-
-RefPtr<Val> ExistentialSpecializedType::substituteImpl(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff)
-{
- int diff = 0;
-
- auto substBaseType = baseType->substituteImpl(astBuilder, subst, &diff).as<Type>();
-
- ExpandedSpecializationArgs substArgs;
- for( auto arg : args )
- {
- ExpandedSpecializationArg substArg;
- substArg.val = Slang::substituteImpl(astBuilder, arg.val, subst, &diff);
- substArg.witness = Slang::substituteImpl(astBuilder, arg.witness, subst, &diff);
- substArgs.add(substArg);
- }
-
- if(!diff)
- return this;
-
- (*ioDiff)++;
-
- RefPtr<ExistentialSpecializedType> substType = astBuilder->create<ExistentialSpecializedType>();
- substType->baseType = substBaseType;
- substType->args = substArgs;
- return substType;
-}
-
-//
-// ThisType
-//
-
-String ThisType::toString()
-{
- String result;
- result.append(interfaceDeclRef.toString());
- result.append(".This");
- return result;
-}
-
-bool ThisType::equalsImpl(Type * type)
-{
- auto other = as<ThisType>(type);
- if(!other)
- return false;
-
- if(!interfaceDeclRef.equals(other->interfaceDeclRef))
- return false;
-
- return true;
-}
-
-HashCode ThisType::getHashCode()
-{
- return combineHash(
- HashCode(typeid(*this).hash_code()),
- interfaceDeclRef.getHashCode());
-}
-
-RefPtr<Type> ThisType::createCanonicalType()
-{
- RefPtr<ThisType> canType = m_astBuilder->create<ThisType>();
-
- // TODO: need to canonicalize the decl-ref
- canType->interfaceDeclRef = interfaceDeclRef;
- return canType;
-}
-
-RefPtr<Val> ThisType::substituteImpl(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff)
-{
- int diff = 0;
-
- auto substInterfaceDeclRef = interfaceDeclRef.substituteImpl(astBuilder, subst, &diff);
-
- auto thisTypeSubst = findThisTypeSubstitution(subst.substitutions, substInterfaceDeclRef.getDecl());
- if( thisTypeSubst )
- {
- return thisTypeSubst->witness->sub;
- }
-
- if(!diff)
- return this;
-
- (*ioDiff)++;
-
- RefPtr<ThisType> substType = m_astBuilder->create<ThisType>();
- substType->interfaceDeclRef = substInterfaceDeclRef;
- return substType;
-}
-
} // namespace Slang