diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2020-06-03 17:22:48 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-06-03 17:22:48 -0400 |
| commit | 1b8731c809761c4e2dbec81dcee207f8a4621903 (patch) | |
| tree | b8c67d97a71df2a8ba776b6d1a39bc13138aeaf0 /source/slang/slang-syntax.cpp | |
| parent | 4e3e7f2a8f032c3f8fc4c530023aa80973598502 (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.cpp | 1598 |
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 |
