summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-ast-builder.cpp95
-rw-r--r--source/slang/slang-ast-builder.h12
-rw-r--r--source/slang/slang-ast-decl-ref.cpp4
-rw-r--r--source/slang/slang-ast-decl.h32
-rw-r--r--source/slang/slang-ast-expr.h23
-rw-r--r--source/slang/slang-ast-modifier.h3
-rw-r--r--source/slang/slang-ast-support-types.h8
-rw-r--r--source/slang/slang-ast-type.cpp206
-rw-r--r--source/slang/slang-ast-type.h67
-rw-r--r--source/slang/slang-ast-val.cpp161
-rw-r--r--source/slang/slang-ast-val.h55
-rw-r--r--source/slang/slang-check-conformance.cpp30
-rw-r--r--source/slang/slang-check-constraint.cpp273
-rw-r--r--source/slang/slang-check-conversion.cpp4
-rw-r--r--source/slang/slang-check-decl.cpp44
-rw-r--r--source/slang/slang-check-expr.cpp120
-rw-r--r--source/slang/slang-check-impl.h53
-rw-r--r--source/slang/slang-check-inheritance.cpp40
-rw-r--r--source/slang/slang-check-overload.cpp401
-rw-r--r--source/slang/slang-check-type.cpp14
-rw-r--r--source/slang/slang-check.h2
-rw-r--r--source/slang/slang-diagnostic-defs.h6
-rw-r--r--source/slang/slang-lower-to-ir.cpp15
-rw-r--r--source/slang/slang-mangle.cpp27
-rw-r--r--source/slang/slang-parser.cpp174
-rw-r--r--source/slang/slang.natvis320
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 = &paramTypes;
}
- 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&lt;*&gt;">
<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*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::InitializerListType">(Slang::InitializerListType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ErrorType">(Slang::ErrorType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BottomType">(Slang::BottomType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DeclRefType">(Slang::DeclRefType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DifferentiableType">(Slang::DeclRefType*)&amp;astNodeType</ExpandedItem>
-
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DifferentialPairType">(Slang::DeclRefType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ArithmeticExpressionType">(Slang::ArithmeticExpressionType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BasicExpressionType">(Slang::BasicExpressionType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::VectorExpressionType">(Slang::VectorExpressionType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::MatrixExpressionType">(Slang::MatrixExpressionType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BuiltinType">(Slang::BuiltinType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::FeedbackType">(Slang::FeedbackType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ResourceType">(Slang::ResourceType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureTypeBase">(Slang::TextureTypeBase*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureType">(Slang::TextureType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLImageType">(Slang::GLSLImageType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::SamplerStateType">(Slang::SamplerStateType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BuiltinGenericType">(Slang::BuiltinGenericType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PointerLikeType">(Slang::PointerLikeType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ParameterGroupType">(Slang::ParameterGroupType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::UniformParameterGroupType">(Slang::UniformParameterGroupType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ConstantBufferType">(Slang::ConstantBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureBufferType">(Slang::TextureBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLShaderStorageBufferType">(Slang::GLSLShaderStorageBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ParameterBlockType">(Slang::ParameterBlockType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::VaryingParameterGroupType">(Slang::VaryingParameterGroupType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLInputParameterGroupType">(Slang::GLSLInputParameterGroupType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLOutputParameterGroupType">(Slang::GLSLOutputParameterGroupType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLStructuredBufferTypeBase">(Slang::HLSLStructuredBufferTypeBase*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLStructuredBufferType">(Slang::HLSLStructuredBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLRWStructuredBufferType">(Slang::HLSLRWStructuredBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLRasterizerOrderedStructuredBufferType">(Slang::HLSLRasterizerOrderedStructuredBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLAppendStructuredBufferType">(Slang::HLSLAppendStructuredBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLConsumeStructuredBufferType">(Slang::HLSLConsumeStructuredBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLStreamOutputType">(Slang::HLSLStreamOutputType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLPointStreamType">(Slang::HLSLPointStreamType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLLineStreamType">(Slang::HLSLLineStreamType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLTriangleStreamType">(Slang::HLSLTriangleStreamType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::MeshOutputType">(Slang::MeshOutputType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::VerticesType">(Slang::VerticesType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::IndicesType">(Slang::IndicesType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PrimitivesType">(Slang::PrimitivesType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::UntypedBufferResourceType">(Slang::UntypedBufferResourceType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLByteAddressBufferType">(Slang::HLSLByteAddressBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLRWByteAddressBufferType">(Slang::HLSLRWByteAddressBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLRasterizerOrderedByteAddressBufferType">(Slang::HLSLRasterizerOrderedByteAddressBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::RaytracingAccelerationStructureType">(Slang::RaytracingAccelerationStructureType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLPatchType">(Slang::HLSLPatchType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLInputPatchType">(Slang::HLSLInputPatchType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLOutputPatchType">(Slang::HLSLOutputPatchType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLInputAttachmentType">(Slang::GLSLInputAttachmentType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::StringTypeBase">(Slang::StringTypeBase*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::StringType">(Slang::StringType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::NativeStringType">(Slang::NativeStringType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DynamicType">(Slang::DynamicType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::EnumTypeType">(Slang::EnumTypeType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PtrTypeBase">(Slang::PtrTypeBase*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PtrType">(Slang::PtrType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ParamDirectionType">(Slang::ParamDirectionType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::OutTypeBase">(Slang::OutTypeBase*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::OutType">(Slang::OutType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::InOutType">(Slang::InOutType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::RefType">(Slang::RefType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::NullPtrType">(Slang::NullPtrType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ArrayExpressionType">(Slang::ArrayExpressionType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TypeType">(Slang::TypeType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::NamedExpressionType">(Slang::NamedExpressionType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::FuncType">(Slang::FuncType*)this</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GenericDeclRefType">(Slang::GenericDeclRefType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::NamespaceType">(Slang::NamespaceType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ExtractExistentialType">(Slang::ExtractExistentialType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ExistentialSpecializedType">(Slang::ExistentialSpecializedType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ThisType">(Slang::ThisType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::AndType">(Slang::AndType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ModifiedType">(Slang::ModifiedType*)&amp;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*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::LookupDeclRef">(Slang::LookupDeclRef*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::MemberDeclRef">(Slang::MemberDeclRef*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GenericAppDeclRef">(Slang::GenericAppDeclRef*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ConstantIntVal">(Slang::ConstantIntVal*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PolynomialIntVal">(Slang::PolynomialIntVal*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PolynomialIntValTerm">(Slang::PolynomialIntValTerm*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PolynomialIntValFactor">(Slang::PolynomialIntValFactor*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GenericParamIntVal">(Slang::GenericParamIntVal*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DeclaredSubtypeWitness">(Slang::DeclaredSubtypeWitness*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TransitiveSubtypeWitness">(Slang::TransitiveSubtypeWitness*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::OverloadGroupType">(Slang::OverloadGroupType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::InitializerListType">(Slang::InitializerListType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ErrorType">(Slang::ErrorType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BottomType">(Slang::BottomType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DeclRefType">(Slang::DeclRefType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DifferentialPairType">(Slang::DeclRefType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ArithmeticExpressionType">(Slang::ArithmeticExpressionType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BasicExpressionType">(Slang::BasicExpressionType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::VectorExpressionType">(Slang::VectorExpressionType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::MatrixExpressionType">(Slang::MatrixExpressionType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BuiltinType">(Slang::BuiltinType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::FeedbackType">(Slang::FeedbackType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ResourceType">(Slang::ResourceType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureTypeBase">(Slang::TextureTypeBase*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureType">(Slang::TextureType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLImageType">(Slang::GLSLImageType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::SamplerStateType">(Slang::SamplerStateType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::BuiltinGenericType">(Slang::BuiltinGenericType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PointerLikeType">(Slang::PointerLikeType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ParameterGroupType">(Slang::ParameterGroupType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::UniformParameterGroupType">(Slang::UniformParameterGroupType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ConstantBufferType">(Slang::ConstantBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TextureBufferType">(Slang::TextureBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLShaderStorageBufferType">(Slang::GLSLShaderStorageBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ParameterBlockType">(Slang::ParameterBlockType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::VaryingParameterGroupType">(Slang::VaryingParameterGroupType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLInputParameterGroupType">(Slang::GLSLInputParameterGroupType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLOutputParameterGroupType">(Slang::GLSLOutputParameterGroupType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLStructuredBufferTypeBase">(Slang::HLSLStructuredBufferTypeBase*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLStructuredBufferType">(Slang::HLSLStructuredBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLRWStructuredBufferType">(Slang::HLSLRWStructuredBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLRasterizerOrderedStructuredBufferType">(Slang::HLSLRasterizerOrderedStructuredBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLAppendStructuredBufferType">(Slang::HLSLAppendStructuredBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLConsumeStructuredBufferType">(Slang::HLSLConsumeStructuredBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLStreamOutputType">(Slang::HLSLStreamOutputType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLPointStreamType">(Slang::HLSLPointStreamType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLLineStreamType">(Slang::HLSLLineStreamType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLTriangleStreamType">(Slang::HLSLTriangleStreamType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::UntypedBufferResourceType">(Slang::UntypedBufferResourceType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLByteAddressBufferType">(Slang::HLSLByteAddressBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLRWByteAddressBufferType">(Slang::HLSLRWByteAddressBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLRasterizerOrderedByteAddressBufferType">(Slang::HLSLRasterizerOrderedByteAddressBufferType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::RaytracingAccelerationStructureType">(Slang::RaytracingAccelerationStructureType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLPatchType">(Slang::HLSLPatchType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLInputPatchType">(Slang::HLSLInputPatchType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::HLSLOutputPatchType">(Slang::HLSLOutputPatchType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GLSLInputAttachmentType">(Slang::GLSLInputAttachmentType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::StringTypeBase">(Slang::StringTypeBase*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::StringType">(Slang::StringType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::NativeStringType">(Slang::NativeStringType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::DynamicType">(Slang::DynamicType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::EnumTypeType">(Slang::EnumTypeType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PtrTypeBase">(Slang::PtrTypeBase*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::PtrType">(Slang::PtrType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ParamDirectionType">(Slang::ParamDirectionType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::OutTypeBase">(Slang::OutTypeBase*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::OutType">(Slang::OutType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::InOutType">(Slang::InOutType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::RefType">(Slang::RefType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::NullPtrType">(Slang::NullPtrType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ArrayExpressionType">(Slang::ArrayExpressionType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::TypeType">(Slang::TypeType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::NamedExpressionType">(Slang::NamedExpressionType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::FuncType">(Slang::FuncType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::GenericDeclRefType">(Slang::GenericDeclRefType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::NamespaceType">(Slang::NamespaceType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ExtractExistentialType">(Slang::ExtractExistentialType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ExistentialSpecializedType">(Slang::ExistentialSpecializedType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ThisType">(Slang::ThisType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::AndType">(Slang::AndType*)&amp;astNodeType</ExpandedItem>
- <ExpandedItem Condition="astNodeType == Slang::ASTNodeType::ModifiedType">(Slang::ModifiedType*)&amp;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} &lt;: {*(Type*)m_operands.m_buffer[1].values.nodeOperand,na})</DisplayString>
- <DisplayString>{astNodeType,en}({*(Type*)m_operands.m_buffer[0].values.nodeOperand,na} &lt;: {*(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>