diff options
| author | Yong He <yonghe@outlook.com> | 2024-08-14 18:41:48 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-14 18:41:48 -0700 |
| commit | 071f1b6062b459928ebfd6f2f60a8d6ad021112b (patch) | |
| tree | 2ba65eb40f39701db6fc775a9258ec8079d161a0 /source/slang | |
| parent | 35a3d32c87f079749f6b100d01b289c3da02d7d6 (diff) | |
Variadic Generics Part 1: parsing and type checking. (#4833)
Diffstat (limited to 'source/slang')
26 files changed, 1633 insertions, 556 deletions
diff --git a/source/slang/slang-ast-builder.cpp b/source/slang/slang-ast-builder.cpp index ce4c32c3a..faf15470f 100644 --- a/source/slang/slang-ast-builder.cpp +++ b/source/slang/slang-ast-builder.cpp @@ -533,12 +533,65 @@ TypeType* ASTBuilder::getTypeType(Type* type) return getOrCreate<TypeType>(type); } +Type* ASTBuilder::getEachType(Type* baseType) +{ + // each expand T ==> T + if (auto expandType = as<ExpandType>(baseType)) + { + return expandType->getPatternType(); + } + + // each Tuple<X> ==> each X, because we know that Tuple type must be in the form of Tuple<ConcreteTypePack<...>>. + if (auto tupleType = as<TupleType>(baseType)) + { + return getEachType(tupleType->getTypePack()); + } + SLANG_ASSERT(!as<EachType>(baseType)); + return getOrCreate<EachType>(baseType); +} + +Type* ASTBuilder::getExpandType(Type* pattern, ArrayView<Type*> capturedPacks) +{ + // expand each T ==> T + if (auto eachType = as<EachType>(pattern)) + { + return eachType->getElementType(); + } + return getOrCreate<ExpandType>(pattern, capturedPacks); +} + +ConcreteTypePack* ASTBuilder::getTypePack(ArrayView<Type*> types) +{ + return getOrCreate<ConcreteTypePack>(types); +} + TypeEqualityWitness* ASTBuilder::getTypeEqualityWitness( Type* type) { return getOrCreate<TypeEqualityWitness>(type, type); } +TypePackSubtypeWitness* ASTBuilder::getSubtypeWitnessPack( + Type* subType, Type* superType, ArrayView<SubtypeWitness*> witnesses) +{ + return getOrCreate<TypePackSubtypeWitness>(subType, superType, witnesses); +} + +SubtypeWitness* ASTBuilder::getExpandSubtypeWitness( + Type* subType, Type* superType, SubtypeWitness* patternWitness) +{ + if (auto eachWitness = as<EachSubtypeWitness>(patternWitness)) + return eachWitness->getPatternTypeWitness(); + return getOrCreate<ExpandSubtypeWitness>(subType, superType, patternWitness); +} + +SubtypeWitness* ASTBuilder::getEachSubtypeWitness( + Type* subType, Type* superType, SubtypeWitness* patternWitness) +{ + if (auto expandWitness = as<ExpandSubtypeWitness>(patternWitness)) + return expandWitness->getPatternTypeWitness(); + return getOrCreate<EachSubtypeWitness>(subType, superType, patternWitness); +} DeclaredSubtypeWitness* ASTBuilder::getDeclaredSubtypeWitness( Type* subType, @@ -651,6 +704,48 @@ top: indexOfCInConjunction); } + // If left hand is a TypePackSubtypeWitness, then we should also return a TypePackSubtypeWitness + // where each witness in the pack is the transitive subtype witness of the corresponding + // witness in the original pack. + // + if (auto witnessPack = as<TypePackSubtypeWitness>(aIsSubtypeOfBWitness)) + { + List<SubtypeWitness*> newWitnesses; + for (Index i = 0; i < witnessPack->getCount(); i++) + { + newWitnesses.add(getTransitiveSubtypeWitness(witnessPack->getWitness(i), bIsSubtypeOfCWitness)); + } + return getSubtypeWitnessPack( + aType, + cType, + newWitnesses.getArrayView()); + } + + // If left hand is a ExpandSubtypeWitness, then we want to perform the transitive lookup + // on the pattern witness, and then form a new ExpandSubtypeWitness with the result. + // + if (auto expandWitness = as<ExpandSubtypeWitness>(aIsSubtypeOfBWitness)) + { + auto innerTransitiveWitness = getTransitiveSubtypeWitness(expandWitness->getPatternTypeWitness(), bIsSubtypeOfCWitness); + return getExpandSubtypeWitness(expandWitness->getSub(), cType, innerTransitiveWitness); + } + + // If left hand is a DeclaredWitness for a type pack parameter T, then we want to perform the + // transitive lookup on `each T`, and then form a new ExpandSubtypeWitness with the result. + // + if (auto declaredWitness = as<DeclaredSubtypeWitness>(aIsSubtypeOfBWitness)) + { + if (auto declRefType = as<DeclRefType>(declaredWitness->getSub())) + { + if (declRefType->getDeclRef().as<GenericTypePackParamDecl>()) + { + auto newLeftHandWitness = getEachSubtypeWitness(getEachType(declaredWitness->getSub()), declaredWitness->getSup(), declaredWitness); + auto transitiveWitness = getTransitiveSubtypeWitness(newLeftHandWitness, bIsSubtypeOfCWitness); + return getExpandSubtypeWitness(aType, cType, transitiveWitness); + } + } + } + // If none of the above special cases applied, then we are just going to create // a `TransitiveSubtypeWitness` directly. // diff --git a/source/slang/slang-ast-builder.h b/source/slang/slang-ast-builder.h index 52858a6b1..64282ce78 100644 --- a/source/slang/slang-ast-builder.h +++ b/source/slang/slang-ast-builder.h @@ -514,6 +514,12 @@ public: TypeType* getTypeType(Type* type); + Type* getEachType(Type* baseType); + + Type* getExpandType(Type* pattern, ArrayView<Type*> capturedPacks); + + ConcreteTypePack* getTypePack(ArrayView<Type*> types); + /// Produce a witness that `T : T` for any type `T` TypeEqualityWitness* getTypeEqualityWitness( Type* type); @@ -523,6 +529,12 @@ public: Type* superType, DeclRef<Decl> const& declRef); + TypePackSubtypeWitness* getSubtypeWitnessPack(Type* subType, Type* superType, ArrayView<SubtypeWitness*> witnesses); + + SubtypeWitness* getExpandSubtypeWitness(Type* subType, Type* superType, SubtypeWitness* patternWitness); + + SubtypeWitness* getEachSubtypeWitness(Type* subType, Type* superType, SubtypeWitness* patternWitness); + /// Produce a witness that `A <: C` given witnesses that `A <: B` and `B <: C` SubtypeWitness* getTransitiveSubtypeWitness( SubtypeWitness* aIsSubtypeOfBWitness, diff --git a/source/slang/slang-ast-decl-ref.cpp b/source/slang/slang-ast-decl-ref.cpp index c9511e4e7..f3c237775 100644 --- a/source/slang/slang-ast-decl-ref.cpp +++ b/source/slang/slang-ast-decl-ref.cpp @@ -235,7 +235,7 @@ void GenericAppDeclRef::_toTextOverride(StringBuilder& out) auto genericDecl = as<GenericDecl>(getGenericDeclRef()->getDecl()); Index paramCount = 0; for (auto member : genericDecl->members) - if (as<GenericTypeParamDecl>(member) || as<GenericValueParamDecl>(member)) + if (as<GenericTypeParamDeclBase>(member) || as<GenericValueParamDecl>(member)) paramCount++; getGenericDeclRef()->toText(out); out << "<"; @@ -428,7 +428,7 @@ DeclRef<Decl> createDefaultSubstitutionsIfNeeded( SemanticsVisitor* semantics, DeclRef<Decl> declRef) { - if (declRef.as<GenericTypeParamDecl>()) + if (declRef.as<GenericTypeParamDeclBase>()) return declRef; if (declRef.as<GenericValueParamDecl>()) return declRef; diff --git a/source/slang/slang-ast-decl.h b/source/slang/slang-ast-decl.h index af03ffbcb..4df5d7b39 100644 --- a/source/slang/slang-ast-decl.h +++ b/source/slang/slang-ast-decl.h @@ -77,7 +77,7 @@ private: // Dictionary for looking up members by name. // This is built on demand before performing lookup. Dictionary<Name*, Decl*> memberDictionary; - + // A list of transparent members, to be used in lookup // Note: this is only valid if `memberDictionaryIsValid` is true List<TransparentMemberInfo> transparentMembers; @@ -281,7 +281,7 @@ class SimpleTypeDecl : public Decl class TypeDefDecl : public SimpleTypeDecl { SLANG_AST_CLASS(TypeDefDecl) - + TypeExp type; }; @@ -339,7 +339,7 @@ class CallableDecl : public ContainerDecl } TypeExp returnType; - + // If this callable throws an error code, `errorType` is the type of the error code. TypeExp errorType; @@ -371,7 +371,7 @@ class FunctionDeclBase : public CallableDecl class ConstructorDecl : public FunctionDeclBase { SLANG_AST_CLASS(ConstructorDecl) - + // Indicates whether the declaration was synthesized by // slang and not actually provided by the user bool isSynthesized = false; @@ -383,7 +383,7 @@ class SubscriptDecl : public CallableDecl SLANG_AST_CLASS(SubscriptDecl) }; - /// A property declaration that abstracts over storage with a getter/setter/etc. +/// A property declaration that abstracts over storage with a getter/setter/etc. class PropertyDecl : public ContainerDecl { SLANG_AST_CLASS(PropertyDecl) @@ -449,7 +449,7 @@ class ModuleDecl : public NamespaceDeclBase /// /// This mapping is filled in during semantic checking, as the decl declarations get checked or generated. /// - OrderedDictionary<Decl*, RefPtr<DeclAssociationList>> mapDeclToAssociatedDecls; + OrderedDictionary<Decl*, RefPtr<DeclAssociationList>> mapDeclToAssociatedDecls; /// Whether the module is defined in legacy language. /// The legacy Slang language does not have visibility modifiers and everything is treated as @@ -476,16 +476,16 @@ class FileDecl : public ContainerDecl SLANG_AST_CLASS(FileDecl); }; - /// A declaration that brings members of another declaration or namespace into scope +/// A declaration that brings members of another declaration or namespace into scope class UsingDecl : public Decl { SLANG_AST_CLASS(UsingDecl) - /// An expression that identifies the entity (e.g., a namespace) to be brought into `scope` + /// An expression that identifies the entity (e.g., a namespace) to be brought into `scope` Expr* arg = nullptr; SLANG_UNREFLECTED - /// The scope that the entity named by `arg` will be brought into + /// The scope that the entity named by `arg` will be brought into Scope* scope = nullptr; }; @@ -547,17 +547,27 @@ class GenericDecl : public ContainerDecl Decl* inner = nullptr; }; -class GenericTypeParamDecl : public SimpleTypeDecl +class GenericTypeParamDeclBase : public SimpleTypeDecl +{ + SLANG_AST_CLASS(GenericTypeParamDeclBase) +}; + +class GenericTypeParamDecl : public GenericTypeParamDeclBase { SLANG_AST_CLASS(GenericTypeParamDecl) // The bound for the type parameter represents a trait that any // type used as this parameter must conform to -// TypeExp bound; + // TypeExp bound; // The "initializer" for the parameter represents a default value TypeExp initType; }; +class GenericTypePackParamDecl : public GenericTypeParamDeclBase +{ + SLANG_AST_CLASS(GenericTypePackParamDecl) +}; + // A constraint placed as part of a generic declaration class GenericTypeConstraintDecl : public TypeConstraintDecl { diff --git a/source/slang/slang-ast-expr.h b/source/slang/slang-ast-expr.h index 9ed725e1a..e6edce8f9 100644 --- a/source/slang/slang-ast-expr.h +++ b/source/slang/slang-ast-expr.h @@ -142,6 +142,18 @@ class GetArrayLengthExpr : public Expr Expr* arrayExpr = nullptr; }; +class ExpandExpr : public Expr +{ + SLANG_AST_CLASS(ExpandExpr) + Expr* baseExpr = nullptr; +}; + +class EachExpr : public Expr +{ + SLANG_AST_CLASS(EachExpr) + Expr* baseExpr = nullptr; +}; + // A base class for expressions with arguments class ExprWithArgsBase : public Expr { @@ -670,6 +682,17 @@ public: List<Val*> knownGenericArgs; }; + + /// An expression that holds a set of argument exprs that got matched to a pack parameter + /// during overload resolution. + /// +class PackExpr : public Expr +{ + SLANG_AST_CLASS(PackExpr) + + List<Expr*> args; +}; + class SPIRVAsmOperand { SLANG_VALUE_CLASS(SPIRVAsmOperand); diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h index a4e01477c..c890b874c 100644 --- a/source/slang/slang-ast-modifier.h +++ b/source/slang/slang-ast-modifier.h @@ -38,6 +38,9 @@ class ToBeSynthesizedModifier : public Modifier {SLANG_AST_CLASS(ToBeSynthesized // Marks that the definition of a decl is synthesized. class SynthesizedModifier : public Modifier { SLANG_AST_CLASS(SynthesizedModifier) }; +// Marks a synthesized variable as local temporary variable. +class LocalTempVarModifier : public Modifier { SLANG_AST_CLASS(LocalTempVarModifier) }; + // An `extern` variable in an extension is used to introduce additional attributes on an existing // field. class ExtensionExternVarModifier : public Modifier diff --git a/source/slang/slang-ast-support-types.h b/source/slang/slang-ast-support-types.h index e94174570..f74c169e7 100644 --- a/source/slang/slang-ast-support-types.h +++ b/source/slang/slang-ast-support-types.h @@ -677,6 +677,14 @@ namespace Slang struct SubstitutionSet { DeclRefBase* declRef = nullptr; + + // The element index if the substitution is happening inside a pack expansion. + // For example, if we are substituting the pattern type of `expand each T`, where + // `T` is a type pack, then packExpansionIndex will have a value starting from 0 + // to the count of the type pack during expansion of the `expand` type when we + // substitute `each T` with the element of `T` at index `packExpansionIndex`. + Index packExpansionIndex = -1; + SubstitutionSet() = default; SubstitutionSet(DeclRefBase* declRefBase) :declRef(declRefBase) diff --git a/source/slang/slang-ast-type.cpp b/source/slang/slang-ast-type.cpp index 44585ee30..1c9f68a48 100644 --- a/source/slang/slang-ast-type.cpp +++ b/source/slang/slang-ast-type.cpp @@ -9,6 +9,22 @@ #include "slang-generated-ast-macro.h" namespace Slang { +bool isAbstractTypePack(Type* type) +{ + if (as<ExpandType>(type)) + return true; + if (isDeclRefTypeOf<GenericTypePackParamDecl>(type)) + return true; + return false; +} + +bool isTypePack(Type* type) +{ + if (as<ConcreteTypePack>(type)) + return true; + return isAbstractTypePack(type); +} + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Type !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Type* Type::_createCanonicalTypeOverride() @@ -119,7 +135,7 @@ Val* DeclRefType::_substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSe return lookupDeclRef->getLookupSource(); } } - else if (as<GenericTypeParamDecl>(substDeclRef.getDecl()) || as<GenericValueParamDecl>(substDeclRef.getDecl())) + else if (as<GenericTypeParamDeclBase>(substDeclRef.getDecl()) || as<GenericValueParamDecl>(substDeclRef.getDecl())) { auto resultVal = maybeSubstituteGenericParam(nullptr, substDeclRef.getDecl(), subst, ioDiff); if (resultVal) @@ -259,6 +275,26 @@ Type* MatrixExpressionType::getRowType() return rowType; } +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! TupleType !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +Type* TupleType::getMember(Index i) const +{ + if (auto typePack = as<ConcreteTypePack>(_getGenericTypeArg(getDeclRefBase(), 0))) + return typePack->getElementType(i); + return nullptr; +} + +Index TupleType::getMemberCount() const +{ + if (auto typePack = as<ConcreteTypePack>(_getGenericTypeArg(getDeclRefBase(), 0))) + return typePack->getTypeCount(); + return 0; +} + +Type* TupleType::getTypePack() const +{ + return as<Type>(_getGenericTypeArg(getDeclRefBase(), 0)); +} + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArrayExpressionType !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Type* ArrayExpressionType::getElementType() @@ -520,47 +556,167 @@ Type* FuncType::_createCanonicalTypeOverride() return canType; } -// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! TupleType !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -void TupleType::_toTextOverride(StringBuilder& out) +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EachType !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +void EachType::_toTextOverride(StringBuilder& out) { - out << toSlice("("); - for (Index pp = 0; pp < getOperandCount(); ++pp) + out << "each "; + if (getElementType()) { - if (pp != 0) - out << toSlice(", "); - out << getOperand(pp); + getElementType()->toText(out); } - out << toSlice(")"); + else + { + out << "<null>"; + } +} + +Type* EachType::_createCanonicalTypeOverride() +{ + return this; } -Val* TupleType::_substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff) +Val* EachType::_substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff) { int diff = 0; + auto substElementType = as<Type>(getElementType()->substituteImpl(astBuilder, subst, &diff)); + if (!diff) + return this; + if (auto typePack = as<ConcreteTypePack>(substElementType)) + { + if (subst.packExpansionIndex >= 0 && subst.packExpansionIndex < typePack->getTypeCount()) + { + (*ioDiff)++; + return typePack->getElementType(subst.packExpansionIndex); + } + } + else if (auto expandType = as<ExpandType>(substElementType)) + { + if (auto innerEach = as<EachType>(expandType->getPatternType())) + { + (*ioDiff)++; + return innerEach; + } + } + (*ioDiff)++; + return astBuilder->getEachType(substElementType); +} - // just recurse into the members - List<Type*> substMemberTypes; - for (Index m = 0; m < getMemberCount(); m++) - substMemberTypes.add(as<Type>(getMember(m)->substituteImpl(astBuilder, subst, &diff))); +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ExpandType !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +void ExpandType::_toTextOverride(StringBuilder& out) +{ + out << "expand "; + getPatternType()->toText(out); +} - // early exit for no change... - if (!diff) +Type* ExpandType::_createCanonicalTypeOverride() +{ + auto canonicalPatternType = getPatternType()->getCanonicalType(); + if (canonicalPatternType == getPatternType()) return this; + ShortList<Type*> capturedPacks; + for (Index i = 0; i < getCapturedTypePackCount(); i++) + { + capturedPacks.add(getCapturedTypePack(i)); + } + return getCurrentASTBuilder()->getExpandType(canonicalPatternType, capturedPacks.getArrayView().arrayView); +} - (*ioDiff)++; - return astBuilder->getTupleType(substMemberTypes); +Val* ExpandType::_substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff) +{ + int diff = 0; + + // Given ExpandType(PatternType, CapturedTypePackParams), we first need to know + // if all captured GenericTypePackParams can be substituted into concrete type packs. + // We can't expand the ExpandType into a concrete type pack, if any of the captured type + // pack parameters aren't concrete themselves. + // + ShortList<Type*> capturedPacks; + ShortList<ConcreteTypePack*> concreteTypePacks; + for (Index i = 0; i < getCapturedTypePackCount(); i++) + { + auto substCapturedTypePack = getCapturedTypePack(i)->substituteImpl(astBuilder, subst, &diff); + if (auto expandType = as<ExpandType>(substCapturedTypePack)) + { + for (Index j = 0; j < expandType->getCapturedTypePackCount(); j++) + capturedPacks.add(expandType->getCapturedTypePack(j)); + } + else + { + capturedPacks.add(as<Type>(substCapturedTypePack)); + if (auto pack = as<ConcreteTypePack>(capturedPacks.getLast())) + { + concreteTypePacks.add(pack); + } + } + } + + if (!diff || concreteTypePacks.getCount() != capturedPacks.getCount()) + { + auto substPatternType = getPatternType()->substituteImpl(astBuilder, subst, &diff); + if (!diff) + return this; + + // If some part of pattern type or captured type can be substituted into something else, + // but not all of the captured types are resolved to concrete type packs yet, we will just + // create a new ExpandType with the substituted pattern/capture types, instead of actually + // expanding into a concrete type pack. + (*ioDiff)++; + return astBuilder->getExpandType(as<Type>(substPatternType), capturedPacks.getArrayView().arrayView); + } + else + { + // All type pack parameters are now concrete type packs, so we can construct a concrete type pack + // by substituting the pattern type with each element of the captured type pack. + ShortList<Type*> expandedTypes; + SLANG_ASSERT(capturedPacks.getCount() != 0); + + for (Index i = 0; i < concreteTypePacks[0]->getTypeCount(); i++) + { + subst.packExpansionIndex = i; + auto substElementType = getPatternType()->substituteImpl(astBuilder, subst, &diff); + expandedTypes.add(as<Type>(substElementType)); + } + if (!diff) + return this; + (*ioDiff)++; + return astBuilder->getTypePack(expandedTypes.getArrayView().arrayView); + } } -Type* TupleType::_createCanonicalTypeOverride() +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ConcreteTypePack !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +void ConcreteTypePack::_toTextOverride(StringBuilder& out) { - // member types - List<Type*> canMemberTypes; - for (Index m = 0; m < getMemberCount(); m++) + for (Index i = 0; i < getTypeCount(); i++) { - canMemberTypes.add(getMember(m)->getCanonicalType()); + if (i != 0) + out << ", "; + getElementType(i)->toText(out); } +} - return getCurrentASTBuilder()->getTupleType(canMemberTypes); +Type* ConcreteTypePack::_createCanonicalTypeOverride() +{ + ShortList<Type*> canonicalElementTypes; + for (Index i = 0; i < getTypeCount(); i++) + { + canonicalElementTypes.add(getElementType(i)->getCanonicalType()); + } + return getCurrentASTBuilder()->getTypePack(canonicalElementTypes.getArrayView().arrayView); +} + +Val* ConcreteTypePack::_substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff) +{ + int diff = 0; + ShortList<Type*> substElementTypes; + for (Index i = 0; i < getTypeCount(); i++) + { + auto substType = as<Type>(getElementType(i)->substituteImpl(astBuilder, subst, &diff)); + substElementTypes.add(substType); + } + if (!diff) + return this; + (*ioDiff)++; + return getCurrentASTBuilder()->getTypePack(substElementTypes.getArrayView().arrayView); } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ExtractExistentialType !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/source/slang/slang-ast-type.h b/source/slang/slang-ast-type.h index 945d051ba..3a1318696 100644 --- a/source/slang/slang-ast-type.h +++ b/source/slang/slang-ast-type.h @@ -71,6 +71,19 @@ class DeclRefType : public Type } }; +template<typename T> +DeclRef<T> isDeclRefTypeOf(Type* type) +{ + if (auto declRefType = as<DeclRefType>(type)) + { + return declRefType->getDeclRef().template as<T>(); + } + return DeclRef<T>(); +} + +bool isTypePack(Type* type); +bool isAbstractTypePack(Type* type); + // Base class for types that can be used in arithmetic expressions class ArithmeticExpressionType : public DeclRefType { @@ -678,21 +691,59 @@ class FuncType : public Type }; // A tuple is a product of its member types -class TupleType : public Type +class TupleType : public DeclRefType { SLANG_AST_CLASS(TupleType) - // Construct a unary tupletion - TupleType(ArrayView<Type*> memberTypes) + Index getMemberCount() const; + Type* getMember(Index i) const; + Type* getTypePack() const; + +}; + +class EachType : public Type +{ + SLANG_AST_CLASS(EachType) + Type* getElementType() const { return as<Type>(getOperand(0)); } + DeclRefType* getElementDeclRefType() const { return as<DeclRefType>(getOperand(0)); } + + EachType(Type* elementType) { - for (auto t : memberTypes) - m_operands.add(ValNodeOperand(t)); + m_operands.add(ValNodeOperand(elementType)); } + void _toTextOverride(StringBuilder& out); + Type* _createCanonicalTypeOverride(); + Val* _substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff); +}; - auto getMemberCount() const { return getOperandCount(); } - Type* getMember(Index i) const { return as<Type>(getOperand(i)); } +class ExpandType : public Type +{ + SLANG_AST_CLASS(ExpandType) + Type* getPatternType() const { return as<Type>(getOperand(0)); } + Index getCapturedTypePackCount() { return getOperandCount() - 1; } + Type* getCapturedTypePack(Index i) { return as<Type>(getOperand(i + 1)); } + ExpandType(Type* patternType, ArrayView<Type*> capturedPacks) + { + m_operands.add(ValNodeOperand(patternType)); + for (auto t : capturedPacks) + m_operands.add(ValNodeOperand(t)); + } + void _toTextOverride(StringBuilder& out); + Type* _createCanonicalTypeOverride(); + Val* _substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff); +}; - // Overrides should be public so base classes can access +// A concrete pack of types. +class ConcreteTypePack : public Type +{ + SLANG_AST_CLASS(ConcreteTypePack) + ConcreteTypePack(ArrayView<Type*> types) + { + for (auto t : types) + m_operands.add(ValNodeOperand(t)); + } + Index getTypeCount() { return getOperandCount(); } + Type* getElementType(Index i) { return as<Type>(getOperand(i)); } void _toTextOverride(StringBuilder& out); Type* _createCanonicalTypeOverride(); Val* _substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff); diff --git a/source/slang/slang-ast-val.cpp b/source/slang/slang-ast-val.cpp index 1d5a875dd..e222e86e1 100644 --- a/source/slang/slang-ast-val.cpp +++ b/source/slang/slang-ast-val.cpp @@ -205,7 +205,7 @@ Val* maybeSubstituteGenericParam(Val* paramVal, Decl* paramDecl, SubstitutionSet (*ioDiff)++; return args[argIndex]; } - else if (const auto typeParam = as<GenericTypeParamDecl>(m)) + else if (const auto typeParam = as<GenericTypeParamDeclBase>(m)) { argIndex++; } @@ -272,6 +272,163 @@ void TypeEqualityWitness::_toTextOverride(StringBuilder& out) out << toSlice("TypeEqualityWitness(") << getSub() << toSlice(")"); } +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! TypePackSubtypeWitness !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Val* TypePackSubtypeWitness::_substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff) +{ + int diff = 0; + ShortList<SubtypeWitness*> newWitnesses; + for (Index i = 0; i < getCount(); i++) + { + auto witness = getWitness(i); + auto newWitness = as<SubtypeWitness>(witness->substituteImpl(astBuilder, subst, &diff)); + newWitnesses.add(newWitness); + } + auto newSub = as<Type>(getSub()->substituteImpl(astBuilder, subst, &diff)); + auto newSup = as<Type>(getSup()->substituteImpl(astBuilder, subst, &diff)); + if (!diff) + return this; + (*ioDiff)++; + return getCurrentASTBuilder()->getSubtypeWitnessPack(newSub, newSup, newWitnesses.getArrayView().arrayView); +} + +Val* TypePackSubtypeWitness::_resolveImplOverride() +{ + int diff = 0; + ShortList<SubtypeWitness*> newWitnesses; + for (Index i = 0; i < getCount(); i++) + { + auto witness = getWitness(i); + auto newWitness = as<SubtypeWitness>(witness->resolve()); + if (witness != newWitness) + diff++; + newWitnesses.add(newWitness); + } + auto newSub = as<Type>(getSub()->resolve()); + if (newSub != getSub()) + diff++; + auto newSup = as<Type>(getSup()->resolve()); + if (newSup != getSup()) + diff++; + + if (!diff) + return this; + return getCurrentASTBuilder()->getSubtypeWitnessPack(newSub, newSup, newWitnesses.getArrayView().arrayView); +} + +void TypePackSubtypeWitness::_toTextOverride(StringBuilder& out) +{ + out << toSlice("Pack("); + for (Index i = 0; i < getCount(); i++) + { + if (i != 0) + out << toSlice(", "); + getWitness(i)->toText(out); + } + out << toSlice(")"); +} + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ExpandSubtypeWitness !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Val* ExpandSubtypeWitness::_substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff) +{ + int diff = 0; + auto newSub = as<Type>(getSub()->substituteImpl(astBuilder, subst, &diff)); + auto newSup = as<Type>(getSup()->substituteImpl(astBuilder, subst, &diff)); + if (!diff) + return this; + if (auto subTypePack = as<ConcreteTypePack>(newSub)) + { + // If sub is substituted into a concrete type pack, we should return a + // TypePackSubtypeWitness. + ShortList<SubtypeWitness*> newWitnesses; + for (Index i = 0; i < subTypePack->getTypeCount(); i++) + { + auto elementType = subTypePack->getElementType(i); + subst.packExpansionIndex = i; + auto elementWitness = as<SubtypeWitness>(getPatternTypeWitness()->substituteImpl(astBuilder, subst, &diff)); + auto newWitness = getCurrentASTBuilder()->getExpandSubtypeWitness(elementType, newSup, elementWitness); + newWitnesses.add(as<SubtypeWitness>(newWitness)); + } + (*ioDiff)++; + return getCurrentASTBuilder()->getSubtypeWitnessPack(newSub, newSup, newWitnesses.getArrayView().arrayView); + } + + (*ioDiff)++; + auto newPatternWitness = as<SubtypeWitness>(getPatternTypeWitness()->substituteImpl(astBuilder, subst, &diff)); + return getCurrentASTBuilder()->getExpandSubtypeWitness(newSub, newSup, newPatternWitness); +} + +Val* ExpandSubtypeWitness::_resolveImplOverride() +{ + int diff = 0; + auto newPatternWitness = as<SubtypeWitness>(getPatternTypeWitness()->resolve()); + if (newPatternWitness != getPatternTypeWitness()) + diff++; + auto newSub = as<Type>(getSub()->resolve()); + if (newSub != getSub()) + diff++; + auto newSup = as<Type>(getSup()->resolve()); + if (newSup != getSup()) + diff++; + if (!diff) + return this; + return getCurrentASTBuilder()->getExpandSubtypeWitness(newSub, newSup, newPatternWitness); +} + +void ExpandSubtypeWitness::_toTextOverride(StringBuilder& out) +{ + out << toSlice("ExpandWitness("); + getPatternTypeWitness()->toText(out); + out << toSlice(")"); +} + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EachSubtypeWitness !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Val* EachSubtypeWitness::_substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff) +{ + int diff = 0; + auto newPatternWitness = as<SubtypeWitness>(getPatternTypeWitness()->substituteImpl(astBuilder, subst, &diff)); + if (auto witnessPack = as<TypePackSubtypeWitness>(newPatternWitness)) + { + if (subst.packExpansionIndex >= 0 && subst.packExpansionIndex < witnessPack->getCount()) + { + auto newWitness = witnessPack->getWitness(subst.packExpansionIndex); + (*ioDiff)++; + return newWitness; + } + } + auto newSub = as<Type>(getSub()->substituteImpl(astBuilder, subst, &diff)); + auto newSup = as<Type>(getSup()->substituteImpl(astBuilder, subst, &diff)); + if (!diff) + return this; + return getCurrentASTBuilder()->getEachSubtypeWitness(newSub, newSup, newPatternWitness); +} + +Val* EachSubtypeWitness::_resolveImplOverride() +{ + int diff = 0; + auto newPatternWitness = as<SubtypeWitness>(getPatternTypeWitness()->resolve()); + if (newPatternWitness != getPatternTypeWitness()) + diff++; + auto newSub = as<Type>(getSub()->resolve()); + if (newSub != getSub()) + diff++; + auto newSup = as<Type>(getSup()->resolve()); + if (newSup != getSup()) + diff++; + if (!diff) + return this; + return getCurrentASTBuilder()->getEachSubtypeWitness(newSub, newSup, newPatternWitness); +} + +void EachSubtypeWitness::_toTextOverride(StringBuilder& out) +{ + out << toSlice("EachWitness("); + getPatternTypeWitness()->toText(out); + out << toSlice(")"); +} + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DeclaredSubtypeWitness !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Val* DeclaredSubtypeWitness::_resolveImplOverride() @@ -336,7 +493,7 @@ Val* DeclaredSubtypeWitness::_substituteImplOverride(ASTBuilder* astBuilder, Sub } if (found) { - auto ordinaryParamCount = genericDecl->getMembersOfType<GenericTypeParamDecl>().getCount() + + auto ordinaryParamCount = genericDecl->getMembersOfType<GenericTypeParamDeclBase>().getCount() + genericDecl->getMembersOfType<GenericValueParamDecl>().getCount(); if (index + ordinaryParamCount < args.getCount()) { diff --git a/source/slang/slang-ast-val.h b/source/slang/slang-ast-val.h index f94cafbda..74e0f27c1 100644 --- a/source/slang/slang-ast-val.h +++ b/source/slang/slang-ast-val.h @@ -522,6 +522,61 @@ class SubtypeWitness : public Witness ConversionCost getOverloadResolutionCost(); }; +class TypePackSubtypeWitness : public SubtypeWitness +{ + SLANG_AST_CLASS(TypePackSubtypeWitness) + + Type* getSub() { return as<Type>(getOperand(0)); } + Type* getSup() { return as<Type>(getOperand(1)); } + + Index getCount() { return getOperandCount() - 2; } + SubtypeWitness* getWitness(Index index) { return as<SubtypeWitness>(getOperand(index + 2)); } + + TypePackSubtypeWitness(Type* sub, Type* sup, ArrayView<SubtypeWitness*> witnesses) + { + setOperands(sub); + addOperands(sup); + for(auto w : witnesses) + addOperands(ValNodeOperand(w)); + } + + void _toTextOverride(StringBuilder& out); + Val* _resolveImplOverride(); + Val* _substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff); +}; + +class EachSubtypeWitness : public SubtypeWitness +{ + SLANG_AST_CLASS(EachSubtypeWitness) + + EachSubtypeWitness(Type* sub, Type* sup, SubtypeWitness* patternWitness) + { + setOperands(sub, sup, patternWitness); + } + Type* getSub() { return as<Type>(getOperand(0)); } + Type* getSup() { return as<Type>(getOperand(1)); } + SubtypeWitness* getPatternTypeWitness() { return as<SubtypeWitness>(getOperand(2)); } + void _toTextOverride(StringBuilder& out); + Val* _resolveImplOverride(); + Val* _substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff); +}; + +class ExpandSubtypeWitness : public SubtypeWitness +{ + SLANG_AST_CLASS(ExpandSubtypeWitness) + + ExpandSubtypeWitness(Type* sub, Type* sup, SubtypeWitness* patternWitness) + { + setOperands(sub, sup, patternWitness); + } + Type* getSub() { return as<Type>(getOperand(0)); } + Type* getSup() { return as<Type>(getOperand(1)); } + SubtypeWitness* getPatternTypeWitness() { return as<SubtypeWitness>(getOperand(2)); } + void _toTextOverride(StringBuilder& out); + Val* _resolveImplOverride(); + Val* _substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff); +}; + class TypeEqualityWitness : public SubtypeWitness { SLANG_AST_CLASS(TypeEqualityWitness) diff --git a/source/slang/slang-check-conformance.cpp b/source/slang/slang-check-conformance.cpp index 0ff4bfed4..9a44cbbb4 100644 --- a/source/slang/slang-check-conformance.cpp +++ b/source/slang/slang-check-conformance.cpp @@ -232,7 +232,35 @@ namespace Slang } return nullptr; } - + else if (auto subTypePack = as<ConcreteTypePack>(subType)) + { + // A type pack (T0, T1, ...) is a subtype of supType, if each of its elements + // is a subtype of the supType. + ShortList<SubtypeWitness*> elementWitnesses; + for (Index i = 0; i < subTypePack->getTypeCount(); i++) + { + auto elementWitness = isSubtype(subTypePack->getElementType(i), superType, IsSubTypeOptions::None); + if (!elementWitness) + return nullptr; + elementWitnesses.add(elementWitness); + } + return m_astBuilder->getSubtypeWitnessPack(subType, superType, elementWitnesses.getArrayView().arrayView); + } + else if (auto expandType = as<ExpandType>(subType)) + { + // A expand type `expand patternType, captureList` is a subtype of supType, if patternType is a subtype of supType. + auto elementWitness = isSubtype(expandType->getPatternType(), superType, IsSubTypeOptions::None); + if (!elementWitness) + return nullptr; + return m_astBuilder->getExpandSubtypeWitness(subType, superType, elementWitness); + } + else if (auto eachType = as<EachType>(subType)) + { + auto elementWitness = isSubtype(eachType->getElementType(), superType, IsSubTypeOptions::None); + if (!elementWitness) + return nullptr; + return m_astBuilder->getEachSubtypeWitness(subType, superType, elementWitness); + } // default is failure return nullptr; } diff --git a/source/slang/slang-check-constraint.cpp b/source/slang/slang-check-constraint.cpp index 1195ed1f9..0f6da156d 100644 --- a/source/slang/slang-check-constraint.cpp +++ b/source/slang/slang-check-constraint.cpp @@ -252,6 +252,27 @@ namespace Slang } } + // We can recursively join two TypePacks. + if (auto leftTypePack = as<ConcreteTypePack>(left)) + { + if (auto rightTypePack = as<ConcreteTypePack>(right)) + { + if(leftTypePack->getTypeCount() != rightTypePack->getTypeCount()) + return nullptr; + ShortList<Type*> joinedTypes; + for (Index i = 0; i < leftTypePack->getTypeCount(); ++i) + { + auto joinedType = TryJoinTypes( + QualType(leftTypePack->getElementType(i), left.isLeftValue), + QualType(rightTypePack->getElementType(i), right.isLeftValue)); + if(!joinedType) + return nullptr; + joinedTypes.add(joinedType); + } + return m_astBuilder->getTypePack(joinedTypes.getArrayView().arrayView); + } + } + // TODO: all the cases for vectors apply to matrices too! // Default case is that we just fail. @@ -285,7 +306,7 @@ namespace Slang // that `X<T>.IndexType == T`. for( auto constraintDeclRef : getMembersOfType<GenericTypeConstraintDecl>(m_astBuilder, genericDeclRef) ) { - if(!TryUnifyTypes(*system, getSub(m_astBuilder, constraintDeclRef), getSup(m_astBuilder, constraintDeclRef))) + if(!TryUnifyTypes(*system, ValUnificationContext(), getSub(m_astBuilder, constraintDeclRef), getSup(m_astBuilder, constraintDeclRef))) return DeclRef<Decl>(); } @@ -322,8 +343,14 @@ namespace Slang Count paramCounter = 0; for (auto m : getMembers(m_astBuilder, genericDeclRef)) { - if (auto typeParam = m.as<GenericTypeParamDecl>()) + if (auto typeParam = m.as<GenericTypeParamDeclBase>()) { + // If the parameter is a type pack, then we may have + // constraints that apply to invidual elements of the pack. + // We will need to handle the type pack case slightly differently. + // + bool isPack = as<GenericTypePackParamDecl>(typeParam) != nullptr; + // If the parameter is one where we already know // the argument value to use, we don't bother with // trying to solve for it, and treat any constraints @@ -342,13 +369,32 @@ namespace Slang continue; } - QualType type; + + // We will use a temporary list to hold the resolved types + // for this generic parameter. + // For normal type parameters, there should be only one type + // in the list. For type pack parameters, there can be one type + // for each element in the pack. + // + ShortList<QualType> types; + if (!isPack) + types.setCount(1); + bool typeConstraintOptional = true; for (auto& c : system->constraints) { if (c.decl != typeParam.getDecl()) continue; + QualType* ptype = nullptr; + if (isPack) + { + types.setCount(Math::Max(types.getCount(), c.indexInPack + 1)); + ptype = &types[c.indexInPack]; + } + else + ptype = &types[0]; + QualType& type = *ptype; auto cType = QualType(as<Type>(c.val), c.isUsedAsLValue); SLANG_RELEASE_ASSERT(cType); @@ -372,12 +418,40 @@ namespace Slang c.satisfied = true; } - if (!type) + // Fail if any of the resolved type element is empty. + for (auto t: types) { - // failure! - return DeclRef<Decl>(); + if (!t) + return DeclRef<Decl>(); + } + if (!isPack) + { + // If the generic parameter is not a pack, we can simply add the first type. + SLANG_ASSERT(types.getCount() == 1); + args.add(types[0]); + } + else + { + // If the generic parameter is a pack, and we are supplying one single pack argument, + // we can use it as is. + if (types.getCount() == 1 && isTypePack(types[0])) + { + args.add(types[0]); + } + else + { + // If we are supplying 0 or multiple arguments for the pack, we need to create a type pack + // and add it to the argument list. + ShortList<Type*> typeList; + bool isLVal = true; + for (auto t : types) + { + typeList.add(t); + isLVal = isLVal && t.isLeftValue; + } + args.add(QualType(m_astBuilder->getTypePack(typeList.getArrayView().arrayView), isLVal)); + } } - args.add(type); } else if (auto valParam = m.as<GenericValueParamDecl>()) { @@ -472,6 +546,8 @@ namespace Slang // Mark sub type as constrained. if (auto subDeclRefType = as<DeclRefType>(constraintDeclRef.getDecl()->sub.type)) constrainedGenericParams.add(subDeclRefType->getDeclRef().getDecl()); + else if (auto subEachType = as<EachType>(constraintDeclRef.getDecl()->sub.type)) + constrainedGenericParams.add(as<DeclRefType>(subEachType->getElementType())->getDeclRef().getDecl()); if (sub->equals(sup)) { @@ -526,6 +602,7 @@ namespace Slang bool SemanticsVisitor::TryUnifyVals( ConstraintSystem& constraints, + ValUnificationContext unifyCtx, Val* fst, bool fstLVal, Val* snd, @@ -536,7 +613,7 @@ namespace Slang { if (auto sndType = as<Type>(snd)) { - return TryUnifyTypes(constraints, QualType(fstType, fstLVal), QualType(sndType, sndLVal)); + return TryUnifyTypes(constraints, unifyCtx, QualType(fstType, fstLVal), QualType(sndType, sndLVal)); } } @@ -564,9 +641,9 @@ namespace Slang bool okay = false; if (fstParam) - okay |= TryUnifyIntParam(constraints, fstParam->getDeclRef(), sndInt); + okay |= TryUnifyIntParam(constraints, unifyCtx, fstParam->getDeclRef(), sndInt); if (sndParam) - okay |= TryUnifyIntParam(constraints, sndParam->getDeclRef(), fstInt); + okay |= TryUnifyIntParam(constraints, unifyCtx, sndParam->getDeclRef(), fstInt); return okay; } @@ -579,6 +656,7 @@ namespace Slang SLANG_ASSERT(constraintDecl1); SLANG_ASSERT(constraintDecl2); return TryUnifyTypes(constraints, + unifyCtx, constraintDecl1.getDecl()->getSup().type, constraintDecl2.getDecl()->getSup().type); } @@ -592,6 +670,7 @@ namespace Slang if (auto sndWit = as<SubtypeWitness>(snd)) { return TryUnifyTypes(constraints, + unifyCtx, fstWit->getSup(), sndWit->getSup()); } @@ -605,6 +684,7 @@ namespace Slang bool SemanticsVisitor::tryUnifyDeclRef( ConstraintSystem& constraints, + ValUnificationContext unifyCtx, DeclRefBase* fst, bool fstIsLVal, DeclRefBase* snd, @@ -620,11 +700,12 @@ namespace Slang return true; if (fstGen == nullptr || sndGen == nullptr) return false; - return tryUnifyGenericAppDeclRef(constraints, fstGen, fstIsLVal, sndGen, sndIsLVal); + return tryUnifyGenericAppDeclRef(constraints, unifyCtx, fstGen, fstIsLVal, sndGen, sndIsLVal); } bool SemanticsVisitor::tryUnifyGenericAppDeclRef( ConstraintSystem& constraints, + ValUnificationContext unifyCtx, GenericAppDeclRef* fst, bool fstIsLVal, GenericAppDeclRef* snd, @@ -645,7 +726,7 @@ namespace Slang bool okay = true; for (Index aa = 0; aa < argCount; ++aa) { - if (!TryUnifyVals(constraints, fstGen->getArgs()[aa], fstIsLVal, sndGen->getArgs()[aa], sndIsLVal)) + if (!TryUnifyVals(constraints, unifyCtx, fstGen->getArgs()[aa], fstIsLVal, sndGen->getArgs()[aa], sndIsLVal)) { okay = false; } @@ -655,7 +736,7 @@ namespace Slang auto fstBase = fst->getBase(); auto sndBase = snd->getBase(); - if (!tryUnifyDeclRef(constraints, fstBase, fstIsLVal, sndBase, sndIsLVal)) + if (!tryUnifyDeclRef(constraints, unifyCtx, fstBase, fstIsLVal, sndBase, sndIsLVal)) { okay = false; } @@ -665,13 +746,15 @@ namespace Slang bool SemanticsVisitor::TryUnifyTypeParam( ConstraintSystem& constraints, - GenericTypeParamDecl* typeParamDecl, + ValUnificationContext unificationContext, + GenericTypeParamDeclBase* typeParamDecl, QualType type) { // We want to constrain the given type parameter // to equal the given type. Constraint constraint; constraint.decl = typeParamDecl; + constraint.indexInPack = unificationContext.indexInTypePack; constraint.val = type; constraint.isUsedAsLValue = type.isLeftValue; constraints.constraints.add(constraint); @@ -681,9 +764,12 @@ namespace Slang bool SemanticsVisitor::TryUnifyIntParam( ConstraintSystem& constraints, + ValUnificationContext unifyCtx, GenericValueParamDecl* paramDecl, IntVal* val) { + SLANG_UNUSED(unifyCtx); + // We only want to accumulate constraints on // the parameters of the declarations being // specialized (don't accidentially constrain @@ -704,12 +790,13 @@ namespace Slang bool SemanticsVisitor::TryUnifyIntParam( ConstraintSystem& constraints, + ValUnificationContext unifyCtx, DeclRef<VarDeclBase> const& varRef, IntVal* val) { if(auto genericValueParamRef = varRef.as<GenericValueParamDecl>()) { - return TryUnifyIntParam(constraints, genericValueParamRef.getDecl(), val); + return TryUnifyIntParam(constraints, unifyCtx, genericValueParamRef.getDecl(), val); } else { @@ -719,6 +806,7 @@ namespace Slang bool SemanticsVisitor::TryUnifyTypesByStructuralMatch( ConstraintSystem& constraints, + ValUnificationContext unifyCtx, QualType fst, QualType snd) { @@ -728,7 +816,7 @@ namespace Slang if (auto typeParamDecl = as<GenericTypeParamDecl>(fstDeclRef.getDecl())) if (typeParamDecl->parentDecl == constraints.genericDecl) - return TryUnifyTypeParam(constraints, typeParamDecl, snd); + return TryUnifyTypeParam(constraints, unifyCtx, typeParamDecl, snd); if (auto sndDeclRefType = as<DeclRefType>(snd)) { @@ -736,7 +824,7 @@ namespace Slang if (auto typeParamDecl = as<GenericTypeParamDecl>(sndDeclRef.getDecl())) if (typeParamDecl->parentDecl == constraints.genericDecl) - return TryUnifyTypeParam(constraints, typeParamDecl, fst); + return TryUnifyTypeParam(constraints, unifyCtx, typeParamDecl, fst); // If they refer to different declarations, we need to check if one type's super type // matches the other type, if so we can unify them. @@ -775,6 +863,7 @@ namespace Slang // to each declaration reference. if (!tryUnifyDeclRef( constraints, + unifyCtx, fstDeclRef, fst.isLeftValue, sndDeclRef, @@ -795,18 +884,46 @@ namespace Slang return false; for(Index i = 0; i < numParams; ++i) { - if(!TryUnifyTypes(constraints, fstFunType->getParamType(i), sndFunType->getParamType(i))) + if(!TryUnifyTypes(constraints, unifyCtx, fstFunType->getParamType(i), sndFunType->getParamType(i))) return false; } - return TryUnifyTypes(constraints, fstFunType->getResultType(), sndFunType->getResultType()); + return TryUnifyTypes(constraints, unifyCtx, fstFunType->getResultType(), sndFunType->getResultType()); + } + } + else if (auto expandType = as<ExpandType>(fst)) + { + if (auto sndExpandType = as<ExpandType>(snd)) + { + return TryUnifyTypes(constraints, unifyCtx, expandType->getPatternType(), sndExpandType->getPatternType()); + } + } + else if (auto eachType = as<EachType>(fst)) + { + if (auto sndEachType = as<EachType>(snd)) + { + return TryUnifyTypes(constraints, unifyCtx, eachType->getElementType(), sndEachType->getElementType()); + } + } + else if (auto typePack = as<ConcreteTypePack>(fst)) + { + if (auto sndTypePack = as<ConcreteTypePack>(snd)) + { + if (typePack->getTypeCount() != sndTypePack->getTypeCount()) + return false; + for (Index i = 0; i < typePack->getTypeCount(); ++i) + { + if (!TryUnifyTypes(constraints, unifyCtx, QualType(typePack->getElementType(i), fst.isLeftValue), QualType(sndTypePack->getElementType(i), snd.isLeftValue))) + return false; + } + return true; } } - return false; } bool SemanticsVisitor::TryUnifyConjunctionType( ConstraintSystem& constraints, + ValUnificationContext unifyCtx, QualType fst, QualType snd) { @@ -820,20 +937,23 @@ namespace Slang // if (auto fstAndType = as<AndType>(fst)) { - return TryUnifyTypes(constraints, QualType(fstAndType->getLeft(), fst.isLeftValue), snd) - && TryUnifyTypes(constraints, QualType(fstAndType->getRight(), fst.isLeftValue), snd); + return TryUnifyTypes(constraints, unifyCtx, QualType(fstAndType->getLeft(), fst.isLeftValue), snd) + && TryUnifyTypes(constraints, unifyCtx, QualType(fstAndType->getRight(), fst.isLeftValue), snd); } else if (auto sndAndType = as<AndType>(snd)) { - return TryUnifyTypes(constraints, fst, QualType(sndAndType->getLeft(), snd.isLeftValue)) - || TryUnifyTypes(constraints, fst, QualType(sndAndType->getRight(), snd.isLeftValue)); + return TryUnifyTypes(constraints, unifyCtx, fst, QualType(sndAndType->getLeft(), snd.isLeftValue)) + || TryUnifyTypes(constraints, unifyCtx, fst, QualType(sndAndType->getRight(), snd.isLeftValue)); } else return false; } - void SemanticsVisitor::maybeUnifyUnconstraintIntParam(ConstraintSystem& constraints, IntVal* param, IntVal* arg, bool paramIsLVal) + void SemanticsVisitor::maybeUnifyUnconstraintIntParam( + ConstraintSystem& constraints, ValUnificationContext unifyCtx, IntVal* param, IntVal* arg, bool paramIsLVal) { + SLANG_UNUSED(unifyCtx); + // If `param` is an unconstrained integer val param, and `arg` is a const int val, // we add a constraint to the system that `param` must be equal to `arg`. // If `param` is already constrained, ignore and do nothing. @@ -857,6 +977,7 @@ namespace Slang bool SemanticsVisitor::TryUnifyTypes( ConstraintSystem& constraints, + ValUnificationContext unifyCtx, QualType fst, QualType snd) { @@ -883,7 +1004,49 @@ namespace Slang // if (as<AndType>(fst) || as<AndType>(snd)) { - return TryUnifyConjunctionType(constraints, fst, snd); + return TryUnifyConjunctionType(constraints, unifyCtx, fst, snd); + } + + // If one of the types is a type pack, we need to recursively unify the element types. + if (auto fstTypePack = as<ConcreteTypePack>(fst)) + { + if (auto sndTypePack = as<ConcreteTypePack>(snd)) + { + if (fstTypePack->getTypeCount() != sndTypePack->getTypeCount()) + return false; + for (Index i = 0; i < fstTypePack->getTypeCount(); ++i) + { + if (!TryUnifyTypes(constraints, unifyCtx,QualType(fstTypePack->getElementType(i), fst.isLeftValue), QualType(sndTypePack->getElementType(i), snd.isLeftValue))) + return false; + } + return true; + } + else if (auto sndExpandType = as<ExpandType>(snd)) + { + for (Index i = 0; i < fstTypePack->getTypeCount(); ++i) + { + ValUnificationContext subUnifyCtx = unifyCtx; + subUnifyCtx.indexInTypePack = i; + if (!TryUnifyTypes(constraints, subUnifyCtx, QualType(fstTypePack->getElementType(i), fst.isLeftValue), QualType(sndExpandType->getPatternType(), snd.isLeftValue))) + return false; + } + return true; + } + } + + if (auto sndTypePack = as<ConcreteTypePack>(snd)) + { + if (auto fstExpandType = as<ExpandType>(fst)) + { + for (Index i = 0; i < sndTypePack->getTypeCount(); ++i) + { + ValUnificationContext subUnifyCtx = unifyCtx; + subUnifyCtx.indexInTypePack = i; + if (!TryUnifyTypes(constraints, subUnifyCtx, QualType(fstExpandType->getPatternType(), fst.isLeftValue), QualType(sndTypePack->getElementType(i), snd.isLeftValue))) + return false; + } + return true; + } } // A generic parameter type can unify with anything. @@ -897,7 +1060,13 @@ namespace Slang if (auto typeParamDecl = as<GenericTypeParamDecl>(fstDeclRef.getDecl())) { if(typeParamDecl->parentDecl == constraints.genericDecl) - return TryUnifyTypeParam(constraints, typeParamDecl, snd); + return TryUnifyTypeParam(constraints, unifyCtx, typeParamDecl, snd); + } + else if (auto typePackParamDecl = as<GenericTypePackParamDecl>(fstDeclRef.getDecl())) + { + if (typePackParamDecl->parentDecl == constraints.genericDecl + && isTypePack(snd)) + return TryUnifyTypeParam(constraints, unifyCtx, typePackParamDecl, snd); } } @@ -905,15 +1074,21 @@ namespace Slang { auto sndDeclRef = sndDeclRefType->getDeclRef(); - if (auto typeParamDecl = as<GenericTypeParamDecl>(sndDeclRef.getDecl())) + if (auto typeParamDecl = as<GenericTypeParamDeclBase>(sndDeclRef.getDecl())) { if(typeParamDecl->parentDecl == constraints.genericDecl) - return TryUnifyTypeParam(constraints, typeParamDecl, fst); + return TryUnifyTypeParam(constraints, unifyCtx, typeParamDecl, fst); + } + else if (auto typePackParamDecl = as<GenericTypePackParamDecl>(sndDeclRef.getDecl())) + { + if (typePackParamDecl->parentDecl == constraints.genericDecl + && isTypePack(fst)) + return TryUnifyTypeParam(constraints, unifyCtx, typePackParamDecl, fst); } } // If we can unify the types structurally, then we are golden - if(TryUnifyTypesByStructuralMatch(constraints, fst, snd)) + if(TryUnifyTypesByStructuralMatch(constraints, unifyCtx, fst, snd)) return true; // Now we need to consider cases where coercion might @@ -930,9 +1105,10 @@ namespace Slang // However, we don't want a failed unification to fail the entire generic argument inference, // because a scalar can still be casted into a vector of any length. - maybeUnifyUnconstraintIntParam(constraints, fstVectorType->getElementCount(), m_astBuilder->getIntVal(m_astBuilder->getIntType(), 1), fst.isLeftValue); + maybeUnifyUnconstraintIntParam(constraints, unifyCtx, fstVectorType->getElementCount(), m_astBuilder->getIntVal(m_astBuilder->getIntType(), 1), fst.isLeftValue); return TryUnifyTypes( constraints, + unifyCtx, QualType(fstVectorType->getElementType(), fst.isLeftValue), QualType(sndScalarType, snd.isLeftValue)); } @@ -942,18 +1118,47 @@ namespace Slang { if(auto sndVectorType = as<VectorExpressionType>(snd)) { - maybeUnifyUnconstraintIntParam(constraints, sndVectorType->getElementCount(), m_astBuilder->getIntVal(m_astBuilder->getIntType(), 1), snd.isLeftValue); + maybeUnifyUnconstraintIntParam(constraints, unifyCtx, sndVectorType->getElementCount(), m_astBuilder->getIntVal(m_astBuilder->getIntType(), 1), snd.isLeftValue); return TryUnifyTypes( constraints, + unifyCtx, QualType(fstScalarType, fst.isLeftValue), QualType(sndVectorType->getElementType(), snd.isLeftValue)); } } if (auto fstUniformParamGroupType = as<UniformParameterGroupType>(fst)) - return TryUnifyTypes(constraints, QualType(fstUniformParamGroupType->getElementType(), fst.isLeftValue), snd); + return TryUnifyTypes(constraints, unifyCtx, QualType(fstUniformParamGroupType->getElementType(), fst.isLeftValue), snd); if (auto sndUniformParamGroupType = as<UniformParameterGroupType>(snd)) - return TryUnifyTypes(constraints, fst, QualType(sndUniformParamGroupType->getElementType(), snd.isLeftValue)); + return TryUnifyTypes(constraints, unifyCtx, fst, QualType(sndUniformParamGroupType->getElementType(), snd.isLeftValue)); + + // Each T can coerce with any DeclRefType. + if (auto eachSnd = as<EachType>(snd)) + { + if (auto innerSnd = eachSnd->getElementDeclRefType()) + { + if (auto sndTypePackParamDecl = as<GenericTypePackParamDecl>(innerSnd->getDeclRef().getDecl())) + { + if (innerSnd->getDeclRef().getDecl()->parentDecl == constraints.genericDecl) + { + return TryUnifyTypeParam(constraints, unifyCtx, sndTypePackParamDecl, fst); + } + } + } + } + if (auto eachFst = as<EachType>(fst)) + { + if (auto innerFst = eachFst->getElementDeclRefType()) + { + if (auto fstTypePackParamDecl = as<GenericTypePackParamDecl>(innerFst->getDeclRef().getDecl())) + { + if (innerFst->getDeclRef().getDecl()->parentDecl == constraints.genericDecl) + { + return TryUnifyTypeParam(constraints, unifyCtx, fstTypePackParamDecl, snd); + } + } + } + } return false; } diff --git a/source/slang/slang-check-conversion.cpp b/source/slang/slang-check-conversion.cpp index c66d4092e..c135ada8d 100644 --- a/source/slang/slang-check-conversion.cpp +++ b/source/slang/slang-check-conversion.cpp @@ -1115,8 +1115,10 @@ namespace Slang OverloadResolveContext overloadContext; overloadContext.disallowNestedConversions = true; overloadContext.argCount = 1; + List<Expr*> args; + args.add(fromExpr); overloadContext.argTypes = &fromType.type; - overloadContext.args = &fromExpr; + overloadContext.args = &args; overloadContext.sourceScope = m_outerScope; overloadContext.originalExpr = nullptr; if(fromExpr) diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 2e5e13360..58fbb4689 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -1561,7 +1561,7 @@ namespace Slang // A variable with an explicit type is simpler, for the // most part. SemanticsVisitor subVisitor(withDeclToExcludeFromLookup(varDecl)); - TypeExp typeExp = subVisitor.CheckUsableType(varDecl->type); + TypeExp typeExp = subVisitor.CheckUsableType(varDecl->type, varDecl); varDecl->type = typeExp; if (varDecl->type.equals(m_astBuilder->getVoidType())) { @@ -7128,6 +7128,11 @@ namespace Slang { args.add(DeclRefType::create(astBuilder, astBuilder->getDirectDeclRef(genericTypeParamDecl))); } + else if (auto genericTypePackParamDecl = as<GenericTypePackParamDecl>(mm)) + { + auto packType = DeclRefType::create(astBuilder, astBuilder->getDirectDeclRef(genericTypePackParamDecl)); + args.add(packType); + } else if (auto genericValueParamDecl = as<GenericValueParamDecl>(mm)) { if (semantics) @@ -7574,7 +7579,7 @@ namespace Slang if(typeExpr.exp) { SemanticsVisitor subVisitor(withDeclToExcludeFromLookup(paramDecl)); - typeExpr = subVisitor.CheckUsableType(typeExpr); + typeExpr = subVisitor.CheckUsableType(typeExpr, paramDecl); paramDecl->type = typeExpr; checkMeshOutputDecl(paramDecl); } @@ -7622,6 +7627,27 @@ namespace Slang } } } + else if (isTypePack(paramDecl->type.type)) + { + // For now, we only allow parameter packs to be `const`. + bool hasConstModifier = false; + for (auto modifier : paramDecl->modifiers) + { + if (as<OutModifier>(modifier) || as<InOutModifier>(modifier) || as<RefModifier>(modifier) || as<ConstRefModifier>(modifier)) + { + getSink()->diagnose(modifier, Diagnostics::parameterPackMustBeConst); + } + else if (as<ConstModifier>(modifier)) + { + hasConstModifier = true; + } + } + if (!hasConstModifier) + { + auto constModifier = this->getASTBuilder()->create<ConstModifier>(); + addModifier(paramDecl, constModifier); + } + } // Only texture types are allowed to have memory qualifiers on parameters if(!paramDecl->type || paramDecl->type->astNodeType != ASTNodeType::TextureType) @@ -8413,7 +8439,7 @@ namespace Slang void SemanticsDeclHeaderVisitor::visitSubscriptDecl(SubscriptDecl* decl) { - decl->returnType = CheckUsableType(decl->returnType); + decl->returnType = CheckUsableType(decl->returnType, decl); visitAbstractStorageDeclCommon(decl); @@ -8423,7 +8449,7 @@ namespace Slang void SemanticsDeclHeaderVisitor::visitPropertyDecl(PropertyDecl* decl) { SemanticsVisitor subVisitor(withDeclToExcludeFromLookup(decl)); - decl->type = subVisitor.CheckUsableType(decl->type); + decl->type = subVisitor.CheckUsableType(decl->type, decl); visitAbstractStorageDeclCommon(decl); checkVisibility(decl); } @@ -8639,7 +8665,7 @@ namespace Slang return createDefaultSubstitutionsIfNeeded(m_astBuilder, this, extDeclRef).as<ExtensionDecl>(); } - if (!TryUnifyTypes(constraints, extDecl->targetType.Ptr(), type)) + if (!TryUnifyTypes(constraints, ValUnificationContext(), extDecl->targetType.Ptr(), type)) return DeclRef<ExtensionDecl>(); ConversionCost baseCost; @@ -9554,12 +9580,12 @@ namespace Slang outTypeList.add(type); } } - OrderedDictionary<GenericTypeParamDecl*, List<Type*>> getCanonicalGenericConstraints( + OrderedDictionary<GenericTypeParamDeclBase*, List<Type*>> getCanonicalGenericConstraints( ASTBuilder* astBuilder, DeclRef<ContainerDecl> genericDecl) { - OrderedDictionary<GenericTypeParamDecl*, List<Type*>> genericConstraints; - for (auto mm : getMembersOfType<GenericTypeParamDecl>(astBuilder, genericDecl)) + OrderedDictionary<GenericTypeParamDeclBase*, List<Type*>> genericConstraints; + for (auto mm : getMembersOfType<GenericTypeParamDeclBase>(astBuilder, genericDecl)) { genericConstraints[mm.getDecl()] = List<Type*>(); } @@ -9574,7 +9600,7 @@ namespace Slang constraintTypes->add(genericTypeConstraintDecl.getDecl()->getSup().type); } - OrderedDictionary<GenericTypeParamDecl*, List<Type*>> result; + OrderedDictionary<GenericTypeParamDeclBase*, List<Type*>> result; for (auto& constraints : genericConstraints) { List<Type*> typeList; diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index 96e0a95d0..561d17c00 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -61,7 +61,10 @@ namespace Slang Expr* SemanticsVisitor::moveTemp(Expr* const& expr, F const& func) { VarDecl* varDecl = m_astBuilder->create<VarDecl>(); - varDecl->parentDecl = nullptr; // TODO: need to fill this in somehow! + varDecl->parentDecl = nullptr; + if (m_outerScope && m_outerScope->containerDecl) + m_outerScope->containerDecl->addMember(varDecl); + addModifier(varDecl, m_astBuilder->create<LocalTempVarModifier>()); varDecl->checkState = DeclCheckState::DefinitionChecked; varDecl->nameAndLoc.loc = expr->loc; varDecl->initExpr = expr; @@ -2091,7 +2094,7 @@ namespace Slang getSink()->diagnose(subscriptExpr, Diagnostics::multiDimensionalArrayNotSupported); } - auto elementType = CoerceToUsableType(TypeExp(baseExpr, baseTypeType->getType())); + auto elementType = CoerceToUsableType(TypeExp(baseExpr, baseTypeType->getType()), nullptr); auto arrayType = getArrayType( m_astBuilder, elementType, @@ -3466,6 +3469,119 @@ namespace Slang return expr; } + + Expr* SemanticsExprVisitor::visitExpandExpr(ExpandExpr* expr) + { + OrderedHashSet<Type*> capturedTypePackSet; + auto subContext = this->withParentExpandExpr(expr, &capturedTypePackSet); + expr->baseExpr = dispatchExpr(expr->baseExpr, subContext); + + Type* patternType = nullptr; + bool isTypeExpr = false; + if (auto typeType = as<TypeType>(expr->baseExpr->type)) + { + patternType = typeType->getType(); + isTypeExpr = true; + } + else + { + patternType = expr->baseExpr->type; + } + if (as<ErrorType>(patternType)) + { + expr->type = m_astBuilder->getErrorType(); + return expr; + } + if (subContext.getCapturedTypePacks()->getCount() == 0) + { + getSink()->diagnose(expr, Diagnostics::expandTermCapturesNoTypePacks); + } + List<Type*> capturedTypePacks; + for (auto capturedType : capturedTypePackSet) + { + capturedTypePacks.add(capturedType); + } + auto expandType = m_astBuilder->getExpandType(patternType, capturedTypePacks.getArrayView()); + if (isTypeExpr) + expr->type = m_astBuilder->getTypeType(expandType); + else + expr->type = QualType(expandType); + return expr; + } + + Expr* SemanticsExprVisitor::visitEachExpr(EachExpr* expr) + { + if (!m_parentExpandExpr) + { + getSink()->diagnose(expr, Diagnostics::eachExprMustBeInsideExpandExpr); + expr->type = m_astBuilder->getErrorType(); + return expr; + } + + expr->baseExpr = CheckTerm(expr->baseExpr); + bool isTypeNode = false; + Type* baseType = nullptr; + if (auto typeType = as<TypeType>(expr->baseExpr->type)) + { + isTypeNode = true; + baseType = typeType->getType(); + } + else + { + baseType = expr->baseExpr->type; + } + if (as<ErrorType>(baseType)) + { + expr->type = m_astBuilder->getErrorType(); + return expr; + } + if (isTypeNode) + { + auto declRefType = as<DeclRefType>(baseType); + if (!declRefType) + { + goto error; + } + if (!declRefType->getDeclRef().as<GenericTypePackParamDecl>()) + { + goto error; + } + } + else + { + if (!isTypePack(baseType) && !as<TupleType>(baseType)) + goto error; + } + { + SLANG_ASSERT(m_capturedTypePacks); + if (auto baseExpandType = as<ExpandType>(baseType)) + { + for (Index i = 0; i < baseExpandType->getCapturedTypePackCount(); i++) + { + auto capturedType = baseExpandType->getCapturedTypePack(i); + m_capturedTypePacks->add(capturedType); + } + } + else + { + m_capturedTypePacks->add(baseType); + } + auto eachType = m_astBuilder->getEachType(baseType); + if (isTypeNode) + expr->type = m_astBuilder->getTypeType(eachType); + else + expr->type = QualType(eachType); + return expr; + } + error:; + expr->type = m_astBuilder->getErrorType(); + if (!as<ErrorType>(baseType)) + { + getSink()->diagnose(expr, Diagnostics::expectTypePackAfterEach); + } + return expr; + } + void SemanticsExprVisitor::maybeCheckKnownBuiltinInvocation(Expr* invokeExpr) { auto checkedInvokeExpr = as<InvokeExpr>(invokeExpr); diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h index 60b8b426d..7565b5472 100644 --- a/source/slang/slang-check-impl.h +++ b/source/slang/slang-check-impl.h @@ -894,6 +894,14 @@ namespace Slang return result; } + SemanticsContext withParentExpandExpr(ExpandExpr* expr, OrderedHashSet<Type*>* capturedTypes) + { + SemanticsContext result(*this); + result.m_parentExpandExpr = expr; + result.m_capturedTypePacks = capturedTypes; + return result; + } + /// Information for tracking one or more outer statements. /// /// During checking of statements, we need to track what @@ -1003,6 +1011,8 @@ namespace Slang Decl* getDeclToExcludeFromLookup() { return m_declToExcludeFromLookup; } + OrderedHashSet<Type*>* getCapturedTypePacks() { return m_capturedTypePacks; } + private: SharedSemanticsContext* m_shared = nullptr; @@ -1044,6 +1054,10 @@ namespace Slang // 2. the logic expression is in the init expression of a static const variable. // 3. the logic expression is in an array size declaration. bool m_shouldShortCircuitLogicExpr = true; + + ExpandExpr* m_parentExpandExpr = nullptr; + + OrderedHashSet<Type*>* m_capturedTypePacks = nullptr; }; struct OuterScopeContextRAII @@ -1341,10 +1355,10 @@ namespace Slang // TODO(tfoley): consider just allowing `void` as a // simple example of a "unit" type, and get rid of // this check. - TypeExp CoerceToUsableType(TypeExp const& typeExp); + TypeExp CoerceToUsableType(TypeExp const& typeExp, Decl* decl); // Check a type, and coerce it to be usable - TypeExp CheckUsableType(TypeExp typeExp); + TypeExp CheckUsableType(TypeExp typeExp, Decl* decl); Expr* CheckTerm(Expr* term); @@ -2060,6 +2074,8 @@ namespace Slang struct Constraint { Decl* decl = nullptr; // the declaration of the thing being constraints + Index indexInPack = 0; // If the constraint is for a type parameter pack, which index in the pack is this constraint for? + Val* val = nullptr; // the value to which we are constraining it bool isUsedAsLValue = false; // If this constraint is for a type parameter, is the type used in an l-value parameter? bool satisfied = false; // Has this constraint been met? @@ -2230,11 +2246,11 @@ namespace Slang // The original arguments to the call Index argCount = 0; - Expr** args = nullptr; + List<Expr*>* args = nullptr; Type** argTypes = nullptr; Index getArgCount() { return argCount; } - Expr*& getArg(Index index) { return args[index]; } + Expr*& getArg(Index index) { return (*args)[index]; } Type* getArgType(Index index) { if(argTypes) @@ -2249,6 +2265,12 @@ namespace Slang else return semantics->maybeResolveOverloadedExpr(getArg(index), LookupMask::Default, nullptr)->type; } + struct MatchedArg + { + Expr* argExpr = nullptr; + Type* argType = nullptr; + }; + bool matchArgumentsToParams(SemanticsVisitor* semantics, const List<QualType>& params, bool computeTypes, ShortList<MatchedArg>& outMatchedArgs); bool disallowNestedConversions = false; @@ -2433,9 +2455,15 @@ namespace Slang // indirect parents. GenericDecl* findNextOuterGeneric(Decl* decl); + struct ValUnificationContext + { + Index indexInTypePack = 0; + }; + // Try to find a unification for two values bool TryUnifyVals( ConstraintSystem& constraints, + ValUnificationContext unificationContext, Val* fst, bool fstLVal, Val* snd, @@ -2443,6 +2471,7 @@ namespace Slang bool tryUnifyDeclRef( ConstraintSystem& constraints, + ValUnificationContext unificationContext, DeclRefBase* fst, bool fstLVal, DeclRefBase* snd, @@ -2450,6 +2479,7 @@ namespace Slang bool tryUnifyGenericAppDeclRef( ConstraintSystem& constraints, + ValUnificationContext unificationContext, GenericAppDeclRef* fst, bool fstLVal, GenericAppDeclRef* snd, @@ -2457,36 +2487,43 @@ namespace Slang bool TryUnifyTypeParam( ConstraintSystem& constraints, - GenericTypeParamDecl* typeParamDecl, + ValUnificationContext unificationContext, + GenericTypeParamDeclBase* typeParamDecl, QualType type); bool TryUnifyIntParam( ConstraintSystem& constraints, + ValUnificationContext unificationContext, GenericValueParamDecl* paramDecl, IntVal* val); bool TryUnifyIntParam( ConstraintSystem& constraints, + ValUnificationContext unificationContext, DeclRef<VarDeclBase> const& varRef, IntVal* val); bool TryUnifyTypesByStructuralMatch( ConstraintSystem& constraints, + ValUnificationContext unificationContext, QualType fst, QualType snd); bool TryUnifyTypes( ConstraintSystem& constraints, + ValUnificationContext unificationContext, QualType fst, QualType snd); bool TryUnifyConjunctionType( ConstraintSystem& constraints, + ValUnificationContext unificationContext, QualType fst, QualType snd); void maybeUnifyUnconstraintIntParam( ConstraintSystem& constraints, + ValUnificationContext unificationContext, IntVal* param, IntVal* arg, bool paramIsLVal); @@ -2696,6 +2733,10 @@ namespace Slang Expr* visitAsTypeExpr(AsTypeExpr* expr); + Expr* visitExpandExpr(ExpandExpr* expr); + + Expr* visitEachExpr(EachExpr* expr); + void maybeCheckKnownBuiltinInvocation(Expr* invokeExpr); // @@ -2726,7 +2767,7 @@ namespace Slang CASE(OpenRefExpr) CASE(MakeOptionalExpr) CASE(PartiallyAppliedGenericExpr) - + CASE(PackExpr) #undef CASE Expr* visitStaticMemberExpr(StaticMemberExpr* expr); diff --git a/source/slang/slang-check-inheritance.cpp b/source/slang/slang-check-inheritance.cpp index 7320d0463..3e59c5e8d 100644 --- a/source/slang/slang-check-inheritance.cpp +++ b/source/slang/slang-check-inheritance.cpp @@ -266,7 +266,7 @@ namespace Slang addDirectBaseType(baseType, satisfyingWitness); } } - else if (auto genericTypeParamDeclRef = declRef.as<GenericTypeParamDecl>()) + else if (auto genericTypeParamDeclRef = declRef.as<GenericTypeParamDeclBase>()) { // The constraints placed on a generic type parameter are siblings of that // parameter in its parent `GenericDecl`, so we need to enumerate all of @@ -298,7 +298,14 @@ namespace Slang // auto subDeclRefType = as<DeclRefType>(subType); if (!subDeclRefType) - continue; + { + if (auto subEachType = as<EachType>(subType)) + { + subDeclRefType = as<DeclRefType>(subEachType->getElementType()); + } + if (!subDeclRefType) + continue; + } if (subDeclRefType->getDeclRef() != genericTypeParamDeclRef) continue; @@ -922,6 +929,35 @@ namespace Slang info.facets = mergedFacets; return info; } + else if (auto eachType = as<EachType>(type)) + { + auto elementInheritanceInfo = getInheritanceInfo(eachType->getElementType()); + SemanticsVisitor visitor(this); + auto directFacet = new(arena) Facet::Impl( + Facet::Kind::Type, + Facet::Directness::Self, + DeclRef<Decl>(), + type, + visitor.createTypeEqualityWitness(type)); + Facet tail = directFacet; + for (auto facet : elementInheritanceInfo.facets) + { + if (facet->directness == Facet::Directness::Direct) + { + auto eachFacet = new(arena) Facet::Impl( + Facet::Kind::Type, + Facet::Directness::Direct, + facet->origin.declRef, + facet->origin.type, + astBuilder->getEachSubtypeWitness(type, facet->subtypeWitness->getSup(), facet->subtypeWitness)); + tail->next = eachFacet; + tail = eachFacet; + } + } + InheritanceInfo info; + info.facets = FacetList(directFacet); + return info; + } else { // As a fallback, any type not covered by the above cases will diff --git a/source/slang/slang-check-overload.cpp b/source/slang/slang-check-overload.cpp index d37c6e469..16f6ed7da 100644 --- a/source/slang/slang-check-overload.cpp +++ b/source/slang/slang-check-overload.cpp @@ -15,22 +15,37 @@ namespace Slang ParamCounts counts = { 0, 0 }; for (auto param : params) { - counts.allowed++; - - // No initializer means no default value - // - // TODO(tfoley): The logic here is currently broken in two ways: - // - // 1. We are assuming that once one parameter has a default, then all do. - // This can/should be validated earlier, so that we can assume it here. - // - // 2. We are not handling the possibility of multiple declarations for - // a single function, where we'd need to merge default parameters across - // all the declarations. - if (!param.getDecl()->initExpr) + Index allowedArgCountToAdd = 1; + auto paramType = getParamType(m_astBuilder, param); + if (isTypePack(paramType)) { + if (auto typePack = as<ConcreteTypePack>(paramType)) + { + counts.required += typePack->getTypeCount(); + allowedArgCountToAdd = typePack->getTypeCount(); + } + else + { + counts.allowed = -1; + } + } + else if (!param.getDecl()->initExpr) + { + // No initializer means no default value + // + // TODO(tfoley): The logic here is currently broken in two ways: + // + // 1. We are assuming that once one parameter has a default, then all do. + // This can/should be validated earlier, so that we can assume it here. + // + // 2. We are not handling the possibility of multiple declarations for + // a single function, where we'd need to merge default parameters across + // all the declarations. counts.required++; } + + if (counts.allowed >= 0) + counts.allowed += allowedArgCountToAdd; } return counts; } @@ -42,7 +57,8 @@ namespace Slang { if (auto typeParam = as<GenericTypeParamDecl>(m)) { - counts.allowed++; + if (counts.allowed >= 0) + counts.allowed++; if (!typeParam->initType.Ptr()) { counts.required++; @@ -50,12 +66,17 @@ namespace Slang } else if (auto valParam = as<GenericValueParamDecl>(m)) { - counts.allowed++; + if (counts.allowed >= 0) + counts.allowed++; if (!valParam->initExpr) { counts.required++; } } + else if (as<GenericTypePackParamDecl>(m)) + { + counts.allowed = -1; + } } return counts; } @@ -130,7 +151,7 @@ namespace Slang break; } - if (argCount >= paramCounts.required && argCount <= paramCounts.allowed) + if (argCount >= paramCounts.required && (paramCounts.allowed == -1 || argCount <= paramCounts.allowed)) return true; // Emit an error message if we are checking this call for real @@ -270,13 +291,35 @@ namespace Slang getSink()->diagnose(context.loc, Diagnostics::cannotSpecializeGeneric, candidate.item.declRef); } }; + List<QualType> paramTypes; + for (auto memberRef : getMembers(m_astBuilder, genericDeclRef)) + { + if (auto typeParamRef = memberRef.as<GenericTypeParamDecl>()) + { + paramTypes.add(DeclRefType::create(m_astBuilder, typeParamRef)); + } + else if (auto valParamRef = memberRef.as<GenericValueParamDecl>()) + { + paramTypes.add(getType(m_astBuilder, valParamRef)); + } + else if (auto typePackParam = memberRef.as<GenericTypePackParamDecl>()) + { + paramTypes.add(DeclRefType::create(m_astBuilder, typePackParam)); + } + } + ShortList<OverloadResolveContext::MatchedArg> matchedArgs; + if (!context.matchArgumentsToParams(this, paramTypes, false, matchedArgs)) + { + maybeReportGeneralError(); + return false; + } Index aa = 0; for (auto memberRef : getMembers(m_astBuilder, genericDeclRef)) { if (auto typeParamRef = memberRef.as<GenericTypeParamDecl>()) { - if (aa >= context.argCount) + if (aa >= matchedArgs.getCount()) { if (allowPartialGenericApp) { @@ -319,15 +362,15 @@ namespace Slang // the checking "for real" in which case any errors // we run into need to be reported. // - auto arg = context.getArg(aa++); + auto arg = matchedArgs[aa++]; if (context.mode == OverloadResolveContext::Mode::JustTrying) { - typeArg = tryCoerceToProperType(TypeExp(arg)); + typeArg = tryCoerceToProperType(TypeExp(arg.argExpr)); } else { - arg = ExpectATypeRepr(arg); - typeArg = CoerceToProperType(TypeExp(arg)); + arg.argExpr = ExpectATypeRepr(arg.argExpr); + typeArg = CoerceToProperType(TypeExp(arg.argExpr)); } // If we failed to get a valid type (either because @@ -345,7 +388,7 @@ namespace Slang } else if (auto valParamRef = memberRef.as<GenericValueParamDecl>()) { - if (aa >= context.argCount) + if (aa >= matchedArgs.getCount()) { if (allowPartialGenericApp) { @@ -384,7 +427,7 @@ namespace Slang // to the type of the parameter (and fail if the // coercion is not possible) // - arg = context.getArg(aa++); + arg = matchedArgs[aa++].argExpr; if (context.mode == OverloadResolveContext::Mode::JustTrying) { ConversionCost cost = kConversionCost_None; @@ -418,6 +461,78 @@ namespace Slang } checkedArgs.add(val); } + else if (auto typePackParam = memberRef.as<GenericTypePackParamDecl>()) + { + Val* val = nullptr; + if (aa >= matchedArgs.getCount()) + { + // If we run out of matched args, we will just create an empty pack. + val = m_astBuilder->getTypePack(ArrayView<Type*>()); + } + else + { + auto matchedArg = matchedArgs[aa++]; + if (auto packExpr = as<PackExpr>(matchedArg.argExpr)) + { + // We are providing a concrete pack of types as arguments to a type pack parameter. + // We need to create a `TypePack` type to serve as the argument. + ShortList<Type*> coercedProperTypes; + + // Coerce all types in the pack to proper types. + for (Index i = 0; i < packExpr->args.getCount(); i++) + { + TypeExp typeArg; + auto elementTypeExpr = packExpr->args[i]; + if (context.mode == OverloadResolveContext::Mode::JustTrying) + { + typeArg = tryCoerceToProperType(TypeExp(elementTypeExpr)); + if (!typeArg.type) + { + typeArg.type = m_astBuilder->getErrorType(); + success = false; + } + } + else + { + elementTypeExpr = ExpectATypeRepr(elementTypeExpr); + typeArg = CoerceToProperType(TypeExp(elementTypeExpr)); + } + // If we failed to get a valid type (either because + // there was no matching argument, or because the + // "just trying" coercion failed), then we create + // an error type to stand in for the argument + // + if (!typeArg.type) + { + typeArg.type = m_astBuilder->getErrorType(); + success = false; + } + coercedProperTypes.add(typeArg.type); + } + val = m_astBuilder->getTypePack(coercedProperTypes.getArrayView().arrayView); + } + else if (auto expandExpr = as<ExpandExpr>(matchedArg.argExpr)) + { + auto argType = expandExpr->type.type; + if (auto typeType = as<TypeType>(argType)) + argType = typeType->getType(); + val = argType; + } + else if (auto typeType = as<TypeType>(matchedArg.argType)) + { + if (isAbstractTypePack(typeType->getType())) + { + val = typeType->getType(); + } + } + } + if (val == nullptr) + { + maybeReportGeneralError(); + return false; + } + checkedArgs.add(val); + } else { continue; @@ -497,37 +612,104 @@ namespace Slang break; } - // Note(tfoley): We might have fewer arguments than parameters in the - // case where one or more parameters had defaults. - SLANG_RELEASE_ASSERT(argCount <= paramTypes.getCount()); + Index paramIndex = 0; + Index argIndex = 0; + struct Arg { Expr* argExpr; Type* type; }; + auto readArg = [&]() -> Arg + { + if (argIndex >= argCount) + return { nullptr, nullptr }; + auto arg = context.getArg(argIndex); + Arg result = { arg, context.getArgType(argIndex) }; + argIndex++; + return result; + }; - for (Index ii = 0; ii < argCount; ++ii) + auto coerceArgToParam = [&](Arg arg, QualType paramType) -> Arg + { + auto argType = QualType(arg.type, paramType.isLeftValue); + if (!paramType) + return { nullptr, nullptr }; + if (!argType) + return { nullptr, nullptr }; + if (context.mode == OverloadResolveContext::Mode::JustTrying) + { + ConversionCost cost = kConversionCost_None; + if (context.disallowNestedConversions) + { + // We need an exact match in this case. + if (!paramType->equals(argType)) + return { nullptr, nullptr }; + } + else if (!canCoerce(paramType, argType, arg.argExpr, &cost)) + { + return { nullptr, nullptr }; + } + candidate.conversionCostSum += cost; + } + else + { + arg.argExpr = coerce(CoercionSite::Argument, paramType, arg.argExpr); + } + return arg; + }; + ShortList<Expr*> resultArgs; + + while (paramIndex < paramTypes.getCount()) { - auto& arg = context.getArg(ii); - auto paramType = paramTypes[ii]; - auto argType = QualType(context.getArgType(ii), paramType.isLeftValue); - if (!paramType) - return false; - if (!argType) - return false; - if (context.mode == OverloadResolveContext::Mode::JustTrying) + auto paramType = paramTypes[paramIndex]; + if (auto paramTypePack = as<ConcreteTypePack>(paramType)) { - ConversionCost cost = kConversionCost_None; - if( context.disallowNestedConversions ) + ShortList<Expr*> innerArgs; + for (Index i = 0; i < paramTypePack->getTypeCount(); i++) { - // We need an exact match in this case. - if(!paramType->equals(argType)) + auto arg = readArg(); + auto coercedArg = coerceArgToParam(arg, QualType(paramTypePack->getElementType(i), paramType.isLeftValue)); + if (!coercedArg.type) + { return false; + } + if (context.mode == OverloadResolveContext::Mode::ForReal) + innerArgs.add(coercedArg.argExpr); } - else if (!canCoerce(paramType, argType, arg, &cost)) + if (context.mode == OverloadResolveContext::Mode::ForReal) { - return false; + auto packArg = m_astBuilder->create<PackExpr>(); + for (auto aa : innerArgs) + packArg->args.add(aa); + packArg->type = paramType; + resultArgs.add(packArg); } - candidate.conversionCostSum += cost; } else { - arg = coerce(CoercionSite::Argument, paramType, arg); + auto arg = readArg(); + if (!arg.type) + { + // If we run out of arguments, we can exit the loop now. + // Note that in this type we don't need to worry about + // default arguments, because we already checked that + // the number of arguments was correct in `TryCheckOverloadCandidateArity`. + break; + } + auto coercedArg = coerceArgToParam(arg, paramType); + if (!coercedArg.type) + { + return false; + } + if (context.mode == OverloadResolveContext::Mode::ForReal) + resultArgs.add(coercedArg.argExpr); + } + paramIndex++; + } + if (context.mode == OverloadResolveContext::Mode::ForReal) + { + context.argCount = resultArgs.getCount(); + if (context.args) + { + context.args->setCount(context.argCount); + for (Index i = 0; i < context.argCount; i++) + (*context.args)[i] = resultArgs[i]; } } return true; @@ -1448,6 +1630,110 @@ namespace Slang AddOverloadCandidate(context, candidate, baseCost); } + bool SemanticsVisitor::OverloadResolveContext::matchArgumentsToParams( + SemanticsVisitor* semantics, + const List<QualType>& params, + bool computeTypes, + ShortList<MatchedArg>& outMatchedArgs) + { + // We allow params to end with one or more variadic packs. + // We will first find out how many type packs there are. + Index typePackCount = 0; + for (Index i = params.getCount() - 1; i >= 0; --i) + { + if (isTypePack(params[i].type)) + typePackCount++; + else + break; + } + auto fixedParamCount = params.getCount() - typePackCount; + + auto remainingArgCount = getArgCount() - fixedParamCount; + + // If there are remaining arguments after matching all fixed parameters, + // we'd better have at least one type pack. + if (remainingArgCount > 0 && typePackCount == 0) + return false; + + // Now we can match the arguments to the parameters. + + // The fixed part comes first. + for (Index i = 0; i < Math::Min(getArgCount(), fixedParamCount); ++i) + { + MatchedArg arg; + arg.argExpr = getArg(i); + arg.argType = getArgType(i); + outMatchedArgs.add(arg); + } + + // Try to match the variadic part. + // Is the corresponding argument a expand expr? If so it will map 1:1 to the type pack param. + auto astBuilder = semantics->getASTBuilder(); + while (remainingArgCount > 0) + { + auto argType = getArgType(fixedParamCount); + if (auto typeType = as<TypeType>(argType)) + { + argType = typeType->getType(); + } + if (isAbstractTypePack(argType)) + { + MatchedArg arg; + arg.argExpr = getArg(fixedParamCount); + arg.argType = getArgType(fixedParamCount); + outMatchedArgs.add(arg); + fixedParamCount++; + remainingArgCount--; + typePackCount--; + continue; + } + break; + } + + if (remainingArgCount <= 0) + return true; + if (typePackCount == 0) + return false; + + // If the number of type packs can't evenly divide the remaining arguments, + // there isn't a match. + if (remainingArgCount % typePackCount != 0) + return false; + + // The default case is to group the remaining arguments into evenly divided PackExprs. + Index typePackSize = remainingArgCount / typePackCount; + for (Index i = 0; i < typePackCount; ++i) + { + PackExpr* packExpr = nullptr; + if (mode == Mode::ForReal) + { + packExpr = astBuilder->create<PackExpr>(); + packExpr->loc = loc; + } + ShortList<Type*> types; + for (Index j = 0; j < typePackSize; ++j) + { + if (packExpr) + { + auto arg = getArg(fixedParamCount + i * typePackSize + j); + packExpr->args.add(arg); + } + if (computeTypes) + types.add(getArgTypeForInference(fixedParamCount + i * typePackSize + j, semantics)); + } + MatchedArg matchedArg; + matchedArg.argExpr = packExpr; + if (computeTypes) + { + matchedArg.argType = astBuilder->getTypePack(types.getArrayView().arrayView); + if (packExpr) + packExpr->type = matchedArg.argType; + } + outMatchedArgs.add(matchedArg); + } + return true; + } + DeclRef<Decl> SemanticsVisitor::inferGenericArguments( DeclRef<GenericDecl> genericDeclRef, OverloadResolveContext& context, @@ -1506,25 +1792,23 @@ namespace Slang innerParameterTypes = ¶mTypes; } - Index valueArgCount = context.getArgCount(); - Index valueParamCount = innerParameterTypes->getCount(); + ShortList<OverloadResolveContext::MatchedArg> matchedArgs; - // If there are too many arguments, we cannot possibly have a match. + // We now try to match arguments to parameters. // // Note that if there are *too few* arguments, we might still have // a match, because the other arguments might have default values // that can be used. // - if (valueArgCount > valueParamCount) + if (!context.matchArgumentsToParams(this, *innerParameterTypes, true, matchedArgs)) { return DeclRef<Decl>(); } - // If any of the arguments were specified explicitly (and are thus known), - // we do not want to take them into account during the unification and - // constraint generation step. + // Perform type unification between arguments and parameters, so + // we can populate the resolve system with inital constraints. // - for (Index aa = 0; aa < valueArgCount; ++aa) + for (Index aa = 0; aa < matchedArgs.getCount(); ++aa) { // The question here is whether failure to "unify" an argument // and parameter should lead to immediate failure. @@ -1543,12 +1827,19 @@ namespace Slang // // So the question is then whether a mismatch during the // unification step should be taken as an immediate failure... - auto argType = context.getArgTypeForInference(aa, this); + auto argType = matchedArgs[aa].argType; auto paramType = (*innerParameterTypes)[aa]; - TryUnifyTypes( + auto canUnify = TryUnifyTypes( constraints, + ValUnificationContext(), QualType(argType, paramType.isLeftValue), paramType); + + // It is an error if we can't unify the argument with a type pack parameter. + if (!canUnify && isTypePack(paramType)) + { + return DeclRef<Decl>(); + } } } else @@ -1984,7 +2275,7 @@ namespace Slang context.originalExpr = expr; context.funcLoc = funcExpr->loc; context.argCount = expr->arguments.getCount(); - context.args = expr->arguments.getBuffer(); + context.args = &expr->arguments; context.loc = expr->loc; context.sourceScope = m_outerScope; context.baseExpr = GetBaseExpr(funcExpr); @@ -2238,7 +2529,7 @@ namespace Slang context.originalExpr = genericAppExpr; context.funcLoc = baseExpr->loc; context.argCount = args.getCount(); - context.args = args.getBuffer(); + context.args = &args; context.loc = genericAppExpr->loc; context.sourceScope = m_outerScope; context.baseExpr = GetBaseExpr(baseExpr); diff --git a/source/slang/slang-check-type.cpp b/source/slang/slang-check-type.cpp index 217d1b545..eeee13561 100644 --- a/source/slang/slang-check-type.cpp +++ b/source/slang/slang-check-type.cpp @@ -389,7 +389,7 @@ namespace Slang return CoerceToProperType(TranslateTypeNode(typeExp)); } - TypeExp SemanticsVisitor::CoerceToUsableType(TypeExp const& typeExp) + TypeExp SemanticsVisitor::CoerceToUsableType(TypeExp const& typeExp, Decl* decl) { TypeExp result = CoerceToProperType(typeExp); Type* type = result.type; @@ -404,12 +404,20 @@ namespace Slang return result; } } + + // A type pack is not a usable type other than for defining parameters. + if (!as<ParamDecl>(decl) && isTypePack(type)) + { + getSink()->diagnose(typeExp.exp, Diagnostics::improperUseOfType, typeExp.type); + result.type = m_astBuilder->getErrorType(); + return result; + } return result; } - TypeExp SemanticsVisitor::CheckUsableType(TypeExp typeExp) + TypeExp SemanticsVisitor::CheckUsableType(TypeExp typeExp, Decl* decl) { - return CoerceToUsableType(TranslateTypeNode(typeExp)); + return CoerceToUsableType(TranslateTypeNode(typeExp), decl); } bool SemanticsVisitor::ValuesAreEqual( diff --git a/source/slang/slang-check.h b/source/slang/slang-check.h index e59f299fa..b5e64f47f 100644 --- a/source/slang/slang-check.h +++ b/source/slang/slang-check.h @@ -23,6 +23,6 @@ namespace Slang void registerBuiltinDecls(Session* session, Decl* decl); - OrderedDictionary<GenericTypeParamDecl*, List<Type*>> getCanonicalGenericConstraints( + OrderedDictionary<GenericTypeParamDeclBase*, List<Type*>> getCanonicalGenericConstraints( ASTBuilder* builder, DeclRef<ContainerDecl> genericDecl); } diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 03e8efbc0..a58b59c0c 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -363,6 +363,12 @@ DIAGNOSTIC(30099, Error, sizeOfArgumentIsInvalid, "argument to sizeof is invalid DIAGNOSTIC(30101, Error, readingFromWriteOnly, "cannot read from writeonly, check modifiers.") DIAGNOSTIC(30102, Error, differentiableMemberShouldHaveCorrespondingFieldInDiffType, "differentiable member '$0' should have a corresponding field in '$1'. Use [DerivativeMember($1.<field-name>)] or mark as no_diff") +DIAGNOSTIC(30103, Error, expectTypePackAfterEach, "expected a type pack or a tuple after 'each'.") +DIAGNOSTIC(30104, Error, eachExprMustBeInsideExpandExpr, "'each' expression must be inside 'expand' expression.") +DIAGNOSTIC(30105, Error, expandTermCapturesNoTypePacks, "'expand' term captures no type packs. At least one type pack must be referenced via an 'each' term inside an 'expand' term.") +DIAGNOSTIC(30106, Error, improperUseOfType, "type '$0' cannot be used in this context.") +DIAGNOSTIC(30107, Error, parameterPackMustBeConst, "a parameter pack must be declared as 'const'.") + // Include DIAGNOSTIC(30500, Error, includedFileMissingImplementing, "missing 'implementing' declaration in the included source file '$0'.") diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index 50d017fb9..95e9d96da 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -4315,6 +4315,21 @@ struct ExprLoweringVisitorBase : public ExprVisitor<Derived, LoweredValInfo> return lowerSubExpr(expr->base); } + LoweredValInfo visitPackExpr(PackExpr*) + { + SLANG_UNIMPLEMENTED_X("codegen for pack expression"); + } + + LoweredValInfo visitEachExpr(EachExpr*) + { + SLANG_UNIMPLEMENTED_X("codegen for each expression"); + } + + LoweredValInfo visitExpandExpr(ExpandExpr*) + { + SLANG_UNIMPLEMENTED_X("codegen for expand expression"); + } + LoweredValInfo getSimpleDefaultVal(IRType* type) { type = (IRType*)unwrapAttributedType(type); diff --git a/source/slang/slang-mangle.cpp b/source/slang/slang-mangle.cpp index 779a6f090..7951ddc38 100644 --- a/source/slang/slang-mangle.cpp +++ b/source/slang/slang-mangle.cpp @@ -266,6 +266,23 @@ namespace Slang emitType(context, andType->getLeft()); emitType(context, andType->getRight()); } + else if (auto expandType = as<ExpandType>(type)) + { + emitRaw(context, "Tx"); + emitType(context, expandType->getPatternType()); + } + else if (auto eachType = as<EachType>(type)) + { + emitRaw(context, "Te"); + emitType(context, eachType->getElementType()); + } + else if (auto typePack = as<ConcreteTypePack>(type)) + { + emitRaw(context, "Tp"); + emit(context, typePack->getTypeCount()); + for (Index i = 0; i < typePack->getTypeCount(); i++) + emitType(context, typePack->getElementType(i)); + } else { SLANG_UNEXPECTED("unimplemented case in type mangling"); @@ -492,6 +509,10 @@ namespace Slang { genericParameterCount++; } + else if (mm.is<GenericTypePackParamDecl>()) + { + genericParameterCount++; + } else { } @@ -499,13 +520,17 @@ namespace Slang emit(context, genericParameterCount); - OrderedDictionary<GenericTypeParamDecl*, List<Type*>> genericConstraints; + OrderedDictionary<GenericTypeParamDeclBase*, List<Type*>> genericConstraints; for (auto mm : getMembers(context->astBuilder, parentGenericDeclRef)) { if (auto genericTypeParamDecl = mm.as<GenericTypeParamDecl>()) { emitRaw(context, "T"); } + if (auto genericTypePackParamDecl = mm.as<GenericTypePackParamDecl>()) + { + emitRaw(context, "TP"); + } else if (auto genericValueParamDecl = mm.as<GenericValueParamDecl>()) { emitRaw(context, "v"); diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index 10b52611f..c1f0f91c2 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -112,6 +112,10 @@ namespace Slang bool hasSeenCompletionToken = false; + // Track whether or not we are inside a generics that has variadic parameters. + // If so we will enable the new `expand` and `each` keyword. + bool isInVariadicGenerics = false; + TokenReader tokenReader; DiagnosticSink* sink; SourceLoc lastErrorLoc; @@ -1476,41 +1480,50 @@ namespace Slang } return paramDecl; } + Decl* paramDecl = nullptr; + if (AdvanceIf(parser, "each")) + { + // A type pack parameter. + paramDecl = parser->astBuilder->create<GenericTypePackParamDecl>(); + parser->FillPosition(paramDecl); + paramDecl->nameAndLoc = NameLoc(parser->ReadToken(TokenType::Identifier)); + } else { // default case is a type parameter - GenericTypeParamDecl* paramDecl = parser->astBuilder->create<GenericTypeParamDecl>(); + paramDecl = parser->astBuilder->create<GenericTypeParamDecl>(); parser->FillPosition(paramDecl); paramDecl->nameAndLoc = NameLoc(parser->ReadToken(TokenType::Identifier)); - if (AdvanceIf(parser, TokenType::Colon)) - { - // The user is apply a constraint to this type parameter... - - auto paramConstraint = parser->astBuilder->create<GenericTypeConstraintDecl>(); - parser->FillPosition(paramConstraint); + } + if (AdvanceIf(parser, TokenType::Colon)) + { + // The user is apply a constraint to this type parameter... - auto paramType = DeclRefType::create( - parser->astBuilder, - DeclRef<Decl>(paramDecl)); + auto paramConstraint = parser->astBuilder->create<GenericTypeConstraintDecl>(); + parser->FillPosition(paramConstraint); - auto paramTypeExpr = parser->astBuilder->create<SharedTypeExpr>(); - paramTypeExpr->loc = paramDecl->loc; - paramTypeExpr->base.type = paramType; - paramTypeExpr->type = QualType(parser->astBuilder->getTypeType(paramType)); - - paramConstraint->sub = TypeExp(paramTypeExpr); - paramConstraint->sup = parser->ParseTypeExp(); + auto paramType = DeclRefType::create( + parser->astBuilder, + DeclRef<Decl>(paramDecl)); - AddMember(genericDecl, paramConstraint); + auto paramTypeExpr = parser->astBuilder->create<SharedTypeExpr>(); + paramTypeExpr->loc = paramDecl->loc; + paramTypeExpr->base.type = paramType; + paramTypeExpr->type = QualType(parser->astBuilder->getTypeType(paramType)); + paramConstraint->sub = TypeExp(paramTypeExpr); + paramConstraint->sup = parser->ParseTypeExp(); - } + AddMember(genericDecl, paramConstraint); + } + if (auto typeParameter = as<GenericTypeParamDecl>(paramDecl)) + { if (AdvanceIf(parser, TokenType::OpAssign)) { - paramDecl->initType = parser->ParseTypeExp(); + typeParameter->initType = parser->ParseTypeExp(); } - return paramDecl; } + return paramDecl; } template<typename TFunc> @@ -1519,6 +1532,9 @@ namespace Slang { parser->ReadToken(TokenType::OpLess); parser->genericDepth++; + bool oldIsInVariadicGenerics = parser->isInVariadicGenerics; + SLANG_DEFER(parser->isInVariadicGenerics = oldIsInVariadicGenerics); + for (;;) { const TokenType tokenType = parser->tokenReader.peekTokenType(); @@ -1530,7 +1546,13 @@ namespace Slang auto currentCursor = parser->tokenReader.getCursor(); - AddMember(decl, ParseGenericParamDecl(parser, decl)); + auto genericParam = ParseGenericParamDecl(parser, decl); + AddMember(decl, genericParam); + + if (as<GenericTypePackParamDecl>(genericParam)) + { + parser->isInVariadicGenerics = true; + } // Make sure we make forward progress. if (parser->tokenReader.getCursor() == currentCursor) @@ -2567,6 +2589,11 @@ namespace Slang typeSpec.expr = createDeclRefType(parser, decl); return typeSpec; } + else if (parser->LookAheadToken("expand") || parser->LookAheadToken("each")) + { + typeSpec.expr = parser->ParseExpression(); + return typeSpec; + } // Uncomment should we decide to enable (a,b,c) tuple types // else if(parser->LookAheadToken(TokenType::LParent)) // { @@ -6161,65 +6188,6 @@ namespace Slang { auto expr = ParseLeafExpression(); return parseInfixExprWithPrecedence(this, expr, level); - -#if 0 - - if (level == Precedence::Prefix) - return ParseLeafExpression(); - if (level == Precedence::TernaryConditional) - { - // parse select clause - auto condition = ParseExpression(Precedence(level + 1)); - if (LookAheadToken(TokenType::QuestionMark)) - { - SelectExpr* select = new SelectExpr(); - FillPosition(select.Ptr()); - - select->Arguments.add(condition); - - select->FunctionExpr = parseOperator(this); - - select->Arguments.add(ParseExpression(level)); - ReadToken(TokenType::Colon); - select->Arguments.add(ParseExpression(level)); - return select; - } - else - return condition; - } - else - { - if (GetAssociativityFromLevel(level) == Associativity::Left) - { - auto left = ParseExpression(Precedence(level + 1)); - while (GetOpLevel(this, tokenReader.PeekTokenType()) == level) - { - OperatorExpr* tmp = new InfixExpr(); - tmp->FunctionExpr = parseOperator(this); - - tmp->Arguments.add(left); - FillPosition(tmp.Ptr()); - tmp->Arguments.add(ParseExpression(Precedence(level + 1))); - left = tmp; - } - return left; - } - else - { - auto left = ParseExpression(Precedence(level + 1)); - if (GetOpLevel(this, tokenReader.PeekTokenType()) == level) - { - OperatorExpr* tmp = new InfixExpr(); - tmp->Arguments.add(left); - FillPosition(tmp.Ptr()); - tmp->FunctionExpr = parseOperator(this); - tmp->Arguments.add(ParseExpression(level)); - left = tmp; - } - return left; - } - } -#endif } // We *might* be looking at an application of a generic to arguments, @@ -7549,10 +7517,10 @@ namespace Slang return ret; } - static Expr* parseSPIRVAsmExpr(Parser* parser) + static Expr* parseSPIRVAsmExpr(Parser* parser, SourceLoc loc) { SPIRVAsmExpr* asmExpr = parser->astBuilder->create<SPIRVAsmExpr>(); - parser->FillPosition(asmExpr); + asmExpr->loc = loc; parser->ReadToken(TokenType::LBrace); while(!parser->tokenReader.isAtEnd()) { @@ -7577,6 +7545,22 @@ namespace Slang return asmExpr; } + static Expr* parseExpandExpr(Parser* parser, SourceLoc loc) + { + ExpandExpr* expandExpr = parser->astBuilder->create<ExpandExpr>(); + expandExpr->loc = loc; + expandExpr->baseExpr = parser->ParseExpression(); + return expandExpr; + } + + static Expr* parseEachExpr(Parser* parser, SourceLoc loc) + { + EachExpr* eachExpr = parser->astBuilder->create<EachExpr>(); + eachExpr->loc = loc; + eachExpr->baseExpr = parser->ParseExpression(); + return eachExpr; + } + static Expr* parsePrefixExpr(Parser* parser) { auto tokenType = peekTokenType(parser); @@ -7584,13 +7568,11 @@ namespace Slang { case TokenType::Identifier: { - auto identifierToken = peekToken(parser); - const auto identifierTokenContent = identifierToken.getContent(); - if (identifierTokenContent == toSlice("new")) + auto tokenLoc = peekToken(parser).getLoc(); + if (AdvanceIf(parser, "new")) { NewExpr* newExpr = parser->astBuilder->create<NewExpr>(); - parser->FillPosition(newExpr); - parser->ReadToken(); + newExpr->loc = tokenLoc; auto subExpr = parsePostfixExpr(parser); if (as<VarExpr>(subExpr) || as<GenericAppExpr>(subExpr)) { @@ -7611,9 +7593,21 @@ namespace Slang } else if (AdvanceIf(parser, "spirv_asm")) { - return parseSPIRVAsmExpr(parser); + return parseSPIRVAsmExpr(parser, tokenLoc); + } + else if (parser->isInVariadicGenerics) + { + // If we are inside a variadic generic, we also need to recognize + // the new `expand` and `each` keyword for dealing with variadic packs. + if (AdvanceIf(parser, "expand")) + { + return parseExpandExpr(parser, tokenLoc); + } + else if (AdvanceIf(parser, "each")) + { + return parseEachExpr(parser, tokenLoc); + } } - return parsePostfixExpr(parser); } default: diff --git a/source/slang/slang.natvis b/source/slang/slang.natvis index 21db4016f..70b57e339 100644 --- a/source/slang/slang.natvis +++ b/source/slang/slang.natvis @@ -9,6 +9,14 @@ <ExpandedItem>rawVal ? ($T1*)((char*)this + rawVal) : ($T1*)0</ExpandedItem> </Expand> </Type> + <Type Name="Slang::ValNodeOperand"> + <DisplayString Condition="kind == Slang::ValNodeOperandKind::ConstantValue">Constant {intOperand}</DisplayString> + <DisplayString Condition="kind == Slang::ValNodeOperandKind::ValNode">{(Slang::Val*)nodeOperand}</DisplayString> + <DisplayString Condition="kind == Slang::ValNodeOperandKind::ASTNode">{nodeOperand}</DisplayString> + <Expand> + <ExpandedItem>*(Slang::Val*)nodeOperand</ExpandedItem> + </Expand> + </Type> <Type Name="Slang::DeclRef<*>"> <DisplayString Condition="declRefBase == 0">DeclRef nullptr</DisplayString> @@ -415,101 +423,22 @@ </Expand> </Type> - <Type Name="Slang::Type" Inheritable="false"> + <Type Name="Slang::Val" Inheritable="true"> <DisplayString Optional="true" Condition="astNodeType == Slang::ASTNodeType::DeclRefType">DeclRefType#{_debugUID} {*(Val*)(((Slang::DeclRefType*)this)->m_operands.m_buffer[0].values.nodeOperand)}</DisplayString> <DisplayString Condition="astNodeType == Slang::ASTNodeType::DeclRefType">DeclRefType {*(Val*)(((Slang::DeclRefType*)this)->m_operands.m_buffer[0].values.nodeOperand)}</DisplayString> + <DisplayString Condition="astNodeType == Slang::ASTNodeType::DirectDeclRef">DirectRef {*(Decl*)m_operands.m_buffer[0].values.nodeOperand}</DisplayString> <DisplayString Optional="true">{astNodeType,en} #{_debugUID}</DisplayString> <DisplayString>{astNodeType,en}</DisplayString> <Expand> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::OverloadGroupType">(Slang::OverloadGroupType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::InitializerListType">(Slang::InitializerListType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ErrorType">(Slang::ErrorType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BottomType">(Slang::BottomType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DeclRefType">(Slang::DeclRefType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DifferentiableType">(Slang::DeclRefType*)&astNodeType</ExpandedItem> - - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DifferentialPairType">(Slang::DeclRefType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ArithmeticExpressionType">(Slang::ArithmeticExpressionType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BasicExpressionType">(Slang::BasicExpressionType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::VectorExpressionType">(Slang::VectorExpressionType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::MatrixExpressionType">(Slang::MatrixExpressionType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BuiltinType">(Slang::BuiltinType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::FeedbackType">(Slang::FeedbackType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ResourceType">(Slang::ResourceType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureTypeBase">(Slang::TextureTypeBase*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureType">(Slang::TextureType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLImageType">(Slang::GLSLImageType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::SamplerStateType">(Slang::SamplerStateType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BuiltinGenericType">(Slang::BuiltinGenericType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PointerLikeType">(Slang::PointerLikeType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ParameterGroupType">(Slang::ParameterGroupType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::UniformParameterGroupType">(Slang::UniformParameterGroupType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ConstantBufferType">(Slang::ConstantBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureBufferType">(Slang::TextureBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLShaderStorageBufferType">(Slang::GLSLShaderStorageBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ParameterBlockType">(Slang::ParameterBlockType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::VaryingParameterGroupType">(Slang::VaryingParameterGroupType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLInputParameterGroupType">(Slang::GLSLInputParameterGroupType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLOutputParameterGroupType">(Slang::GLSLOutputParameterGroupType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLStructuredBufferTypeBase">(Slang::HLSLStructuredBufferTypeBase*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLStructuredBufferType">(Slang::HLSLStructuredBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLRWStructuredBufferType">(Slang::HLSLRWStructuredBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLRasterizerOrderedStructuredBufferType">(Slang::HLSLRasterizerOrderedStructuredBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLAppendStructuredBufferType">(Slang::HLSLAppendStructuredBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLConsumeStructuredBufferType">(Slang::HLSLConsumeStructuredBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLStreamOutputType">(Slang::HLSLStreamOutputType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLPointStreamType">(Slang::HLSLPointStreamType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLLineStreamType">(Slang::HLSLLineStreamType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLTriangleStreamType">(Slang::HLSLTriangleStreamType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::MeshOutputType">(Slang::MeshOutputType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::VerticesType">(Slang::VerticesType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::IndicesType">(Slang::IndicesType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PrimitivesType">(Slang::PrimitivesType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::UntypedBufferResourceType">(Slang::UntypedBufferResourceType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLByteAddressBufferType">(Slang::HLSLByteAddressBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLRWByteAddressBufferType">(Slang::HLSLRWByteAddressBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLRasterizerOrderedByteAddressBufferType">(Slang::HLSLRasterizerOrderedByteAddressBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::RaytracingAccelerationStructureType">(Slang::RaytracingAccelerationStructureType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLPatchType">(Slang::HLSLPatchType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLInputPatchType">(Slang::HLSLInputPatchType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLOutputPatchType">(Slang::HLSLOutputPatchType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLInputAttachmentType">(Slang::GLSLInputAttachmentType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::StringTypeBase">(Slang::StringTypeBase*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::StringType">(Slang::StringType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::NativeStringType">(Slang::NativeStringType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DynamicType">(Slang::DynamicType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::EnumTypeType">(Slang::EnumTypeType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PtrTypeBase">(Slang::PtrTypeBase*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PtrType">(Slang::PtrType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ParamDirectionType">(Slang::ParamDirectionType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::OutTypeBase">(Slang::OutTypeBase*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::OutType">(Slang::OutType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::InOutType">(Slang::InOutType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::RefType">(Slang::RefType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::NullPtrType">(Slang::NullPtrType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ArrayExpressionType">(Slang::ArrayExpressionType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TypeType">(Slang::TypeType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::NamedExpressionType">(Slang::NamedExpressionType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::FuncType">(Slang::FuncType*)this</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GenericDeclRefType">(Slang::GenericDeclRefType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::NamespaceType">(Slang::NamespaceType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ExtractExistentialType">(Slang::ExtractExistentialType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ExistentialSpecializedType">(Slang::ExistentialSpecializedType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ThisType">(Slang::ThisType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::AndType">(Slang::AndType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ModifiedType">(Slang::ModifiedType*)&astNodeType</ExpandedItem> + <Synthetic Name = "[Kind]"> + <DisplayString>{astNodeType}</DisplayString> + </Synthetic> - <Item Name="[Raw View]">(Slang::Type*)this,!</Item> + <ExpandedItem>m_operands</ExpandedItem> </Expand> </Type> - <Type Name="Slang::DirectDeclRef"> - <DisplayString>DirectDeclRef{(Decl*)m_operands.m_buffer[0].values.nodeOperand}</DisplayString> - <Expand> - <ExpandedItem>(Decl*)m_operands.m_buffer[0].values.nodeOperand</ExpandedItem> - </Expand> - </Type> <Type Name="Slang::SubstitutionSet"> <DisplayString>SubstitutionSet{declRef,en}</DisplayString> <Expand> @@ -557,183 +486,10 @@ <DisplayString>{values.nodeOperand}</DisplayString> <Expand> <ExpandedItem Condition="kind==Slang::ValNodeOperandKind::ValNode">*(Val*)values.nodeOperand</ExpandedItem> - <ExpandedItem Condition="kind==Slang::ValNodeOperandKind::ASTNode">*values.nodeOperand</ExpandedItem> - </Expand> - </Type> - <Type Name="Slang::Val" Inheritable="false"> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::DirectDeclRef">{*(Slang::DirectDeclRef*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::LookupDeclRef">{*(Slang::LookupDeclRef*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::MemberDeclRef">{*(Slang::MemberDeclRef*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::GenericAppDeclRef">{*(Slang::GenericAppDeclRef*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::ConstantIntVal">{*(Slang::ConstantIntVal*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::PolynomialIntVal">{*(Slang::PolynomialIntVal*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::PolynomialIntValTerm">{*(Slang::PolynomialIntValTerm*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::PolynomialIntValFactor">{*(Slang::PolynomialIntValFactor*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::GenericParamIntVal">{*(Slang::GenericParamIntVal*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::DeclaredSubtypeWitness">{*(Slang::DeclaredSubtypeWitness*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::TransitiveSubtypeWitness">{*(Slang::TransitiveSubtypeWitness*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::OverloadGroupType">{*(Slang::OverloadGroupType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::InitializerListType">{*(Slang::InitializerListType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::ErrorType">{*(Slang::ErrorType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::BottomType">{*(Slang::BottomType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::DeclRefType">{*(Slang::DeclRefType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::DifferentialPairType">{*(Slang::DeclRefType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::ArithmeticExpressionType">{*(Slang::ArithmeticExpressionType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::BasicExpressionType">{*(Slang::BasicExpressionType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::VectorExpressionType">{*(Slang::VectorExpressionType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::MatrixExpressionType">{*(Slang::MatrixExpressionType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::BuiltinType">{*(Slang::BuiltinType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::FeedbackType">{*(Slang::FeedbackType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::ResourceType">{*(Slang::ResourceType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::TextureTypeBase">{*(Slang::TextureTypeBase*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::TextureType">{*(Slang::TextureType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::GLSLImageType">{*(Slang::GLSLImageType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::SamplerStateType">{*(Slang::SamplerStateType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::BuiltinGenericType">{*(Slang::BuiltinGenericType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::PointerLikeType">{*(Slang::PointerLikeType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::ParameterGroupType">{*(Slang::ParameterGroupType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::UniformParameterGroupType">{*(Slang::UniformParameterGroupType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::ConstantBufferType">{*(Slang::ConstantBufferType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::TextureBufferType">{*(Slang::TextureBufferType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::GLSLShaderStorageBufferType">{*(Slang::GLSLShaderStorageBufferType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::ParameterBlockType">{*(Slang::ParameterBlockType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::VaryingParameterGroupType">{*(Slang::VaryingParameterGroupType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::GLSLInputParameterGroupType">{*(Slang::GLSLInputParameterGroupType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::GLSLOutputParameterGroupType">{*(Slang::GLSLOutputParameterGroupType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::HLSLStructuredBufferTypeBase">{*(Slang::HLSLStructuredBufferTypeBase*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::HLSLStructuredBufferType">{*(Slang::HLSLStructuredBufferType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::HLSLRWStructuredBufferType">{*(Slang::HLSLRWStructuredBufferType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::HLSLRasterizerOrderedStructuredBufferType">{*(Slang::HLSLRasterizerOrderedStructuredBufferType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::HLSLAppendStructuredBufferType">{*(Slang::HLSLAppendStructuredBufferType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::HLSLConsumeStructuredBufferType">{*(Slang::HLSLConsumeStructuredBufferType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::HLSLStreamOutputType">{*(Slang::HLSLStreamOutputType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::HLSLPointStreamType">{*(Slang::HLSLPointStreamType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::HLSLLineStreamType">{*(Slang::HLSLLineStreamType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::HLSLTriangleStreamType">{*(Slang::HLSLTriangleStreamType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::UntypedBufferResourceType">{*(Slang::UntypedBufferResourceType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::HLSLByteAddressBufferType">{*(Slang::HLSLByteAddressBufferType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::HLSLRWByteAddressBufferType">{*(Slang::HLSLRWByteAddressBufferType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::HLSLRasterizerOrderedByteAddressBufferType">{*(Slang::HLSLRasterizerOrderedByteAddressBufferType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::RaytracingAccelerationStructureType">{*(Slang::RaytracingAccelerationStructureType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::HLSLPatchType">{*(Slang::HLSLPatchType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::HLSLInputPatchType">{*(Slang::HLSLInputPatchType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::HLSLOutputPatchType">{*(Slang::HLSLOutputPatchType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::GLSLInputAttachmentType">{*(Slang::GLSLInputAttachmentType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::StringTypeBase">{*(Slang::StringTypeBase*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::StringType">{*(Slang::StringType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::NativeStringType">{*(Slang::NativeStringType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::DynamicType">{*(Slang::DynamicType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::EnumTypeType">{*(Slang::EnumTypeType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::PtrTypeBase">{*(Slang::PtrTypeBase*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::PtrType">{*(Slang::PtrType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::ParamDirectionType">{(Slang::ParamDirectionType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::OutTypeBase">{*(Slang::OutTypeBase*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::OutType">{*(Slang::OutType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::InOutType">{*(Slang::InOutType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::RefType">{*(Slang::RefType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::NullPtrType">{*(Slang::NullPtrType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::ArrayExpressionType">{*(Slang::ArrayExpressionType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::TypeType">{*(Slang::TypeType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::NamedExpressionType">{*(Slang::NamedExpressionType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::FuncType">{*(Slang::FuncType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::GenericDeclRefType">{*(Slang::GenericDeclRefType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::NamespaceType">{*(Slang::NamespaceType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::ExtractExistentialType">{*(Slang::ExtractExistentialType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::ExistentialSpecializedType">{*(Slang::ExistentialSpecializedType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::ThisType">{*(Slang::ThisType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::AndType">{*(Slang::AndType*)this}</DisplayString> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::ModifiedType">{*(Slang::ModifiedType*)this}</DisplayString> - - <Expand> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DirectDeclRef">(Slang::DirectDeclRef*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::LookupDeclRef">(Slang::LookupDeclRef*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::MemberDeclRef">(Slang::MemberDeclRef*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GenericAppDeclRef">(Slang::GenericAppDeclRef*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ConstantIntVal">(Slang::ConstantIntVal*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PolynomialIntVal">(Slang::PolynomialIntVal*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PolynomialIntValTerm">(Slang::PolynomialIntValTerm*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PolynomialIntValFactor">(Slang::PolynomialIntValFactor*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GenericParamIntVal">(Slang::GenericParamIntVal*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DeclaredSubtypeWitness">(Slang::DeclaredSubtypeWitness*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TransitiveSubtypeWitness">(Slang::TransitiveSubtypeWitness*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::OverloadGroupType">(Slang::OverloadGroupType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::InitializerListType">(Slang::InitializerListType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ErrorType">(Slang::ErrorType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BottomType">(Slang::BottomType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DeclRefType">(Slang::DeclRefType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DifferentialPairType">(Slang::DeclRefType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ArithmeticExpressionType">(Slang::ArithmeticExpressionType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BasicExpressionType">(Slang::BasicExpressionType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::VectorExpressionType">(Slang::VectorExpressionType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::MatrixExpressionType">(Slang::MatrixExpressionType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BuiltinType">(Slang::BuiltinType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::FeedbackType">(Slang::FeedbackType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ResourceType">(Slang::ResourceType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureTypeBase">(Slang::TextureTypeBase*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureType">(Slang::TextureType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLImageType">(Slang::GLSLImageType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::SamplerStateType">(Slang::SamplerStateType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BuiltinGenericType">(Slang::BuiltinGenericType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PointerLikeType">(Slang::PointerLikeType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ParameterGroupType">(Slang::ParameterGroupType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::UniformParameterGroupType">(Slang::UniformParameterGroupType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ConstantBufferType">(Slang::ConstantBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureBufferType">(Slang::TextureBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLShaderStorageBufferType">(Slang::GLSLShaderStorageBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ParameterBlockType">(Slang::ParameterBlockType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::VaryingParameterGroupType">(Slang::VaryingParameterGroupType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLInputParameterGroupType">(Slang::GLSLInputParameterGroupType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLOutputParameterGroupType">(Slang::GLSLOutputParameterGroupType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLStructuredBufferTypeBase">(Slang::HLSLStructuredBufferTypeBase*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLStructuredBufferType">(Slang::HLSLStructuredBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLRWStructuredBufferType">(Slang::HLSLRWStructuredBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLRasterizerOrderedStructuredBufferType">(Slang::HLSLRasterizerOrderedStructuredBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLAppendStructuredBufferType">(Slang::HLSLAppendStructuredBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLConsumeStructuredBufferType">(Slang::HLSLConsumeStructuredBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLStreamOutputType">(Slang::HLSLStreamOutputType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLPointStreamType">(Slang::HLSLPointStreamType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLLineStreamType">(Slang::HLSLLineStreamType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLTriangleStreamType">(Slang::HLSLTriangleStreamType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::UntypedBufferResourceType">(Slang::UntypedBufferResourceType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLByteAddressBufferType">(Slang::HLSLByteAddressBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLRWByteAddressBufferType">(Slang::HLSLRWByteAddressBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLRasterizerOrderedByteAddressBufferType">(Slang::HLSLRasterizerOrderedByteAddressBufferType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::RaytracingAccelerationStructureType">(Slang::RaytracingAccelerationStructureType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLPatchType">(Slang::HLSLPatchType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLInputPatchType">(Slang::HLSLInputPatchType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLOutputPatchType">(Slang::HLSLOutputPatchType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLInputAttachmentType">(Slang::GLSLInputAttachmentType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::StringTypeBase">(Slang::StringTypeBase*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::StringType">(Slang::StringType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::NativeStringType">(Slang::NativeStringType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DynamicType">(Slang::DynamicType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::EnumTypeType">(Slang::EnumTypeType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PtrTypeBase">(Slang::PtrTypeBase*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PtrType">(Slang::PtrType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ParamDirectionType">(Slang::ParamDirectionType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::OutTypeBase">(Slang::OutTypeBase*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::OutType">(Slang::OutType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::InOutType">(Slang::InOutType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::RefType">(Slang::RefType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::NullPtrType">(Slang::NullPtrType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ArrayExpressionType">(Slang::ArrayExpressionType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TypeType">(Slang::TypeType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::NamedExpressionType">(Slang::NamedExpressionType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::FuncType">(Slang::FuncType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GenericDeclRefType">(Slang::GenericDeclRefType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::NamespaceType">(Slang::NamespaceType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ExtractExistentialType">(Slang::ExtractExistentialType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ExistentialSpecializedType">(Slang::ExistentialSpecializedType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ThisType">(Slang::ThisType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::AndType">(Slang::AndType*)&astNodeType</ExpandedItem> - <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ModifiedType">(Slang::ModifiedType*)&astNodeType</ExpandedItem> - <Synthetic Name="[RawOperands]"> - <Expand> - <ExpandedItem>m_operands</ExpandedItem> - </Expand> - </Synthetic> + <ExpandedItem Condition="kind==Slang::ValNodeOperandKind::ASTNode">*(Decl*)values.nodeOperand</ExpandedItem> </Expand> </Type> + <Type Name="Slang::Facet"> <SmartPointer Usage="Minimal">_impl</SmartPointer> <DisplayString Condition="_impl == 0">nullptr</DisplayString> @@ -759,49 +515,7 @@ </LinkedListItems> </Expand> </Type> - <Type Name="Slang::SubtypeWitness"> - <DisplayString Condition="astNodeType == Slang::ASTNodeType::TypeEqualityWitness">{*(Slang::TypeEqualityWitness*)this}</DisplayString> - <DisplayString Optional="true">{astNodeType,en}#{_debugUID}({*(Type*)m_operands.m_buffer[0].values.nodeOperand,na} <: {*(Type*)m_operands.m_buffer[1].values.nodeOperand,na})</DisplayString> - <DisplayString>{astNodeType,en}({*(Type*)m_operands.m_buffer[0].values.nodeOperand,na} <: {*(Type*)m_operands.m_buffer[1].values.nodeOperand,na})</DisplayString> - - <Expand> - <Synthetic Name="[Sub]"> - <DisplayString>{*(Type*)m_operands.m_buffer[0].values.nodeOperand}</DisplayString> - <Expand> - <ExpandedItem>(Type*)m_operands.m_buffer[0].values.nodeOperand</ExpandedItem> - </Expand> - </Synthetic> - <Synthetic Name="[Sup]"> - <DisplayString>{*(Type*)m_operands.m_buffer[1].values.nodeOperand}</DisplayString> - <Expand> - <ExpandedItem>(Type*)m_operands.m_buffer[1].values.nodeOperand</ExpandedItem> - </Expand> - </Synthetic> - <Synthetic Name="[DeclRef]" Condition="astNodeType == Slang::ASTNodeType::DeclaredSubtypeWitness"> - <DisplayString>{*(Val*)m_operands.m_buffer[2].values.nodeOperand}</DisplayString> - <Expand> - <ExpandedItem>(DeclRefBase*)m_operands.m_buffer[2].values.nodeOperand</ExpandedItem> - </Expand> - </Synthetic> - <Synthetic Name="[SubToMid]" Condition="astNodeType == Slang::ASTNodeType::TransitiveSubtypeWitness"> - <DisplayString>{*(SubtypeWitness*)m_operands.m_buffer[2].values.nodeOperand}</DisplayString> - <Expand> - <ExpandedItem>(SubtypeWitness*)m_operands.m_buffer[2].values.nodeOperand</ExpandedItem> - </Expand> - </Synthetic> - <Synthetic Name="[MidToSup]" Condition="astNodeType == Slang::ASTNodeType::TransitiveSubtypeWitness"> - <DisplayString>{*(SubtypeWitness*)m_operands.m_buffer[3].values.nodeOperand}</DisplayString> - <Expand> - <ExpandedItem>(SubtypeWitness*)m_operands.m_buffer[3].values.nodeOperand</ExpandedItem> - </Expand> - </Synthetic> - </Expand> - </Type> - <Type Name="Slang::TypeEqualityWitness"> - <DisplayString>{sub,na} == {sup,na}</DisplayString> - </Type> - - <Type Name="Slang::ConstantIntVal"> + <Type Name="Slang::ConstantIntVal"> <DisplayString Optional="true">{astNodeType,en}#{_debugUID} ({m_operands.m_buffer[1].values.intOperand} : {*(Type*)m_operands.m_buffer[0].values.nodeOperand}) </DisplayString> <DisplayString>ConstantIntVal ({m_operands.m_buffer[1].values.intOperand} : {*(Type*)m_operands.m_buffer[0].values.nodeOperand})</DisplayString> </Type> |
