summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2020-05-08 14:31:40 -0400
committerGitHub <noreply@github.com>2020-05-08 14:31:40 -0400
commit798f3bc2236ce81499b05662dc11e7c071e7cde8 (patch)
treefbfa2ef90d4cfdace9ce3667cf441e22137792fb /source
parentc16abd4fe1bda5ebcd50dbb22f30c6be43bb885f (diff)
AST nodes using C++ Extractor (#1341)
* Extractor builds without any reference to syntax (as it will be helping to produce this!). * Change macros to include the super class. * WIP replacing defs files. * Added indexOf(const UnownedSubString& in) to UnownedSubString. Refactored extractor * Output a macro for each type with the extracted info - can be used during injection in class * Simplify the header file - as can get super type and last from macro now * Store the 'origin' of a definition * Some small tidy ups to the extractor. * Improve comments on the extractor options. * Made CPPExtractor own SourceOrigins * Small fixes around SourceOrigin. * Small tidy up around macroOrign * WIP Visitor seems now to work correctly. Split out types used by ast into slang-ast-support-types.h * Fix remaining problems with C++ extractor being used with AST nodes. Add CountOf to extractor type ids. Added ReflectClassInfo::getInfo to turn an ASTNodeType into a ReflectClassInfo * Fix compiling on linux. Fix typo in memset. * Small tidy up around comments/layout. Moved NodeBase casting to NodeBase. * Make premake generate project that builds with cpp-extractor for AST. * Get the source directory from the filter in premake. * Fix typo in source path * Explicitly set the source path for premake generation for AST. * Special case handling of override to apease Clang. * Use a more general way to find the slang-ast-reflect.h file to run the extractor. * Appveyor is not triggering slang-cpp-extractor - try putting dependson together. * Put building slang-cpp-extractor first. * Disable some project options to stop MSBuild producing internal compiler errors. * Try reordering the projects in premake5.lua * Hack to try and make slang-cpp-extractor built on appveyor. * Disable flags - not required for MSBuild on appveyor. * Disable flags not required for build on AppVeyor. * Updated Visual Studio projects with slang-cpp-extractor. * Added Visual Studio slang-cpp-extractor project.
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-ast-all.h12
-rw-r--r--source/slang/slang-ast-base.h (renamed from source/slang/slang-syntax-base-defs.h)276
-rw-r--r--source/slang/slang-ast-decl.h (renamed from source/slang/slang-decl-defs.h)367
-rw-r--r--source/slang/slang-ast-expr.h311
-rw-r--r--source/slang/slang-ast-modifier.h883
-rw-r--r--source/slang/slang-ast-reflect.cpp70
-rw-r--r--source/slang/slang-ast-reflect.h37
-rw-r--r--source/slang/slang-ast-stmt.h213
-rw-r--r--source/slang/slang-ast-support-types.h1330
-rw-r--r--source/slang/slang-ast-type.h (renamed from source/slang/slang-type-defs.h)532
-rw-r--r--source/slang/slang-ast-val.h (renamed from source/slang/slang-val-defs.h)125
-rw-r--r--source/slang/slang-expr-defs.h216
-rw-r--r--source/slang/slang-modifier-defs.h495
-rw-r--r--source/slang/slang-object-meta-begin.h43
-rw-r--r--source/slang/slang-object-meta-end.h17
-rw-r--r--source/slang/slang-parser.cpp2
-rw-r--r--source/slang/slang-stmt-defs.h124
-rw-r--r--source/slang/slang-syntax-defs.h10
-rw-r--r--source/slang/slang-syntax.cpp196
-rw-r--r--source/slang/slang-syntax.h1389
-rw-r--r--source/slang/slang-visitor.h371
-rw-r--r--source/slang/slang.cpp14
-rw-r--r--source/slang/slang.vcxproj35
-rw-r--r--source/slang/slang.vcxproj.filters72
24 files changed, 3868 insertions, 3272 deletions
diff --git a/source/slang/slang-ast-all.h b/source/slang/slang-ast-all.h
new file mode 100644
index 000000000..096c95f53
--- /dev/null
+++ b/source/slang/slang-ast-all.h
@@ -0,0 +1,12 @@
+// slang-ast-all.h
+
+#pragma once
+
+#include "slang-ast-base.h"
+
+#include "slang-ast-expr.h"
+#include "slang-ast-decl.h"
+#include "slang-ast-modifier.h"
+#include "slang-ast-stmt.h"
+#include "slang-ast-type.h"
+#include "slang-ast-val.h"
diff --git a/source/slang/slang-syntax-base-defs.h b/source/slang/slang-ast-base.h
index 60e888b56..ee044eae3 100644
--- a/source/slang/slang-syntax-base-defs.h
+++ b/source/slang/slang-ast-base.h
@@ -1,32 +1,85 @@
-// slang-syntax-base-defs.h
+// slang-ast-base.h
+
+#pragma once
+
+#include "slang-ast-support-types.h"
+
+#include "slang-ast-generated.h"
+#include "slang-ast-reflect.h"
// This file defines the primary base classes for the hierarchy of
// AST nodes and related objects. For example, this is where the
// basic `Decl`, `Stmt`, `Expr`, `type`, etc. definitions come from.
-ABSTRACT_SYNTAX_CLASS(NodeBase, RefObject)
- // A helper to access the corresponding class on a concrete instance
- RAW(virtual const SyntaxClassBase::ClassInfo& getClassInfo() const = 0;)
- RAW(SyntaxClass<NodeBase> getClass() { return SyntaxClass<NodeBase>(&getClassInfo()); } )
-END_SYNTAX_CLASS()
+namespace Slang
+{
+
+#define SLANG_ABSTRACT_CLASS(x) SLANG_ABSTRACT_CLASS_REFLECT(x)
+// We don't use SLANG_CLASS_REFLECT_WITH_ACCEPT(x), as we don't want accept method on these classes
+#define SLANG_CLASS(x) SLANG_CLASS_REFLECT_DEFAULT(x)
+
+// Signals to C++ extractor that RefObject is a base class, that isn't reflected to C++ extractor
+SLANG_REFLECT_BASE_CLASS(RefObject)
+
+struct ReflectClassInfo;
+
+class NodeBase : public RefObject
+{
+ SLANG_ABSTRACT_CLASS(NodeBase)
+
+ SyntaxClass<NodeBase> getClass() { return SyntaxClass<NodeBase>(&getClassInfo()); }
+};
+
+// Casting of NodeBase
+
+template<typename T>
+SLANG_FORCE_INLINE T* dynamicCast(NodeBase* node)
+{
+ return (node && node->getClassInfo().isSubClassOf(T::kReflectClassInfo)) ? static_cast<T*>(node) : nullptr;
+}
+
+template<typename T>
+SLANG_FORCE_INLINE const T* dynamicCast(const NodeBase* node)
+{
+ return (node && node->getClassInfo().isSubClassOf(T::kReflectClassInfo)) ? static_cast<const T*>(node) : nullptr;
+}
+
+template<typename T>
+SLANG_FORCE_INLINE T* as(NodeBase* node)
+{
+ return (node && node->getClassInfo().isSubClassOf(T::kReflectClassInfo)) ? static_cast<T*>(node) : nullptr;
+}
+
+template<typename T>
+SLANG_FORCE_INLINE const T* as(const NodeBase* node)
+{
+ return (node && node->getClassInfo().isSubClassOf(T::kReflectClassInfo)) ? static_cast<const T*>(node) : nullptr;
+}
+
// Base class for all nodes representing actual syntax
// (thus having a location in the source code)
-ABSTRACT_SYNTAX_CLASS(SyntaxNodeBase, NodeBase)
+class SyntaxNodeBase : public NodeBase
+{
+ SLANG_ABSTRACT_CLASS(SyntaxNodeBase)
+
// The primary source location associated with this AST node
- FIELD(SourceLoc, loc)
-END_SYNTAX_CLASS()
+ SourceLoc loc;
+};
// Base class for compile-time values (most often a type).
// These are *not* syntax nodes, because they do not have
// a unique location, and any two `Val`s representing
// the same value should be conceptually equal.
-ABSTRACT_SYNTAX_CLASS(Val, NodeBase)
- RAW(typedef IValVisitor Visitor;)
- RAW(virtual void accept(IValVisitor* visitor, void* extra) = 0;)
+class Val : public NodeBase
+{
+ SLANG_ABSTRACT_CLASS(Val)
+
+ typedef IValVisitor Visitor;
+
+ virtual void accept(IValVisitor* visitor, void* extra) = 0;
- RAW(
// construct a new value by applying a set of parameter
// substitutions to this one
RefPtr<Val> Substitute(SubstitutionSet subst);
@@ -45,18 +98,15 @@ ABSTRACT_SYNTAX_CLASS(Val, NodeBase)
{
return EqualsVal(const_cast<Val*>(&v));
}
- )
-END_SYNTAX_CLASS()
+};
-RAW(
- class Type;
-
- template <typename T>
- SLANG_FORCE_INLINE T* as(Type* obj);
- template <typename T>
- SLANG_FORCE_INLINE const T* as(const Type* obj);
- )
+class Type;
+template <typename T>
+SLANG_FORCE_INLINE T* as(Type* obj);
+template <typename T>
+SLANG_FORCE_INLINE const T* as(const Type* obj);
+
// A type, representing a classifier for some term in the AST.
//
// Types can include "sugar" in that they may refer to a
@@ -68,13 +118,15 @@ RAW(
// "canonical" type. The representation caches a pointer to
// a canonical type on every type, so we can easily
// operate on the raw representation when needed.
-ABSTRACT_SYNTAX_CLASS(Type, Val)
- RAW(typedef ITypeVisitor Visitor;)
+class Type: public Val
+{
+ SLANG_ABSTRACT_CLASS(Type)
- RAW(virtual void accept(IValVisitor* visitor, void* extra) override;)
- RAW(virtual void accept(ITypeVisitor* visitor, void* extra) = 0;)
+ typedef ITypeVisitor Visitor;
+
+ virtual void accept(IValVisitor* visitor, void* extra) override;
+ virtual void accept(ITypeVisitor* visitor, void* extra) = 0;
-RAW(
public:
Session* getSession() { return this->session; }
void setSession(Session* s) { this->session = s; }
@@ -96,44 +148,45 @@ protected:
Type* canonicalType = nullptr;
Session* session = nullptr;
- )
-END_SYNTAX_CLASS()
-RAW(
- template <typename T>
- SLANG_FORCE_INLINE T* as(Type* obj) { return obj ? dynamicCast<T>(obj->GetCanonicalType()) : nullptr; }
- template <typename T>
- SLANG_FORCE_INLINE const T* as(const Type* obj) { return obj ? dynamicCast<T>(const_cast<Type*>(obj)->GetCanonicalType()) : nullptr; }
-)
+};
+
+template <typename T>
+SLANG_FORCE_INLINE T* as(Type* obj) { return obj ? dynamicCast<T>(obj->GetCanonicalType()) : nullptr; }
+template <typename T>
+SLANG_FORCE_INLINE const T* as(const Type* obj) { return obj ? dynamicCast<T>(const_cast<Type*>(obj)->GetCanonicalType()) : nullptr; }
// A substitution represents a binding of certain
// type-level variables to concrete argument values
-ABSTRACT_SYNTAX_CLASS(Substitutions, RefObject)
+class Substitutions: public RefObject
+{
+ SLANG_ABSTRACT_CLASS(Substitutions)
+
// The next outer that this one refines.
- FIELD(RefPtr<Substitutions>, outer)
+ RefPtr<Substitutions> outer;
- RAW(
// Apply a set of substitutions to the bindings in this substitution
virtual RefPtr<Substitutions> applySubstitutionsShallow(SubstitutionSet substSet, RefPtr<Substitutions> substOuter, int* ioDiff) = 0;
- // Check if these are equivalent substitutiosn to another set
+ // Check if these are equivalent substitutions to another set
virtual bool Equals(Substitutions* subst) = 0;
virtual int GetHashCode() const = 0;
- )
-END_SYNTAX_CLASS()
+};
+
+class GenericSubstitution : public Substitutions
+{
+ SLANG_CLASS(GenericSubstitution)
-SYNTAX_CLASS(GenericSubstitution, Substitutions)
// The generic declaration that defines the
// parameters we are binding to arguments
- DECL_FIELD(GenericDecl*, genericDecl)
+ GenericDecl* genericDecl;
// The actual values of the arguments
- SYNTAX_FIELD(List<RefPtr<Val>>, args)
+ List<RefPtr<Val> > args;
- RAW(
// Apply a set of substitutions to the bindings in this substitution
virtual RefPtr<Substitutions> applySubstitutionsShallow(SubstitutionSet substSet, RefPtr<Substitutions> substOuter, int* ioDiff) override;
- // Check if these are equivalent substitutiosn to another set
+ // Check if these are equivalent substitutions to another set
virtual bool Equals(Substitutions* subst) override;
virtual int GetHashCode() const override
@@ -146,52 +199,51 @@ SYNTAX_CLASS(GenericSubstitution, Substitutions)
}
return rs;
}
- )
-END_SYNTAX_CLASS()
+};
+
+class ThisTypeSubstitution : public Substitutions
+{
+ SLANG_CLASS(ThisTypeSubstitution)
-SYNTAX_CLASS(ThisTypeSubstitution, Substitutions)
// The declaration of the interface that we are specializing
- FIELD_INIT(InterfaceDecl*, interfaceDecl, nullptr)
+ InterfaceDecl* interfaceDecl = nullptr;
// A witness that shows that the concrete type used to
// specialize the interface conforms to the interface.
- FIELD(RefPtr<SubtypeWitness>, witness)
+ RefPtr<SubtypeWitness> witness;
// The actual type that provides the lookup scope for an associated type
- RAW(
// Apply a set of substitutions to the bindings in this substitution
virtual RefPtr<Substitutions> applySubstitutionsShallow(SubstitutionSet substSet, RefPtr<Substitutions> substOuter, int* ioDiff) override;
- // Check if these are equivalent substitutiosn to another set
+ // Check if these are equivalent substitutions to another set
virtual bool Equals(Substitutions* subst) override;
virtual int GetHashCode() const override;
- )
-END_SYNTAX_CLASS()
+};
-SYNTAX_CLASS(GlobalGenericParamSubstitution, Substitutions)
+class GlobalGenericParamSubstitution : public Substitutions
+{
+ SLANG_CLASS(GlobalGenericParamSubstitution)
// the type_param decl to be substituted
- DECL_FIELD(GlobalGenericParamDecl*, paramDecl)
+ GlobalGenericParamDecl* paramDecl;
// the actual type to substitute in
- SYNTAX_FIELD(RefPtr<Type>, actualType)
+ RefPtr<Type> actualType;
- RAW(
struct ConstraintArg
{
RefPtr<Decl> decl;
RefPtr<Val> val;
};
- )
// the values that satisfy any constraints on the type parameter
- SYNTAX_FIELD(List<ConstraintArg>, constraintArgs)
+ List<ConstraintArg> constraintArgs;
-RAW(
// Apply a set of substitutions to the bindings in this substitution
virtual RefPtr<Substitutions> applySubstitutionsShallow(SubstitutionSet substSet, RefPtr<Substitutions> substOuter, int* ioDiff) override;
- // Check if these are equivalent substitutiosn to another set
+ // Check if these are equivalent substitutions to another set
virtual bool Equals(Substitutions* subst) override;
virtual int GetHashCode() const override
@@ -203,40 +255,42 @@ RAW(
}
return rs;
}
- )
-END_SYNTAX_CLASS()
+};
-ABSTRACT_SYNTAX_CLASS(SyntaxNode, SyntaxNodeBase)
-END_SYNTAX_CLASS()
+class SyntaxNode : public SyntaxNodeBase
+{
+ SLANG_ABSTRACT_CLASS(SyntaxNode);
+};
//
// All modifiers are represented as full-fledged objects in the AST
// (that is, we don't use a bitfield, even for simple/common flags).
// This ensures that we can track source locations for all modifiers.
//
-ABSTRACT_SYNTAX_CLASS(Modifier, SyntaxNode)
- RAW(typedef IModifierVisitor Visitor;)
+class Modifier : public SyntaxNode
+{
+ SLANG_ABSTRACT_CLASS(Modifier)
+ typedef IModifierVisitor Visitor;
- RAW(virtual void accept(IModifierVisitor* visitor, void* extra) = 0;)
+ virtual void accept(IModifierVisitor* visitor, void* extra) = 0;
// Next modifier in linked list of modifiers on same piece of syntax
- SYNTAX_FIELD(RefPtr<Modifier>, next)
+ RefPtr<Modifier> next;
// The keyword that was used to introduce t that was used to name this modifier.
- FIELD(Name*, name)
+ Name* name;
- RAW(
- Name* getName() { return name; }
- NameLoc getNameAndLoc() { return NameLoc(name, loc); }
- )
-END_SYNTAX_CLASS()
+ Name* getName() { return name; }
+ NameLoc getNameAndLoc() { return NameLoc(name, loc); }
+};
// A syntax node which can have modifiers applied
-ABSTRACT_SYNTAX_CLASS(ModifiableSyntaxNode, SyntaxNode)
+class ModifiableSyntaxNode : public SyntaxNode
+{
+ SLANG_ABSTRACT_CLASS(ModifiableSyntaxNode)
- SYNTAX_FIELD(Modifiers, modifiers)
+ Modifiers modifiers;
- RAW(
template<typename T>
FilteredModifierList<T> GetModifiersOfType() { return FilteredModifierList<T>(modifiers.first.Ptr()); }
@@ -249,58 +303,68 @@ ABSTRACT_SYNTAX_CLASS(ModifiableSyntaxNode, SyntaxNode)
template<typename T>
bool HasModifier() { return FindModifier<T>() != nullptr; }
- )
-END_SYNTAX_CLASS()
+};
// An intermediate type to represent either a single declaration, or a group of declarations
-ABSTRACT_SYNTAX_CLASS(DeclBase, ModifiableSyntaxNode)
- RAW(typedef IDeclVisitor Visitor;)
+class DeclBase : public ModifiableSyntaxNode
+{
+ SLANG_ABSTRACT_CLASS(DeclBase)
- RAW(virtual void accept(IDeclVisitor* visitor, void* extra) = 0;)
+ typedef IDeclVisitor Visitor;
+ virtual void accept(IDeclVisitor* visitor, void* extra) = 0;
+};
-END_SYNTAX_CLASS()
+class Decl : public DeclBase
+{
+public:
+ SLANG_ABSTRACT_CLASS(Decl)
-ABSTRACT_SYNTAX_CLASS(Decl, DeclBase)
- DECL_FIELD(ContainerDecl*, ParentDecl RAW(=nullptr))
+ ContainerDecl* ParentDecl = nullptr;
- FIELD(NameLoc, nameAndLoc)
+ NameLoc nameAndLoc;
- RAW(
Name* getName() { return nameAndLoc.name; }
SourceLoc getNameLoc() { return nameAndLoc.loc ; }
NameLoc getNameAndLoc() { return nameAndLoc ; }
- )
- FIELD_INIT(DeclCheckStateExt, checkState, DeclCheckState::Unchecked)
+ DeclCheckStateExt checkState = DeclCheckState::Unchecked;
// The next declaration defined in the same container with the same name
- DECL_FIELD(Decl*, nextInContainerWithSameName RAW(= nullptr))
+ Decl* nextInContainerWithSameName = nullptr;
- RAW(
bool IsChecked(DeclCheckState state) { return checkState >= state; }
void SetCheckState(DeclCheckState state)
{
SLANG_RELEASE_ASSERT(state >= checkState.getState());
checkState.setState(state);
}
- )
-END_SYNTAX_CLASS()
+};
+
+class Expr : public SyntaxNode
+{
+ SLANG_ABSTRACT_CLASS(Expr)
+
+ typedef IExprVisitor Visitor;
+
+ QualType type;
-ABSTRACT_SYNTAX_CLASS(Expr, SyntaxNode)
- RAW(typedef IExprVisitor Visitor;)
+ virtual void accept(IExprVisitor* visitor, void* extra) = 0;
+};
- FIELD(QualType, type)
+class Stmt : public ModifiableSyntaxNode
+{
+ SLANG_ABSTRACT_CLASS(Stmt)
- RAW(virtual void accept(IExprVisitor* visitor, void* extra) = 0;)
+ typedef IStmtVisitor Visitor;
-END_SYNTAX_CLASS()
+ virtual void accept(IStmtVisitor* visitor, void* extra) = 0;
+};
-ABSTRACT_SYNTAX_CLASS(Stmt, ModifiableSyntaxNode)
- RAW(typedef IStmtVisitor Visitor;)
+#undef SLANG_ABSTRACT_CLASS
+#undef SLANG_CLASS
- RAW(virtual void accept(IStmtVisitor* visitor, void* extra) = 0;)
-END_SYNTAX_CLASS()
+} // namespace Slang
diff --git a/source/slang/slang-decl-defs.h b/source/slang/slang-ast-decl.h
index 7dc58539c..f151b6ca0 100644
--- a/source/slang/slang-decl-defs.h
+++ b/source/slang/slang-ast-decl.h
@@ -1,17 +1,32 @@
// slang-decl-defs.h
+#pragma once
+
+#include "slang-ast-base.h"
+
+namespace Slang {
+
+#define SLANG_ABSTRACT_CLASS(x) SLANG_ABSTRACT_CLASS_REFLECT(x)
+#define SLANG_CLASS(x) SLANG_CLASS_REFLECT_WITH_ACCEPT(x)
+
// Syntax class definitions for declarations.
// A group of declarations that should be treated as a unit
-SYNTAX_CLASS(DeclGroup, DeclBase)
- SYNTAX_FIELD(List<RefPtr<Decl>>, decls)
-END_SYNTAX_CLASS()
+class DeclGroup: public DeclBase
+{
+ SLANG_CLASS(DeclGroup)
+
+ List<RefPtr<Decl>> decls;
+};
+
// A "container" decl is a parent to other declarations
-ABSTRACT_SYNTAX_CLASS(ContainerDecl, Decl)
- SYNTAX_FIELD(List<RefPtr<Decl>>, Members)
+class ContainerDecl: public Decl
+{
+ SLANG_ABSTRACT_CLASS(ContainerDecl)
+
+ List<RefPtr<Decl>> Members;
- RAW(
template<typename T>
FilteredMemberList<T> getMembersOfType()
{
@@ -35,30 +50,33 @@ ABSTRACT_SYNTAX_CLASS(ContainerDecl, Decl)
// A list of transparent members, to be used in lookup
// Note: this is only valid if `memberDictionaryIsValid` is true
List<TransparentMemberInfo> transparentMembers;
- )
-END_SYNTAX_CLASS()
+};
// Base class for all variable declarations
-ABSTRACT_SYNTAX_CLASS(VarDeclBase, Decl)
+class VarDeclBase : public Decl
+{
+ SLANG_ABSTRACT_CLASS(VarDeclBase)
// type of the variable
- SYNTAX_FIELD(TypeExp, type)
+ TypeExp type;
- RAW(
- Type* getType() { return type.type.Ptr(); }
- )
+ Type* getType() { return (Type*)type.type.Ptr(); }
// Initializer expression (optional)
- SYNTAX_FIELD(RefPtr<Expr>, initExpr)
-END_SYNTAX_CLASS()
+ RefPtr<Expr> initExpr;
+};
// Ordinary potentially-mutable variables (locals, globals, and member variables)
-SYNTAX_CLASS(VarDecl, VarDeclBase)
-END_SYNTAX_CLASS()
+class VarDecl : public VarDeclBase
+{
+ SLANG_CLASS(VarDecl)
+};
// A variable declaration that is always immutable (whether local, global, or member variable)
-SYNTAX_CLASS(LetDecl, VarDecl)
-END_SYNTAX_CLASS()
+class LetDecl : public VarDecl
+{
+ SLANG_CLASS(LetDecl)
+};
// An `AggTypeDeclBase` captures the shared functionality
// between true aggregate type declarations and extension
@@ -68,44 +86,58 @@ END_SYNTAX_CLASS()
// - Both can have declared bases
// - Both expose a `this` variable in their body
//
-ABSTRACT_SYNTAX_CLASS(AggTypeDeclBase, ContainerDecl)
-END_SYNTAX_CLASS()
+class AggTypeDeclBase : public ContainerDecl
+{
+ SLANG_ABSTRACT_CLASS(AggTypeDeclBase);
+};
// An extension to apply to an existing type
-SYNTAX_CLASS(ExtensionDecl, AggTypeDeclBase)
- SYNTAX_FIELD(TypeExp, targetType)
+class ExtensionDecl : public AggTypeDeclBase
+{
+ SLANG_CLASS(ExtensionDecl)
+
+ TypeExp targetType;
// next extension attached to the same nominal type
- DECL_FIELD(ExtensionDecl*, nextCandidateExtension RAW(= nullptr))
-END_SYNTAX_CLASS()
+ ExtensionDecl* nextCandidateExtension = nullptr;
+};
// Declaration of a type that represents some sort of aggregate
-ABSTRACT_SYNTAX_CLASS(AggTypeDecl, AggTypeDeclBase)
+class AggTypeDecl : public AggTypeDeclBase
+{
+ SLANG_ABSTRACT_CLASS(AggTypeDecl)
-RAW(
// extensions that might apply to this declaration
ExtensionDecl* candidateExtensions = nullptr;
+
FilteredMemberList<VarDecl> GetFields()
{
return getMembersOfType<VarDecl>();
}
- )
-END_SYNTAX_CLASS()
+};
-SIMPLE_SYNTAX_CLASS(StructDecl, AggTypeDecl)
+class StructDecl: public AggTypeDecl
+{
+ SLANG_CLASS(StructDecl);
+};
+
+class ClassDecl : public AggTypeDecl
+{
+ SLANG_CLASS(ClassDecl)
+};
-SIMPLE_SYNTAX_CLASS(ClassDecl, AggTypeDecl)
// TODO: Is it appropriate to treat an `enum` as an aggregate type?
// Most code that looks for, e.g., conformances assumes user-defined
// types are all `AggTypeDecl`, so this is the right choice for now
// if we want `enum` types to be able to implement interfaces, etc.
//
-SYNTAX_CLASS(EnumDecl, AggTypeDecl)
-RAW(
+class EnumDecl : public AggTypeDecl
+{
+ SLANG_CLASS(EnumDecl)
+
RefPtr<Type> tagType;
-)
-END_SYNTAX_CLASS()
+};
// A single case in an enum.
//
@@ -117,36 +149,43 @@ END_SYNTAX_CLASS()
// case, with `0` as an explicit expression for its
// _tag value_.
//
-SYNTAX_CLASS(EnumCaseDecl, Decl)
+class EnumCaseDecl : public Decl
+{
+ SLANG_CLASS(EnumCaseDecl)
// type of the parent `enum`
- SYNTAX_FIELD(TypeExp, type)
+ TypeExp type;
- RAW(
- Type* getType() { return type.type.Ptr(); }
- )
+ Type* getType() { return (Type*)type.type.Ptr(); }
// Tag value
- SYNTAX_FIELD(RefPtr<Expr>, tagExpr)
-END_SYNTAX_CLASS()
+ RefPtr<Expr> tagExpr;
+};
// An interface which other types can conform to
-SIMPLE_SYNTAX_CLASS(InterfaceDecl, AggTypeDecl)
+class InterfaceDecl : public AggTypeDecl
+{
+ SLANG_CLASS(InterfaceDecl)
+};
-ABSTRACT_SYNTAX_CLASS(TypeConstraintDecl, Decl)
- RAW(
+
+class TypeConstraintDecl : public Decl
+{
+ SLANG_ABSTRACT_CLASS(TypeConstraintDecl)
+
virtual TypeExp& getSup() = 0;
- )
-END_SYNTAX_CLASS()
+};
// A kind of pseudo-member that represents an explicit
// or implicit inheritance relationship.
//
-SYNTAX_CLASS(InheritanceDecl, TypeConstraintDecl)
+class InheritanceDecl : public TypeConstraintDecl
+{
+ SLANG_CLASS(InheritanceDecl)
+
// The type expression as written
- SYNTAX_FIELD(TypeExp, base)
+ TypeExp base;
- RAW(
// After checking, this dictionary will map members
// required by the base type to their concrete
// implementations in the type that contains
@@ -156,8 +195,7 @@ SYNTAX_CLASS(InheritanceDecl, TypeConstraintDecl)
{
return base;
}
- )
-END_SYNTAX_CLASS()
+};
// TODO: may eventually need sub-classes for explicit/direct vs. implicit/indirect inheritance
@@ -166,51 +204,76 @@ END_SYNTAX_CLASS()
//
// TODO: probably all types will be aggregate decls eventually,
// so that we can easily store conformances/constraints on type variables
-ABSTRACT_SYNTAX_CLASS(SimpleTypeDecl, Decl)
-END_SYNTAX_CLASS()
+class SimpleTypeDecl : public Decl
+{
+ SLANG_ABSTRACT_CLASS(SimpleTypeDecl)
+};
// A `typedef` declaration
-SYNTAX_CLASS(TypeDefDecl, SimpleTypeDecl)
- SYNTAX_FIELD(TypeExp, type)
-END_SYNTAX_CLASS()
-
-SIMPLE_SYNTAX_CLASS(TypeAliasDecl, TypeDefDecl)
+class TypeDefDecl : public SimpleTypeDecl
+{
+ SLANG_CLASS(TypeDefDecl)
+
+ TypeExp type;
+};
+
+class TypeAliasDecl : public TypeDefDecl
+{
+ SLANG_CLASS(TypeAliasDecl)
+};
// An 'assoctype' declaration, it is a container of inheritance clauses
-SYNTAX_CLASS(AssocTypeDecl, AggTypeDecl)
-END_SYNTAX_CLASS()
+class AssocTypeDecl : public AggTypeDecl
+{
+ SLANG_CLASS(AssocTypeDecl)
+};
// A 'type_param' declaration, which defines a generic
// entry-point parameter. Is a container of GenericTypeConstraintDecl
-SYNTAX_CLASS(GlobalGenericParamDecl, AggTypeDecl)
-END_SYNTAX_CLASS()
+class GlobalGenericParamDecl : public AggTypeDecl
+{
+ SLANG_CLASS(GlobalGenericParamDecl)
+};
// A `__generic_value_param` declaration, which defines an existential
// value parameter (not a type parameter.
-SYNTAX_CLASS(GlobalGenericValueParamDecl, VarDeclBase)
-END_SYNTAX_CLASS()
+class GlobalGenericValueParamDecl : public VarDeclBase
+{
+ SLANG_CLASS(GlobalGenericValueParamDecl)
+};
// A scope for local declarations (e.g., as part of a statement)
-SIMPLE_SYNTAX_CLASS(ScopeDecl, ContainerDecl)
+class ScopeDecl : public ContainerDecl
+{
+ SLANG_CLASS(ScopeDecl)
+};
// A function/initializer/subscript parameter (potentially mutable)
-SIMPLE_SYNTAX_CLASS(ParamDecl, VarDeclBase)
+class ParamDecl : public VarDeclBase
+{
+ SLANG_CLASS(ParamDecl)
+};
// A parameter of a function declared in "modern" types (immutable unless explicitly `out` or `inout`)
-SIMPLE_SYNTAX_CLASS(ModernParamDecl, ParamDecl)
+class ModernParamDecl : public ParamDecl
+{
+ SLANG_CLASS(ModernParamDecl)
+};
// Base class for things that have parameter lists and can thus be applied to arguments ("called")
-ABSTRACT_SYNTAX_CLASS(CallableDecl, ContainerDecl)
- RAW(
+class CallableDecl : public ContainerDecl
+{
+ SLANG_ABSTRACT_CLASS(CallableDecl)
+
FilteredMemberList<ParamDecl> GetParameters()
{
return getMembersOfType<ParamDecl>();
- })
+ }
- SYNTAX_FIELD(TypeExp, ReturnType)
+ TypeExp ReturnType;
// Fields related to redeclaration, so that we
- // can support multiple specialized varaitions
+ // can support multiple specialized variations
// of the "same" logical function.
//
// This should also help us to support redeclaration
@@ -218,35 +281,61 @@ ABSTRACT_SYNTAX_CLASS(CallableDecl, ContainerDecl)
// The "primary" declaration of the function, which will
// be used whenever we need to unique things.
- FIELD_INIT(CallableDecl*, primaryDecl, nullptr)
+ CallableDecl* primaryDecl = nullptr;
// The next declaration of the "same" function (that is,
// with the same `primaryDecl`).
- FIELD_INIT(CallableDecl*, nextDecl, nullptr);
-
-END_SYNTAX_CLASS()
+ CallableDecl* nextDecl = nullptr;
+};
// Base class for callable things that may also have a body that is evaluated to produce their result
-ABSTRACT_SYNTAX_CLASS(FunctionDeclBase, CallableDecl)
- SYNTAX_FIELD(RefPtr<Stmt>, Body)
-END_SYNTAX_CLASS()
+class FunctionDeclBase : public CallableDecl
+{
+ SLANG_ABSTRACT_CLASS(FunctionDeclBase)
+
+ RefPtr<Stmt> Body;
+};
// A constructor/initializer to create instances of a type
-SIMPLE_SYNTAX_CLASS(ConstructorDecl, FunctionDeclBase)
+class ConstructorDecl : public FunctionDeclBase
+{
+ SLANG_CLASS(ConstructorDecl)
+};
// A subscript operation used to index instances of a type
-SIMPLE_SYNTAX_CLASS(SubscriptDecl, CallableDecl)
+class SubscriptDecl : public CallableDecl
+{
+ SLANG_CLASS(SubscriptDecl)
+};
// An "accessor" for a subscript or property
-SIMPLE_SYNTAX_CLASS(AccessorDecl, FunctionDeclBase)
-
-SIMPLE_SYNTAX_CLASS(GetterDecl, AccessorDecl)
-SIMPLE_SYNTAX_CLASS(SetterDecl, AccessorDecl)
-SIMPLE_SYNTAX_CLASS(RefAccessorDecl, AccessorDecl)
-
-SIMPLE_SYNTAX_CLASS(FuncDecl, FunctionDeclBase)
-
-SIMPLE_SYNTAX_CLASS(NamespaceDeclBase, ContainerDecl)
+class AccessorDecl : public FunctionDeclBase
+{
+ SLANG_CLASS(AccessorDecl)
+};
+
+class GetterDecl : public AccessorDecl
+{
+ SLANG_CLASS(GetterDecl)
+};
+class SetterDecl : public AccessorDecl
+{
+ SLANG_CLASS(SetterDecl)
+};
+class RefAccessorDecl : public AccessorDecl
+{
+ SLANG_CLASS(RefAccessorDecl)
+};
+
+class FuncDecl : public FunctionDeclBase
+{
+ SLANG_CLASS(FuncDecl)
+};
+
+class NamespaceDeclBase : public ContainerDecl
+{
+ SLANG_CLASS(NamespaceDeclBase)
+};
// A `namespace` declaration inside some module, that provides
// a named scope for declarations inside it.
@@ -256,63 +345,80 @@ SIMPLE_SYNTAX_CLASS(NamespaceDeclBase, ContainerDecl)
// `NamespaceDecl` during parsing, so this declaration does
// not directly represent what is present in the input syntax.
//
-SIMPLE_SYNTAX_CLASS(NamespaceDecl, NamespaceDeclBase)
+class NamespaceDecl : public NamespaceDeclBase
+{
+ SLANG_CLASS(NamespaceDecl)
+};
- // A "module" of code (essentiately, a single translation unit)
+ // A "module" of code (essentially, a single translation unit)
// that provides a scope for some number of declarations.
-SYNTAX_CLASS(ModuleDecl, NamespaceDeclBase)
+class ModuleDecl : public NamespaceDeclBase
+{
+ SLANG_CLASS(ModuleDecl)
// The API-level module that this declaration belong to.
//
// This field allows lookup of the `Module` based on a
// declaration nested under a `ModuleDecl` by following
// its chain of parents.
//
- RAW(Module* module = nullptr;)
-END_SYNTAX_CLASS()
+ Module* module = nullptr;
+};
+
+class ImportDecl : public Decl
+{
+ SLANG_CLASS(ImportDecl)
-SYNTAX_CLASS(ImportDecl, Decl)
// The name of the module we are trying to import
- FIELD(NameLoc, moduleNameAndLoc)
+ NameLoc moduleNameAndLoc;
// The scope that we want to import into
- FIELD(RefPtr<Scope>, scope)
+ RefPtr<Scope> scope;
// The module that actually got imported
- DECL_FIELD(RefPtr<ModuleDecl>, importedModuleDecl)
-END_SYNTAX_CLASS()
+ RefPtr<ModuleDecl> importedModuleDecl;
+};
// A generic declaration, parameterized on types/values
-SYNTAX_CLASS(GenericDecl, ContainerDecl)
+class GenericDecl : public ContainerDecl
+{
+ SLANG_CLASS(GenericDecl)
// The decl that is genericized...
- SYNTAX_FIELD(RefPtr<Decl>, inner)
-END_SYNTAX_CLASS()
+ RefPtr<Decl> inner;
+};
-SYNTAX_CLASS(GenericTypeParamDecl, SimpleTypeDecl)
+class GenericTypeParamDecl : public SimpleTypeDecl
+{
+ SLANG_CLASS(GenericTypeParamDecl)
// The bound for the type parameter represents a trait that any
// type used as this parameter must conform to
// TypeExp bound;
// The "initializer" for the parameter represents a default value
- SYNTAX_FIELD(TypeExp, initType)
-END_SYNTAX_CLASS()
+ TypeExp initType;
+};
// A constraint placed as part of a generic declaration
-SYNTAX_CLASS(GenericTypeConstraintDecl, TypeConstraintDecl)
+class GenericTypeConstraintDecl : public TypeConstraintDecl
+{
+ SLANG_CLASS(GenericTypeConstraintDecl)
+
// A type constraint like `T : U` is constraining `T` to be "below" `U`
// on a lattice of types. This may not be a subtyping relationship
// per se, but it makes sense to use that terminology here, so we
- // think of these fields as the sub-type and sup-ertype, respectively.
- SYNTAX_FIELD(TypeExp, sub)
- SYNTAX_FIELD(TypeExp, sup)
- RAW(
+ // think of these fields as the sub-type and super-type, respectively.
+ TypeExp sub;
+ TypeExp sup;
+
virtual TypeExp& getSup() override
{
return sup;
}
- )
-END_SYNTAX_CLASS()
+};
-SIMPLE_SYNTAX_CLASS(GenericValueParamDecl, VarDeclBase)
+class GenericValueParamDecl : public VarDeclBase
+{
+ SLANG_CLASS(GenericValueParamDecl)
+};
// An empty declaration (which might still have modifiers attached).
//
@@ -323,23 +429,36 @@ SIMPLE_SYNTAX_CLASS(GenericValueParamDecl, VarDeclBase)
//
// layout(local_size_x = 16) in;
//
-SIMPLE_SYNTAX_CLASS(EmptyDecl, Decl)
+class EmptyDecl : public Decl
+{
+ SLANG_CLASS(EmptyDecl)
+};
// A declaration used by the implementation to put syntax keywords
// into the current scope.
//
-SYNTAX_CLASS(SyntaxDecl, Decl)
+class SyntaxDecl : public Decl
+{
+ SLANG_CLASS(SyntaxDecl)
+
// What type of syntax node will be produced when parsing with this keyword?
- FIELD(SyntaxClass<RefObject>, syntaxClass)
+ SyntaxClass<RefObject> syntaxClass;
// Callback to invoke in order to parse syntax with this keyword.
- FIELD(SyntaxParseCallback, parseCallback)
- FIELD(void*, parseUserData)
-END_SYNTAX_CLASS()
+ SyntaxParseCallback parseCallback;
+ void* parseUserData;
+};
// A declaration of an attribute to be used with `[name(...)]` syntax.
//
-SYNTAX_CLASS(AttributeDecl, ContainerDecl)
+class AttributeDecl : public ContainerDecl
+{
+ SLANG_CLASS(AttributeDecl)
// What type of syntax node will be produced to represent this attribute.
- FIELD(SyntaxClass<RefObject>, syntaxClass)
-END_SYNTAX_CLASS()
+ SyntaxClass<RefObject> syntaxClass;
+};
+
+#undef SLANG_ABSTRACT_CLASS
+#undef SLANG_CLASS
+
+} // namespace Slang
diff --git a/source/slang/slang-ast-expr.h b/source/slang/slang-ast-expr.h
new file mode 100644
index 000000000..31e3869d3
--- /dev/null
+++ b/source/slang/slang-ast-expr.h
@@ -0,0 +1,311 @@
+// slang-ast-expr.h
+
+#pragma once
+
+#include "slang-ast-base.h"
+
+namespace Slang {
+
+#define SLANG_ABSTRACT_CLASS(x) SLANG_ABSTRACT_CLASS_REFLECT(x)
+#define SLANG_CLASS(x) SLANG_CLASS_REFLECT_WITH_ACCEPT(x)
+
+// Syntax class definitions for expressions.
+
+// Base class for expressions that will reference declarations
+class DeclRefExpr: public Expr
+{
+ SLANG_ABSTRACT_CLASS(DeclRefExpr)
+
+ // The scope in which to perform lookup
+ RefPtr<Scope> scope;
+
+ // The declaration of the symbol being referenced
+ DeclRef<Decl> declRef;
+
+ // The name of the symbol being referenced
+ Name* name;
+};
+
+class VarExpr : public DeclRefExpr
+{
+ SLANG_CLASS(VarExpr)
+};
+
+// An expression that references an overloaded set of declarations
+// having the same name.
+class OverloadedExpr : public Expr
+{
+ SLANG_CLASS(OverloadedExpr)
+
+ // The name that was looked up and found to be overloaded
+ Name* name;
+
+ // Optional: the base expression is this overloaded result
+ // arose from a member-reference expression.
+ RefPtr<Expr> base;
+
+ // The lookup result that was ambiguous
+ LookupResult lookupResult2;
+};
+
+// An expression that references an overloaded set of declarations
+// having the same name.
+class OverloadedExpr2: public Expr
+{
+ SLANG_CLASS(OverloadedExpr2)
+
+ // Optional: the base expression is this overloaded result
+ // arose from a member-reference expression.
+ RefPtr<Expr> base;
+
+ // The lookup result that was ambiguous
+ List<RefPtr<Expr>> candidiateExprs;
+};
+
+class LiteralExpr : public Expr
+{
+ SLANG_ABSTRACT_CLASS(LiteralExpr)
+ // The token that was used to express the literal. This can be
+ // used to get the raw text of the literal, including any suffix.
+ Token token;
+};
+
+class IntegerLiteralExpr : public LiteralExpr
+{
+ SLANG_CLASS(IntegerLiteralExpr)
+
+ IntegerLiteralValue value;
+};
+
+class FloatingPointLiteralExpr: public LiteralExpr
+{
+ SLANG_CLASS(FloatingPointLiteralExpr)
+ FloatingPointLiteralValue value;
+};
+
+class BoolLiteralExpr : public LiteralExpr
+{
+ SLANG_CLASS(BoolLiteralExpr)
+ bool value;
+};
+
+class StringLiteralExpr : public LiteralExpr
+{
+ SLANG_CLASS(StringLiteralExpr)
+
+ // TODO: consider storing the "segments" of the string
+ // literal, in the case where multiple literals were
+ //lined up at the lexer level, e.g.:
+ //
+ // "first" "second" "third"
+ //
+ String value;
+};
+
+// An initializer list, e.g. `{ 1, 2, 3 }`
+class InitializerListExpr : public Expr
+{
+ SLANG_CLASS(InitializerListExpr)
+ List<RefPtr<Expr>> args;
+};
+
+// A base class for expressions with arguments
+class ExprWithArgsBase : public Expr
+{
+ SLANG_ABSTRACT_CLASS(ExprWithArgsBase)
+
+ List<RefPtr<Expr>> Arguments;
+};
+
+// An aggregate type constructor
+class AggTypeCtorExpr : public ExprWithArgsBase
+{
+ SLANG_CLASS(AggTypeCtorExpr)
+
+ TypeExp base;;
+};
+
+
+// A base expression being applied to arguments: covers
+// both ordinary `()` function calls and `<>` generic application
+class AppExprBase : public ExprWithArgsBase
+{
+ SLANG_ABSTRACT_CLASS(AppExprBase)
+
+ RefPtr<Expr> FunctionExpr;
+};
+
+class InvokeExpr: public AppExprBase
+{
+ SLANG_CLASS(InvokeExpr)
+};
+
+class OperatorExpr: public InvokeExpr
+{
+ SLANG_CLASS(OperatorExpr)
+};
+
+class InfixExpr: public OperatorExpr
+{
+ SLANG_CLASS(InfixExpr)
+};
+class PrefixExpr: public OperatorExpr
+{
+ SLANG_CLASS(PrefixExpr)
+};
+class PostfixExpr: public OperatorExpr
+{
+ SLANG_CLASS(PostfixExpr)
+};
+
+class IndexExpr: public Expr
+{
+ SLANG_CLASS(IndexExpr)
+
+ RefPtr<Expr> BaseExpression;
+ RefPtr<Expr> IndexExpression;
+};
+
+class MemberExpr: public DeclRefExpr
+{
+ SLANG_CLASS(MemberExpr)
+ RefPtr<Expr> BaseExpression;
+};
+
+// Member looked up on a type, rather than a value
+class StaticMemberExpr: public DeclRefExpr
+{
+ SLANG_CLASS(StaticMemberExpr)
+ RefPtr<Expr> BaseExpression;
+};
+
+class SwizzleExpr: public Expr
+{
+ SLANG_CLASS(SwizzleExpr)
+ RefPtr<Expr> base;
+ int elementCount;
+ int elementIndices[4];
+};
+
+// A dereference of a pointer or pointer-like type
+class DerefExpr: public Expr
+{
+ SLANG_CLASS(DerefExpr)
+ RefPtr<Expr> base;
+};
+
+// Any operation that performs type-casting
+class TypeCastExpr: public InvokeExpr
+{
+ SLANG_CLASS(TypeCastExpr)
+// TypeExp TargetType;
+// RefPtr<Expr> Expression;
+};
+
+// An explicit type-cast that appear in the user's code with `(type) expr` syntax
+class ExplicitCastExpr: public TypeCastExpr
+{
+ SLANG_CLASS(ExplicitCastExpr)
+};
+
+// An implicit type-cast inserted during semantic checking
+class ImplicitCastExpr : public TypeCastExpr
+{
+ SLANG_CLASS(ImplicitCastExpr)
+};
+
+ /// A cast from a value to an interface ("existential") type.
+class CastToInterfaceExpr: public Expr
+{
+ SLANG_CLASS(CastToInterfaceExpr)
+
+ /// The value being cast to an interface type
+ RefPtr<Expr> valueArg;
+
+ /// A witness showing that `valueArg` conforms to the chosen interface
+ RefPtr<Val> witnessArg;
+};
+
+class SelectExpr: public OperatorExpr
+{
+ SLANG_CLASS(SelectExpr)
+};
+
+class GenericAppExpr: public AppExprBase
+{
+ SLANG_CLASS(GenericAppExpr)
+};
+
+// An expression representing re-use of the syntax for a type in more
+// than once conceptually-distinct declaration
+class SharedTypeExpr: public Expr
+{
+ SLANG_CLASS(SharedTypeExpr)
+ // The underlying type expression that we want to share
+ TypeExp base;
+};
+
+class AssignExpr: public Expr
+{
+ SLANG_CLASS(AssignExpr)
+ RefPtr<Expr> left;;
+ RefPtr<Expr> right;;
+};
+
+// Just an expression inside parentheses `(exp)`
+//
+// We keep this around explicitly to be sure we don't lose any structure
+// when we do rewriter stuff.
+class ParenExpr: public Expr
+{
+ SLANG_CLASS(ParenExpr)
+ RefPtr<Expr> base;;
+};
+
+// An object-oriented `this` expression, used to
+// refer to the current instance of an enclosing type.
+class ThisExpr: public Expr
+{
+ SLANG_CLASS(ThisExpr)
+ RefPtr<Scope> scope;;
+};
+
+// An expression that binds a temporary variable in a local expression context
+class LetExpr: public Expr
+{
+ SLANG_CLASS(LetExpr)
+ RefPtr<VarDecl> decl;
+ RefPtr<Expr> body;
+};
+
+class ExtractExistentialValueExpr: public Expr
+{
+ SLANG_CLASS(ExtractExistentialValueExpr)
+ DeclRef<VarDeclBase> declRef;
+};
+
+ /// A type expression of the form `__TaggedUnion(A, ...)`.
+ ///
+ /// An expression of this form will resolve to a `TaggedUnionType`
+ /// when checked.
+ ///
+class TaggedUnionTypeExpr: public Expr
+{
+ SLANG_CLASS(TaggedUnionTypeExpr)
+ List<TypeExp> caseTypes;
+};
+
+ /// A type expression of the form `This`
+ ///
+ /// Refers to the type of `this` in the current context.
+ ///
+class ThisTypeExpr: public Expr
+{
+ SLANG_CLASS(ThisTypeExpr)
+ RefPtr<Scope> scope;
+};
+
+#undef SLANG_ABSTRACT_CLASS
+#undef SLANG_CLASS
+
+} // namespace Slang
diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h
new file mode 100644
index 000000000..440575171
--- /dev/null
+++ b/source/slang/slang-ast-modifier.h
@@ -0,0 +1,883 @@
+// slang-ast-modifier.h
+
+#pragma once
+
+#include "slang-ast-base.h"
+
+namespace Slang {
+
+#define SLANG_ABSTRACT_CLASS(x) SLANG_ABSTRACT_CLASS_REFLECT(x)
+#define SLANG_CLASS(x) SLANG_CLASS_REFLECT_WITH_ACCEPT(x)
+
+// Syntax class definitions for modifiers.
+
+// Simple modifiers have no state beyond their identity
+
+class InModifier : public Modifier { SLANG_CLASS(InModifier)};
+class OutModifier : public Modifier { SLANG_CLASS(OutModifier)};
+class ConstModifier : public Modifier { SLANG_CLASS(ConstModifier)};
+class InstanceModifier : public Modifier { SLANG_CLASS(InstanceModifier)};
+class BuiltinModifier : public Modifier { SLANG_CLASS(BuiltinModifier)};
+class InlineModifier : public Modifier { SLANG_CLASS(InlineModifier)};
+class PublicModifier : public Modifier { SLANG_CLASS(PublicModifier)};
+class RequireModifier : public Modifier { SLANG_CLASS(RequireModifier)};
+class ParamModifier : public Modifier { SLANG_CLASS(ParamModifier)};
+class ExternModifier : public Modifier { SLANG_CLASS(ExternModifier)};
+class InputModifier : public Modifier { SLANG_CLASS(InputModifier)};
+class TransparentModifier : public Modifier { SLANG_CLASS(TransparentModifier)};
+class FromStdLibModifier : public Modifier { SLANG_CLASS(FromStdLibModifier)};
+class PrefixModifier : public Modifier { SLANG_CLASS(PrefixModifier)};
+class PostfixModifier : public Modifier { SLANG_CLASS(PostfixModifier)};
+class ExportedModifier : public Modifier { SLANG_CLASS(ExportedModifier)};
+class ConstExprModifier : public Modifier { SLANG_CLASS(ConstExprModifier)};
+class GloballyCoherentModifier : public Modifier { SLANG_CLASS(GloballyCoherentModifier)};
+
+// A modifier that marks something as an operation that
+// has a one-to-one translation to the IR, and thus
+// has no direct definition in the high-level language.
+//
+class IntrinsicOpModifier : public Modifier
+{
+ SLANG_CLASS(IntrinsicOpModifier)
+
+ // Token that names the intrinsic op.
+ Token opToken;
+
+ // The IR opcode for the intrinsic operation.
+ //
+ uint32_t op = 0;
+};
+
+// A modifier that marks something as an intrinsic function,
+// for some subset of targets.
+class TargetIntrinsicModifier : public Modifier
+{
+ SLANG_CLASS(TargetIntrinsicModifier)
+
+ // Token that names the target that the operation
+ // is an intrisic for.
+ Token targetToken;
+
+ // A custom definition for the operation
+ Token definitionToken;
+};
+
+// A modifier that marks a declaration as representing a
+// specialization that should be preferred on a particular
+// target.
+class SpecializedForTargetModifier : public Modifier
+{
+ SLANG_CLASS(SpecializedForTargetModifier)
+
+ // Token that names the target that the operation
+ // has been specialized for.
+ Token targetToken;
+};
+
+// A modifier to tag something as an intrinsic that requires
+// a certain GLSL extension to be enabled when used
+class RequiredGLSLExtensionModifier : public Modifier
+{
+ SLANG_CLASS(RequiredGLSLExtensionModifier)
+
+ Token extensionNameToken;
+};
+
+// A modifier to tag something as an intrinsic that requires
+// a certain GLSL version to be enabled when used
+class RequiredGLSLVersionModifier : public Modifier
+{
+ SLANG_CLASS(RequiredGLSLVersionModifier)
+
+ Token versionNumberToken;
+};
+
+
+// A modifier to tag something as an intrinsic that requires
+// a certain SPIRV version to be enabled when used. Specified as "major.minor"
+class RequiredSPIRVVersionModifier : public Modifier
+{
+ SLANG_CLASS(RequiredSPIRVVersionModifier)
+
+ SemanticVersion version;
+};
+
+// A modifier to tag something as an intrinsic that requires
+// a certain CUDA SM version to be enabled when used. Specified as "major.minor"
+class RequiredCUDASMVersionModifier : public Modifier
+{
+ SLANG_CLASS(RequiredCUDASMVersionModifier)
+
+ SemanticVersion version;
+};
+
+class InOutModifier : public OutModifier
+{
+ SLANG_CLASS(InOutModifier)
+};
+
+
+// `__ref` modifier for by-reference parameter passing
+class RefModifier : public Modifier
+{
+ SLANG_CLASS(RefModifier)
+};
+
+
+// This is a special sentinel modifier that gets added
+// to the list when we have multiple variable declarations
+// all sharing the same modifiers:
+//
+// static uniform int a : FOO, *b : register(x0);
+//
+// In this case both `a` and `b` share the syntax
+// for part of their modifier list, but then have
+// their own modifiers as well:
+//
+// a: SemanticModifier("FOO") --> SharedModifiers --> StaticModifier --> UniformModifier
+// /
+// b: RegisterModifier("x0") /
+//
+class SharedModifiers : public Modifier
+{
+ SLANG_CLASS(SharedModifiers)
+};
+
+
+// A GLSL `layout` modifier
+//
+// We use a distinct modifier for each key that
+// appears within the `layout(...)` construct,
+// and each key might have an optional value token.
+//
+// TODO: We probably want a notion of "modifier groups"
+// so that we can recover good source location info
+// for modifiers that were part of the same vs.
+// different constructs.
+class GLSLLayoutModifier : public Modifier
+{
+ SLANG_ABSTRACT_CLASS(GLSLLayoutModifier)
+
+
+ // The token used to introduce the modifier is stored
+ // as the `nameToken` field.
+
+ // TODO: may want to accept a full expression here
+ Token valToken;
+};
+
+// AST nodes to represent the begin/end of a `layout` modifier group
+class GLSLLayoutModifierGroupMarker : public Modifier
+{
+ SLANG_ABSTRACT_CLASS(GLSLLayoutModifierGroupMarker)
+};
+
+class GLSLLayoutModifierGroupBegin : public GLSLLayoutModifierGroupMarker
+{
+ SLANG_CLASS(GLSLLayoutModifierGroupBegin)
+};
+
+class GLSLLayoutModifierGroupEnd : public GLSLLayoutModifierGroupMarker
+{
+ SLANG_CLASS(GLSLLayoutModifierGroupEnd)
+};
+
+
+// We divide GLSL `layout` modifiers into those we have parsed
+// (in the sense of having some notion of their semantics), and
+// those we have not.
+class GLSLParsedLayoutModifier : public GLSLLayoutModifier
+{
+ SLANG_ABSTRACT_CLASS(GLSLParsedLayoutModifier)
+};
+
+class GLSLUnparsedLayoutModifier : public GLSLLayoutModifier
+{
+ SLANG_CLASS(GLSLUnparsedLayoutModifier)
+};
+
+
+// Specific cases for known GLSL `layout` modifiers that we need to work with
+class GLSLConstantIDLayoutModifier : public GLSLParsedLayoutModifier
+{
+ SLANG_CLASS(GLSLConstantIDLayoutModifier)
+};
+
+class GLSLLocationLayoutModifier : public GLSLParsedLayoutModifier
+{
+ SLANG_CLASS(GLSLLocationLayoutModifier)
+};
+
+
+// A catch-all for single-keyword modifiers
+class SimpleModifier : public Modifier
+{
+ SLANG_CLASS(SimpleModifier)
+};
+
+
+// Some GLSL-specific modifiers
+class GLSLBufferModifier : public SimpleModifier
+{
+ SLANG_CLASS(GLSLBufferModifier)
+};
+
+class GLSLWriteOnlyModifier : public SimpleModifier
+{
+ SLANG_CLASS(GLSLWriteOnlyModifier)
+};
+
+class GLSLReadOnlyModifier : public SimpleModifier
+{
+ SLANG_CLASS(GLSLReadOnlyModifier)
+};
+
+class GLSLPatchModifier : public SimpleModifier
+{
+ SLANG_CLASS(GLSLPatchModifier)
+};
+
+
+// Indicates that this is a variable declaration that corresponds to
+// a parameter block declaration in the source program.
+class ImplicitParameterGroupVariableModifier : public Modifier
+{
+ SLANG_CLASS(ImplicitParameterGroupVariableModifier)
+};
+
+
+// Indicates that this is a type that corresponds to the element
+// type of a parameter block declaration in the source program.
+class ImplicitParameterGroupElementTypeModifier : public Modifier
+{
+ SLANG_CLASS(ImplicitParameterGroupElementTypeModifier)
+};
+
+
+// An HLSL semantic
+class HLSLSemantic : public Modifier
+{
+ SLANG_ABSTRACT_CLASS(HLSLSemantic)
+
+ Token name;
+};
+
+// An HLSL semantic that affects layout
+class HLSLLayoutSemantic : public HLSLSemantic
+{
+ SLANG_CLASS(HLSLLayoutSemantic)
+
+ Token registerName;
+ Token componentMask;
+};
+
+// An HLSL `register` semantic
+class HLSLRegisterSemantic : public HLSLLayoutSemantic
+{
+ SLANG_CLASS(HLSLRegisterSemantic)
+
+ Token spaceName;
+};
+
+// TODO(tfoley): `packoffset`
+class HLSLPackOffsetSemantic : public HLSLLayoutSemantic
+{
+ SLANG_CLASS(HLSLPackOffsetSemantic)
+};
+
+
+// An HLSL semantic that just associated a declaration with a semantic name
+class HLSLSimpleSemantic : public HLSLSemantic
+{
+ SLANG_CLASS(HLSLSimpleSemantic)
+};
+
+
+// GLSL
+
+// Directives that came in via the preprocessor, but
+// that we need to keep around for later steps
+class GLSLPreprocessorDirective : public Modifier
+{
+ SLANG_CLASS(GLSLPreprocessorDirective)
+};
+
+
+// A GLSL `#version` directive
+class GLSLVersionDirective : public GLSLPreprocessorDirective
+{
+ SLANG_CLASS(GLSLVersionDirective)
+
+
+ // Token giving the version number to use
+ Token versionNumberToken;
+
+ // Optional token giving the sub-profile to be used
+ Token glslProfileToken;
+};
+
+// A GLSL `#extension` directive
+class GLSLExtensionDirective : public GLSLPreprocessorDirective
+{
+ SLANG_CLASS(GLSLExtensionDirective)
+
+
+ // Token giving the version number to use
+ Token extensionNameToken;
+
+ // Optional token giving the sub-profile to be used
+ Token dispositionToken;
+};
+
+class ParameterGroupReflectionName : public Modifier
+{
+ SLANG_CLASS(ParameterGroupReflectionName)
+
+ NameLoc nameAndLoc;
+};
+
+// A modifier that indicates a built-in base type (e.g., `float`)
+class BuiltinTypeModifier : public Modifier
+{
+ SLANG_CLASS(BuiltinTypeModifier)
+
+ BaseType tag;
+};
+
+// A modifier that indicates a built-in type that isn't a base type (e.g., `vector`)
+//
+// TODO(tfoley): This deserves a better name than "magic"
+class MagicTypeModifier : public Modifier
+{
+ SLANG_CLASS(MagicTypeModifier)
+
+ String name;
+ uint32_t tag;
+};
+
+// A modifier applied to declarations of builtin types to indicate how they
+// should be lowered to the IR.
+//
+// TODO: This should really subsume `BuiltinTypeModifier` and
+// `MagicTypeModifier` so that we don't have to apply all of them.
+class IntrinsicTypeModifier : public Modifier
+{
+ SLANG_CLASS(IntrinsicTypeModifier)
+
+ // The IR opcode to use when constructing a type
+ uint32_t irOp;
+
+ // Additional literal opreands to provide when creating instances.
+ // (e.g., for a texture type this passes in shape/mutability info)
+ List<uint32_t> irOperands;
+};
+
+// Modifiers that affect the storage layout for matrices
+class MatrixLayoutModifier : public Modifier
+{
+ SLANG_CLASS(MatrixLayoutModifier)
+};
+
+
+// Modifiers that specify row- and column-major layout, respectively
+class RowMajorLayoutModifier : public MatrixLayoutModifier
+{
+ SLANG_CLASS(RowMajorLayoutModifier)
+};
+
+class ColumnMajorLayoutModifier : public MatrixLayoutModifier
+{
+ SLANG_CLASS(ColumnMajorLayoutModifier)
+};
+
+
+// The HLSL flavor of those modifiers
+class HLSLRowMajorLayoutModifier : public RowMajorLayoutModifier
+{
+ SLANG_CLASS(HLSLRowMajorLayoutModifier)
+};
+
+class HLSLColumnMajorLayoutModifier : public ColumnMajorLayoutModifier
+{
+ SLANG_CLASS(HLSLColumnMajorLayoutModifier)
+};
+
+
+// The GLSL flavor of those modifiers
+//
+// Note(tfoley): The GLSL versions of these modifiers are "backwards"
+// in the sense that when a GLSL programmer requests row-major layout,
+// we actually interpret that as requesting column-major. This makes
+// sense because we interpret matrix conventions backwards from how
+// GLSL specifies them.
+class GLSLRowMajorLayoutModifier : public ColumnMajorLayoutModifier
+{
+ SLANG_CLASS(GLSLRowMajorLayoutModifier)
+};
+
+class GLSLColumnMajorLayoutModifier : public RowMajorLayoutModifier
+{
+ SLANG_CLASS(GLSLColumnMajorLayoutModifier)
+};
+
+
+// More HLSL Keyword
+
+class InterpolationModeModifier : public Modifier
+{
+ SLANG_ABSTRACT_CLASS(InterpolationModeModifier)
+
+};
+
+// HLSL `nointerpolation` modifier
+class HLSLNoInterpolationModifier : public InterpolationModeModifier
+{
+ SLANG_CLASS(HLSLNoInterpolationModifier)
+};
+
+
+// HLSL `noperspective` modifier
+class HLSLNoPerspectiveModifier : public InterpolationModeModifier
+{
+ SLANG_CLASS(HLSLNoPerspectiveModifier)
+};
+
+
+// HLSL `linear` modifier
+class HLSLLinearModifier : public InterpolationModeModifier
+{
+ SLANG_CLASS(HLSLLinearModifier)
+};
+
+
+// HLSL `sample` modifier
+class HLSLSampleModifier : public InterpolationModeModifier
+{
+ SLANG_CLASS(HLSLSampleModifier)
+};
+
+
+// HLSL `centroid` modifier
+class HLSLCentroidModifier : public InterpolationModeModifier
+{
+ SLANG_CLASS(HLSLCentroidModifier)
+};
+
+
+// HLSL `precise` modifier
+class PreciseModifier : public Modifier
+{
+ SLANG_CLASS(PreciseModifier)
+};
+
+
+// HLSL `shared` modifier (which is used by the effect system,
+// and shouldn't be confused with `groupshared`)
+class HLSLEffectSharedModifier : public Modifier
+{
+ SLANG_CLASS(HLSLEffectSharedModifier)
+};
+
+
+// HLSL `groupshared` modifier
+class HLSLGroupSharedModifier : public Modifier
+{
+ SLANG_CLASS(HLSLGroupSharedModifier)
+};
+
+
+// HLSL `static` modifier (probably doesn't need to be
+// treated as HLSL-specific)
+class HLSLStaticModifier : public Modifier
+{
+ SLANG_CLASS(HLSLStaticModifier)
+};
+
+
+// HLSL `uniform` modifier (distinct meaning from GLSL
+// use of the keyword)
+class HLSLUniformModifier : public Modifier
+{
+ SLANG_CLASS(HLSLUniformModifier)
+};
+
+
+// HLSL `volatile` modifier (ignored)
+class HLSLVolatileModifier : public Modifier
+{
+ SLANG_CLASS(HLSLVolatileModifier)
+};
+
+
+class AttributeTargetModifier : public Modifier
+{
+ SLANG_CLASS(AttributeTargetModifier)
+
+ // A class to which the declared attribute type is applicable
+ SyntaxClass<RefObject> syntaxClass;
+};
+
+// Base class for checked and unchecked `[name(arg0, ...)]` style attribute.
+class AttributeBase : public Modifier
+{
+ SLANG_CLASS(AttributeBase)
+
+ List<RefPtr<Expr>> args;
+};
+
+// A `[name(...)]` attribute that hasn't undergone any semantic analysis.
+// After analysis, this will be transformed into a more specific case.
+class UncheckedAttribute : public AttributeBase
+{
+ SLANG_CLASS(UncheckedAttribute)
+
+ RefPtr<Scope> scope;
+};
+
+// A `[name(arg0, ...)]` style attribute that has been validated.
+class Attribute : public AttributeBase
+{
+ SLANG_CLASS(Attribute)
+
+ AttributeArgumentValueDict intArgVals;
+};
+
+class UserDefinedAttribute : public Attribute
+{
+ SLANG_CLASS(UserDefinedAttribute)
+
+};
+
+class AttributeUsageAttribute : public Attribute
+{
+ SLANG_CLASS(AttributeUsageAttribute)
+
+ SyntaxClass<RefObject> targetSyntaxClass;
+};
+
+// An `[unroll]` or `[unroll(count)]` attribute
+class UnrollAttribute : public Attribute
+{
+ SLANG_CLASS(UnrollAttribute)
+
+ IntegerLiteralValue getCount();
+};
+
+class LoopAttribute : public Attribute
+{
+ SLANG_CLASS(LoopAttribute)
+};
+ // `[loop]`
+class FastOptAttribute : public Attribute
+{
+ SLANG_CLASS(FastOptAttribute)
+};
+ // `[fastopt]`
+class AllowUAVConditionAttribute : public Attribute
+{
+ SLANG_CLASS(AllowUAVConditionAttribute)
+};
+ // `[allow_uav_condition]`
+class BranchAttribute : public Attribute
+{
+ SLANG_CLASS(BranchAttribute)
+};
+ // `[branch]`
+class FlattenAttribute : public Attribute
+{
+ SLANG_CLASS(FlattenAttribute)
+};
+ // `[flatten]`
+class ForceCaseAttribute : public Attribute
+{
+ SLANG_CLASS(ForceCaseAttribute)
+};
+ // `[forcecase]`
+class CallAttribute : public Attribute
+{
+ SLANG_CLASS(CallAttribute)
+};
+ // `[call]`
+
+
+// [[vk_push_constant]] [[push_constant]]
+class PushConstantAttribute : public Attribute
+{
+ SLANG_CLASS(PushConstantAttribute)
+};
+
+
+// [[vk_shader_record]] [[shader_record]]
+class ShaderRecordAttribute : public Attribute
+{
+ SLANG_CLASS(ShaderRecordAttribute)
+};
+
+
+// [[vk_binding]]
+class GLSLBindingAttribute : public Attribute
+{
+ SLANG_CLASS(GLSLBindingAttribute)
+
+ int32_t binding = 0;
+ int32_t set = 0;
+};
+
+class GLSLSimpleIntegerLayoutAttribute : public Attribute
+{
+ SLANG_CLASS(GLSLSimpleIntegerLayoutAttribute)
+
+ int32_t value = 0;
+};
+
+// [[vk_location]]
+class GLSLLocationAttribute : public GLSLSimpleIntegerLayoutAttribute
+{
+ SLANG_CLASS(GLSLLocationAttribute)
+};
+
+
+// [[vk_index]]
+class GLSLIndexAttribute : public GLSLSimpleIntegerLayoutAttribute
+{
+ SLANG_CLASS(GLSLIndexAttribute)
+};
+
+
+// TODO: for attributes that take arguments, the syntax node
+// classes should provide accessors for the values of those arguments.
+
+class MaxTessFactorAttribute : public Attribute
+{
+ SLANG_CLASS(MaxTessFactorAttribute)
+};
+
+class OutputControlPointsAttribute : public Attribute
+{
+ SLANG_CLASS(OutputControlPointsAttribute)
+};
+
+class OutputTopologyAttribute : public Attribute
+{
+ SLANG_CLASS(OutputTopologyAttribute)
+};
+
+class PartitioningAttribute : public Attribute
+{
+ SLANG_CLASS(PartitioningAttribute)
+};
+
+class PatchConstantFuncAttribute : public Attribute
+{
+ SLANG_CLASS(PatchConstantFuncAttribute)
+
+ RefPtr<FuncDecl> patchConstantFuncDecl;
+};
+class DomainAttribute : public Attribute
+{
+ SLANG_CLASS(DomainAttribute)
+};
+
+
+class EarlyDepthStencilAttribute : public Attribute
+{
+ SLANG_CLASS(EarlyDepthStencilAttribute)
+};
+ // `[earlydepthstencil]`
+
+// An HLSL `[numthreads(x,y,z)]` attribute
+class NumThreadsAttribute : public Attribute
+{
+ SLANG_CLASS(NumThreadsAttribute)
+
+ // The number of threads to use along each axis
+ //
+ // TODO: These should be accessors that use the
+ // ordinary `args` list, rather than side data.
+ int32_t x;
+ int32_t y;
+ int32_t z;
+};
+
+class MaxVertexCountAttribute : public Attribute
+{
+ SLANG_CLASS(MaxVertexCountAttribute)
+
+ // The number of max vertex count for geometry shader
+ //
+ // TODO: This should be an accessor that uses the
+ // ordinary `args` list, rather than side data.
+ int32_t value;
+};
+
+class InstanceAttribute : public Attribute
+{
+ SLANG_CLASS(InstanceAttribute)
+
+ // The number of instances to run for geometry shader
+ //
+ // TODO: This should be an accessor that uses the
+ // ordinary `args` list, rather than side data.
+ int32_t value;
+};
+
+// A `[shader("stageName")]` attribute, which marks an entry point
+// to be compiled, and specifies the stage for that entry point
+class EntryPointAttribute : public Attribute
+{
+ SLANG_CLASS(EntryPointAttribute)
+
+ // The resolved stage that the entry point is targetting.
+ //
+ // TODO: This should be an accessor that uses the
+ // ordinary `args` list, rather than side data.
+ Stage stage;;
+};
+
+// A `[__vulkanRayPayload]` attribute, which is used in the
+// standard library implementation to indicate that a variable
+// actually represents the input/output interface for a Vulkan
+// ray tracing shader to pass per-ray payload information.
+class VulkanRayPayloadAttribute : public Attribute
+{
+ SLANG_CLASS(VulkanRayPayloadAttribute)
+};
+
+
+// A `[__vulkanCallablePayload]` attribute, which is used in the
+// standard library implementation to indicate that a variable
+// actually represents the input/output interface for a Vulkan
+// ray tracing shader to pass payload information to/from a callee.
+class VulkanCallablePayloadAttribute : public Attribute
+{
+ SLANG_CLASS(VulkanCallablePayloadAttribute)
+};
+
+
+// A `[__vulkanHitAttributes]` attribute, which is used in the
+// standard library implementation to indicate that a variable
+// actually represents the output interface for a Vulkan
+// intersection shader to pass hit attribute information.
+class VulkanHitAttributesAttribute : public Attribute
+{
+ SLANG_CLASS(VulkanHitAttributesAttribute)
+};
+
+
+// A `[mutating]` attribute, which indicates that a member
+// function is allowed to modify things through its `this`
+// argument.
+//
+class MutatingAttribute : public Attribute
+{
+ SLANG_CLASS(MutatingAttribute)
+};
+
+
+// A `[__readNone]` attribute, which indicates that a function
+// computes its results strictly based on argument values, without
+// reading or writing through any pointer arguments, or any other
+// state that could be observed by a caller.
+//
+class ReadNoneAttribute : public Attribute
+{
+ SLANG_CLASS(ReadNoneAttribute)
+};
+
+
+
+// HLSL modifiers for geometry shader input topology
+class HLSLGeometryShaderInputPrimitiveTypeModifier : public Modifier
+{
+ SLANG_CLASS(HLSLGeometryShaderInputPrimitiveTypeModifier)
+};
+
+class HLSLPointModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier
+{
+ SLANG_CLASS(HLSLPointModifier)
+};
+
+class HLSLLineModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier
+{
+ SLANG_CLASS(HLSLLineModifier)
+};
+
+class HLSLTriangleModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier
+{
+ SLANG_CLASS(HLSLTriangleModifier)
+};
+
+class HLSLLineAdjModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier
+{
+ SLANG_CLASS(HLSLLineAdjModifier)
+};
+
+class HLSLTriangleAdjModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier
+{
+ SLANG_CLASS(HLSLTriangleAdjModifier)
+};
+
+
+// A modifier to be attached to syntax after we've computed layout
+class ComputedLayoutModifier : public Modifier
+{
+ SLANG_CLASS(ComputedLayoutModifier)
+
+ RefPtr<Layout> layout;
+};
+
+
+class TupleVarModifier : public Modifier
+{
+ SLANG_CLASS(TupleVarModifier)
+
+// TupleFieldModifier* tupleField = nullptr;
+};
+
+// A modifier to indicate that a constructor/initializer can be used
+// to perform implicit type conversion, and to specify the cost of
+// the conversion, if applied.
+class ImplicitConversionModifier : public Modifier
+{
+ SLANG_CLASS(ImplicitConversionModifier)
+
+ // The conversion cost, used to rank conversions
+ ConversionCost cost;
+};
+
+class FormatAttribute : public Attribute
+{
+ SLANG_CLASS(FormatAttribute)
+
+ ImageFormat format;
+};
+
+class AllowAttribute : public Attribute
+{
+ SLANG_CLASS(AllowAttribute)
+
+ DiagnosticInfo const* diagnostic = nullptr;
+};
+
+
+// A `[__extern]` attribute, which indicates that a function/type is defined externally
+//
+class ExternAttribute : public Attribute
+{
+ SLANG_CLASS(ExternAttribute)
+};
+
+
+// An `[__unsafeForceInlineExternal]` attribute indicates that the callee should be inlined
+// into call sites after initial IR generation (that is, as early as possible).
+//
+class UnsafeForceInlineEarlyAttribute : public Attribute
+{
+ SLANG_CLASS(UnsafeForceInlineEarlyAttribute)
+};
+
+
+#undef SLANG_ABSTRACT_CLASS
+#undef SLANG_CLASS
+
+} // namespace Slang
diff --git a/source/slang/slang-ast-reflect.cpp b/source/slang/slang-ast-reflect.cpp
new file mode 100644
index 000000000..471daf92b
--- /dev/null
+++ b/source/slang/slang-ast-reflect.cpp
@@ -0,0 +1,70 @@
+#include "../../slang.h"
+
+#include "slang-ast-reflect.h"
+
+#include "../core/slang-smart-pointer.h"
+
+#include "slang-ast-all.h"
+
+#include <typeinfo>
+#include <assert.h>
+
+#include "slang-ast-generated-macro.h"
+
+namespace Slang
+{
+
+#define SLANG_REFLECT_GET_REFLECT_CLASS_INFO(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) infos.infos[int(ASTNodeType::NAME)] = &NAME::kReflectClassInfo;
+
+static ReflectClassInfo::Infos _calcInfos()
+{
+ ReflectClassInfo::Infos infos;
+ memset(&infos, 0, sizeof(infos));
+ SLANG_ALL_ASTNode_NodeBase(SLANG_REFLECT_GET_REFLECT_CLASS_INFO, _)
+ SLANG_ALL_ASTNode_Substitutions(SLANG_REFLECT_GET_REFLECT_CLASS_INFO, _)
+ return infos;
+}
+
+/* static */const ReflectClassInfo::Infos ReflectClassInfo::kInfos = _calcInfos();
+
+bool ReflectClassInfo::isSubClassOfSlow(const ThisType& super) const
+{
+ ReflectClassInfo const* info = this;
+ while (info)
+ {
+ if (info == &super)
+ return true;
+ info = info->m_superClass;
+ }
+ return false;
+}
+
+// Now try and implement all of the classes
+// Macro generated is of the format
+
+
+template <typename T>
+struct CreateImpl
+{
+ static void* create() { return new T; }
+};
+
+#define SLANG_GET_SUPER_BASE(SUPER) nullptr
+#define SLANG_GET_SUPER_INNER(SUPER) &SUPER::kReflectClassInfo
+#define SLANG_GET_SUPER_LEAF(SUPER) &SUPER::kReflectClassInfo
+
+#define SLANG_GET_CREATE_FUNC_ABSTRACT(NAME) nullptr
+#define SLANG_GET_CREATE_FUNC_NONE(NAME) &CreateImpl<NAME>::create
+
+#define SLANG_GET_CREATE_FUNC_NON_VISITOR_ABSTRACT(NAME) nullptr
+#define SLANG_GET_CREATE_FUNC_NON_VISITOR(NAME) &CreateImpl<NAME>::create
+
+
+#define SLANG_REFLECT_CLASS_INFO(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \
+ /* static */const ReflectClassInfo NAME::kReflectClassInfo = { uint32_t(ASTNodeType::NAME), uint32_t(ASTNodeType::LAST), SLANG_GET_SUPER_##TYPE(SUPER), #NAME, SLANG_GET_CREATE_FUNC_##MARKER(NAME) };
+
+SLANG_ALL_ASTNode_NodeBase(SLANG_REFLECT_CLASS_INFO, _)
+SLANG_ALL_ASTNode_Substitutions(SLANG_REFLECT_CLASS_INFO, _)
+
+
+} // namespace Slang
diff --git a/source/slang/slang-ast-reflect.h b/source/slang/slang-ast-reflect.h
new file mode 100644
index 000000000..953c1eaf1
--- /dev/null
+++ b/source/slang/slang-ast-reflect.h
@@ -0,0 +1,37 @@
+// slang-ast-reflect.h
+
+#ifndef SLANG_AST_REFLECT_H
+#define SLANG_AST_REFLECT_H
+
+#include "slang-ast-generated.h"
+
+#define SLANG_AST_OVERRIDE_BASE
+#define SLANG_AST_OVERRIDE_INNER override
+#define SLANG_AST_OVERRIDE_LEAF override
+
+// Implement the part that uses the class definition
+#define SLANG_CLASS_REFLECT_DEFAULT_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \
+ typedef SUPER Super; \
+ SLANG_FORCE_INLINE static bool isDerivedFrom(ASTNodeType type) { return int(type) >= int(kType) && int(type) <= int(ASTNodeType::LAST); } \
+ virtual const ReflectClassInfo& getClassInfo() const SLANG_AST_OVERRIDE_##TYPE { return kReflectClassInfo; } \
+
+
+#define SLANG_CLASS_REFLECT_DEFAULT(NAME) \
+ public: \
+ static const ASTNodeType kType = ASTNodeType::NAME; \
+ static const ReflectClassInfo kReflectClassInfo; \
+ SLANG_ASTNode_##NAME(SLANG_CLASS_REFLECT_DEFAULT_IMPL, _)
+
+#define SLANG_CLASS_REFLECT_WITH_ACCEPT(NAME) \
+ SLANG_CLASS_REFLECT_DEFAULT(NAME) \
+ virtual void accept(NAME::Visitor* visitor, void* extra) override;
+
+#define SLANG_ABSTRACT_CLASS_REFLECT(NAME) SLANG_CLASS_REFLECT_DEFAULT(NAME)
+#define SLANG_CLASS_REFLECT(NAME) SLANG_CLASS_REFLECT_DEFAULT(NAME)
+
+// Used for C++ extractor, does nothing here
+#define SLANG_REFLECT_BASE_CLASS(x) /* ... */
+
+
+
+#endif // SLANG_AST_REFLECT_H
diff --git a/source/slang/slang-ast-stmt.h b/source/slang/slang-ast-stmt.h
new file mode 100644
index 000000000..28b8162a2
--- /dev/null
+++ b/source/slang/slang-ast-stmt.h
@@ -0,0 +1,213 @@
+// slang-ast-stmt.h
+
+#pragma once
+
+#include "slang-ast-base.h"
+
+namespace Slang {
+
+#define SLANG_ABSTRACT_CLASS(x) SLANG_ABSTRACT_CLASS_REFLECT(x)
+#define SLANG_CLASS(x) SLANG_CLASS_REFLECT_WITH_ACCEPT(x)
+
+// Syntax class definitions for statements.
+
+class ScopeStmt : public Stmt
+{
+ SLANG_ABSTRACT_CLASS(ScopeStmt)
+
+ RefPtr<ScopeDecl> scopeDecl;
+};
+
+// A sequence of statements, treated as a single statement
+class SeqStmt : public Stmt
+{
+ SLANG_CLASS(SeqStmt)
+
+ List<RefPtr<Stmt>> stmts;
+};
+
+// The simplest kind of scope statement: just a `{...}` block
+class BlockStmt : public ScopeStmt
+{
+ SLANG_CLASS(BlockStmt)
+
+ RefPtr<Stmt> body;;
+};
+
+// A statement that we aren't going to parse or check, because
+// we want to let a downstream compiler handle any issues
+class UnparsedStmt : public Stmt
+{
+ SLANG_CLASS(UnparsedStmt)
+
+ // The tokens that were contained between `{` and `}`
+ List<Token> tokens;
+};
+
+class EmptyStmt : public Stmt
+{
+ SLANG_CLASS(EmptyStmt)
+};
+
+class DiscardStmt : public Stmt
+{
+ SLANG_CLASS(DiscardStmt)
+};
+
+class DeclStmt : public Stmt
+{
+ SLANG_CLASS(DeclStmt)
+
+ RefPtr<DeclBase> decl;
+};
+
+class IfStmt : public Stmt
+{
+ SLANG_CLASS(IfStmt)
+
+ RefPtr<Expr> Predicate;
+ RefPtr<Stmt> PositiveStatement;
+ RefPtr<Stmt> NegativeStatement;
+};
+
+// A statement that can be escaped with a `break`
+class BreakableStmt : public ScopeStmt
+{
+ SLANG_ABSTRACT_CLASS(BreakableStmt)
+
+};
+
+class SwitchStmt : public BreakableStmt
+{
+ SLANG_CLASS(SwitchStmt)
+
+ RefPtr<Expr> condition;
+ RefPtr<Stmt> body;
+};
+
+// A statement that is expected to appear lexically nested inside
+// some other construct, and thus needs to keep track of the
+// outer statement that it is associated with...
+class ChildStmt : public Stmt
+{
+ SLANG_ABSTRACT_CLASS(ChildStmt)
+
+ Stmt* parentStmt = nullptr;
+};
+
+// a `case` or `default` statement inside a `switch`
+//
+// Note(tfoley): A correct AST for a C-like language would treat
+// these as a labelled statement, and so they would contain a
+// sub-statement. I'm leaving that out for now for simplicity.
+class CaseStmtBase : public ChildStmt
+{
+ SLANG_ABSTRACT_CLASS(CaseStmtBase)
+
+};
+
+// a `case` statement inside a `switch`
+class CaseStmt : public CaseStmtBase
+{
+ SLANG_CLASS(CaseStmt)
+
+ RefPtr<Expr> expr;
+};
+
+// a `default` statement inside a `switch`
+class DefaultStmt : public CaseStmtBase
+{
+ SLANG_CLASS(DefaultStmt)
+};
+
+// A statement that represents a loop, and can thus be escaped with a `continue`
+class LoopStmt : public BreakableStmt
+{
+ SLANG_ABSTRACT_CLASS(LoopStmt)
+
+};
+
+// A `for` statement
+class ForStmt : public LoopStmt
+{
+ SLANG_CLASS(ForStmt)
+
+ RefPtr<Stmt> InitialStatement;
+ RefPtr<Expr> SideEffectExpression;
+ RefPtr<Expr> PredicateExpression;
+ RefPtr<Stmt> Statement;
+};
+
+// A `for` statement in a language that doesn't restrict the scope
+// of the loop variable to the body.
+class UnscopedForStmt : public ForStmt
+{
+ SLANG_CLASS(UnscopedForStmt)
+;
+};
+
+class WhileStmt : public LoopStmt
+{
+ SLANG_CLASS(WhileStmt)
+
+ RefPtr<Expr> Predicate;
+ RefPtr<Stmt> Statement;
+};
+
+class DoWhileStmt : public LoopStmt
+{
+ SLANG_CLASS(DoWhileStmt)
+
+ RefPtr<Stmt> Statement;
+ RefPtr<Expr> Predicate;
+};
+
+// A compile-time, range-based `for` loop, which will not appear in the output code
+class CompileTimeForStmt : public ScopeStmt
+{
+ SLANG_CLASS(CompileTimeForStmt)
+
+ RefPtr<VarDecl> varDecl;
+ RefPtr<Expr> rangeBeginExpr;
+ RefPtr<Expr> rangeEndExpr;
+ RefPtr<Stmt> body;
+ RefPtr<IntVal> rangeBeginVal;
+ RefPtr<IntVal> rangeEndVal;
+};
+
+// The case of child statements that do control flow relative
+// to their parent statement.
+class JumpStmt : public ChildStmt
+{
+ SLANG_ABSTRACT_CLASS(JumpStmt)
+
+};
+
+class BreakStmt : public JumpStmt
+{
+ SLANG_CLASS(BreakStmt)
+};
+
+class ContinueStmt : public JumpStmt
+{
+ SLANG_CLASS(ContinueStmt)
+};
+
+class ReturnStmt : public Stmt
+{
+ SLANG_CLASS(ReturnStmt)
+
+ RefPtr<Expr> Expression;
+};
+
+class ExpressionStmt : public Stmt
+{
+ SLANG_CLASS(ExpressionStmt)
+
+ RefPtr<Expr> Expression;
+};
+
+#undef SLANG_ABSTRACT_CLASS
+#undef SLANG_CLASS
+
+} // namespace Slang
diff --git a/source/slang/slang-ast-support-types.h b/source/slang/slang-ast-support-types.h
new file mode 100644
index 000000000..c1072c923
--- /dev/null
+++ b/source/slang/slang-ast-support-types.h
@@ -0,0 +1,1330 @@
+#ifndef SLANG_AST_SUPPORT_TYPES_H
+#define SLANG_AST_SUPPORT_TYPES_H
+
+#include "../core/slang-basic.h"
+#include "slang-lexer.h"
+#include "slang-profile.h"
+#include "slang-type-system-shared.h"
+#include "../../slang.h"
+
+#include "../core/slang-semantic-version.h"
+
+#include "slang-ast-generated.h"
+
+#include "slang-ast-reflect.h"
+
+
+
+#include "slang-name.h"
+
+#include <assert.h>
+
+namespace Slang
+{
+ class Module;
+ class Name;
+ class Session;
+ class Substitutions;
+ class SyntaxVisitor;
+ class FuncDecl;
+ class Layout;
+
+ struct IExprVisitor;
+ struct IDeclVisitor;
+ struct IModifierVisitor;
+ struct IStmtVisitor;
+ struct ITypeVisitor;
+ struct IValVisitor;
+
+ class Parser;
+ class SyntaxNode;
+
+ class Decl;
+ struct QualType;
+ class Type;
+ struct TypeExp;
+ class Val;
+
+ void printDiagnosticArg(StringBuilder& sb, Decl* decl);
+ void printDiagnosticArg(StringBuilder& sb, Type* type);
+ void printDiagnosticArg(StringBuilder& sb, TypeExp const& type);
+ void printDiagnosticArg(StringBuilder& sb, QualType const& type);
+ void printDiagnosticArg(StringBuilder& sb, Val* val);
+
+ class SyntaxNode;
+ SourceLoc const& getDiagnosticPos(SyntaxNode const* syntax);
+ SourceLoc const& getDiagnosticPos(TypeExp const& typeExp);
+
+ typedef RefPtr<RefObject> (*SyntaxParseCallback)(Parser* parser, void* userData);
+
+ typedef unsigned int ConversionCost;
+ enum : ConversionCost
+ {
+ // No conversion at all
+ kConversionCost_None = 0,
+
+ // Conversion from a buffer to the type it carries needs to add a minimal
+ // extra cost, just so we can distinguish an overload on `ConstantBuffer<Foo>`
+ // from one on `Foo`
+ kConversionCost_ImplicitDereference = 10,
+
+ // Conversions based on explicit sub-typing relationships are the cheapest
+ //
+ // TODO(tfoley): We will eventually need a discipline for ranking
+ // when two up-casts are comparable.
+ kConversionCost_CastToInterface = 50,
+
+ // Conversion that is lossless and keeps the "kind" of the value the same
+ kConversionCost_RankPromotion = 150,
+
+ // Conversions that are lossless, but change "kind"
+ kConversionCost_UnsignedToSignedPromotion = 200,
+
+ // Conversion from signed->unsigned integer of same or greater size
+ kConversionCost_SignedToUnsignedConversion = 300,
+
+ // Cost of converting an integer to a floating-point type
+ kConversionCost_IntegerToFloatConversion = 400,
+
+ // Default case (usable for user-defined conversions)
+ kConversionCost_Default = 500,
+
+ // Catch-all for conversions that should be discouraged
+ // (i.e., that really shouldn't be made implicitly)
+ //
+ // TODO: make these conversions not be allowed implicitly in "Slang mode"
+ kConversionCost_GeneralConversion = 900,
+
+ // This is the cost of an explicit conversion, which should
+ // not actually be performed.
+ kConversionCost_Explicit = 90000,
+
+ // Additional conversion cost to add when promoting from a scalar to
+ // a vector (this will be added to the cost, if any, of converting
+ // the element type of the vector)
+ kConversionCost_ScalarToVector = 1,
+
+ // Conversion is impossible
+ kConversionCost_Impossible = 0xFFFFFFFF,
+ };
+
+ enum class ImageFormat
+ {
+#define FORMAT(NAME) NAME,
+#include "slang-image-format-defs.h"
+ };
+
+ bool findImageFormatByName(char const* name, ImageFormat* outFormat);
+ char const* getGLSLNameForImageFormat(ImageFormat format);
+
+ // TODO(tfoley): We should ditch this enumeration
+ // and just use the IR opcodes that represent these
+ // types directly. The one major complication there
+ // is that the order of the enum values currently
+ // matters, since it determines promotion rank.
+ // We either need to keep that restriction, or
+ // look up promotion rank by some other means.
+ //
+
+ class Decl;
+ class Val;
+
+#if 0
+ // Forward-declare all syntax classes
+#define SYNTAX_CLASS(NAME, BASE, ...) class NAME;
+#include "slang-object-meta-begin.h"
+#include "slang-syntax-defs.h"
+#include "slang-object-meta-end.h"
+#endif
+
+ // Helper type for pairing up a name and the location where it appeared
+ struct NameLoc
+ {
+ Name* name;
+ SourceLoc loc;
+
+ NameLoc()
+ : name(nullptr)
+ {}
+
+ explicit NameLoc(Name* inName)
+ : name(inName)
+ {}
+
+
+ NameLoc(Name* inName, SourceLoc inLoc)
+ : name(inName)
+ , loc(inLoc)
+ {}
+
+ NameLoc(Token const& token)
+ : name(token.getNameOrNull())
+ , loc(token.getLoc())
+ {}
+ };
+
+ struct StringSliceLoc
+ {
+ UnownedStringSlice name;
+ SourceLoc loc;
+
+ StringSliceLoc()
+ : name(nullptr)
+ {}
+ explicit StringSliceLoc(const UnownedStringSlice& inName)
+ : name(inName)
+ {}
+ StringSliceLoc(const UnownedStringSlice& inName, SourceLoc inLoc)
+ : name(inName)
+ , loc(inLoc)
+ {}
+ StringSliceLoc(Token const& token)
+ : loc(token.getLoc())
+ {
+ Name* tokenName = token.getNameOrNull();
+ if (tokenName)
+ {
+ name = tokenName->text.getUnownedSlice();
+ }
+ }
+ };
+
+ // Helper class for iterating over a list of heap-allocated modifiers
+ struct ModifierList
+ {
+ struct Iterator
+ {
+ Modifier* current;
+
+ Modifier* operator*()
+ {
+ return current;
+ }
+
+ void operator++();
+#if 0
+ {
+ current = current->next.Ptr();
+ }
+#endif
+
+ bool operator!=(Iterator other)
+ {
+ return current != other.current;
+ };
+
+ Iterator()
+ : current(nullptr)
+ {}
+
+ Iterator(Modifier* modifier)
+ : current(modifier)
+ {}
+ };
+
+ ModifierList()
+ : modifiers(nullptr)
+ {}
+
+ ModifierList(Modifier* modifiers)
+ : modifiers(modifiers)
+ {}
+
+ Iterator begin() { return Iterator(modifiers); }
+ Iterator end() { return Iterator(nullptr); }
+
+ Modifier* modifiers;
+ };
+
+ // Helper class for iterating over heap-allocated modifiers
+ // of a specific type.
+ template<typename T>
+ struct FilteredModifierList
+ {
+ struct Iterator
+ {
+ Modifier* current;
+
+ T* operator*()
+ {
+ return (T*)current;
+ }
+
+ void operator++();
+ #if 0
+ {
+ current = Adjust(current->next.Ptr());
+ }
+ #endif
+
+ bool operator!=(Iterator other)
+ {
+ return current != other.current;
+ };
+
+ Iterator()
+ : current(nullptr)
+ {}
+
+ Iterator(Modifier* modifier)
+ : current(modifier)
+ {}
+ };
+
+ FilteredModifierList()
+ : modifiers(nullptr)
+ {}
+
+ FilteredModifierList(Modifier* modifiers)
+ : modifiers(Adjust(modifiers))
+ {}
+
+ Iterator begin() { return Iterator(modifiers); }
+ Iterator end() { return Iterator(nullptr); }
+
+ static Modifier* Adjust(Modifier* modifier);
+ #if 0
+ {
+ Modifier* m = modifier;
+ for (;;)
+ {
+ if (!m) return m;
+ if (dynamicCast<T>(m)) return m;
+ m = m->next.Ptr();
+ }
+ }
+ #endif
+
+ Modifier* modifiers;
+ };
+
+ // A set of modifiers attached to a syntax node
+ struct Modifiers
+ {
+ // The first modifier in the linked list of heap-allocated modifiers
+ RefPtr<Modifier> first;
+
+ template<typename T>
+ FilteredModifierList<T> getModifiersOfType() { return FilteredModifierList<T>(first.Ptr()); }
+
+ // Find the first modifier of a given type, or return `nullptr` if none is found.
+ template<typename T>
+ T* findModifier()
+ {
+ return *getModifiersOfType<T>().begin();
+ }
+
+ template<typename T>
+ bool hasModifier() { return findModifier<T>() != nullptr; }
+
+ FilteredModifierList<Modifier>::Iterator begin() { return FilteredModifierList<Modifier>::Iterator(first.Ptr()); }
+ FilteredModifierList<Modifier>::Iterator end() { return FilteredModifierList<Modifier>::Iterator(nullptr); }
+ };
+
+ class NamedExpressionType;
+ class GenericDecl;
+ class ContainerDecl;
+
+ // Try to extract a simple integer value from an `IntVal`.
+ // This fill assert-fail if the object doesn't represent a literal value.
+ IntegerLiteralValue GetIntVal(RefPtr<IntVal> val);
+
+ /// Represents how much checking has been applied to a declaration.
+ enum class DeclCheckState : uint8_t
+ {
+ /// The declaration has been parsed, but
+ /// is otherwise completely unchecked.
+ ///
+ Unchecked,
+
+ /// Basic checks on the modifiers of the declaration have been applied.
+ ///
+ /// For example, when a declaration has attributes, the transformation
+ /// of an attribute from the parsed-but-unchecked form into a checked
+ /// form (in which it has the appropriate C++ subclass) happens here.
+ ///
+ ModifiersChecked,
+
+ /// The type/signature of the declaration has been checked.
+ ///
+ /// For a value declaration like a variable or function, this means that
+ /// the type of the declaration can be queried.
+ ///
+ /// For a type declaration like a `struct` or `typedef` this means
+ /// that a `Type` referring to that declaration can be formed.
+ ///
+ SignatureChecked,
+
+ /// The declaration's basic signature has been checked to the point that
+ /// it is ready to be referenced in other places.
+ ///
+ /// For a function, this means that it has been organized into a
+ /// "redeclration group" if there are multiple functions with the
+ /// same name in a scope.
+ ///
+ ReadyForReference,
+
+ /// The declaration is ready for lookup operations to be performed.
+ ///
+ /// For type declarations (e.g., aggregate types, generic type parameters)
+ /// this means that any base type or constraint clauses have been
+ /// sufficiently checked so that we can enumerate the inheritance
+ /// hierarchy of the type and discover all its members.
+ ///
+ ReadyForLookup,
+
+ /// Any conformance declared on the declaration have been validated.
+ ///
+ /// In particular, this step means that a "witness table" has been
+ /// created to show how a type satisfies the requirements of any
+ /// interfaces it conforms to.
+ ///
+ ReadyForConformances,
+
+ /// The declaration is fully checked.
+ ///
+ /// This step includes any validation of the declaration that is
+ /// immaterial to clients code using the declaration, but that is
+ /// nonetheless relevant to checking correctness.
+ ///
+ /// The canonical example here is checking the body of functions.
+ /// Client code cannot depend on *how* a function is implemented,
+ /// but we still need to (eventually) check the bodies of all
+ /// functions, so it belongs in the last phase of checking.
+ ///
+ Checked,
+
+ // For convenience at sites that call `ensureDecl()`, we define
+ // some aliases for the above states that are expressed in terms
+ // of what client code needs to be able to do with a declaration.
+ //
+ // These aliases can be changed over time if we decide to add
+ // more phases to semantic checking.
+
+ CanEnumerateBases = ReadyForLookup,
+ CanUseBaseOfInheritanceDecl = ReadyForLookup,
+ CanUseTypeOfValueDecl = ReadyForReference,
+ CanUseExtensionTargetType = ReadyForLookup,
+ CanUseAsType = ReadyForReference,
+ CanUseFuncSignature = ReadyForReference,
+ CanSpecializeGeneric = ReadyForReference,
+ CanReadInterfaceRequirements = ReadyForLookup,
+ };
+
+ /// A `DeclCheckState` plus a bit to track whether a declaration is currently being checked.
+ struct DeclCheckStateExt
+ {
+ public:
+ DeclCheckStateExt() {}
+ DeclCheckStateExt(DeclCheckState state)
+ : m_raw(uint8_t(state))
+ {}
+
+ enum : uint8_t
+ {
+ /// A flag to indicate that a declaration is being checked.
+ ///
+ /// The value of this flag is chosen so that it can be
+ /// represented in the bits of a `DeclCheckState` without
+ /// colliding with the bits that represent actual states.
+ ///
+ kBeingCheckedBit = 0x80,
+ };
+
+ DeclCheckState getState() const { return DeclCheckState(m_raw & ~kBeingCheckedBit); }
+ void setState(DeclCheckState state)
+ {
+ m_raw = (m_raw & kBeingCheckedBit) | uint8_t(state);
+ }
+
+ bool isBeingChecked() const { return (m_raw & kBeingCheckedBit) != 0; }
+
+ void setIsBeingChecked(bool isBeingChecked)
+ {
+ m_raw = (m_raw & ~kBeingCheckedBit)
+ | (isBeingChecked ? kBeingCheckedBit : 0);
+ }
+
+ bool operator>=(DeclCheckState state) const
+ {
+ return getState() >= state;
+ }
+
+ private:
+ uint8_t m_raw = 0;
+ };
+
+ void addModifier(
+ RefPtr<ModifiableSyntaxNode> syntax,
+ RefPtr<Modifier> modifier);
+
+ struct QualType
+ {
+ RefPtr<Type> type;
+ bool IsLeftValue;
+
+ QualType()
+ : IsLeftValue(false)
+ {}
+
+ QualType(Type* type)
+ : type(type)
+ , IsLeftValue(false)
+ {}
+
+ Type* Ptr() { return type.Ptr(); }
+
+ operator Type*() { return type; }
+ operator RefPtr<Type>() { return type; }
+ RefPtr<Type> operator->() { return type; }
+ };
+
+ struct ReflectClassInfo
+ {
+ typedef ReflectClassInfo ThisType;
+
+ typedef void* (*CreateFunc)();
+
+ /// A constant time implementation of isSubClassOf
+ SLANG_FORCE_INLINE bool isSubClassOf(const ThisType& super) const
+ {
+ // We include super.m_classId, because it's a subclass of itself.
+ return m_classId >= super.m_classId && m_classId <= super.m_lastClassId;
+ }
+ /// Will produce the same result as isSubClassOf, but more slowly by traversing the m_superClass
+ /// Works without initRange being called.
+ bool isSubClassOfSlow(const ThisType& super) const;
+
+ uint32_t m_classId;
+ uint32_t m_lastClassId;
+
+ const ReflectClassInfo* m_superClass; ///< The super class of this class, or nullptr if has no super class.
+ const char* m_name; ///< Textual class name, for debugging
+ CreateFunc m_createFunc; ///< Callback to use when creating instances
+
+ struct Infos
+ {
+ const ReflectClassInfo* infos[int(ASTNodeType::CountOf)];
+ };
+
+ SLANG_FORCE_INLINE static const ReflectClassInfo* getInfo(ASTNodeType type) { return kInfos.infos[int(type)]; }
+
+ static const Infos kInfos;
+ };
+
+ // A reference to a class of syntax node, that can be
+ // used to create instances on the fly
+ struct SyntaxClassBase
+ {
+ typedef void* (*CreateFunc)();
+
+ SyntaxClassBase()
+ {}
+
+ SyntaxClassBase(ReflectClassInfo const* inClassInfo)
+ : classInfo(inClassInfo)
+ {}
+
+ void* createInstanceImpl() const
+ {
+ auto ci = classInfo;
+ if (!ci) return nullptr;
+
+ auto cf = ci->m_createFunc;
+ if (!cf) return nullptr;
+
+ return cf();
+ }
+
+ SLANG_FORCE_INLINE bool isSubClassOfImpl(SyntaxClassBase const& super) const { return classInfo->isSubClassOf(*super.classInfo); }
+
+ ReflectClassInfo const* classInfo = nullptr;
+ };
+
+ template<typename T>
+ struct SyntaxClass : SyntaxClassBase
+ {
+ SyntaxClass()
+ {}
+
+ template <typename U>
+ SyntaxClass(SyntaxClass<U> const& other,
+ typename EnableIf<IsConvertible<T*, U*>::Value, void>::type* = 0)
+ : SyntaxClassBase(other.classInfo)
+ {
+ }
+
+ T* createInstance() const
+ {
+ return (T*)createInstanceImpl();
+ }
+
+ SyntaxClass(const ReflectClassInfo* inClassInfo):
+ SyntaxClassBase(inClassInfo)
+ {}
+
+ static SyntaxClass<T> getClass()
+ {
+ return SyntaxClass<T>(&T::kReflectClassInfo);
+ }
+
+ template<typename U>
+ bool isSubClassOf(SyntaxClass<U> super)
+ {
+ return isSubClassOfImpl(super);
+ }
+
+ template<typename U>
+ bool isSubClassOf()
+ {
+ return isSubClassOf(SyntaxClass<U>::getClass());
+ }
+ };
+
+ template<typename T>
+ SyntaxClass<T> getClass()
+ {
+ return SyntaxClass<T>::getClass();
+ }
+
+ struct SubstitutionSet
+ {
+ RefPtr<Substitutions> substitutions;
+ operator Substitutions*() const
+ {
+ return substitutions;
+ }
+
+ SubstitutionSet() {}
+ SubstitutionSet(RefPtr<Substitutions> subst)
+ : substitutions(subst)
+ {
+ }
+ bool Equals(const SubstitutionSet& substSet) const;
+ int GetHashCode() const;
+ };
+
+ template<typename T>
+ struct DeclRef;
+
+ // A reference to a declaration, which may include
+ // substitutions for generic parameters.
+ struct DeclRefBase
+ {
+ typedef Decl DeclType;
+
+ // The underlying declaration
+ Decl* decl = nullptr;
+ Decl* getDecl() const { return decl; }
+
+ // Optionally, a chain of substitutions to perform
+ SubstitutionSet substitutions;
+
+ DeclRefBase()
+ {}
+
+ DeclRefBase(Decl* decl)
+ :decl(decl)
+ {}
+
+ DeclRefBase(Decl* decl, SubstitutionSet subst)
+ :decl(decl),
+ substitutions(subst)
+ {}
+
+ DeclRefBase(Decl* decl, RefPtr<Substitutions> subst)
+ : decl(decl)
+ , substitutions(subst)
+ {}
+
+ // Apply substitutions to a type or declaration
+ RefPtr<Type> Substitute(RefPtr<Type> type) const;
+
+ DeclRefBase Substitute(DeclRefBase declRef) const;
+
+ // Apply substitutions to an expression
+ RefPtr<Expr> Substitute(RefPtr<Expr> expr) const;
+
+ // Apply substitutions to this declaration reference
+ DeclRefBase SubstituteImpl(SubstitutionSet subst, int* ioDiff);
+
+ // Returns true if 'as' will return a valid cast
+ template <typename T>
+ bool is() const { return Slang::as<T>(decl) != nullptr; }
+
+ // "dynamic cast" to a more specific declaration reference type
+ template<typename T>
+ DeclRef<T> as() const;
+
+ // Check if this is an equivalent declaration reference to another
+ bool Equals(DeclRefBase const& declRef) const;
+ bool operator == (const DeclRefBase& other) const
+ {
+ return Equals(other);
+ }
+
+ // Convenience accessors for common properties of declarations
+ Name* GetName() const;
+ SourceLoc getLoc() const;
+ DeclRefBase GetParent() const;
+
+ int GetHashCode() const;
+
+ // Debugging:
+ String toString() const;
+ };
+
+ template<typename T>
+ struct DeclRef : DeclRefBase
+ {
+ typedef T DeclType;
+
+ DeclRef()
+ {}
+
+ DeclRef(T* decl, SubstitutionSet subst)
+ : DeclRefBase(decl, subst)
+ {}
+
+ DeclRef(T* decl, RefPtr<Substitutions> subst)
+ : DeclRefBase(decl, SubstitutionSet(subst))
+ {}
+
+ template <typename U>
+ DeclRef(DeclRef<U> const& other,
+ typename EnableIf<IsConvertible<T*, U*>::Value, void>::type* = 0)
+ : DeclRefBase(other.decl, other.substitutions)
+ {
+ }
+
+ T* getDecl() const
+ {
+ return (T*)decl;
+ }
+
+ operator T*() const
+ {
+ return getDecl();
+ }
+
+ //
+ static DeclRef<T> unsafeInit(DeclRefBase const& declRef)
+ {
+ return DeclRef<T>((T*) declRef.decl, declRef.substitutions);
+ }
+
+ RefPtr<Type> Substitute(RefPtr<Type> type) const
+ {
+ return DeclRefBase::Substitute(type);
+ }
+ RefPtr<Expr> Substitute(RefPtr<Expr> expr) const
+ {
+ return DeclRefBase::Substitute(expr);
+ }
+
+ // Apply substitutions to a type or declaration
+ template<typename U>
+ DeclRef<U> Substitute(DeclRef<U> declRef) const
+ {
+ return DeclRef<U>::unsafeInit(DeclRefBase::Substitute(declRef));
+ }
+
+ // Apply substitutions to this declaration reference
+ DeclRef<T> SubstituteImpl(SubstitutionSet subst, int* ioDiff)
+ {
+ return DeclRef<T>::unsafeInit(DeclRefBase::SubstituteImpl(subst, ioDiff));
+ }
+
+ DeclRef<ContainerDecl> GetParent() const
+ {
+ return DeclRef<ContainerDecl>::unsafeInit(DeclRefBase::GetParent());
+ }
+ };
+
+ template<typename T>
+ DeclRef<T> DeclRefBase::as() const
+ {
+ DeclRef<T> result;
+ result.decl = Slang::as<T>(decl);
+ result.substitutions = substitutions;
+ return result;
+ }
+
+ template<typename T>
+ inline DeclRef<T> makeDeclRef(T* decl)
+ {
+ return DeclRef<T>(decl, nullptr);
+ }
+
+ enum class MemberFilterStyle
+ {
+ All, ///< All members
+ Instance, ///< Only instance members
+ Static, ///< Only static (ie non instance) members
+ };
+
+ const RefPtr<Decl>* adjustFilterCursorImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end);
+ const RefPtr<Decl>* getFilterCursorByIndexImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end, Index index);
+ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end);
+
+
+ template <typename T>
+ const RefPtr<Decl>* adjustFilterCursor(MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end)
+ {
+ return adjustFilterCursorImpl(T::kReflectClassInfo, filterStyle, ptr, end);
+ }
+
+ /// Finds the element at index. If there is no element at the index (for example has too few elements), returns nullptr.
+ template <typename T>
+ const RefPtr<Decl>* getFilterCursorByIndex(MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end, Index index)
+ {
+ return getFilterCursorByIndexImpl(T::kReflectClassInfo, filterStyle, ptr, end, index);
+ }
+
+ template <typename T>
+ Index getFilterCount(MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end)
+ {
+ return getFilterCountImpl(T::kReflectClassInfo, filterStyle, ptr, end);
+ }
+
+ template <typename T>
+ bool isFilterNonEmpty(MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end)
+ {
+ return adjustFilterCursorImpl(T::kReflectClassInfo, filterStyle, ptr, end) != end;
+ }
+
+ template<typename T>
+ struct FilteredMemberList
+ {
+ typedef RefPtr<Decl> Element;
+
+ FilteredMemberList()
+ : m_begin(nullptr)
+ , m_end(nullptr)
+ {}
+
+ explicit FilteredMemberList(
+ List<Element> const& list,
+ MemberFilterStyle filterStyle = MemberFilterStyle::All)
+ : m_begin(adjustFilterCursor<T>(filterStyle, list.begin(), list.end()))
+ , m_end(list.end())
+ , m_filterStyle(filterStyle)
+ {}
+
+ struct Iterator
+ {
+ const Element* m_cursor;
+ const Element* m_end;
+ MemberFilterStyle m_filterStyle;
+
+ bool operator!=(Iterator const& other) const { return m_cursor != other.m_cursor; }
+
+ void operator++() { m_cursor = adjustFilterCursor<T>(m_filterStyle, m_cursor + 1, m_end); }
+
+ const RefPtr<T>& operator*() { return *(RefPtr<T>*)(m_cursor); }
+ };
+
+ Iterator begin()
+ {
+ Iterator iter = { m_begin, m_end, m_filterStyle };
+ return iter;
+ }
+
+ Iterator end()
+ {
+ Iterator iter = { m_end, m_end, m_filterStyle };
+ return iter;
+ }
+
+ // TODO(tfoley): It is ugly to have these.
+ // We should probably fix the call sites instead.
+ const RefPtr<T>& getFirst() { return *begin(); }
+ Index getCount() { return getFilterCount<T>(m_filterStyle, m_begin, m_end); }
+
+ RefPtr<T> operator[](Index index) const
+ {
+ const RefPtr<Decl>* ptr = getFilterCursorByIndex<T>(m_filterStyle, m_begin, m_end, index);
+ SLANG_ASSERT(ptr);
+ return *(RefPtr<T>*)(ptr);
+ }
+
+ /// Returns true if empty (equivalent to getCount() == 0)
+ bool isEmpty() const
+ {
+ /// Note we don't have to scan, because m_begin has already been adjusted, when the FilteredMemberList is constructed
+ return m_begin == m_end;
+ }
+ /// Returns true if non empty (equivalent to getCount() != 0 but faster)
+ bool isNonEmpty() const { return !isEmpty(); }
+
+ List<RefPtr<T>> toArray()
+ {
+ List<RefPtr<T>> result;
+ for (auto element : (*this))
+ {
+ result.add(element);
+ }
+ return result;
+ }
+
+ const Element* m_begin; ///< Is either equal to m_end, or points to first *valid* filtered member
+ const Element* m_end;
+ MemberFilterStyle m_filterStyle;
+ };
+
+ struct TransparentMemberInfo
+ {
+ // The declaration of the transparent member
+ Decl* decl;
+ };
+
+ template<typename T>
+ struct FilteredMemberRefList
+ {
+ List<RefPtr<Decl>> const& m_decls;
+ SubstitutionSet m_substitutions;
+ MemberFilterStyle m_filterStyle;
+
+ FilteredMemberRefList(
+ List<RefPtr<Decl>> const& decls,
+ SubstitutionSet substitutions,
+ MemberFilterStyle filterStyle = MemberFilterStyle::All)
+ : m_decls(decls)
+ , m_substitutions(substitutions)
+ , m_filterStyle(filterStyle)
+ {}
+
+ Index getCount() const { return getFilterCount<T>(m_filterStyle, m_decls.begin(), m_decls.end()); }
+
+ /// True if empty (equivalent to getCount == 0, but faster)
+ bool isEmpty() const { return !isNonEmpty(); }
+ /// True if non empty (equivalent to getCount() != 0 but faster)
+ bool isNonEmpty() const { return isFilterNonEmpty<T>(m_filterStyle, m_decls.begin(), m_decls.end()); }
+
+ DeclRef<T> operator[](Index index) const
+ {
+ const RefPtr<Decl>* decl = getFilterCursorByIndex<T>(m_filterStyle, m_decls.begin(), m_decls.end(), index);
+ SLANG_ASSERT(decl);
+ return DeclRef<T>((T*) decl->Ptr(), m_substitutions);
+ }
+
+ List<DeclRef<T>> toArray() const
+ {
+ List<DeclRef<T>> result;
+ for (auto d : *this)
+ result.add(d);
+ return result;
+ }
+
+ struct Iterator
+ {
+ FilteredMemberRefList const* m_list;
+ const RefPtr<Decl>* m_ptr;
+ const RefPtr<Decl>* m_end;
+ MemberFilterStyle m_filterStyle;
+
+ Iterator() : m_list(nullptr), m_ptr(nullptr), m_filterStyle(MemberFilterStyle::All) {}
+ Iterator(
+ FilteredMemberRefList const* list,
+ const RefPtr<Decl>* ptr,
+ const RefPtr<Decl>* end,
+ MemberFilterStyle filterStyle
+ )
+ : m_list(list)
+ , m_ptr(ptr)
+ , m_end(end)
+ , m_filterStyle(filterStyle)
+ {}
+
+ bool operator!=(const Iterator& other) const { return m_ptr != other.m_ptr; }
+
+ void operator++() { m_ptr = adjustFilterCursor<T>(m_filterStyle, m_ptr + 1, m_end); }
+
+ DeclRef<T> operator*() { return DeclRef<T>((T*) m_ptr->Ptr(), m_list->m_substitutions); }
+ };
+
+ Iterator begin() const { return Iterator(this, adjustFilterCursor<T>(m_filterStyle, m_decls.begin(), m_decls.end()), m_decls.end(), m_filterStyle); }
+ Iterator end() const { return Iterator(this, m_decls.end(), m_decls.end(), m_filterStyle); }
+ };
+
+ //
+ // type Expressions
+ //
+
+ // A "type expression" is a term that we expect to resolve to a type during checking.
+ // We store both the original syntax and the resolved type here.
+ struct TypeExp
+ {
+ TypeExp() {}
+ TypeExp(TypeExp const& other)
+ : exp(other.exp)
+ , type(other.type)
+ {}
+ explicit TypeExp(RefPtr<Expr> exp)
+ : exp(exp)
+ {}
+ explicit TypeExp(RefPtr<Type> type)
+ : type(type)
+ {}
+ TypeExp(RefPtr<Expr> exp, RefPtr<Type> type)
+ : exp(exp)
+ , type(type)
+ {}
+
+ RefPtr<Expr> exp;
+ RefPtr<Type> type;
+
+ bool Equals(Type* other);
+#if 0
+ {
+ return type->Equals(other);
+ }
+#endif
+ bool Equals(RefPtr<Type> other);
+#if 0
+ {
+ return type->Equals(other.Ptr());
+ }
+#endif
+ Type* Ptr() { return type.Ptr(); }
+ operator Type*()
+ {
+ return type;
+ }
+ Type* operator->() { return Ptr(); }
+
+ TypeExp Accept(SyntaxVisitor* visitor);
+ };
+
+
+
+ struct Scope : public RefObject
+ {
+ // The parent of this scope (where lookup should go if nothing is found locally)
+ RefPtr<Scope> parent;
+
+ // The next sibling of this scope (a peer for lookup)
+ RefPtr<Scope> nextSibling;
+
+ // The container to use for lookup
+ //
+ // Note(tfoley): This is kept as an unowned pointer
+ // so that a scope can't keep parts of the AST alive,
+ // but the opposite it allowed.
+ ContainerDecl* containerDecl;
+ };
+
+ // Masks to be applied when lookup up declarations
+ enum class LookupMask : uint8_t
+ {
+ type = 0x1,
+ Function = 0x2,
+ Value = 0x4,
+ Attribute = 0x8,
+
+ Default = type | Function | Value,
+ };
+
+ // Represents one item found during lookup
+ struct LookupResultItem
+ {
+ // Sometimes lookup finds an item, but there were additional
+ // "hops" taken to reach it. We need to remember these steps
+ // so that if/when we consturct a full expression we generate
+ // appropriate AST nodes for all the steps.
+ //
+ // We build up a list of these "breadcrumbs" while doing
+ // lookup, and store them alongside each item found.
+ //
+ // As an example, suppose we have an HLSL `cbuffer` declaration:
+ //
+ // cbuffer C { float4 f; }
+ //
+ // This is syntax sugar for a global-scope variable of
+ // type `ConstantBuffer<T>` where `T` is a `struct` containing
+ // all the members:
+ //
+ // struct Anon0 { float4 f; };
+ // __transparent ConstantBuffer<Anon0> anon1;
+ //
+ // The `__transparent` modifier there captures the fact that
+ // when somebody writes `f` in their code, they expect it to
+ // "see through" the `cbuffer` declaration (or the global variable,
+ // in this case) and find the member inside.
+ //
+ // But when the user writes `f` we can't just create a simple
+ // `VarExpr` that refers directly to that field, because that
+ // doesn't actually reflect the required steps in a way that
+ // code generation can use.
+ //
+ // Instead we need to construct an expression like `(*anon1).f`,
+ // where there is are two additional steps in the process:
+ //
+ // 1. We needed to dereference the pointer-like type `ConstantBuffer<Anon0>`
+ // to get at a value of type `Anon0`
+ // 2. We needed to access a sub-field of the aggregate type `Anon0`
+ //
+ // We *could* just create these full-formed expressions during
+ // lookup, but this might mean creating a large number of
+ // AST nodes in cases where the user calls an overloaded function.
+ // At the very least we'd rather not heap-allocate in the common
+ // case where no "extra" steps need to be performed to get to
+ // the declarations.
+ //
+ // This is where "breadcrumbs" come in. A breadcrumb represents
+ // an extra "step" that must be performed to turn a declaration
+ // found by lookup into a valid expression to splice into the
+ // AST. Most of the time lookup result items don't have any
+ // breadcrumbs, so that no extra heap allocation takes place.
+ // When an item does have breadcrumbs, and it is chosen as
+ // the unique result (perhaps by overload resolution), then
+ // we can walk the list of breadcrumbs to create a full
+ // expression.
+ class Breadcrumb : public RefObject
+ {
+ public:
+ enum class Kind : uint8_t
+ {
+ // The lookup process looked "through" an in-scope
+ // declaration to the fields inside of it, so that
+ // even if lookup started with a simple name `f`,
+ // it needs to result in a member expression `obj.f`.
+ Member,
+
+ // The lookup process took a pointer(-like) value, and then
+ // proceeded to derefence it and look at the thing(s)
+ // it points to instead, so that the final expression
+ // needs to have `(*obj)`
+ Deref,
+
+ // The lookup process saw a value `obj` of type `T` and
+ // took into account an in-scope constraint that says
+ // `T` is a subtype of some other type `U`, so that
+ // lookup was able to find a member through type `U`
+ // instead.
+ Constraint,
+
+ // The lookup process considered a member of an
+ // enclosing type as being in scope, so that any
+ // reference to that member needs to use a `this`
+ // expression as appropriate.
+ This,
+ };
+
+ // The kind of lookup step that was performed
+ Kind kind;
+
+ // For the `Kind::This` case, what does the implicit
+ // `this` or `This` parameter refer to?
+ //
+ enum class ThisParameterMode : uint8_t
+ {
+ ImmutableValue, // An immutable `this` value
+ MutableValue, // A mutable `this` value
+ Type, // A `This` type
+
+ Default = ImmutableValue,
+ };
+ ThisParameterMode thisParameterMode = ThisParameterMode::Default;
+
+ // As needed, a reference to the declaration that faciliated
+ // the lookup step.
+ //
+ // For a `Member` lookup step, this is the declaration whose
+ // members were implicitly pulled into scope.
+ //
+ // For a `Constraint` lookup step, this is the `ConstraintDecl`
+ // that serves to witness the subtype relationship.
+ //
+ DeclRef<Decl> declRef;
+
+ // The next implicit step that the lookup process took to
+ // arrive at a final value.
+ RefPtr<Breadcrumb> next;
+
+ Breadcrumb(
+ Kind kind,
+ DeclRef<Decl> declRef,
+ RefPtr<Breadcrumb> next,
+ ThisParameterMode thisParameterMode = ThisParameterMode::Default)
+ : kind(kind)
+ , thisParameterMode(thisParameterMode)
+ , declRef(declRef)
+ , next(next)
+ {}
+ };
+
+ // A properly-specialized reference to the declaration that was found.
+ DeclRef<Decl> declRef;
+
+ // Any breadcrumbs needed in order to turn that declaration
+ // reference into a well-formed expression.
+ //
+ // This is unused in the simple case where a declaration
+ // is being referenced directly (rather than through
+ // transparent members).
+ RefPtr<Breadcrumb> breadcrumbs;
+
+ LookupResultItem() = default;
+ explicit LookupResultItem(DeclRef<Decl> declRef)
+ : declRef(declRef)
+ {}
+ LookupResultItem(DeclRef<Decl> declRef, RefPtr<Breadcrumb> breadcrumbs)
+ : declRef(declRef)
+ , breadcrumbs(breadcrumbs)
+ {}
+ };
+
+
+ // Result of looking up a name in some lexical/semantic environment.
+ // Can be used to enumerate all the declarations matching that name,
+ // in the case where the result is overloaded.
+ struct LookupResult
+ {
+ // The one item that was found, in the smple case
+ LookupResultItem item;
+
+ // All of the items that were found, in the complex case.
+ // Note: if there was no overloading, then this list isn't
+ // used at all, to avoid allocation.
+ List<LookupResultItem> items;
+
+ // Was at least one result found?
+ bool isValid() const { return item.declRef.getDecl() != nullptr; }
+
+ bool isOverloaded() const { return items.getCount() > 1; }
+
+ Name* getName() const
+ {
+ return items.getCount() > 1 ? items[0].declRef.GetName() : item.declRef.GetName();
+ }
+ LookupResultItem* begin()
+ {
+ if (isValid())
+ {
+ if (isOverloaded())
+ return items.begin();
+ else
+ return &item;
+ }
+ else
+ return nullptr;
+ }
+ LookupResultItem* end()
+ {
+ if (isValid())
+ {
+ if (isOverloaded())
+ return items.end();
+ else
+ return &item + 1;
+ }
+ else
+ return nullptr;
+ }
+ };
+
+ struct SemanticsVisitor;
+
+ struct LookupRequest
+ {
+ SemanticsVisitor* semantics = nullptr;
+ RefPtr<Scope> scope = nullptr;
+ RefPtr<Scope> endScope = nullptr;
+
+ LookupMask mask = LookupMask::Default;
+ };
+
+ struct WitnessTable;
+
+ // A value that witnesses the satisfaction of an interface
+ // requirement by a particular declaration or value.
+ struct RequirementWitness
+ {
+ RequirementWitness()
+ : m_flavor(Flavor::none)
+ {}
+
+ RequirementWitness(DeclRef<Decl> declRef)
+ : m_flavor(Flavor::declRef)
+ , m_declRef(declRef)
+ {}
+
+ RequirementWitness(RefPtr<Val> val);
+
+ RequirementWitness(RefPtr<WitnessTable> witnessTable);
+
+ enum class Flavor
+ {
+ none,
+ declRef,
+ val,
+ witnessTable,
+ };
+
+ Flavor getFlavor()
+ {
+ return m_flavor;
+ }
+
+ DeclRef<Decl> getDeclRef()
+ {
+ SLANG_ASSERT(getFlavor() == Flavor::declRef);
+ return m_declRef;
+ }
+
+ RefPtr<Val> getVal()
+ {
+ SLANG_ASSERT(getFlavor() == Flavor::val);
+ return m_obj.as<Val>();
+ }
+
+ RefPtr<WitnessTable> getWitnessTable();
+
+ RequirementWitness specialize(SubstitutionSet const& subst);
+
+ Flavor m_flavor;
+ DeclRef<Decl> m_declRef;
+ RefPtr<RefObject> m_obj;
+
+ };
+
+ typedef Dictionary<Decl*, RequirementWitness> RequirementDictionary;
+
+ struct WitnessTable : RefObject
+ {
+ RequirementDictionary requirementDictionary;
+ };
+
+ typedef Dictionary<unsigned int, RefPtr<RefObject>> AttributeArgumentValueDict;
+
+ struct SpecializationParam
+ {
+ enum class Flavor
+ {
+ GenericType,
+ GenericValue,
+ ExistentialType,
+ ExistentialValue,
+ };
+ Flavor flavor;
+ SourceLoc loc;
+ RefPtr<NodeBase> object;
+ };
+ typedef List<SpecializationParam> SpecializationParams;
+
+ struct SpecializationArg
+ {
+ RefPtr<Val> val;
+ };
+ typedef List<SpecializationArg> SpecializationArgs;
+
+ struct ExpandedSpecializationArg : SpecializationArg
+ {
+ RefPtr<Val> witness;
+ };
+ typedef List<ExpandedSpecializationArg> ExpandedSpecializationArgs;
+
+} // namespace Slang
+
+#endif
diff --git a/source/slang/slang-type-defs.h b/source/slang/slang-ast-type.h
index 356aa05d2..454b7228e 100644
--- a/source/slang/slang-type-defs.h
+++ b/source/slang/slang-ast-type.h
@@ -1,10 +1,21 @@
-// slang-type-defs.h
+// slang-ast-type.h
+
+#pragma once
+
+#include "slang-ast-base.h"
+
+namespace Slang {
+
+#define SLANG_ABSTRACT_CLASS(x) SLANG_ABSTRACT_CLASS_REFLECT(x)
+#define SLANG_CLASS(x) SLANG_CLASS_REFLECT_WITH_ACCEPT(x)
// Syntax class definitions for types.
// The type of a reference to an overloaded name
-SYNTAX_CLASS(OverloadGroupType, Type)
-RAW(
+class OverloadGroupType : public Type
+{
+ SLANG_CLASS(OverloadGroupType)
+
public:
virtual String ToString() override;
@@ -12,25 +23,27 @@ protected:
virtual bool EqualsImpl(Type * type) override;
virtual RefPtr<Type> CreateCanonicalType() override;
virtual int GetHashCode() override;
-)
-END_SYNTAX_CLASS()
+};
// The type of an initializer-list expression (before it has
// been coerced to some other type)
-SYNTAX_CLASS(InitializerListType, Type)
-RAW(
+class InitializerListType : public Type
+{
+ SLANG_CLASS(InitializerListType)
+
virtual String ToString() override;
protected:
virtual bool EqualsImpl(Type * type) override;
virtual RefPtr<Type> CreateCanonicalType() override;
virtual int GetHashCode() override;
-)
-END_SYNTAX_CLASS()
+};
// The type of an expression that was erroneous
-SYNTAX_CLASS(ErrorType, Type)
-RAW(
+class ErrorType : public Type
+{
+ SLANG_CLASS(ErrorType)
+
public:
virtual String ToString() override;
@@ -39,14 +52,15 @@ protected:
virtual RefPtr<Val> SubstituteImpl(SubstitutionSet subst, int* ioDiff) override;
virtual RefPtr<Type> CreateCanonicalType() override;
virtual int GetHashCode() override;
-)
-END_SYNTAX_CLASS()
+};
// A type that takes the form of a reference to some declaration
-SYNTAX_CLASS(DeclRefType, Type)
- DECL_FIELD(DeclRef<Decl>, declRef)
+class DeclRefType : public Type
+{
+ SLANG_CLASS(DeclRefType)
+
+ DeclRef<Decl> declRef;
-RAW(
virtual String ToString() override;
virtual RefPtr<Val> SubstituteImpl(SubstitutionSet subst, int* ioDiff) override;
@@ -64,22 +78,24 @@ protected:
virtual int GetHashCode() override;
virtual bool EqualsImpl(Type * type) override;
virtual RefPtr<Type> CreateCanonicalType() override;
-)
-END_SYNTAX_CLASS()
+};
// Base class for types that can be used in arithmetic expressions
-ABSTRACT_SYNTAX_CLASS(ArithmeticExpressionType, DeclRefType)
-RAW(
+class ArithmeticExpressionType : public DeclRefType
+{
+ SLANG_ABSTRACT_CLASS(ArithmeticExpressionType)
+
public:
virtual BasicExpressionType* GetScalarType() = 0;
-)
-END_SYNTAX_CLASS()
+};
-SYNTAX_CLASS(BasicExpressionType, ArithmeticExpressionType)
+class BasicExpressionType : public ArithmeticExpressionType
+{
+ SLANG_CLASS(BasicExpressionType)
- FIELD(BaseType, baseType)
-RAW(
+ BaseType baseType;
+
BasicExpressionType() {}
BasicExpressionType(
Slang::BaseType baseType)
@@ -89,38 +105,43 @@ protected:
virtual BasicExpressionType* GetScalarType() override;
virtual bool EqualsImpl(Type * type) override;
virtual RefPtr<Type> CreateCanonicalType() override;
-)
-END_SYNTAX_CLASS()
+
+};
// Base type for things that are built in to the compiler,
// and will usually have special behavior or a custom
// mapping to the IR level.
-ABSTRACT_SYNTAX_CLASS(BuiltinType, DeclRefType)
-END_SYNTAX_CLASS()
+class BuiltinType : public DeclRefType
+{
+ SLANG_ABSTRACT_CLASS(BuiltinType)
+
+};
// Resources that contain "elements" that can be fetched
-ABSTRACT_SYNTAX_CLASS(ResourceType, BuiltinType)
+class ResourceType : public BuiltinType
+{
+ SLANG_ABSTRACT_CLASS(ResourceType)
+
// The type that results from fetching an element from this resource
- SYNTAX_FIELD(RefPtr<Type>, elementType)
+ RefPtr<Type> elementType;
// Shape and access level information for this resource type
- FIELD(TextureFlavor, flavor)
-
- RAW(
- TextureFlavor::Shape GetBaseShape()
- {
- return flavor.GetBaseShape();
- }
- bool isMultisample() { return flavor.isMultisample(); }
- bool isArray() { return flavor.isArray(); }
- SlangResourceShape getShape() const { return flavor.getShape(); }
- SlangResourceAccess getAccess() { return flavor.getAccess(); }
-
- )
-END_SYNTAX_CLASS()
-
-ABSTRACT_SYNTAX_CLASS(TextureTypeBase, ResourceType)
-RAW(
+ TextureFlavor flavor;
+
+ TextureFlavor::Shape GetBaseShape()
+ {
+ return flavor.GetBaseShape();
+ }
+ bool isMultisample() { return flavor.isMultisample(); }
+ bool isArray() { return flavor.isArray(); }
+ SlangResourceShape getShape() const { return flavor.getShape(); }
+ SlangResourceAccess getAccess() { return flavor.getAccess(); }
+};
+
+class TextureTypeBase : public ResourceType
+{
+ SLANG_ABSTRACT_CLASS(TextureTypeBase)
+
TextureTypeBase()
{}
TextureTypeBase(
@@ -130,11 +151,12 @@ RAW(
this->elementType = elementType;
this->flavor = flavor;
}
-)
-END_SYNTAX_CLASS()
+};
+
+class TextureType : public TextureTypeBase
+{
+ SLANG_CLASS(TextureType)
-SYNTAX_CLASS(TextureType, TextureTypeBase)
-RAW(
TextureType()
{}
TextureType(
@@ -142,13 +164,14 @@ RAW(
RefPtr<Type> elementType)
: TextureTypeBase(flavor, elementType)
{}
-)
-END_SYNTAX_CLASS()
+};
// This is a base type for texture/sampler pairs,
// as they exist in, e.g., GLSL
-SYNTAX_CLASS(TextureSamplerType, TextureTypeBase)
-RAW(
+class TextureSamplerType : public TextureTypeBase
+{
+ SLANG_CLASS(TextureSamplerType)
+
TextureSamplerType()
{}
TextureSamplerType(
@@ -156,12 +179,13 @@ RAW(
RefPtr<Type> elementType)
: TextureTypeBase(flavor, elementType)
{}
-)
-END_SYNTAX_CLASS()
+};
// This is a base type for `image*` types, as they exist in GLSL
-SYNTAX_CLASS(GLSLImageType, TextureTypeBase)
-RAW(
+class GLSLImageType : public TextureTypeBase
+{
+ SLANG_CLASS(GLSLImageType)
+
GLSLImageType()
{}
GLSLImageType(
@@ -169,91 +193,209 @@ RAW(
RefPtr<Type> elementType)
: TextureTypeBase(flavor, elementType)
{}
-)
-END_SYNTAX_CLASS()
+};
+
+class SamplerStateType : public BuiltinType
+{
+ SLANG_CLASS(SamplerStateType)
-SYNTAX_CLASS(SamplerStateType, BuiltinType)
// What flavor of sampler state is this
- FIELD(SamplerStateFlavor, flavor)
-END_SYNTAX_CLASS()
+ SamplerStateFlavor flavor;
+};
// Other cases of generic types known to the compiler
-SYNTAX_CLASS(BuiltinGenericType, BuiltinType)
- SYNTAX_FIELD(RefPtr<Type>, elementType)
+class BuiltinGenericType : public BuiltinType
+{
+ SLANG_CLASS(BuiltinGenericType)
+
+ RefPtr<Type> elementType;
- RAW(Type* getElementType() { return elementType; })
-END_SYNTAX_CLASS()
+ Type* getElementType() { return elementType; }
+};
// Types that behave like pointers, in that they can be
// dereferenced (implicitly) to access members defined
// in the element type.
-SIMPLE_SYNTAX_CLASS(PointerLikeType, BuiltinGenericType)
+class PointerLikeType : public BuiltinGenericType
+{
+ SLANG_CLASS(PointerLikeType)
+};
+
// HLSL buffer-type resources
-SIMPLE_SYNTAX_CLASS(HLSLStructuredBufferTypeBase, BuiltinGenericType)
-SIMPLE_SYNTAX_CLASS(HLSLStructuredBufferType, HLSLStructuredBufferTypeBase)
-SIMPLE_SYNTAX_CLASS(HLSLRWStructuredBufferType, HLSLStructuredBufferTypeBase)
-SIMPLE_SYNTAX_CLASS(HLSLRasterizerOrderedStructuredBufferType, HLSLStructuredBufferTypeBase)
+class HLSLStructuredBufferTypeBase : public BuiltinGenericType
+{
+ SLANG_CLASS(HLSLStructuredBufferTypeBase)
+};
+
+class HLSLStructuredBufferType : public HLSLStructuredBufferTypeBase
+{
+ SLANG_CLASS(HLSLStructuredBufferType)
+};
+
+class HLSLRWStructuredBufferType : public HLSLStructuredBufferTypeBase
+{
+ SLANG_CLASS(HLSLRWStructuredBufferType)
+};
+
+class HLSLRasterizerOrderedStructuredBufferType : public HLSLStructuredBufferTypeBase
+{
+ SLANG_CLASS(HLSLRasterizerOrderedStructuredBufferType)
+};
+
+
+class UntypedBufferResourceType : public BuiltinType
+{
+ SLANG_CLASS(UntypedBufferResourceType)
+};
+
+class HLSLByteAddressBufferType : public UntypedBufferResourceType
+{
+ SLANG_CLASS(HLSLByteAddressBufferType)
+};
+
+class HLSLRWByteAddressBufferType : public UntypedBufferResourceType
+{
+ SLANG_CLASS(HLSLRWByteAddressBufferType)
+};
+
+class HLSLRasterizerOrderedByteAddressBufferType : public UntypedBufferResourceType
+{
+ SLANG_CLASS(HLSLRasterizerOrderedByteAddressBufferType)
+};
+
+class RaytracingAccelerationStructureType : public UntypedBufferResourceType
+{
+ SLANG_CLASS(RaytracingAccelerationStructureType)
+};
+
+
+class HLSLAppendStructuredBufferType : public HLSLStructuredBufferTypeBase
+{
+ SLANG_CLASS(HLSLAppendStructuredBufferType)
+};
-SIMPLE_SYNTAX_CLASS(UntypedBufferResourceType, BuiltinType)
-SIMPLE_SYNTAX_CLASS(HLSLByteAddressBufferType, UntypedBufferResourceType)
-SIMPLE_SYNTAX_CLASS(HLSLRWByteAddressBufferType, UntypedBufferResourceType)
-SIMPLE_SYNTAX_CLASS(HLSLRasterizerOrderedByteAddressBufferType, UntypedBufferResourceType)
-SIMPLE_SYNTAX_CLASS(RaytracingAccelerationStructureType, UntypedBufferResourceType)
+class HLSLConsumeStructuredBufferType : public HLSLStructuredBufferTypeBase
+{
+ SLANG_CLASS(HLSLConsumeStructuredBufferType)
+};
-SIMPLE_SYNTAX_CLASS(HLSLAppendStructuredBufferType, HLSLStructuredBufferTypeBase)
-SIMPLE_SYNTAX_CLASS(HLSLConsumeStructuredBufferType, HLSLStructuredBufferTypeBase)
-SYNTAX_CLASS(HLSLPatchType, BuiltinType)
-RAW(
+class HLSLPatchType : public BuiltinType
+{
+ SLANG_CLASS(HLSLPatchType)
+
Type* getElementType();
- IntVal* getElementCount();
-)
-END_SYNTAX_CLASS()
+ IntVal* getElementCount();
+};
+
+class HLSLInputPatchType : public HLSLPatchType
+{
+ SLANG_CLASS(HLSLInputPatchType)
+};
+
+class HLSLOutputPatchType : public HLSLPatchType
+{
+ SLANG_CLASS(HLSLOutputPatchType)
+};
-SIMPLE_SYNTAX_CLASS(HLSLInputPatchType, HLSLPatchType)
-SIMPLE_SYNTAX_CLASS(HLSLOutputPatchType, HLSLPatchType)
// HLSL geometry shader output stream types
-SIMPLE_SYNTAX_CLASS(HLSLStreamOutputType, BuiltinGenericType)
-SIMPLE_SYNTAX_CLASS(HLSLPointStreamType, HLSLStreamOutputType)
-SIMPLE_SYNTAX_CLASS(HLSLLineStreamType, HLSLStreamOutputType)
-SIMPLE_SYNTAX_CLASS(HLSLTriangleStreamType, HLSLStreamOutputType)
+class HLSLStreamOutputType : public BuiltinGenericType
+{
+ SLANG_CLASS(HLSLStreamOutputType)
+};
+
+class HLSLPointStreamType : public HLSLStreamOutputType
+{
+ SLANG_CLASS(HLSLPointStreamType)
+};
+
+class HLSLLineStreamType : public HLSLStreamOutputType
+{
+ SLANG_CLASS(HLSLLineStreamType)
+};
+
+class HLSLTriangleStreamType : public HLSLStreamOutputType
+{
+ SLANG_CLASS(HLSLTriangleStreamType)
+};
+
//
-SIMPLE_SYNTAX_CLASS(GLSLInputAttachmentType, BuiltinType)
+class GLSLInputAttachmentType : public BuiltinType
+{
+ SLANG_CLASS(GLSLInputAttachmentType)
+};
+
// Base class for types used when desugaring parameter block
// declarations, includeing HLSL `cbuffer` or GLSL `uniform` blocks.
-SIMPLE_SYNTAX_CLASS(ParameterGroupType, PointerLikeType)
+class ParameterGroupType : public PointerLikeType
+{
+ SLANG_CLASS(ParameterGroupType)
+};
+
+class UniformParameterGroupType : public ParameterGroupType
+{
+ SLANG_CLASS(UniformParameterGroupType)
+};
+
+class VaryingParameterGroupType : public ParameterGroupType
+{
+ SLANG_CLASS(VaryingParameterGroupType)
+};
-SIMPLE_SYNTAX_CLASS(UniformParameterGroupType, ParameterGroupType)
-SIMPLE_SYNTAX_CLASS(VaryingParameterGroupType, ParameterGroupType)
// type for HLSL `cbuffer` declarations, and `ConstantBuffer<T>`
// ALso used for GLSL `uniform` blocks.
-SIMPLE_SYNTAX_CLASS(ConstantBufferType, UniformParameterGroupType)
+class ConstantBufferType : public UniformParameterGroupType
+{
+ SLANG_CLASS(ConstantBufferType)
+};
+
// type for HLSL `tbuffer` declarations, and `TextureBuffer<T>`
-SIMPLE_SYNTAX_CLASS(TextureBufferType, UniformParameterGroupType)
+class TextureBufferType : public UniformParameterGroupType
+{
+ SLANG_CLASS(TextureBufferType)
+};
+
// type for GLSL `in` and `out` blocks
-SIMPLE_SYNTAX_CLASS(GLSLInputParameterGroupType, VaryingParameterGroupType)
-SIMPLE_SYNTAX_CLASS(GLSLOutputParameterGroupType, VaryingParameterGroupType)
+class GLSLInputParameterGroupType : public VaryingParameterGroupType
+{
+ SLANG_CLASS(GLSLInputParameterGroupType)
+};
+
+class GLSLOutputParameterGroupType : public VaryingParameterGroupType
+{
+ SLANG_CLASS(GLSLOutputParameterGroupType)
+};
+
// type for GLLSL `buffer` blocks
-SIMPLE_SYNTAX_CLASS(GLSLShaderStorageBufferType, UniformParameterGroupType)
+class GLSLShaderStorageBufferType : public UniformParameterGroupType
+{
+ SLANG_CLASS(GLSLShaderStorageBufferType)
+};
+
// type for Slang `ParameterBlock<T>` type
-SIMPLE_SYNTAX_CLASS(ParameterBlockType, UniformParameterGroupType)
+class ParameterBlockType : public UniformParameterGroupType
+{
+ SLANG_CLASS(ParameterBlockType)
+};
-SYNTAX_CLASS(ArrayExpressionType, Type)
- SYNTAX_FIELD(RefPtr<Type>, baseType)
- SYNTAX_FIELD(RefPtr<IntVal>, ArrayLength)
+class ArrayExpressionType : public Type
+{
+ SLANG_CLASS(ArrayExpressionType)
+
+ RefPtr<Type> baseType;
+ RefPtr<IntVal> ArrayLength;
-RAW(
virtual Slang::String ToString() override;
protected:
@@ -261,17 +403,18 @@ protected:
virtual RefPtr<Type> CreateCanonicalType() override;
virtual RefPtr<Val> SubstituteImpl(SubstitutionSet subst, int* ioDiff) override;
virtual int GetHashCode() override;
- )
-END_SYNTAX_CLASS()
+};
// The "type" of an expression that resolves to a type.
// For example, in the expression `float(2)` the sub-expression,
// `float` would have the type `TypeType(float)`.
-SYNTAX_CLASS(TypeType, Type)
+class TypeType : public Type
+{
+ SLANG_CLASS(TypeType)
+
// The type that this is the type of...
- SYNTAX_FIELD(RefPtr<Type>, type)
+ RefPtr<Type> type;
-RAW(
public:
TypeType()
{}
@@ -285,30 +428,30 @@ protected:
virtual bool EqualsImpl(Type * type) override;
virtual RefPtr<Type> CreateCanonicalType() override;
virtual int GetHashCode() override;
-)
-END_SYNTAX_CLASS()
+};
// A vector type, e.g., `vector<T,N>`
-SYNTAX_CLASS(VectorExpressionType, ArithmeticExpressionType)
+class VectorExpressionType : public ArithmeticExpressionType
+{
+ SLANG_CLASS(VectorExpressionType)
// The type of vector elements.
// As an invariant, this should be a basic type or an alias.
- SYNTAX_FIELD(RefPtr<Type>, elementType)
+ RefPtr<Type> elementType;
// The number of elements
- SYNTAX_FIELD(RefPtr<IntVal>, elementCount)
+ RefPtr<IntVal> elementCount;
-RAW(
virtual String ToString() override;
protected:
virtual BasicExpressionType* GetScalarType() override;
-)
-END_SYNTAX_CLASS()
+};
// A matrix type, e.g., `matrix<T,R,C>`
-SYNTAX_CLASS(MatrixExpressionType, ArithmeticExpressionType)
-RAW(
+class MatrixExpressionType : public ArithmeticExpressionType
+{
+ SLANG_CLASS(MatrixExpressionType)
Type* getElementType();
IntVal* getRowCount();
@@ -323,55 +466,71 @@ protected:
private:
RefPtr<Type> mRowType;
-)
-END_SYNTAX_CLASS()
+};
// The built-in `String` type
-SIMPLE_SYNTAX_CLASS(StringType, BuiltinType)
-
-// Type built-in `__EnumType` type
-SYNTAX_CLASS(EnumTypeType, BuiltinType)
+class StringType : public BuiltinType
+{
+ SLANG_CLASS(StringType)
+};
-// TODO: provide accessors for the declaration, the "tag" type, etc.
-END_SYNTAX_CLASS()
+// Type built-in `__EnumType` type
+class EnumTypeType : public BuiltinType
+{
+ SLANG_CLASS(EnumTypeType)
+ // TODO: provide accessors for the declaration, the "tag" type, etc.
+};
// Base class for types that map down to
// simple pointers as part of code generation.
-SYNTAX_CLASS(PtrTypeBase, BuiltinType)
-RAW(
+class PtrTypeBase : public BuiltinType
+{
+ SLANG_CLASS(PtrTypeBase)
+
// Get the type of the pointed-to value.
Type* getValueType();
-)
-END_SYNTAX_CLASS()
+};
// A true (user-visible) pointer type, e.g., `T*`
-SYNTAX_CLASS(PtrType, PtrTypeBase)
-END_SYNTAX_CLASS()
+class PtrType : public PtrTypeBase
+{
+ SLANG_CLASS(PtrType)
+};
// A type that represents the behind-the-scenes
// logical pointer that is passed for an `out`
// or `in out` parameter
-SYNTAX_CLASS(OutTypeBase, PtrTypeBase)
-END_SYNTAX_CLASS()
+class OutTypeBase : public PtrTypeBase
+{
+ SLANG_CLASS(OutTypeBase)
+};
// The type for an `out` parameter, e.g., `out T`
-SYNTAX_CLASS(OutType, OutTypeBase)
-END_SYNTAX_CLASS()
+class OutType : public OutTypeBase
+{
+ SLANG_CLASS(OutType)
+};
// The type for an `in out` parameter, e.g., `in out T`
-SYNTAX_CLASS(InOutType, OutTypeBase)
-END_SYNTAX_CLASS()
+class InOutType : public OutTypeBase
+{
+ SLANG_CLASS(InOutType)
+};
// The type for an `ref` parameter, e.g., `ref T`
-SYNTAX_CLASS(RefType, PtrTypeBase)
-END_SYNTAX_CLASS()
+class RefType : public PtrTypeBase
+{
+ SLANG_CLASS(RefType)
+};
// A type alias of some kind (e.g., via `typedef`)
-SYNTAX_CLASS(NamedExpressionType, Type)
-DECL_FIELD(DeclRef<TypeDefDecl>, declRef)
+class NamedExpressionType : public Type
+{
+ SLANG_CLASS(NamedExpressionType)
+
+ DeclRef<TypeDefDecl> declRef;
-RAW(
RefPtr<Type> innerType;
NamedExpressionType()
{}
@@ -380,19 +539,19 @@ RAW(
: declRef(declRef)
{}
-
virtual String ToString() override;
protected:
virtual bool EqualsImpl(Type * type) override;
virtual RefPtr<Type> CreateCanonicalType() override;
virtual int GetHashCode() override;
-)
-END_SYNTAX_CLASS()
+};
// A function type is defined by its parameter types
// and its result type.
-SYNTAX_CLASS(FuncType, Type)
+class FuncType : public Type
+{
+ SLANG_CLASS(FuncType)
// TODO: We may want to preserve parameter names
// in the list here, just so that we can print
@@ -400,9 +559,9 @@ SYNTAX_CLASS(FuncType, Type)
// type, even if they don't affect the actual
// semantic type underneath.
- FIELD(List<RefPtr<Type>>, paramTypes)
- FIELD(RefPtr<Type>, resultType)
-RAW(
+ List<RefPtr<Type>> paramTypes;
+ RefPtr<Type> resultType;
+
FuncType()
{}
@@ -416,15 +575,15 @@ protected:
virtual bool EqualsImpl(Type * type) override;
virtual RefPtr<Type> CreateCanonicalType() override;
virtual int GetHashCode() override;
-)
-END_SYNTAX_CLASS()
+};
// The "type" of an expression that names a generic declaration.
-SYNTAX_CLASS(GenericDeclRefType, Type)
+class GenericDeclRefType : public Type
+{
+ SLANG_CLASS(GenericDeclRefType)
- DECL_FIELD(DeclRef<GenericDecl>, declRef)
+ DeclRef<GenericDecl> declRef;
- RAW(
GenericDeclRefType()
{}
GenericDeclRefType(
@@ -432,7 +591,6 @@ SYNTAX_CLASS(GenericDeclRefType, Type)
: declRef(declRef)
{}
-
DeclRef<GenericDecl> const& GetDeclRef() const { return declRef; }
virtual String ToString() override;
@@ -441,14 +599,15 @@ protected:
virtual bool EqualsImpl(Type * type) override;
virtual int GetHashCode() override;
virtual RefPtr<Type> CreateCanonicalType() override;
-)
-END_SYNTAX_CLASS()
+};
// The "type" of a reference to a module or namespace
-SYNTAX_CLASS(NamespaceType, Type)
- DECL_FIELD(DeclRef<NamespaceDeclBase>, m_declRef)
+class NamespaceType : public Type
+{
+ SLANG_CLASS(NamespaceType)
+
+ DeclRef<NamespaceDeclBase> m_declRef;
-RAW(
NamespaceType()
{}
@@ -460,13 +619,14 @@ protected:
virtual bool EqualsImpl(Type * type) override;
virtual int GetHashCode() override;
virtual RefPtr<Type> CreateCanonicalType() override;
-)
-END_SYNTAX_CLASS()
+};
// The concrete type for a value wrapped in an existential, accessible
// when the existential is "opened" in some context.
-SYNTAX_CLASS(ExtractExistentialType, Type)
-RAW(
+class ExtractExistentialType : public Type
+{
+ SLANG_CLASS(ExtractExistentialType)
+
DeclRef<VarDeclBase> declRef;
virtual String ToString() override;
@@ -474,12 +634,13 @@ RAW(
virtual int GetHashCode() override;
virtual RefPtr<Type> CreateCanonicalType() override;
virtual RefPtr<Val> SubstituteImpl(SubstitutionSet subst, int* ioDiff) override;
-)
-END_SYNTAX_CLASS()
+};
/// A tagged union of zero or more other types.
-SYNTAX_CLASS(TaggedUnionType, Type)
-RAW(
+class TaggedUnionType : public Type
+{
+ SLANG_CLASS(TaggedUnionType)
+
/// The distinct "cases" the tagged union can store.
///
/// For each type in this array, the array index is the
@@ -492,11 +653,12 @@ RAW(
virtual int GetHashCode() override;
virtual RefPtr<Type> CreateCanonicalType() override;
virtual RefPtr<Val> SubstituteImpl(SubstitutionSet subst, int* ioDiff) override;
-)
-END_SYNTAX_CLASS()
+};
+
+class ExistentialSpecializedType : public Type
+{
+ SLANG_CLASS(ExistentialSpecializedType)
-SYNTAX_CLASS(ExistentialSpecializedType, Type)
-RAW(
RefPtr<Type> baseType;
ExpandedSpecializationArgs args;
@@ -505,12 +667,13 @@ RAW(
virtual int GetHashCode() override;
virtual RefPtr<Type> CreateCanonicalType() override;
virtual RefPtr<Val> SubstituteImpl(SubstitutionSet subst, int* ioDiff) override;
-)
-END_SYNTAX_CLASS()
+};
/// The type of `this` within a polymorphic declaration
-SYNTAX_CLASS(ThisType, Type)
-RAW(
+class ThisType : public Type
+{
+ SLANG_CLASS(ThisType)
+
DeclRef<InterfaceDecl> interfaceDeclRef;
virtual String ToString() override;
@@ -518,5 +681,10 @@ RAW(
virtual int GetHashCode() override;
virtual RefPtr<Type> CreateCanonicalType() override;
virtual RefPtr<Val> SubstituteImpl(SubstitutionSet subst, int* ioDiff) override;
-)
-END_SYNTAX_CLASS()
+
+};
+
+#undef SLANG_ABSTRACT_CLASS
+#undef SLANG_CLASS
+
+} // namespace Slang
diff --git a/source/slang/slang-val-defs.h b/source/slang/slang-ast-val.h
index 5024554d4..a47acc92d 100644
--- a/source/slang/slang-val-defs.h
+++ b/source/slang/slang-ast-val.h
@@ -1,16 +1,29 @@
-// slang-val-defs.h
+// slang-ast-val.h
+
+#pragma once
+
+#include "slang-ast-base.h"
+
+namespace Slang {
+
+#define SLANG_ABSTRACT_CLASS(x) SLANG_ABSTRACT_CLASS_REFLECT(x)
+#define SLANG_CLASS(x) SLANG_CLASS_REFLECT_WITH_ACCEPT(x)
// Syntax class definitions for compile-time values.
// A compile-time integer (may not have a specific concrete value)
-ABSTRACT_SYNTAX_CLASS(IntVal, Val)
-END_SYNTAX_CLASS()
+class IntVal : public Val
+{
+ SLANG_ABSTRACT_CLASS(IntVal)
+};
// Trivial case of a value that is just a constant integer
-SYNTAX_CLASS(ConstantIntVal, IntVal)
- FIELD(IntegerLiteralValue, value)
+class ConstantIntVal : public IntVal
+{
+ SLANG_CLASS(ConstantIntVal)
+
+ IntegerLiteralValue value;
- RAW(
ConstantIntVal()
{}
ConstantIntVal(IntegerLiteralValue value)
@@ -20,14 +33,15 @@ SYNTAX_CLASS(ConstantIntVal, IntVal)
virtual bool EqualsVal(Val* val) override;
virtual String ToString() override;
virtual int GetHashCode() override;
- )
-END_SYNTAX_CLASS()
+};
// The logical "value" of a rererence to a generic value parameter
-SYNTAX_CLASS(GenericParamIntVal, IntVal)
- DECL_FIELD(DeclRef<VarDeclBase>, declRef)
+class GenericParamIntVal : public IntVal
+{
+ SLANG_CLASS(GenericParamIntVal)
+
+ DeclRef<VarDeclBase> declRef;
- RAW(
GenericParamIntVal()
{}
GenericParamIntVal(DeclRef<VarDeclBase> declRef)
@@ -38,17 +52,17 @@ SYNTAX_CLASS(GenericParamIntVal, IntVal)
virtual String ToString() override;
virtual int GetHashCode() override;
virtual RefPtr<Val> SubstituteImpl(SubstitutionSet subst, int* ioDiff) override;
-)
-END_SYNTAX_CLASS()
+};
/// An unknown integer value indicating an erroneous sub-expression
-SYNTAX_CLASS(ErrorIntVal, IntVal)
+class ErrorIntVal : public IntVal
+{
+ SLANG_CLASS(ErrorIntVal)
// TODO: We should probably eventually just have an `ErrorVal` here
// and have all `Val`s that represent ordinary values hold their
// `Type` so that we can have an `ErrorVal` of any type.
- RAW(
ErrorIntVal()
{}
@@ -56,8 +70,7 @@ SYNTAX_CLASS(ErrorIntVal, IntVal)
virtual String ToString() override;
virtual int GetHashCode() override;
virtual RefPtr<Val> SubstituteImpl(SubstitutionSet subst, int* ioDiff) override;
-)
-END_SYNTAX_CLASS()
+};
// A witness to the fact that some proposition is true, encoded
// at the level of the type system.
@@ -92,58 +105,72 @@ END_SYNTAX_CLASS()
// the concrete declarations that provide the implementation
// of `ILight` for `X`.
//
-ABSTRACT_SYNTAX_CLASS(Witness, Val)
-END_SYNTAX_CLASS()
+class Witness : public Val
+{
+ SLANG_ABSTRACT_CLASS(Witness)
+};
// A witness that one type is a subtype of another
// (where by "subtype" we include both inheritance
// relationships and type-conforms-to-interface relationships)
//
// TODO: we may need to tease those apart.
-ABSTRACT_SYNTAX_CLASS(SubtypeWitness, Witness)
- FIELD(RefPtr<Type>, sub)
- FIELD(RefPtr<Type>, sup)
-END_SYNTAX_CLASS()
+class SubtypeWitness : public Witness
+{
+ SLANG_ABSTRACT_CLASS(SubtypeWitness)
+
+ RefPtr<Type> sub;
+ RefPtr<Type> sup;
+};
+
+class TypeEqualityWitness : public SubtypeWitness
+{
+ SLANG_CLASS(TypeEqualityWitness)
+
-SYNTAX_CLASS(TypeEqualityWitness, SubtypeWitness)
-RAW(
virtual bool EqualsVal(Val* val) override;
virtual String ToString() override;
virtual int GetHashCode() override;
virtual RefPtr<Val> SubstituteImpl(SubstitutionSet subst, int * ioDiff) override;
-)
-END_SYNTAX_CLASS()
+};
+
// A witness that one type is a subtype of another
// because some in-scope declaration says so
-SYNTAX_CLASS(DeclaredSubtypeWitness, SubtypeWitness)
- FIELD(DeclRef<Decl>, declRef);
-RAW(
+class DeclaredSubtypeWitness : public SubtypeWitness
+{
+ SLANG_CLASS(DeclaredSubtypeWitness)
+
+ DeclRef<Decl> declRef;
+
virtual bool EqualsVal(Val* val) override;
virtual String ToString() override;
virtual int GetHashCode() override;
virtual RefPtr<Val> SubstituteImpl(SubstitutionSet subst, int * ioDiff) override;
-)
-END_SYNTAX_CLASS()
+};
// A witness that `sub : sup` because `sub : mid` and `mid : sup`
-SYNTAX_CLASS(TransitiveSubtypeWitness, SubtypeWitness)
+class TransitiveSubtypeWitness : public SubtypeWitness
+{
+ SLANG_CLASS(TransitiveSubtypeWitness)
+
// Witness that `sub : mid`
- FIELD(RefPtr<SubtypeWitness>, subToMid);
+ RefPtr<SubtypeWitness> subToMid;
// Witness that `mid : sup`
- FIELD(DeclRef<Decl>, midToSup);
-RAW(
+ DeclRef<Decl> midToSup;
+
virtual bool EqualsVal(Val* val) override;
virtual String ToString() override;
virtual int GetHashCode() override;
virtual RefPtr<Val> SubstituteImpl(SubstitutionSet subst, int * ioDiff) override;
-)
-END_SYNTAX_CLASS()
+};
// A witness taht `sub : sup` because `sub` was wrapped into
// an existential of type `sup`.
-SYNTAX_CLASS(ExtractExistentialSubtypeWitness, SubtypeWitness)
-RAW(
+class ExtractExistentialSubtypeWitness : public SubtypeWitness
+{
+ SLANG_CLASS(ExtractExistentialSubtypeWitness)
+
// The declaration of the existential value that has been opened
DeclRef<VarDeclBase> declRef;
@@ -151,15 +178,16 @@ RAW(
virtual String ToString() override;
virtual int GetHashCode() override;
virtual RefPtr<Val> SubstituteImpl(SubstitutionSet subst, int * ioDiff) override;
-)
-END_SYNTAX_CLASS()
+};
// A witness that `sub : sup`, because `sub` is a tagged union
// of the form `A | B | C | ...` and each of `A : sup`,
// `B : sup`, `C : sup`, etc.
//
-SYNTAX_CLASS(TaggedUnionSubtypeWitness, SubtypeWitness)
-RAW(
+class TaggedUnionSubtypeWitness : public SubtypeWitness
+{
+ SLANG_CLASS(TaggedUnionSubtypeWitness)
+
// Witnesses that each of the "case" types in the union
// is a subtype of `sup`.
//
@@ -169,5 +197,10 @@ RAW(
virtual String ToString() override;
virtual int GetHashCode() override;
virtual RefPtr<Val> SubstituteImpl(SubstitutionSet subst, int * ioDiff) override;
-)
-END_SYNTAX_CLASS()
+};
+
+
+#undef SLANG_ABSTRACT_CLASS
+#undef SLANG_CLASS
+
+} // namespace Slang
diff --git a/source/slang/slang-expr-defs.h b/source/slang/slang-expr-defs.h
deleted file mode 100644
index 725bbb62d..000000000
--- a/source/slang/slang-expr-defs.h
+++ /dev/null
@@ -1,216 +0,0 @@
-// slang-expr-defs.h
-
-// Syntax class definitions for expressions.
-
-
-// Base class for expressions that will reference declarations
-ABSTRACT_SYNTAX_CLASS(DeclRefExpr, Expr)
-
-// The scope in which to perform lookup
- FIELD(RefPtr<Scope>, scope)
-
- // The declaration of the symbol being referenced
- DECL_FIELD(DeclRef<Decl>, declRef)
-
- // The name of the symbol being referenced
- FIELD(Name*, name)
-END_SYNTAX_CLASS()
-
-SIMPLE_SYNTAX_CLASS(VarExpr, DeclRefExpr)
-
-// An expression that references an overloaded set of declarations
-// having the same name.
-SYNTAX_CLASS(OverloadedExpr, Expr)
- // The name that was looked up and found to be overloaded
- FIELD(Name*, name)
-
- // Optional: the base expression is this overloaded result
- // arose from a member-reference expression.
- SYNTAX_FIELD(RefPtr<Expr>, base)
-
- // The lookup result that was ambiguous
- FIELD(LookupResult, lookupResult2)
-END_SYNTAX_CLASS()
-
-// An expression that references an overloaded set of declarations
-// having the same name.
-SYNTAX_CLASS(OverloadedExpr2, Expr)
-
- // Optional: the base expression is this overloaded result
- // arose from a member-reference expression.
- SYNTAX_FIELD(RefPtr<Expr>, base)
-
- // The lookup result that was ambiguous
- FIELD(List<RefPtr<Expr>>, candidiateExprs)
-END_SYNTAX_CLASS()
-
-ABSTRACT_SYNTAX_CLASS(LiteralExpr, Expr)
- // The token that was used to express the literal. This can be
- // used to get the raw text of the literal, including any suffix.
- FIELD(Token, token)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(IntegerLiteralExpr, LiteralExpr)
- FIELD(IntegerLiteralValue, value)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(FloatingPointLiteralExpr, LiteralExpr)
- FIELD(FloatingPointLiteralValue, value)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(BoolLiteralExpr, LiteralExpr)
- FIELD(bool, value)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(StringLiteralExpr, LiteralExpr)
- // TODO: consider storing the "segments" of the string
- // literal, in the case where multiple literals were
- //lined up at the lexer level, e.g.:
- //
- // "first" "second" "third"
- //
- FIELD(String, value)
-END_SYNTAX_CLASS()
-
-// An initializer list, e.g. `{ 1, 2, 3 }`
-SYNTAX_CLASS(InitializerListExpr, Expr)
- SYNTAX_FIELD(List<RefPtr<Expr>>, args)
-END_SYNTAX_CLASS()
-
-// A base class for expressions with arguments
-ABSTRACT_SYNTAX_CLASS(ExprWithArgsBase, Expr)
- SYNTAX_FIELD(List<RefPtr<Expr>>, Arguments)
-END_SYNTAX_CLASS()
-
-// An aggregate type constructor
-SYNTAX_CLASS(AggTypeCtorExpr, ExprWithArgsBase)
- SYNTAX_FIELD(TypeExp, base);
-END_SYNTAX_CLASS()
-
-
-// A base expression being applied to arguments: covers
-// both ordinary `()` function calls and `<>` generic application
-ABSTRACT_SYNTAX_CLASS(AppExprBase, ExprWithArgsBase)
- SYNTAX_FIELD(RefPtr<Expr>, FunctionExpr)
-END_SYNTAX_CLASS()
-
-SIMPLE_SYNTAX_CLASS(InvokeExpr, AppExprBase)
-
-SIMPLE_SYNTAX_CLASS(OperatorExpr, InvokeExpr)
-
-SIMPLE_SYNTAX_CLASS(InfixExpr , OperatorExpr)
-SIMPLE_SYNTAX_CLASS(PrefixExpr , OperatorExpr)
-SIMPLE_SYNTAX_CLASS(PostfixExpr, OperatorExpr)
-
-SYNTAX_CLASS(IndexExpr, Expr)
- SYNTAX_FIELD(RefPtr<Expr>, BaseExpression)
- SYNTAX_FIELD(RefPtr<Expr>, IndexExpression)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(MemberExpr, DeclRefExpr)
- SYNTAX_FIELD(RefPtr<Expr>, BaseExpression)
-END_SYNTAX_CLASS()
-
-// Member looked up on a type, rather than a value
-SYNTAX_CLASS(StaticMemberExpr, DeclRefExpr)
- SYNTAX_FIELD(RefPtr<Expr>, BaseExpression)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(SwizzleExpr, Expr)
- SYNTAX_FIELD(RefPtr<Expr>, base)
- FIELD(int, elementCount)
- FIELD(int, elementIndices[4])
-END_SYNTAX_CLASS()
-
-// A dereference of a pointer or pointer-like type
-SYNTAX_CLASS(DerefExpr, Expr)
- SYNTAX_FIELD(RefPtr<Expr>, base)
-END_SYNTAX_CLASS()
-
-// Any operation that performs type-casting
-SYNTAX_CLASS(TypeCastExpr, InvokeExpr)
-// SYNTAX_FIELD(TypeExp, TargetType)
-// SYNTAX_FIELD(RefPtr<Expr>, Expression)
-END_SYNTAX_CLASS()
-
-// An explicit type-cast that appear in the user's code with `(type) expr` syntax
-SYNTAX_CLASS(ExplicitCastExpr, TypeCastExpr)
-END_SYNTAX_CLASS()
-
-// An implicit type-cast inserted during semantic checking
-SYNTAX_CLASS(ImplicitCastExpr, TypeCastExpr)
-END_SYNTAX_CLASS()
-
- /// A cast from a value to an interface ("existential") type.
-SYNTAX_CLASS(CastToInterfaceExpr, Expr)
-RAW(
- /// The value being cast to an interface type
- RefPtr<Expr> valueArg;
-
- /// A witness showing that `valueArg` conforms to the chosen interface
- RefPtr<Val> witnessArg;
-)
-END_SYNTAX_CLASS()
-
-SIMPLE_SYNTAX_CLASS(SelectExpr, OperatorExpr)
-
-SIMPLE_SYNTAX_CLASS(GenericAppExpr, AppExprBase)
-
-// An expression representing re-use of the syntax for a type in more
-// than once conceptually-distinct declaration
-SYNTAX_CLASS(SharedTypeExpr, Expr)
- // The underlying type expression that we want to share
- SYNTAX_FIELD(TypeExp, base)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(AssignExpr, Expr)
- SYNTAX_FIELD(RefPtr<Expr>, left);
- SYNTAX_FIELD(RefPtr<Expr>, right);
-END_SYNTAX_CLASS()
-
-// Just an expression inside parentheses `(exp)`
-//
-// We keep this around explicitly to be sure we don't lose any structure
-// when we do rewriter stuff.
-SYNTAX_CLASS(ParenExpr, Expr)
- SYNTAX_FIELD(RefPtr<Expr>, base);
-END_SYNTAX_CLASS()
-
-// An object-oriented `this` expression, used to
-// refer to the current instance of an enclosing type.
-SYNTAX_CLASS(ThisExpr, Expr)
- FIELD(RefPtr<Scope>, scope);
-END_SYNTAX_CLASS()
-
-// An expression that binds a temporary variable in a local expression context
-SYNTAX_CLASS(LetExpr, Expr)
-RAW(
- RefPtr<VarDecl> decl;
- RefPtr<Expr> body;
-)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(ExtractExistentialValueExpr, Expr)
-RAW(
- DeclRef<VarDeclBase> declRef;
-)
-END_SYNTAX_CLASS()
-
- /// A type expression of the form `__TaggedUnion(A, ...)`.
- ///
- /// An expression of this form will resolve to a `TaggedUnionType`
- /// when checked.
- ///
-SYNTAX_CLASS(TaggedUnionTypeExpr, Expr)
-RAW(
- List<TypeExp> caseTypes;
-)
-END_SYNTAX_CLASS()
-
- /// A type expression of the form `This`
- ///
- /// Refers to the type of `this` in the current context.
- ///
-SYNTAX_CLASS(ThisTypeExpr, Expr)
- FIELD(RefPtr<Scope>, scope);
-END_SYNTAX_CLASS()
diff --git a/source/slang/slang-modifier-defs.h b/source/slang/slang-modifier-defs.h
deleted file mode 100644
index 0c7156c72..000000000
--- a/source/slang/slang-modifier-defs.h
+++ /dev/null
@@ -1,495 +0,0 @@
-// slang-modifier-defs.h
-
-// Syntax class definitions for modifiers.
-
-// Simple modifiers have no state beyond their identity
-#define SIMPLE_MODIFIER(NAME) \
- SIMPLE_SYNTAX_CLASS(NAME##Modifier, Modifier)
-
-SIMPLE_MODIFIER(In);
-SIMPLE_MODIFIER(Out);
-SIMPLE_MODIFIER(Const);
-SIMPLE_MODIFIER(Instance);
-SIMPLE_MODIFIER(Builtin);
-SIMPLE_MODIFIER(Inline);
-SIMPLE_MODIFIER(Public);
-SIMPLE_MODIFIER(Require);
-SIMPLE_MODIFIER(Param);
-SIMPLE_MODIFIER(Extern);
-SIMPLE_MODIFIER(Input);
-SIMPLE_MODIFIER(Transparent);
-SIMPLE_MODIFIER(FromStdLib);
-SIMPLE_MODIFIER(Prefix);
-SIMPLE_MODIFIER(Postfix);
-SIMPLE_MODIFIER(Exported);
-SIMPLE_MODIFIER(ConstExpr);
-SIMPLE_MODIFIER(GloballyCoherent)
-
-#undef SIMPLE_MODIFIER
-
-// A modifier that marks something as an operation that
-// has a one-to-one translation to the IR, and thus
-// has no direct definition in the high-level language.
-//
-SYNTAX_CLASS(IntrinsicOpModifier, Modifier)
-
- // Token that names the intrinsic op.
- FIELD(Token, opToken)
-
- // The IR opcode for the intrinsic operation.
- //
- FIELD_INIT(uint32_t, op, 0)
-END_SYNTAX_CLASS()
-
-// A modifier that marks something as an intrinsic function,
-// for some subset of targets.
-SYNTAX_CLASS(TargetIntrinsicModifier, Modifier)
- // Token that names the target that the operation
- // is an intrisic for.
- FIELD(Token, targetToken)
-
- // A custom definition for the operation
- FIELD(Token, definitionToken)
-END_SYNTAX_CLASS()
-
-// A modifier that marks a declaration as representing a
-// specialization that should be preferred on a particular
-// target.
-SYNTAX_CLASS(SpecializedForTargetModifier, Modifier)
- // Token that names the target that the operation
- // has been specialized for.
- FIELD(Token, targetToken)
-END_SYNTAX_CLASS()
-
-// A modifier to tag something as an intrinsic that requires
-// a certain GLSL extension to be enabled when used
-SYNTAX_CLASS(RequiredGLSLExtensionModifier, Modifier)
-FIELD(Token, extensionNameToken)
-END_SYNTAX_CLASS()
-
-// A modifier to tag something as an intrinsic that requires
-// a certain GLSL version to be enabled when used
-SYNTAX_CLASS(RequiredGLSLVersionModifier, Modifier)
-FIELD(Token, versionNumberToken)
-END_SYNTAX_CLASS()
-
-
-// A modifier to tag something as an intrinsic that requires
-// a certain SPIRV version to be enabled when used. Specified as "major.minor"
-SYNTAX_CLASS(RequiredSPIRVVersionModifier, Modifier)
-FIELD(SemanticVersion, version)
-END_SYNTAX_CLASS()
-
-// A modifier to tag something as an intrinsic that requires
-// a certain CUDA SM version to be enabled when used. Specified as "major.minor"
-SYNTAX_CLASS(RequiredCUDASMVersionModifier, Modifier)
-FIELD(SemanticVersion, version)
-END_SYNTAX_CLASS()
-
-SIMPLE_SYNTAX_CLASS(InOutModifier, OutModifier)
-
-// `__ref` modifier for by-reference parameter passing
-SIMPLE_SYNTAX_CLASS(RefModifier, Modifier)
-
-// This is a special sentinel modifier that gets added
-// to the list when we have multiple variable declarations
-// all sharing the same modifiers:
-//
-// static uniform int a : FOO, *b : register(x0);
-//
-// In this case both `a` and `b` share the syntax
-// for part of their modifier list, but then have
-// their own modifiers as well:
-//
-// a: SemanticModifier("FOO") --> SharedModifiers --> StaticModifier --> UniformModifier
-// /
-// b: RegisterModifier("x0") /
-//
-SIMPLE_SYNTAX_CLASS(SharedModifiers, Modifier)
-
-// A GLSL `layout` modifier
-//
-// We use a distinct modifier for each key that
-// appears within the `layout(...)` construct,
-// and each key might have an optional value token.
-//
-// TODO: We probably want a notion of "modifier groups"
-// so that we can recover good source location info
-// for modifiers that were part of the same vs.
-// different constructs.
-ABSTRACT_SYNTAX_CLASS(GLSLLayoutModifier, Modifier)
-
-// The token used to introduce the modifier is stored
-// as the `nameToken` field.
-
-// TODO: may want to accept a full expression here
-FIELD(Token, valToken)
-END_SYNTAX_CLASS()
-
-// AST nodes to represent the begin/end of a `layout` modifier group
-ABSTRACT_SYNTAX_CLASS(GLSLLayoutModifierGroupMarker, Modifier)
-END_SYNTAX_CLASS()
-SIMPLE_SYNTAX_CLASS(GLSLLayoutModifierGroupBegin, GLSLLayoutModifierGroupMarker)
-SIMPLE_SYNTAX_CLASS(GLSLLayoutModifierGroupEnd, GLSLLayoutModifierGroupMarker)
-
-// We divide GLSL `layout` modifiers into those we have parsed
-// (in the sense of having some notion of their semantics), and
-// those we have not.
-ABSTRACT_SYNTAX_CLASS(GLSLParsedLayoutModifier , GLSLLayoutModifier)
-END_SYNTAX_CLASS()
-
-SIMPLE_SYNTAX_CLASS(GLSLUnparsedLayoutModifier , GLSLLayoutModifier)
-
-// Specific cases for known GLSL `layout` modifiers that we need to work with
-SIMPLE_SYNTAX_CLASS(GLSLConstantIDLayoutModifier , GLSLParsedLayoutModifier)
-SIMPLE_SYNTAX_CLASS(GLSLLocationLayoutModifier , GLSLParsedLayoutModifier)
-
-// A catch-all for single-keyword modifiers
-SIMPLE_SYNTAX_CLASS(SimpleModifier, Modifier)
-
-// Some GLSL-specific modifiers
-SIMPLE_SYNTAX_CLASS(GLSLBufferModifier , SimpleModifier)
-SIMPLE_SYNTAX_CLASS(GLSLWriteOnlyModifier, SimpleModifier)
-SIMPLE_SYNTAX_CLASS(GLSLReadOnlyModifier , SimpleModifier)
-SIMPLE_SYNTAX_CLASS(GLSLPatchModifier , SimpleModifier)
-
-// Indicates that this is a variable declaration that corresponds to
-// a parameter block declaration in the source program.
-SIMPLE_SYNTAX_CLASS(ImplicitParameterGroupVariableModifier , Modifier)
-
-// Indicates that this is a type that corresponds to the element
-// type of a parameter block declaration in the source program.
-SIMPLE_SYNTAX_CLASS(ImplicitParameterGroupElementTypeModifier, Modifier)
-
-// An HLSL semantic
-ABSTRACT_SYNTAX_CLASS(HLSLSemantic, Modifier)
- FIELD(Token, name)
-END_SYNTAX_CLASS()
-
-// An HLSL semantic that affects layout
-SYNTAX_CLASS(HLSLLayoutSemantic, HLSLSemantic)
-
- FIELD(Token, registerName)
- FIELD(Token, componentMask)
-END_SYNTAX_CLASS()
-
-// An HLSL `register` semantic
-SYNTAX_CLASS(HLSLRegisterSemantic, HLSLLayoutSemantic)
- FIELD(Token, spaceName)
-END_SYNTAX_CLASS()
-
-// TODO(tfoley): `packoffset`
-SIMPLE_SYNTAX_CLASS(HLSLPackOffsetSemantic, HLSLLayoutSemantic)
-
-// An HLSL semantic that just associated a declaration with a semantic name
-SIMPLE_SYNTAX_CLASS(HLSLSimpleSemantic, HLSLSemantic)
-
-// GLSL
-
-// Directives that came in via the preprocessor, but
-// that we need to keep around for later steps
-SIMPLE_SYNTAX_CLASS(GLSLPreprocessorDirective, Modifier)
-
-// A GLSL `#version` directive
-SYNTAX_CLASS(GLSLVersionDirective, GLSLPreprocessorDirective)
-
- // Token giving the version number to use
- FIELD(Token, versionNumberToken)
-
- // Optional token giving the sub-profile to be used
- FIELD(Token, glslProfileToken)
-END_SYNTAX_CLASS()
-
-// A GLSL `#extension` directive
-SYNTAX_CLASS(GLSLExtensionDirective, GLSLPreprocessorDirective)
-
- // Token giving the version number to use
- FIELD(Token, extensionNameToken)
-
- // Optional token giving the sub-profile to be used
- FIELD(Token, dispositionToken)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(ParameterGroupReflectionName, Modifier)
- FIELD(NameLoc, nameAndLoc)
-END_SYNTAX_CLASS()
-
-// A modifier that indicates a built-in base type (e.g., `float`)
-SYNTAX_CLASS(BuiltinTypeModifier, Modifier)
- FIELD(BaseType, tag)
-END_SYNTAX_CLASS()
-
-// A modifier that indicates a built-in type that isn't a base type (e.g., `vector`)
-//
-// TODO(tfoley): This deserves a better name than "magic"
-SYNTAX_CLASS(MagicTypeModifier, Modifier)
- FIELD(String, name)
- FIELD(uint32_t, tag)
-END_SYNTAX_CLASS()
-
-// A modifier applied to declarations of builtin types to indicate how they
-// should be lowered to the IR.
-//
-// TODO: This should really subsume `BuiltinTypeModifier` and
-// `MagicTypeModifier` so that we don't have to apply all of them.
-SYNTAX_CLASS(IntrinsicTypeModifier, Modifier)
- // The IR opcode to use when constructing a type
- FIELD(uint32_t, irOp)
-
- // Additional literal opreands to provide when creating instances.
- // (e.g., for a texture type this passes in shape/mutability info)
- FIELD(List<uint32_t>, irOperands)
-END_SYNTAX_CLASS()
-
-// Modifiers that affect the storage layout for matrices
-SIMPLE_SYNTAX_CLASS(MatrixLayoutModifier, Modifier)
-
-// Modifiers that specify row- and column-major layout, respectively
-SIMPLE_SYNTAX_CLASS(RowMajorLayoutModifier, MatrixLayoutModifier)
-SIMPLE_SYNTAX_CLASS(ColumnMajorLayoutModifier, MatrixLayoutModifier)
-
-// The HLSL flavor of those modifiers
-SIMPLE_SYNTAX_CLASS(HLSLRowMajorLayoutModifier, RowMajorLayoutModifier)
-SIMPLE_SYNTAX_CLASS(HLSLColumnMajorLayoutModifier, ColumnMajorLayoutModifier)
-
-// The GLSL flavor of those modifiers
-//
-// Note(tfoley): The GLSL versions of these modifiers are "backwards"
-// in the sense that when a GLSL programmer requests row-major layout,
-// we actually interpret that as requesting column-major. This makes
-// sense because we interpret matrix conventions backwards from how
-// GLSL specifies them.
-SIMPLE_SYNTAX_CLASS(GLSLRowMajorLayoutModifier, ColumnMajorLayoutModifier)
-SIMPLE_SYNTAX_CLASS(GLSLColumnMajorLayoutModifier, RowMajorLayoutModifier)
-
-// More HLSL Keyword
-
-ABSTRACT_SYNTAX_CLASS(InterpolationModeModifier, Modifier)
-END_SYNTAX_CLASS()
-
-// HLSL `nointerpolation` modifier
-SIMPLE_SYNTAX_CLASS(HLSLNoInterpolationModifier, InterpolationModeModifier)
-
-// HLSL `noperspective` modifier
-SIMPLE_SYNTAX_CLASS(HLSLNoPerspectiveModifier, InterpolationModeModifier)
-
-// HLSL `linear` modifier
-SIMPLE_SYNTAX_CLASS(HLSLLinearModifier, InterpolationModeModifier)
-
-// HLSL `sample` modifier
-SIMPLE_SYNTAX_CLASS(HLSLSampleModifier, InterpolationModeModifier)
-
-// HLSL `centroid` modifier
-SIMPLE_SYNTAX_CLASS(HLSLCentroidModifier, InterpolationModeModifier)
-
-// HLSL `precise` modifier
-SIMPLE_SYNTAX_CLASS(PreciseModifier, Modifier)
-
-// HLSL `shared` modifier (which is used by the effect system,
-// and shouldn't be confused with `groupshared`)
-SIMPLE_SYNTAX_CLASS(HLSLEffectSharedModifier, Modifier)
-
-// HLSL `groupshared` modifier
-SIMPLE_SYNTAX_CLASS(HLSLGroupSharedModifier, Modifier)
-
-// HLSL `static` modifier (probably doesn't need to be
-// treated as HLSL-specific)
-SIMPLE_SYNTAX_CLASS(HLSLStaticModifier, Modifier)
-
-// HLSL `uniform` modifier (distinct meaning from GLSL
-// use of the keyword)
-SIMPLE_SYNTAX_CLASS(HLSLUniformModifier, Modifier)
-
-// HLSL `volatile` modifier (ignored)
-SIMPLE_SYNTAX_CLASS(HLSLVolatileModifier, Modifier)
-
-SYNTAX_CLASS(AttributeTargetModifier, Modifier)
- // A class to which the declared attribute type is applicable
- FIELD(SyntaxClass<RefObject>, syntaxClass)
-END_SYNTAX_CLASS()
-
-// Base class for checked and unchecked `[name(arg0, ...)]` style attribute.
-SYNTAX_CLASS(AttributeBase, Modifier)
- SYNTAX_FIELD(List<RefPtr<Expr>>, args)
-END_SYNTAX_CLASS()
-
-// A `[name(...)]` attribute that hasn't undergone any semantic analysis.
-// After analysis, this will be transformed into a more specific case.
-SYNTAX_CLASS(UncheckedAttribute, AttributeBase)
- FIELD(RefPtr<Scope>, scope)
-END_SYNTAX_CLASS()
-
-// A `[name(arg0, ...)]` style attribute that has been validated.
-SYNTAX_CLASS(Attribute, AttributeBase)
- FIELD(AttributeArgumentValueDict, intArgVals)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(UserDefinedAttribute, Attribute)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(AttributeUsageAttribute, Attribute)
- FIELD(SyntaxClass<RefObject>, targetSyntaxClass)
-END_SYNTAX_CLASS()
-
-// An `[unroll]` or `[unroll(count)]` attribute
-SYNTAX_CLASS(UnrollAttribute, Attribute)
- RAW(IntegerLiteralValue getCount();)
-END_SYNTAX_CLASS()
-
-SIMPLE_SYNTAX_CLASS(LoopAttribute, Attribute) // `[loop]`
-SIMPLE_SYNTAX_CLASS(FastOptAttribute, Attribute) // `[fastopt]`
-SIMPLE_SYNTAX_CLASS(AllowUAVConditionAttribute, Attribute) // `[allow_uav_condition]`
-SIMPLE_SYNTAX_CLASS(BranchAttribute, Attribute) // `[branch]`
-SIMPLE_SYNTAX_CLASS(FlattenAttribute, Attribute) // `[flatten]`
-SIMPLE_SYNTAX_CLASS(ForceCaseAttribute, Attribute) // `[forcecase]`
-SIMPLE_SYNTAX_CLASS(CallAttribute, Attribute) // `[call]`
-
-
-// [[vk_push_constant]] [[push_constant]]
-SIMPLE_SYNTAX_CLASS(PushConstantAttribute, Attribute)
-
-// [[vk_shader_record]] [[shader_record]]
-SIMPLE_SYNTAX_CLASS(ShaderRecordAttribute, Attribute)
-
-// [[vk_binding]]
-SYNTAX_CLASS(GLSLBindingAttribute, Attribute)
- FIELD(int32_t, binding = 0)
- FIELD(int32_t, set = 0)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(GLSLSimpleIntegerLayoutAttribute, Attribute)
- FIELD(int32_t, value = 0)
-END_SYNTAX_CLASS()
-
-// [[vk_location]]
-SIMPLE_SYNTAX_CLASS(GLSLLocationAttribute, GLSLSimpleIntegerLayoutAttribute)
-
-// [[vk_index]]
-SIMPLE_SYNTAX_CLASS(GLSLIndexAttribute, GLSLSimpleIntegerLayoutAttribute)
-
-// TODO: for attributes that take arguments, the syntax node
-// classes should provide accessors for the values of those arguments.
-
-SIMPLE_SYNTAX_CLASS(MaxTessFactorAttribute, Attribute)
-SIMPLE_SYNTAX_CLASS(OutputControlPointsAttribute, Attribute)
-SIMPLE_SYNTAX_CLASS(OutputTopologyAttribute, Attribute)
-SIMPLE_SYNTAX_CLASS(PartitioningAttribute, Attribute)
-SYNTAX_CLASS(PatchConstantFuncAttribute, Attribute)
- FIELD(RefPtr<FuncDecl>, patchConstantFuncDecl)
-END_SYNTAX_CLASS()
-SIMPLE_SYNTAX_CLASS(DomainAttribute, Attribute)
-
-SIMPLE_SYNTAX_CLASS(EarlyDepthStencilAttribute, Attribute) // `[earlydepthstencil]`
-
-// An HLSL `[numthreads(x,y,z)]` attribute
-SYNTAX_CLASS(NumThreadsAttribute, Attribute)
- // The number of threads to use along each axis
- //
- // TODO: These should be accessors that use the
- // ordinary `args` list, rather than side data.
- FIELD(int32_t, x)
- FIELD(int32_t, y)
- FIELD(int32_t, z)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(MaxVertexCountAttribute, Attribute)
- // The number of max vertex count for geometry shader
- //
- // TODO: This should be an accessor that uses the
- // ordinary `args` list, rather than side data.
- FIELD(int32_t, value)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(InstanceAttribute, Attribute)
- // The number of instances to run for geometry shader
- //
- // TODO: This should be an accessor that uses the
- // ordinary `args` list, rather than side data.
- FIELD(int32_t, value)
-END_SYNTAX_CLASS()
-
-// A `[shader("stageName")]` attribute, which marks an entry point
-// to be compiled, and specifies the stage for that entry point
-SYNTAX_CLASS(EntryPointAttribute, Attribute)
- // The resolved stage that the entry point is targetting.
- //
- // TODO: This should be an accessor that uses the
- // ordinary `args` list, rather than side data.
- FIELD(Stage, stage);
-END_SYNTAX_CLASS()
-
-// A `[__vulkanRayPayload]` attribute, which is used in the
-// standard library implementation to indicate that a variable
-// actually represents the input/output interface for a Vulkan
-// ray tracing shader to pass per-ray payload information.
-SIMPLE_SYNTAX_CLASS(VulkanRayPayloadAttribute, Attribute)
-
-// A `[__vulkanCallablePayload]` attribute, which is used in the
-// standard library implementation to indicate that a variable
-// actually represents the input/output interface for a Vulkan
-// ray tracing shader to pass payload information to/from a callee.
-SIMPLE_SYNTAX_CLASS(VulkanCallablePayloadAttribute, Attribute)
-
-// A `[__vulkanHitAttributes]` attribute, which is used in the
-// standard library implementation to indicate that a variable
-// actually represents the output interface for a Vulkan
-// intersection shader to pass hit attribute information.
-SIMPLE_SYNTAX_CLASS(VulkanHitAttributesAttribute, Attribute)
-
-// A `[mutating]` attribute, which indicates that a member
-// function is allowed to modify things through its `this`
-// argument.
-//
-SIMPLE_SYNTAX_CLASS(MutatingAttribute, Attribute)
-
-// A `[__readNone]` attribute, which indicates that a function
-// computes its results strictly based on argument values, without
-// reading or writing through any pointer arguments, or any other
-// state that could be observed by a caller.
-//
-SIMPLE_SYNTAX_CLASS(ReadNoneAttribute, Attribute)
-
-
-// HLSL modifiers for geometry shader input topology
-SIMPLE_SYNTAX_CLASS(HLSLGeometryShaderInputPrimitiveTypeModifier, Modifier)
-SIMPLE_SYNTAX_CLASS(HLSLPointModifier , HLSLGeometryShaderInputPrimitiveTypeModifier)
-SIMPLE_SYNTAX_CLASS(HLSLLineModifier , HLSLGeometryShaderInputPrimitiveTypeModifier)
-SIMPLE_SYNTAX_CLASS(HLSLTriangleModifier , HLSLGeometryShaderInputPrimitiveTypeModifier)
-SIMPLE_SYNTAX_CLASS(HLSLLineAdjModifier , HLSLGeometryShaderInputPrimitiveTypeModifier)
-SIMPLE_SYNTAX_CLASS(HLSLTriangleAdjModifier , HLSLGeometryShaderInputPrimitiveTypeModifier)
-
-// A modifier to be attached to syntax after we've computed layout
-SYNTAX_CLASS(ComputedLayoutModifier, Modifier)
- FIELD(RefPtr<Layout>, layout)
-END_SYNTAX_CLASS()
-
-
-SYNTAX_CLASS(TupleVarModifier, Modifier)
-// FIELD_INIT(TupleFieldModifier*, tupleField, nullptr)
-END_SYNTAX_CLASS()
-
-// A modifier to indicate that a constructor/initializer can be used
-// to perform implicit type conversion, and to specify the cost of
-// the conversion, if applied.
-SYNTAX_CLASS(ImplicitConversionModifier, Modifier)
- // The conversion cost, used to rank conversions
- FIELD(ConversionCost, cost)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(FormatAttribute, Attribute)
- FIELD(ImageFormat, format)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(AllowAttribute, Attribute)
- FIELD_INIT(DiagnosticInfo const*, diagnostic, nullptr)
-END_SYNTAX_CLASS()
-
-
-// A `[__extern]` attribute, which indicates that a function/type is defined externally
-//
-SIMPLE_SYNTAX_CLASS(ExternAttribute, Attribute)
-
-// An `[__unsafeForceInlineExternal]` attribute indicates that the callee should be inlined
-// into call sites after initial IR generation (that is, as early as possible).
-//
-SIMPLE_SYNTAX_CLASS(UnsafeForceInlineEarlyAttribute, Attribute)
diff --git a/source/slang/slang-object-meta-begin.h b/source/slang/slang-object-meta-begin.h
deleted file mode 100644
index 9c09e845d..000000000
--- a/source/slang/slang-object-meta-begin.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// slang-object-meta-begin.h
-
-#ifndef SYNTAX_CLASS
-#error The 'SYNTAX_CLASS' macro should be defined before including 'object-meta-begin.h'
-#endif
-
-#ifndef ABSTRACT_SYNTAX_CLASS
-#define ABSTRACT_SYNTAX_CLASS(NAME, BASE) SYNTAX_CLASS(NAME, BASE)
-#endif
-
-#ifndef END_SYNTAX_CLASS
-#define END_SYNTAX_CLASS() /* empty */
-#endif
-
-#ifndef DECL_FIELD
-#define DECL_FIELD(TYPE, NAME) SYNTAX_FIELD(TYPE, NAME)
-#endif
-
-#ifndef SYNTAX_FIELD
-#define SYNTAX_FIELD(TYPE, NAME) FIELD(TYPE, NAME)
-#endif
-
-#ifndef FIELD_INIT
-#define FIELD_INIT(TYPE, NAME, INIT) FIELD(TYPE, NAME)
-#endif
-
-#ifndef FIELD
-#define FIELD(...) /* empty */
-#endif
-
-#ifndef RAW
-#define RAW(...) /* empty */
-#endif
-
-#define SIMPLE_SYNTAX_CLASS(NAME, BASE) SYNTAX_CLASS(NAME, BASE) END_SYNTAX_CLASS()
-
-// Hack to remove 'warning C4702: unreachable code' on VS2017, blocking compilation
-// Note! This is matched in object-meta-end.h
-#if _MSC_VER >= 1910
-#pragma warning(push)
-#pragma warning(disable: 4702)
-#endif
-
diff --git a/source/slang/slang-object-meta-end.h b/source/slang/slang-object-meta-end.h
deleted file mode 100644
index 5018b5ede..000000000
--- a/source/slang/slang-object-meta-end.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// slang-object-meta-end.h
-
-#undef SYNTAX_CLASS
-#undef ABSTRACT_SYNTAX_CLASS
-#undef END_SYNTAX_CLASS
-#undef SYNTAX_FIELD
-#undef FIELD
-#undef FIELD_INIT
-#undef DECL_FIELD
-#undef RAW
-#undef SIMPLE_SYNTAX_CLASS
-
-// Hack to remove 'warning C4702: unreachable code' on VS2017, blocking compilation
-// Note! This is matched in object-meta-begin.h
-#if _MSC_VER >= 1910
-#pragma warning(pop)
-#endif
diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp
index d8b0d9463..cdd573a97 100644
--- a/source/slang/slang-parser.cpp
+++ b/source/slang/slang-parser.cpp
@@ -2833,7 +2833,7 @@ namespace Slang
// the class of AST node to construct.
static RefPtr<RefObject> parseSimpleSyntax(Parser* /*parser*/, void* userData)
{
- SyntaxClassBase syntaxClass((SyntaxClassBase::ClassInfo*) userData);
+ SyntaxClassBase syntaxClass((ReflectClassInfo*) userData);
return (RefObject*) syntaxClass.createInstanceImpl();
}
diff --git a/source/slang/slang-stmt-defs.h b/source/slang/slang-stmt-defs.h
deleted file mode 100644
index bf25f1706..000000000
--- a/source/slang/slang-stmt-defs.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// slang-stmt-defs.h
-
-// Syntax class definitions for statements.
-
-ABSTRACT_SYNTAX_CLASS(ScopeStmt, Stmt)
- SYNTAX_FIELD(RefPtr<ScopeDecl>, scopeDecl)
-END_SYNTAX_CLASS()
-
-// A sequence of statements, treated as a single statement
-SYNTAX_CLASS(SeqStmt, Stmt)
- SYNTAX_FIELD(List<RefPtr<Stmt>>, stmts)
-END_SYNTAX_CLASS()
-
-// The simplest kind of scope statement: just a `{...}` block
-SYNTAX_CLASS(BlockStmt, ScopeStmt)
- SYNTAX_FIELD(RefPtr<Stmt>, body);
-END_SYNTAX_CLASS()
-
-// A statement that we aren't going to parse or check, because
-// we want to let a downstream compiler handle any issues
-SYNTAX_CLASS(UnparsedStmt, Stmt)
- // The tokens that were contained between `{` and `}`
- FIELD(List<Token>, tokens)
-END_SYNTAX_CLASS()
-
-SIMPLE_SYNTAX_CLASS(EmptyStmt, Stmt)
-
-SIMPLE_SYNTAX_CLASS(DiscardStmt, Stmt)
-
-SYNTAX_CLASS(DeclStmt, Stmt)
- SYNTAX_FIELD(RefPtr<DeclBase>, decl)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(IfStmt, Stmt)
- SYNTAX_FIELD(RefPtr<Expr>, Predicate)
- SYNTAX_FIELD(RefPtr<Stmt>, PositiveStatement)
- SYNTAX_FIELD(RefPtr<Stmt>, NegativeStatement)
-END_SYNTAX_CLASS()
-
-// A statement that can be escaped with a `break`
-ABSTRACT_SYNTAX_CLASS(BreakableStmt, ScopeStmt)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(SwitchStmt, BreakableStmt)
- SYNTAX_FIELD(RefPtr<Expr>, condition)
- SYNTAX_FIELD(RefPtr<Stmt>, body)
-END_SYNTAX_CLASS()
-
-// A statement that is expected to appear lexically nested inside
-// some other construct, and thus needs to keep track of the
-// outer statement that it is associated with...
-ABSTRACT_SYNTAX_CLASS(ChildStmt, Stmt)
- DECL_FIELD(Stmt*, parentStmt RAW(= nullptr))
-END_SYNTAX_CLASS()
-
-// a `case` or `default` statement inside a `switch`
-//
-// Note(tfoley): A correct AST for a C-like language would treat
-// these as a labelled statement, and so they would contain a
-// sub-statement. I'm leaving that out for now for simplicity.
-ABSTRACT_SYNTAX_CLASS(CaseStmtBase, ChildStmt)
-END_SYNTAX_CLASS()
-
-// a `case` statement inside a `switch`
-SYNTAX_CLASS(CaseStmt, CaseStmtBase)
- SYNTAX_FIELD(RefPtr<Expr>, expr)
-END_SYNTAX_CLASS()
-
-// a `default` statement inside a `switch`
-SIMPLE_SYNTAX_CLASS(DefaultStmt, CaseStmtBase)
-
-// A statement that represents a loop, and can thus be escaped with a `continue`
-ABSTRACT_SYNTAX_CLASS(LoopStmt, BreakableStmt)
-END_SYNTAX_CLASS()
-
-// A `for` statement
-SYNTAX_CLASS(ForStmt, LoopStmt)
- SYNTAX_FIELD(RefPtr<Stmt>, InitialStatement)
- SYNTAX_FIELD(RefPtr<Expr>, SideEffectExpression)
- SYNTAX_FIELD(RefPtr<Expr>, PredicateExpression)
- SYNTAX_FIELD(RefPtr<Stmt>, Statement)
-END_SYNTAX_CLASS()
-
-// A `for` statement in a language that doesn't restrict the scope
-// of the loop variable to the body.
-SYNTAX_CLASS(UnscopedForStmt, ForStmt);
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(WhileStmt, LoopStmt)
- SYNTAX_FIELD(RefPtr<Expr>, Predicate)
- SYNTAX_FIELD(RefPtr<Stmt>, Statement)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(DoWhileStmt, LoopStmt)
- SYNTAX_FIELD(RefPtr<Stmt>, Statement)
- SYNTAX_FIELD(RefPtr<Expr>, Predicate)
-END_SYNTAX_CLASS()
-
-// A compile-time, range-based `for` loop, which will not appear in the output code
-SYNTAX_CLASS(CompileTimeForStmt, ScopeStmt)
- SYNTAX_FIELD(RefPtr<VarDecl>, varDecl)
- SYNTAX_FIELD(RefPtr<Expr>, rangeBeginExpr)
- SYNTAX_FIELD(RefPtr<Expr>, rangeEndExpr)
- SYNTAX_FIELD(RefPtr<Stmt>, body)
- SYNTAX_FIELD(RefPtr<IntVal>, rangeBeginVal)
- SYNTAX_FIELD(RefPtr<IntVal>, rangeEndVal)
-END_SYNTAX_CLASS()
-
-// The case of child statements that do control flow relative
-// to their parent statement.
-ABSTRACT_SYNTAX_CLASS(JumpStmt, ChildStmt)
-END_SYNTAX_CLASS()
-
-SIMPLE_SYNTAX_CLASS(BreakStmt, JumpStmt)
-
-SIMPLE_SYNTAX_CLASS(ContinueStmt, JumpStmt)
-
-SYNTAX_CLASS(ReturnStmt, Stmt)
- SYNTAX_FIELD(RefPtr<Expr>, Expression)
-END_SYNTAX_CLASS()
-
-SYNTAX_CLASS(ExpressionStmt, Stmt)
- SYNTAX_FIELD(RefPtr<Expr>, Expression)
-END_SYNTAX_CLASS()
diff --git a/source/slang/slang-syntax-defs.h b/source/slang/slang-syntax-defs.h
deleted file mode 100644
index 5a16c3709..000000000
--- a/source/slang/slang-syntax-defs.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// slang-syntax-defs.h
-
-#include "slang-syntax-base-defs.h"
-
-#include "slang-expr-defs.h"
-#include "slang-decl-defs.h"
-#include "slang-modifier-defs.h"
-#include "slang-stmt-defs.h"
-#include "slang-type-defs.h"
-#include "slang-val-defs.h"
diff --git a/source/slang/slang-syntax.cpp b/source/slang/slang-syntax.cpp
index 2055c2422..cb75622bc 100644
--- a/source/slang/slang-syntax.cpp
+++ b/source/slang/slang-syntax.cpp
@@ -8,182 +8,11 @@
namespace Slang
{
- // We want this first, before the kClassInfo variables so it is constructed before anything else.
- /* static*/ SyntaxClassBase::ClassInfo* SyntaxClassBase::ClassInfo::s_first = nullptr;
- // BasicExpressionType
-
- bool BasicExpressionType::EqualsImpl(Type * type)
- {
- auto basicType = as<BasicExpressionType>(type);
- return basicType && basicType->baseType == this->baseType;
- }
-
- RefPtr<Type> BasicExpressionType::CreateCanonicalType()
- {
- // A basic type is already canonical, in our setup
- return this;
- }
-
- // Generate dispatch logic and other definitions for all syntax classes
-#define SYNTAX_CLASS(NAME, BASE) /* empty */
-#include "slang-object-meta-begin.h"
-
-#include "slang-syntax-base-defs.h"
-#undef SYNTAX_CLASS
-#undef ABSTRACT_SYNTAX_CLASS
-
-#define ABSTRACT_SYNTAX_CLASS(NAME, BASE) \
- template<> \
- SyntaxClassBase::ClassInfo const SyntaxClassBase::Impl<NAME>::kClassInfo(#NAME, nullptr, &SyntaxClassBase::Impl<BASE>::kClassInfo);
-
-#define SYNTAX_CLASS(NAME, BASE) \
- template<> \
- void* SyntaxClassBase::Impl<NAME>::createFunc() { return new NAME(); } \
- template<> \
- SyntaxClassBase::ClassInfo const SyntaxClassBase::Impl<NAME>::kClassInfo( #NAME, &SyntaxClassBase::Impl<NAME>::createFunc, &SyntaxClassBase::Impl<BASE>::kClassInfo); \
- void NAME::accept(NAME::Visitor* visitor, void* extra) \
- { visitor->dispatch_##NAME(this, extra); } \
- const SyntaxClassBase::ClassInfo& NAME::getClassInfo() const { return SyntaxClassBase::Impl<NAME>::kClassInfo; }
-
-template<>
-SyntaxClassBase::ClassInfo const SyntaxClassBase::Impl<RefObject>::kClassInfo("RefObject", nullptr, nullptr);
-
-ABSTRACT_SYNTAX_CLASS(NodeBase, RefObject);
-ABSTRACT_SYNTAX_CLASS(SyntaxNodeBase, NodeBase);
-ABSTRACT_SYNTAX_CLASS(SyntaxNode, SyntaxNodeBase);
-ABSTRACT_SYNTAX_CLASS(ModifiableSyntaxNode, SyntaxNode);
-ABSTRACT_SYNTAX_CLASS(DeclBase, ModifiableSyntaxNode);
-ABSTRACT_SYNTAX_CLASS(Decl, DeclBase);
-ABSTRACT_SYNTAX_CLASS(Stmt, ModifiableSyntaxNode);
-ABSTRACT_SYNTAX_CLASS(Val, NodeBase);
-ABSTRACT_SYNTAX_CLASS(Type, Val);
-ABSTRACT_SYNTAX_CLASS(Modifier, SyntaxNodeBase);
-ABSTRACT_SYNTAX_CLASS(Expr, SyntaxNode);
-
-ABSTRACT_SYNTAX_CLASS(Substitutions, SyntaxNode);
-ABSTRACT_SYNTAX_CLASS(GenericSubstitution, Substitutions);
-ABSTRACT_SYNTAX_CLASS(ThisTypeSubstitution, Substitutions);
-ABSTRACT_SYNTAX_CLASS(GlobalGenericParamSubstitution, Substitutions);
-
-#include "slang-expr-defs.h"
-#include "slang-decl-defs.h"
-#include "slang-modifier-defs.h"
-#include "slang-stmt-defs.h"
-#include "slang-type-defs.h"
-#include "slang-val-defs.h"
-#include "slang-object-meta-end.h"
-
-
-SyntaxClassBase::ClassInfo::ClassInfo(const char* name, CreateFunc createFunc, const ClassInfo* superClass):
- m_name(name),
- m_createFunc(createFunc),
- m_superClass(superClass),
- m_next(s_first)
-{
- m_classId = 0;
- m_childrenEndClassId = 0;
-
- s_first = this;
-}
-
-
-
-static uint32_t _calcRangeRec(const SyntaxClassBase::ClassInfo* classInfo, const Dictionary<const SyntaxClassBase::ClassInfo*, List<const SyntaxClassBase::ClassInfo*> >& childMap, uint32_t index)
-{
- classInfo->m_classId = index++;
- // Do the calc range for all the children
- auto list = childMap.TryGetValue(classInfo);
+#define SLANG_CLASS_ACCEPT_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \
+ void NAME::accept(NAME::Visitor* visitor, void* extra) { visitor->dispatch_##NAME(this, extra); }
- if (list)
- {
- for (auto child : *list)
- {
- index = _calcRangeRec(child, childMap, index);
- }
- }
-
- classInfo->m_childrenEndClassId = index;
- return index;
-}
-
-bool SyntaxClassBase::ClassInfo::isSubClassOfSlow(const ThisType& super) const
-{
- SyntaxClassBase::ClassInfo const* info = this;
- while (info)
- {
- if (info == &super)
- return true;
- info = info->m_superClass;
- }
- return false;
-}
-
-static bool _checkSubClassRange()
-{
- typedef SyntaxClassBase::ClassInfo ClassInfo;
-
- List<const ClassInfo*> list;
- for (const ClassInfo* type = ClassInfo::s_first; type; type = type->m_next)
- {
- list.add(type);
- }
-
- for (Index i = 0; i < list.getCount(); ++i)
- {
- for (Index j = 0; j < list.getCount(); ++j)
- {
- auto a = list[i];
- auto b = list[j];
- if (a->isSubClassOf(*b) != a->isSubClassOfSlow(*b))
- {
- return false;
- }
- }
- }
-
- return true;
-}
-
-
-/* static */SlangResult SyntaxClassBase::ClassInfo::initRanges()
-{
- // Remove the warning about not referenced
- SLANG_UNUSED(&_checkSubClassRange);
-
- // TODO(JS):
- // Note that the calculating of the ranges could be done more efficiently by adding to an array of struct { super, class }, sorting, by super classs
- // and using a dictionary to map from class it's first in list of super class use. This works for now though.
-
- // We want to produce a map from a node that holds all of it's children
- Dictionary<const ThisType*, List<const ThisType*> > childMap;
-
- const List<const ThisType*> emptyList;
-
- {
- for (const ThisType* type = s_first; type; type = type->m_next)
- {
- if (type->m_superClass)
- {
- // Add to that item
- List<const ThisType*>* list = childMap.TryGetValueOrAdd(type->m_superClass, emptyList);
- if (!list)
- {
- list = childMap.TryGetValue(type->m_superClass);
- }
- SLANG_ASSERT(list);
- list->add(type);
- }
- }
- }
-
- // We want to recursively work out a range
- _calcRangeRec(&SyntaxClassBase::Impl<RefObject>::kClassInfo, childMap, 1);
-
- SLANG_ASSERT(_checkSubClassRange());
-
- return SLANG_OK;
-}
+SLANG_ALL_ASTNode_NodeBase(SLANG_CLASS_ONLY, SLANG_CLASS_ACCEPT_IMPL)
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! DiagnosticSink impls !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -225,10 +54,23 @@ SourceLoc const& getDiagnosticPos(TypeExp const& typeExp)
return typeExp.exp->loc;
}
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! BasicExpressionType !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+bool BasicExpressionType::EqualsImpl(Type * type)
+{
+ auto basicType = as<BasicExpressionType>(type);
+ return basicType && basicType->baseType == this->baseType;
+}
+
+RefPtr<Type> BasicExpressionType::CreateCanonicalType()
+{
+ // A basic type is already canonical, in our setup
+ return this;
+}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! Free functions !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-const RefPtr<Decl>* adjustFilterCursorImpl(const SyntaxClassBase::ClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end)
+const RefPtr<Decl>* adjustFilterCursorImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end)
{
switch (filterStyle)
{
@@ -273,7 +115,7 @@ const RefPtr<Decl>* adjustFilterCursorImpl(const SyntaxClassBase::ClassInfo& cls
return end;
}
-const RefPtr<Decl>* getFilterCursorByIndexImpl(const SyntaxClassBase::ClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end, Index index)
+const RefPtr<Decl>* getFilterCursorByIndexImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end, Index index)
{
switch (filterStyle)
{
@@ -330,7 +172,7 @@ const RefPtr<Decl>* getFilterCursorByIndexImpl(const SyntaxClassBase::ClassInfo&
return nullptr;
}
-Index getFilterCountImpl(const SyntaxClassBase::ClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end)
+Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end)
{
Index count = 0;
switch (filterStyle)
diff --git a/source/slang/slang-syntax.h b/source/slang/slang-syntax.h
index 5e1f057e4..e29a641a1 100644
--- a/source/slang/slang-syntax.h
+++ b/source/slang/slang-syntax.h
@@ -1,1373 +1,12 @@
#ifndef SLANG_SYNTAX_H
#define SLANG_SYNTAX_H
-#include "../core/slang-basic.h"
-#include "slang-lexer.h"
-#include "slang-profile.h"
-#include "slang-type-system-shared.h"
-#include "../../slang.h"
+#include "slang-ast-support-types.h"
-#include "../core/slang-semantic-version.h"
-
-#include "slang-name.h"
-
-#include <assert.h>
+#include "slang-ast-all.h"
namespace Slang
{
- class Module;
- class Name;
- class Session;
- class Substitutions;
- class SyntaxVisitor;
- class FuncDecl;
- class Layout;
-
- struct IExprVisitor;
- struct IDeclVisitor;
- struct IModifierVisitor;
- struct IStmtVisitor;
- struct ITypeVisitor;
- struct IValVisitor;
-
- class Parser;
- class SyntaxNode;
-
- class Decl;
- struct QualType;
- class Type;
- struct TypeExp;
- class Val;
-
- void printDiagnosticArg(StringBuilder& sb, Decl* decl);
- void printDiagnosticArg(StringBuilder& sb, Type* type);
- void printDiagnosticArg(StringBuilder& sb, TypeExp const& type);
- void printDiagnosticArg(StringBuilder& sb, QualType const& type);
- void printDiagnosticArg(StringBuilder& sb, Val* val);
-
- class SyntaxNode;
- SourceLoc const& getDiagnosticPos(SyntaxNode const* syntax);
- SourceLoc const& getDiagnosticPos(TypeExp const& typeExp);
-
- typedef RefPtr<RefObject> (*SyntaxParseCallback)(Parser* parser, void* userData);
-
- typedef unsigned int ConversionCost;
- enum : ConversionCost
- {
- // No conversion at all
- kConversionCost_None = 0,
-
- // Conversion from a buffer to the type it carries needs to add a minimal
- // extra cost, just so we can distinguish an overload on `ConstantBuffer<Foo>`
- // from one on `Foo`
- kConversionCost_ImplicitDereference = 10,
-
- // Conversions based on explicit sub-typing relationships are the cheapest
- //
- // TODO(tfoley): We will eventually need a discipline for ranking
- // when two up-casts are comparable.
- kConversionCost_CastToInterface = 50,
-
- // Conversion that is lossless and keeps the "kind" of the value the same
- kConversionCost_RankPromotion = 150,
-
- // Conversions that are lossless, but change "kind"
- kConversionCost_UnsignedToSignedPromotion = 200,
-
- // Conversion from signed->unsigned integer of same or greater size
- kConversionCost_SignedToUnsignedConversion = 300,
-
- // Cost of converting an integer to a floating-point type
- kConversionCost_IntegerToFloatConversion = 400,
-
- // Default case (usable for user-defined conversions)
- kConversionCost_Default = 500,
-
- // Catch-all for conversions that should be discouraged
- // (i.e., that really shouldn't be made implicitly)
- //
- // TODO: make these conversions not be allowed implicitly in "Slang mode"
- kConversionCost_GeneralConversion = 900,
-
- // This is the cost of an explicit conversion, which should
- // not actually be performed.
- kConversionCost_Explicit = 90000,
-
- // Additional conversion cost to add when promoting from a scalar to
- // a vector (this will be added to the cost, if any, of converting
- // the element type of the vector)
- kConversionCost_ScalarToVector = 1,
-
- // Conversion is impossible
- kConversionCost_Impossible = 0xFFFFFFFF,
- };
-
- enum class ImageFormat
- {
-#define FORMAT(NAME) NAME,
-#include "slang-image-format-defs.h"
- };
-
- bool findImageFormatByName(char const* name, ImageFormat* outFormat);
- char const* getGLSLNameForImageFormat(ImageFormat format);
-
- // TODO(tfoley): We should ditch this enumeration
- // and just use the IR opcodes that represent these
- // types directly. The one major complication there
- // is that the order of the enum values currently
- // matters, since it determines promotion rank.
- // We either need to keep that restriction, or
- // look up promotion rank by some other means.
- //
-
- class Decl;
- class Val;
-
- // Forward-declare all syntax classes
-#define SYNTAX_CLASS(NAME, BASE, ...) class NAME;
-#include "slang-object-meta-begin.h"
-#include "slang-syntax-defs.h"
-#include "slang-object-meta-end.h"
-
- // Helper type for pairing up a name and the location where it appeared
- struct NameLoc
- {
- Name* name;
- SourceLoc loc;
-
- NameLoc()
- : name(nullptr)
- {}
-
- explicit NameLoc(Name* inName)
- : name(inName)
- {}
-
-
- NameLoc(Name* inName, SourceLoc inLoc)
- : name(inName)
- , loc(inLoc)
- {}
-
- NameLoc(Token const& token)
- : name(token.getNameOrNull())
- , loc(token.getLoc())
- {}
- };
-
- struct StringSliceLoc
- {
- UnownedStringSlice name;
- SourceLoc loc;
-
- StringSliceLoc()
- : name(nullptr)
- {}
- explicit StringSliceLoc(const UnownedStringSlice& inName)
- : name(inName)
- {}
- StringSliceLoc(const UnownedStringSlice& inName, SourceLoc inLoc)
- : name(inName)
- , loc(inLoc)
- {}
- StringSliceLoc(Token const& token)
- : loc(token.getLoc())
- {
- Name* tokenName = token.getNameOrNull();
- if (tokenName)
- {
- name = tokenName->text.getUnownedSlice();
- }
- }
- };
-
- // Helper class for iterating over a list of heap-allocated modifiers
- struct ModifierList
- {
- struct Iterator
- {
- Modifier* current;
-
- Modifier* operator*()
- {
- return current;
- }
-
- void operator++();
-#if 0
- {
- current = current->next.Ptr();
- }
-#endif
-
- bool operator!=(Iterator other)
- {
- return current != other.current;
- };
-
- Iterator()
- : current(nullptr)
- {}
-
- Iterator(Modifier* modifier)
- : current(modifier)
- {}
- };
-
- ModifierList()
- : modifiers(nullptr)
- {}
-
- ModifierList(Modifier* modifiers)
- : modifiers(modifiers)
- {}
-
- Iterator begin() { return Iterator(modifiers); }
- Iterator end() { return Iterator(nullptr); }
-
- Modifier* modifiers;
- };
-
- // Helper class for iterating over heap-allocated modifiers
- // of a specific type.
- template<typename T>
- struct FilteredModifierList
- {
- struct Iterator
- {
- Modifier* current;
-
- T* operator*()
- {
- return (T*)current;
- }
-
- void operator++();
- #if 0
- {
- current = Adjust(current->next.Ptr());
- }
- #endif
-
- bool operator!=(Iterator other)
- {
- return current != other.current;
- };
-
- Iterator()
- : current(nullptr)
- {}
-
- Iterator(Modifier* modifier)
- : current(modifier)
- {}
- };
-
- FilteredModifierList()
- : modifiers(nullptr)
- {}
-
- FilteredModifierList(Modifier* modifiers)
- : modifiers(Adjust(modifiers))
- {}
-
- Iterator begin() { return Iterator(modifiers); }
- Iterator end() { return Iterator(nullptr); }
-
- static Modifier* Adjust(Modifier* modifier);
- #if 0
- {
- Modifier* m = modifier;
- for (;;)
- {
- if (!m) return m;
- if (dynamicCast<T>(m)) return m;
- m = m->next.Ptr();
- }
- }
- #endif
-
- Modifier* modifiers;
- };
-
- // A set of modifiers attached to a syntax node
- struct Modifiers
- {
- // The first modifier in the linked list of heap-allocated modifiers
- RefPtr<Modifier> first;
-
- template<typename T>
- FilteredModifierList<T> getModifiersOfType() { return FilteredModifierList<T>(first.Ptr()); }
-
- // Find the first modifier of a given type, or return `nullptr` if none is found.
- template<typename T>
- T* findModifier()
- {
- return *getModifiersOfType<T>().begin();
- }
-
- template<typename T>
- bool hasModifier() { return findModifier<T>() != nullptr; }
-
- FilteredModifierList<Modifier>::Iterator begin() { return FilteredModifierList<Modifier>::Iterator(first.Ptr()); }
- FilteredModifierList<Modifier>::Iterator end() { return FilteredModifierList<Modifier>::Iterator(nullptr); }
- };
-
- class NamedExpressionType;
- class GenericDecl;
- class ContainerDecl;
-
- // Try to extract a simple integer value from an `IntVal`.
- // This fill assert-fail if the object doesn't represent a literal value.
- IntegerLiteralValue GetIntVal(RefPtr<IntVal> val);
-
- /// Represents how much checking has been applied to a declaration.
- enum class DeclCheckState : uint8_t
- {
- /// The declaration has been parsed, but
- /// is otherwise completely unchecked.
- ///
- Unchecked,
-
- /// Basic checks on the modifiers of the declaration have been applied.
- ///
- /// For example, when a declaration has attributes, the transformation
- /// of an attribute from the parsed-but-unchecked form into a checked
- /// form (in which it has the appropriate C++ subclass) happens here.
- ///
- ModifiersChecked,
-
- /// The type/signature of the declaration has been checked.
- ///
- /// For a value declaration like a variable or function, this means that
- /// the type of the declaration can be queried.
- ///
- /// For a type declaration like a `struct` or `typedef` this means
- /// that a `Type` referring to that declaration can be formed.
- ///
- SignatureChecked,
-
- /// The declaration's basic signature has been checked to the point that
- /// it is ready to be referenced in other places.
- ///
- /// For a function, this means that it has been organized into a
- /// "redeclration group" if there are multiple functions with the
- /// same name in a scope.
- ///
- ReadyForReference,
-
- /// The declaration is ready for lookup operations to be performed.
- ///
- /// For type declarations (e.g., aggregate types, generic type parameters)
- /// this means that any base type or constraint clauses have been
- /// sufficiently checked so that we can enumerate the inheritance
- /// hierarchy of the type and discover all its members.
- ///
- ReadyForLookup,
-
- /// Any conformance declared on the declaration have been validated.
- ///
- /// In particular, this step means that a "witness table" has been
- /// created to show how a type satisfies the requirements of any
- /// interfaces it conforms to.
- ///
- ReadyForConformances,
-
- /// The declaration is fully checked.
- ///
- /// This step includes any validation of the declaration that is
- /// immaterial to clients code using the declaration, but that is
- /// nonetheless relevant to checking correctness.
- ///
- /// The canonical example here is checking the body of functions.
- /// Client code cannot depend on *how* a function is implemented,
- /// but we still need to (eventually) check the bodies of all
- /// functions, so it belongs in the last phase of checking.
- ///
- Checked,
-
- // For convenience at sites that call `ensureDecl()`, we define
- // some aliases for the above states that are expressed in terms
- // of what client code needs to be able to do with a declaration.
- //
- // These aliases can be changed over time if we decide to add
- // more phases to semantic checking.
-
- CanEnumerateBases = ReadyForLookup,
- CanUseBaseOfInheritanceDecl = ReadyForLookup,
- CanUseTypeOfValueDecl = ReadyForReference,
- CanUseExtensionTargetType = ReadyForLookup,
- CanUseAsType = ReadyForReference,
- CanUseFuncSignature = ReadyForReference,
- CanSpecializeGeneric = ReadyForReference,
- CanReadInterfaceRequirements = ReadyForLookup,
- };
-
- /// A `DeclCheckState` plus a bit to track whether a declaration is currently being checked.
- struct DeclCheckStateExt
- {
- public:
- DeclCheckStateExt() {}
- DeclCheckStateExt(DeclCheckState state)
- : m_raw(uint8_t(state))
- {}
-
- enum : uint8_t
- {
- /// A flag to indicate that a declaration is being checked.
- ///
- /// The value of this flag is chosen so that it can be
- /// represented in the bits of a `DeclCheckState` without
- /// colliding with the bits that represent actual states.
- ///
- kBeingCheckedBit = 0x80,
- };
-
- DeclCheckState getState() const { return DeclCheckState(m_raw & ~kBeingCheckedBit); }
- void setState(DeclCheckState state)
- {
- m_raw = (m_raw & kBeingCheckedBit) | uint8_t(state);
- }
-
- bool isBeingChecked() const { return (m_raw & kBeingCheckedBit) != 0; }
-
- void setIsBeingChecked(bool isBeingChecked)
- {
- m_raw = (m_raw & ~kBeingCheckedBit)
- | (isBeingChecked ? kBeingCheckedBit : 0);
- }
-
- bool operator>=(DeclCheckState state) const
- {
- return getState() >= state;
- }
-
- private:
- uint8_t m_raw = 0;
- };
-
- void addModifier(
- RefPtr<ModifiableSyntaxNode> syntax,
- RefPtr<Modifier> modifier);
-
- struct QualType
- {
- RefPtr<Type> type;
- bool IsLeftValue;
-
- QualType()
- : IsLeftValue(false)
- {}
-
- QualType(Type* type)
- : type(type)
- , IsLeftValue(false)
- {}
-
- Type* Ptr() { return type.Ptr(); }
-
- operator Type*() { return type; }
- operator RefPtr<Type>() { return type; }
- RefPtr<Type> operator->() { return type; }
- };
-
- // A reference to a class of syntax node, that can be
- // used to create instances on the fly
- struct SyntaxClassBase
- {
- typedef void* (*CreateFunc)();
-
- // Run-time type representation for syntax nodes
- struct ClassInfo
- {
- typedef ClassInfo ThisType;
-
- /// A constant time implementation of isSubClassOf
- SLANG_FORCE_INLINE bool isSubClassOf(const ThisType& super) const
- {
- // We include super.m_classId, because it's a subclass of itself.
- return m_classId >= super.m_classId && m_classId < super.m_childrenEndClassId;
- }
- /// Will produce the same result as isSubClassOf, but more slowly by traversing the m_superClass
- /// Works without initRange being called.
- bool isSubClassOfSlow(const ThisType& super) const;
-
- /// This function must have been called before any dynamic casting will work (via the m_classId/m_childrenEndClassId.
- /// It sets up the m_rangeStart/m_rangeEnd values to make.
- /// Is called within the creation of Session
- static SlangResult initRanges();
-
- /// Ctor
- ClassInfo(const char* name, CreateFunc createFunc, const ClassInfo* superClass);
-
- /// The id for this class. The children of this class are in the range of m_classId + 1 to (but not including) m_childrenEndId.
- mutable uint32_t m_classId;
- /// Non inclusive end of range of children.
- mutable uint32_t m_childrenEndClassId;
-
- const ClassInfo* m_superClass; ///< The super class of this class, or nullptr if has no super class.
- const char* m_name; ///< Textual class name, for debugging
- CreateFunc m_createFunc; ///< Callback to use when creating instances
-
- ClassInfo* m_next; ///< Next in list starting from s_first
- static ClassInfo* s_first;
- };
-
- SyntaxClassBase()
- {}
-
- SyntaxClassBase(ClassInfo const* classInfoIn)
- : classInfo(classInfoIn)
- {}
-
- void* createInstanceImpl() const
- {
- auto ci = classInfo;
- if (!ci) return nullptr;
-
- auto cf = ci->m_createFunc;
- if (!cf) return nullptr;
-
- return cf();
- }
-
- SLANG_FORCE_INLINE bool isSubClassOfImpl(SyntaxClassBase const& super) const { return classInfo->isSubClassOf(*super.classInfo); }
-
- ClassInfo const* classInfo = nullptr;
-
- template<typename T>
- struct Impl
- {
- static void* createFunc();
- static const ClassInfo kClassInfo;
- };
- };
-
- template<typename T>
- struct SyntaxClass : SyntaxClassBase
- {
- SyntaxClass()
- {}
-
- template <typename U>
- SyntaxClass(SyntaxClass<U> const& other,
- typename EnableIf<IsConvertible<T*, U*>::Value, void>::type* = 0)
- : SyntaxClassBase(other.classInfo)
- {
- }
-
- T* createInstance() const
- {
- return (T*)createInstanceImpl();
- }
-
- SyntaxClass(const ClassInfo* classInfoIn):
- SyntaxClassBase(classInfoIn)
- {}
-
- static SyntaxClass<T> getClass()
- {
- return SyntaxClass<T>(&SyntaxClassBase::Impl<T>::kClassInfo);
- }
-
- template<typename U>
- bool isSubClassOf(SyntaxClass<U> super)
- {
- return isSubClassOfImpl(super);
- }
-
- template<typename U>
- bool isSubClassOf()
- {
- return isSubClassOf(SyntaxClass<U>::getClass());
- }
- };
-
- template<typename T>
- SyntaxClass<T> getClass()
- {
- return SyntaxClass<T>::getClass();
- }
-
- template<typename T>
- SLANG_FORCE_INLINE T* dynamicCast(NodeBase* node);
-
- template<typename T>
- SLANG_FORCE_INLINE const T* dynamicCast(const NodeBase* node);
-
- template<typename T>
- SLANG_FORCE_INLINE T* as(NodeBase* node);
-
- template<typename T>
- SLANG_FORCE_INLINE const T* as(const NodeBase* node);
-
- struct SubstitutionSet
- {
- RefPtr<Substitutions> substitutions;
- operator Substitutions*() const
- {
- return substitutions;
- }
-
- SubstitutionSet() {}
- SubstitutionSet(RefPtr<Substitutions> subst)
- : substitutions(subst)
- {
- }
- bool Equals(const SubstitutionSet& substSet) const;
- int GetHashCode() const;
- };
-
- template<typename T>
- struct DeclRef;
-
- // A reference to a declaration, which may include
- // substitutions for generic parameters.
- struct DeclRefBase
- {
- typedef Decl DeclType;
-
- // The underlying declaration
- Decl* decl = nullptr;
- Decl* getDecl() const { return decl; }
-
- // Optionally, a chain of substitutions to perform
- SubstitutionSet substitutions;
-
- DeclRefBase()
- {}
-
- DeclRefBase(Decl* decl)
- :decl(decl)
- {}
-
- DeclRefBase(Decl* decl, SubstitutionSet subst)
- :decl(decl),
- substitutions(subst)
- {}
-
- DeclRefBase(Decl* decl, RefPtr<Substitutions> subst)
- : decl(decl)
- , substitutions(subst)
- {}
-
- // Apply substitutions to a type or declaration
- RefPtr<Type> Substitute(RefPtr<Type> type) const;
-
- DeclRefBase Substitute(DeclRefBase declRef) const;
-
- // Apply substitutions to an expression
- RefPtr<Expr> Substitute(RefPtr<Expr> expr) const;
-
- // Apply substitutions to this declaration reference
- DeclRefBase SubstituteImpl(SubstitutionSet subst, int* ioDiff);
-
- // Returns true if 'as' will return a valid cast
- template <typename T>
- bool is() const { return Slang::as<T>(decl) != nullptr; }
-
- // "dynamic cast" to a more specific declaration reference type
- template<typename T>
- DeclRef<T> as() const;
-
- // Check if this is an equivalent declaration reference to another
- bool Equals(DeclRefBase const& declRef) const;
- bool operator == (const DeclRefBase& other) const
- {
- return Equals(other);
- }
-
- // Convenience accessors for common properties of declarations
- Name* GetName() const;
- SourceLoc getLoc() const;
- DeclRefBase GetParent() const;
-
- int GetHashCode() const;
-
- // Debugging:
- String toString() const;
- };
-
- template<typename T>
- struct DeclRef : DeclRefBase
- {
- typedef T DeclType;
-
- DeclRef()
- {}
-
- DeclRef(T* decl, SubstitutionSet subst)
- : DeclRefBase(decl, subst)
- {}
-
- DeclRef(T* decl, RefPtr<Substitutions> subst)
- : DeclRefBase(decl, SubstitutionSet(subst))
- {}
-
- template <typename U>
- DeclRef(DeclRef<U> const& other,
- typename EnableIf<IsConvertible<T*, U*>::Value, void>::type* = 0)
- : DeclRefBase(other.decl, other.substitutions)
- {
- }
-
- T* getDecl() const
- {
- return (T*)decl;
- }
-
- operator T*() const
- {
- return getDecl();
- }
-
- //
- static DeclRef<T> unsafeInit(DeclRefBase const& declRef)
- {
- return DeclRef<T>((T*) declRef.decl, declRef.substitutions);
- }
-
- RefPtr<Type> Substitute(RefPtr<Type> type) const
- {
- return DeclRefBase::Substitute(type);
- }
- RefPtr<Expr> Substitute(RefPtr<Expr> expr) const
- {
- return DeclRefBase::Substitute(expr);
- }
-
- // Apply substitutions to a type or declaration
- template<typename U>
- DeclRef<U> Substitute(DeclRef<U> declRef) const
- {
- return DeclRef<U>::unsafeInit(DeclRefBase::Substitute(declRef));
- }
-
- // Apply substitutions to this declaration reference
- DeclRef<T> SubstituteImpl(SubstitutionSet subst, int* ioDiff)
- {
- return DeclRef<T>::unsafeInit(DeclRefBase::SubstituteImpl(subst, ioDiff));
- }
-
- DeclRef<ContainerDecl> GetParent() const
- {
- return DeclRef<ContainerDecl>::unsafeInit(DeclRefBase::GetParent());
- }
- };
-
- template<typename T>
- DeclRef<T> DeclRefBase::as() const
- {
- DeclRef<T> result;
- result.decl = Slang::as<T>(decl);
- result.substitutions = substitutions;
- return result;
- }
-
- template<typename T>
- inline DeclRef<T> makeDeclRef(T* decl)
- {
- return DeclRef<T>(decl, nullptr);
- }
-
- enum class MemberFilterStyle
- {
- All, ///< All members
- Instance, ///< Only instance members
- Static, ///< Only static (ie non instance) members
- };
-
- const RefPtr<Decl>* adjustFilterCursorImpl(const SyntaxClassBase::ClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end);
- const RefPtr<Decl>* getFilterCursorByIndexImpl(const SyntaxClassBase::ClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end, Index index);
- Index getFilterCountImpl(const SyntaxClassBase::ClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end);
-
-
- template <typename T>
- const RefPtr<Decl>* adjustFilterCursor(MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end)
- {
- return adjustFilterCursorImpl(SyntaxClassBase::Impl<T>::kClassInfo, filterStyle, ptr, end);
- }
-
- /// Finds the element at index. If there is no element at the index (for example has too few elements), returns nullptr.
- template <typename T>
- const RefPtr<Decl>* getFilterCursorByIndex(MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end, Index index)
- {
- return getFilterCursorByIndexImpl(SyntaxClassBase::Impl<T>::kClassInfo, filterStyle, ptr, end, index);
- }
-
- template <typename T>
- Index getFilterCount(MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end)
- {
- return getFilterCountImpl(SyntaxClassBase::Impl<T>::kClassInfo, filterStyle, ptr, end);
- }
-
- template <typename T>
- bool isFilterNonEmpty(MemberFilterStyle filterStyle, const RefPtr<Decl>* ptr, const RefPtr<Decl>* end)
- {
- return adjustFilterCursorImpl(SyntaxClassBase::Impl<T>::kClassInfo, filterStyle, ptr, end) != end;
- }
-
- template<typename T>
- struct FilteredMemberList
- {
- typedef RefPtr<Decl> Element;
-
- FilteredMemberList()
- : m_begin(nullptr)
- , m_end(nullptr)
- {}
-
- explicit FilteredMemberList(
- List<Element> const& list,
- MemberFilterStyle filterStyle = MemberFilterStyle::All)
- : m_begin(adjustFilterCursor<T>(filterStyle, list.begin(), list.end()))
- , m_end(list.end())
- , m_filterStyle(filterStyle)
- {}
-
- struct Iterator
- {
- const Element* m_cursor;
- const Element* m_end;
- MemberFilterStyle m_filterStyle;
-
- bool operator!=(Iterator const& other) const { return m_cursor != other.m_cursor; }
-
- void operator++() { m_cursor = adjustFilterCursor<T>(m_filterStyle, m_cursor + 1, m_end); }
-
- const RefPtr<T>& operator*() { return *(RefPtr<T>*)(m_cursor); }
- };
-
- Iterator begin()
- {
- Iterator iter = { m_begin, m_end, m_filterStyle };
- return iter;
- }
-
- Iterator end()
- {
- Iterator iter = { m_end, m_end, m_filterStyle };
- return iter;
- }
-
- // TODO(tfoley): It is ugly to have these.
- // We should probably fix the call sites instead.
- const RefPtr<T>& getFirst() { return *begin(); }
- Index getCount() { return getFilterCount<T>(m_filterStyle, m_begin, m_end); }
-
- RefPtr<T> operator[](Index index) const
- {
- const RefPtr<Decl>* ptr = getFilterCursorByIndex<T>(m_filterStyle, m_begin, m_end, index);
- SLANG_ASSERT(ptr);
- return *(RefPtr<T>*)(ptr);
- }
-
- /// Returns true if empty (equivalent to getCount() == 0)
- bool isEmpty() const
- {
- /// Note we don't have to scan, because m_begin has already been adjusted, when the FilteredMemberList is constructed
- return m_begin == m_end;
- }
- /// Returns true if non empty (equivalent to getCount() != 0 but faster)
- bool isNonEmpty() const { return !isEmpty(); }
-
- List<RefPtr<T>> toArray()
- {
- List<RefPtr<T>> result;
- for (auto element : (*this))
- {
- result.add(element);
- }
- return result;
- }
-
- const Element* m_begin; ///< Is either equal to m_end, or points to first *valid* filtered member
- const Element* m_end;
- MemberFilterStyle m_filterStyle;
- };
-
- struct TransparentMemberInfo
- {
- // The declaration of the transparent member
- Decl* decl;
- };
-
- template<typename T>
- struct FilteredMemberRefList
- {
- List<RefPtr<Decl>> const& m_decls;
- SubstitutionSet m_substitutions;
- MemberFilterStyle m_filterStyle;
-
- FilteredMemberRefList(
- List<RefPtr<Decl>> const& decls,
- SubstitutionSet substitutions,
- MemberFilterStyle filterStyle = MemberFilterStyle::All)
- : m_decls(decls)
- , m_substitutions(substitutions)
- , m_filterStyle(filterStyle)
- {}
-
- Index getCount() const { return getFilterCount<T>(m_filterStyle, m_decls.begin(), m_decls.end()); }
-
- /// True if empty (equivalent to getCount == 0, but faster)
- bool isEmpty() const { return !isNonEmpty(); }
- /// True if non empty (equivalent to getCount() != 0 but faster)
- bool isNonEmpty() const { return isFilterNonEmpty<T>(m_filterStyle, m_decls.begin(), m_decls.end()); }
-
- DeclRef<T> operator[](Index index) const
- {
- const RefPtr<Decl>* decl = getFilterCursorByIndex<T>(m_filterStyle, m_decls.begin(), m_decls.end(), index);
- SLANG_ASSERT(decl);
- return DeclRef<T>((T*) decl->Ptr(), m_substitutions);
- }
-
- List<DeclRef<T>> toArray() const
- {
- List<DeclRef<T>> result;
- for (auto d : *this)
- result.add(d);
- return result;
- }
-
- struct Iterator
- {
- FilteredMemberRefList const* m_list;
- const RefPtr<Decl>* m_ptr;
- const RefPtr<Decl>* m_end;
- MemberFilterStyle m_filterStyle;
-
- Iterator() : m_list(nullptr), m_ptr(nullptr), m_filterStyle(MemberFilterStyle::All) {}
- Iterator(
- FilteredMemberRefList const* list,
- const RefPtr<Decl>* ptr,
- const RefPtr<Decl>* end,
- MemberFilterStyle filterStyle
- )
- : m_list(list)
- , m_ptr(ptr)
- , m_end(end)
- , m_filterStyle(filterStyle)
- {}
-
- bool operator!=(const Iterator& other) const { return m_ptr != other.m_ptr; }
-
- void operator++() { m_ptr = adjustFilterCursor<T>(m_filterStyle, m_ptr + 1, m_end); }
-
- DeclRef<T> operator*() { return DeclRef<T>((T*) m_ptr->Ptr(), m_list->m_substitutions); }
- };
-
- Iterator begin() const { return Iterator(this, adjustFilterCursor<T>(m_filterStyle, m_decls.begin(), m_decls.end()), m_decls.end(), m_filterStyle); }
- Iterator end() const { return Iterator(this, m_decls.end(), m_decls.end(), m_filterStyle); }
- };
-
- //
- // type Expressions
- //
-
- // A "type expression" is a term that we expect to resolve to a type during checking.
- // We store both the original syntax and the resolved type here.
- struct TypeExp
- {
- TypeExp() {}
- TypeExp(TypeExp const& other)
- : exp(other.exp)
- , type(other.type)
- {}
- explicit TypeExp(RefPtr<Expr> exp)
- : exp(exp)
- {}
- explicit TypeExp(RefPtr<Type> type)
- : type(type)
- {}
- TypeExp(RefPtr<Expr> exp, RefPtr<Type> type)
- : exp(exp)
- , type(type)
- {}
-
- RefPtr<Expr> exp;
- RefPtr<Type> type;
-
- bool Equals(Type* other);
-#if 0
- {
- return type->Equals(other);
- }
-#endif
- bool Equals(RefPtr<Type> other);
-#if 0
- {
- return type->Equals(other.Ptr());
- }
-#endif
- Type* Ptr() { return type.Ptr(); }
- operator Type*()
- {
- return type;
- }
- Type* operator->() { return Ptr(); }
-
- TypeExp Accept(SyntaxVisitor* visitor);
- };
-
-
-
- struct Scope : public RefObject
- {
- // The parent of this scope (where lookup should go if nothing is found locally)
- RefPtr<Scope> parent;
-
- // The next sibling of this scope (a peer for lookup)
- RefPtr<Scope> nextSibling;
-
- // The container to use for lookup
- //
- // Note(tfoley): This is kept as an unowned pointer
- // so that a scope can't keep parts of the AST alive,
- // but the opposite it allowed.
- ContainerDecl* containerDecl;
- };
-
- // Masks to be applied when lookup up declarations
- enum class LookupMask : uint8_t
- {
- type = 0x1,
- Function = 0x2,
- Value = 0x4,
- Attribute = 0x8,
-
- Default = type | Function | Value,
- };
-
- // Represents one item found during lookup
- struct LookupResultItem
- {
- // Sometimes lookup finds an item, but there were additional
- // "hops" taken to reach it. We need to remember these steps
- // so that if/when we consturct a full expression we generate
- // appropriate AST nodes for all the steps.
- //
- // We build up a list of these "breadcrumbs" while doing
- // lookup, and store them alongside each item found.
- //
- // As an example, suppose we have an HLSL `cbuffer` declaration:
- //
- // cbuffer C { float4 f; }
- //
- // This is syntax sugar for a global-scope variable of
- // type `ConstantBuffer<T>` where `T` is a `struct` containing
- // all the members:
- //
- // struct Anon0 { float4 f; };
- // __transparent ConstantBuffer<Anon0> anon1;
- //
- // The `__transparent` modifier there captures the fact that
- // when somebody writes `f` in their code, they expect it to
- // "see through" the `cbuffer` declaration (or the global variable,
- // in this case) and find the member inside.
- //
- // But when the user writes `f` we can't just create a simple
- // `VarExpr` that refers directly to that field, because that
- // doesn't actually reflect the required steps in a way that
- // code generation can use.
- //
- // Instead we need to construct an expression like `(*anon1).f`,
- // where there is are two additional steps in the process:
- //
- // 1. We needed to dereference the pointer-like type `ConstantBuffer<Anon0>`
- // to get at a value of type `Anon0`
- // 2. We needed to access a sub-field of the aggregate type `Anon0`
- //
- // We *could* just create these full-formed expressions during
- // lookup, but this might mean creating a large number of
- // AST nodes in cases where the user calls an overloaded function.
- // At the very least we'd rather not heap-allocate in the common
- // case where no "extra" steps need to be performed to get to
- // the declarations.
- //
- // This is where "breadcrumbs" come in. A breadcrumb represents
- // an extra "step" that must be performed to turn a declaration
- // found by lookup into a valid expression to splice into the
- // AST. Most of the time lookup result items don't have any
- // breadcrumbs, so that no extra heap allocation takes place.
- // When an item does have breadcrumbs, and it is chosen as
- // the unique result (perhaps by overload resolution), then
- // we can walk the list of breadcrumbs to create a full
- // expression.
- class Breadcrumb : public RefObject
- {
- public:
- enum class Kind : uint8_t
- {
- // The lookup process looked "through" an in-scope
- // declaration to the fields inside of it, so that
- // even if lookup started with a simple name `f`,
- // it needs to result in a member expression `obj.f`.
- Member,
-
- // The lookup process took a pointer(-like) value, and then
- // proceeded to derefence it and look at the thing(s)
- // it points to instead, so that the final expression
- // needs to have `(*obj)`
- Deref,
-
- // The lookup process saw a value `obj` of type `T` and
- // took into account an in-scope constraint that says
- // `T` is a subtype of some other type `U`, so that
- // lookup was able to find a member through type `U`
- // instead.
- Constraint,
-
- // The lookup process considered a member of an
- // enclosing type as being in scope, so that any
- // reference to that member needs to use a `this`
- // expression as appropriate.
- This,
- };
-
- // The kind of lookup step that was performed
- Kind kind;
-
- // For the `Kind::This` case, what does the implicit
- // `this` or `This` parameter refer to?
- //
- enum class ThisParameterMode : uint8_t
- {
- ImmutableValue, // An immutable `this` value
- MutableValue, // A mutable `this` value
- Type, // A `This` type
-
- Default = ImmutableValue,
- };
- ThisParameterMode thisParameterMode = ThisParameterMode::Default;
-
- // As needed, a reference to the declaration that faciliated
- // the lookup step.
- //
- // For a `Member` lookup step, this is the declaration whose
- // members were implicitly pulled into scope.
- //
- // For a `Constraint` lookup step, this is the `ConstraintDecl`
- // that serves to witness the subtype relationship.
- //
- DeclRef<Decl> declRef;
-
- // The next implicit step that the lookup process took to
- // arrive at a final value.
- RefPtr<Breadcrumb> next;
-
- Breadcrumb(
- Kind kind,
- DeclRef<Decl> declRef,
- RefPtr<Breadcrumb> next,
- ThisParameterMode thisParameterMode = ThisParameterMode::Default)
- : kind(kind)
- , thisParameterMode(thisParameterMode)
- , declRef(declRef)
- , next(next)
- {}
- };
-
- // A properly-specialized reference to the declaration that was found.
- DeclRef<Decl> declRef;
-
- // Any breadcrumbs needed in order to turn that declaration
- // reference into a well-formed expression.
- //
- // This is unused in the simple case where a declaration
- // is being referenced directly (rather than through
- // transparent members).
- RefPtr<Breadcrumb> breadcrumbs;
-
- LookupResultItem() = default;
- explicit LookupResultItem(DeclRef<Decl> declRef)
- : declRef(declRef)
- {}
- LookupResultItem(DeclRef<Decl> declRef, RefPtr<Breadcrumb> breadcrumbs)
- : declRef(declRef)
- , breadcrumbs(breadcrumbs)
- {}
- };
-
-
- // Result of looking up a name in some lexical/semantic environment.
- // Can be used to enumerate all the declarations matching that name,
- // in the case where the result is overloaded.
- struct LookupResult
- {
- // The one item that was found, in the smple case
- LookupResultItem item;
-
- // All of the items that were found, in the complex case.
- // Note: if there was no overloading, then this list isn't
- // used at all, to avoid allocation.
- List<LookupResultItem> items;
-
- // Was at least one result found?
- bool isValid() const { return item.declRef.getDecl() != nullptr; }
-
- bool isOverloaded() const { return items.getCount() > 1; }
-
- Name* getName() const
- {
- return items.getCount() > 1 ? items[0].declRef.GetName() : item.declRef.GetName();
- }
- LookupResultItem* begin()
- {
- if (isValid())
- {
- if (isOverloaded())
- return items.begin();
- else
- return &item;
- }
- else
- return nullptr;
- }
- LookupResultItem* end()
- {
- if (isValid())
- {
- if (isOverloaded())
- return items.end();
- else
- return &item + 1;
- }
- else
- return nullptr;
- }
- };
-
- struct SemanticsVisitor;
-
- struct LookupRequest
- {
- SemanticsVisitor* semantics = nullptr;
- RefPtr<Scope> scope = nullptr;
- RefPtr<Scope> endScope = nullptr;
-
- LookupMask mask = LookupMask::Default;
- };
-
- struct WitnessTable;
-
- // A value that witnesses the satisfaction of an interface
- // requirement by a particular declaration or value.
- struct RequirementWitness
- {
- RequirementWitness()
- : m_flavor(Flavor::none)
- {}
-
- RequirementWitness(DeclRef<Decl> declRef)
- : m_flavor(Flavor::declRef)
- , m_declRef(declRef)
- {}
-
- RequirementWitness(RefPtr<Val> val);
-
- RequirementWitness(RefPtr<WitnessTable> witnessTable);
-
- enum class Flavor
- {
- none,
- declRef,
- val,
- witnessTable,
- };
-
- Flavor getFlavor()
- {
- return m_flavor;
- }
-
- DeclRef<Decl> getDeclRef()
- {
- SLANG_ASSERT(getFlavor() == Flavor::declRef);
- return m_declRef;
- }
-
- RefPtr<Val> getVal()
- {
- SLANG_ASSERT(getFlavor() == Flavor::val);
- return m_obj.as<Val>();
- }
-
- RefPtr<WitnessTable> getWitnessTable();
-
- RequirementWitness specialize(SubstitutionSet const& subst);
-
- Flavor m_flavor;
- DeclRef<Decl> m_declRef;
- RefPtr<RefObject> m_obj;
-
- };
-
- typedef Dictionary<Decl*, RequirementWitness> RequirementDictionary;
-
- struct WitnessTable : RefObject
- {
- RequirementDictionary requirementDictionary;
- };
-
- typedef Dictionary<unsigned int, RefPtr<RefObject>> AttributeArgumentValueDict;
-
- struct SpecializationParam
- {
- enum class Flavor
- {
- GenericType,
- GenericValue,
- ExistentialType,
- ExistentialValue,
- };
- Flavor flavor;
- SourceLoc loc;
- RefPtr<NodeBase> object;
- };
- typedef List<SpecializationParam> SpecializationParams;
-
- struct SpecializationArg
- {
- RefPtr<Val> val;
- };
- typedef List<SpecializationArg> SpecializationArgs;
-
- struct ExpandedSpecializationArg : SpecializationArg
- {
- RefPtr<Val> witness;
- };
- typedef List<ExpandedSpecializationArg> ExpandedSpecializationArgs;
-
- // Generate class definition for all syntax classes
-#define SYNTAX_FIELD(TYPE, NAME) TYPE NAME;
-#define FIELD(TYPE, NAME) TYPE NAME;
-#define FIELD_INIT(TYPE, NAME, INIT) TYPE NAME = INIT;
-#define RAW(...) __VA_ARGS__
-#define END_SYNTAX_CLASS() };
-#define SYNTAX_CLASS(NAME, BASE, ...) class NAME : public BASE {public:
-#include "slang-object-meta-begin.h"
-
-#include "slang-syntax-base-defs.h"
-#undef SYNTAX_CLASS
-
-#undef ABSTRACT_SYNTAX_CLASS
-#define ABSTRACT_SYNTAX_CLASS(NAME, BASE, ...) \
- class NAME : public BASE { \
- public: /* ... */
-#define SYNTAX_CLASS(NAME, BASE, ...) \
- class NAME : public BASE { \
- virtual void accept(NAME::Visitor* visitor, void* extra) override; \
- public: virtual const SyntaxClassBase::ClassInfo& getClassInfo() const override; \
- public: /* ... */
-#include "slang-expr-defs.h"
-#include "slang-decl-defs.h"
-#include "slang-modifier-defs.h"
-#include "slang-stmt-defs.h"
-#include "slang-type-defs.h"
-#include "slang-val-defs.h"
-
-#include "slang-object-meta-end.h"
inline RefPtr<Type> GetSub(DeclRef<GenericTypeConstraintDecl> const& declRef)
{
@@ -1629,29 +268,7 @@ namespace Slang
/// Get the module that a declaration is associated with, if any.
Module* getModule(Decl* decl);
- template<typename T>
- SLANG_FORCE_INLINE T* dynamicCast(NodeBase* node)
- {
- return (node && node->getClassInfo().isSubClassOf(SyntaxClassBase::Impl<T>::kClassInfo)) ? static_cast<T*>(node) : nullptr;
- }
-
- template<typename T>
- SLANG_FORCE_INLINE const T* dynamicCast(const NodeBase* node)
- {
- return (node && node->getClassInfo().isSubClassOf(SyntaxClassBase::Impl<T>::kClassInfo)) ? static_cast<const T*>(node) : nullptr;
- }
-
- template<typename T>
- SLANG_FORCE_INLINE T* as(NodeBase* node)
- {
- return (node && node->getClassInfo().isSubClassOf(SyntaxClassBase::Impl<T>::kClassInfo)) ? static_cast<T*>(node) : nullptr;
- }
-
- template<typename T>
- SLANG_FORCE_INLINE const T* as(const NodeBase* node)
- {
- return (node && node->getClassInfo().isSubClassOf(SyntaxClassBase::Impl<T>::kClassInfo)) ? static_cast<const T*>(node) : nullptr;
- }
+
} // namespace Slang
diff --git a/source/slang/slang-visitor.h b/source/slang/slang-visitor.h
index c6d63cd40..449fda917 100644
--- a/source/slang/slang-visitor.h
+++ b/source/slang/slang-visitor.h
@@ -7,21 +7,52 @@
#include "slang-syntax.h"
+#include "slang-ast-generated-macro.h"
+
namespace Slang {
+// Macros to generate from ast-generated-macro file the vistors
+
+// Only runs 'param' macro if the marker is NONE (ie not ABSTRACT here)
+#define SLANG_CLASS_ONLY_ABSTRACT(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param)
+#define SLANG_CLASS_ONLY_NONE(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) param(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param)
+
+#define SLANG_CLASS_ONLY(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) SLANG_CLASS_ONLY_##MARKER(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param)
+
+// Dispatch decl
+#define SLANG_VISITOR_DISPATCH_DECL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \
+ virtual void dispatch_##NAME(NAME* obj, void* extra) = 0;
+
+// Dispatch
+
+#define SLANG_VISITOR_DISPATCH_RESULT_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \
+ virtual void dispatch_##NAME(NAME* obj, void* extra) override { *(Result*)extra = ((Derived*) this)->visit##NAME(obj); }
+
+#define SLANG_VISITOR_DISPATCH_VOID_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \
+ virtual void dispatch_##NAME(NAME* obj, void*) override { ((Derived*) this)->visit##NAME(obj); }
+
+// Visitor with and without result
+
+#define SLANG_VISITOR_RESULT_VISIT_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \
+ Result visit##NAME(NAME* obj) { return ((Derived*) this)->visit##SUPER(obj); } \
+
+#define SLANG_VISITOR_VOID_VISIT_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \
+ void visit##NAME(NAME* obj) { ((Derived*) this)->visit##SUPER(obj); }
+
+// Args
+
+#define SLANG_VISITOR_DISPATCH_ARG_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \
+ virtual void dispatch_##NAME(NAME* obj, void* arg) override { ((Derived*) this)->visit##NAME(obj, *(Arg*)arg); }
+
+#define SLANG_VISITOR_VOID_VISIT_ARG_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \
+ void visit##NAME(NAME* obj, Arg const& arg) { ((Derived*) this)->visit##SUPER(obj, arg); }
//
// type Visitors
//
struct ITypeVisitor
{
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void* extra) = 0;
-
-#include "slang-object-meta-begin.h"
-#include "slang-type-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_Type(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL)
};
template<typename Derived, typename Result = void, typename Base = ITypeVisitor>
@@ -41,23 +72,8 @@ struct TypeVisitor : Base
return result;
}
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void* extra) override \
- { *(Result*)extra = ((Derived*) this)->visit##NAME(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-type-defs.h"
-#include "slang-object-meta-end.h"
-
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE)
-#define SYNTAX_CLASS(NAME, BASE) \
- Result visit##NAME(NAME* obj) \
- { return ((Derived*) this)->visit##BASE(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-type-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_Type(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL)
+ SLANG_CHILDREN_ASTNode_Type(SLANG_VISITOR_RESULT_VISIT_IMPL, _)
};
template<typename Derived, typename Base>
@@ -73,23 +89,8 @@ struct TypeVisitor<Derived,void,Base> : Base
type->accept(this, 0);
}
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void*) override \
- { ((Derived*) this)->visit##NAME(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-type-defs.h"
-#include "slang-object-meta-end.h"
-
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE)
-#define SYNTAX_CLASS(NAME, BASE) \
- void visit##NAME(NAME* obj) \
- { ((Derived*) this)->visit##BASE(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-type-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_Type(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL)
+ SLANG_CHILDREN_ASTNode_Type(SLANG_VISITOR_VOID_VISIT_IMPL, _)
};
template<typename Derived, typename Arg, typename Base = ITypeVisitor>
@@ -100,23 +101,8 @@ struct TypeVisitorWithArg : Base
type->accept(this, (void*)&arg);
}
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void* arg) override \
- { ((Derived*) this)->visit##NAME(obj, *(Arg*)arg); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-type-defs.h"
-#include "slang-object-meta-end.h"
-
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE)
-#define SYNTAX_CLASS(NAME, BASE) \
- void visit##NAME(NAME* obj, Arg const& arg) \
- { ((Derived*) this)->visit##BASE(obj, arg); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-type-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_Type(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_ARG_IMPL)
+ SLANG_CHILDREN_ASTNode_Type(SLANG_VISITOR_VOID_VISIT_ARG_IMPL, _)
};
//
@@ -125,13 +111,7 @@ struct TypeVisitorWithArg : Base
struct IExprVisitor
{
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void* extra) = 0;
-
-#include "slang-object-meta-begin.h"
-#include "slang-expr-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_Expr(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL)
};
template<typename Derived, typename Result = void>
@@ -144,23 +124,8 @@ struct ExprVisitor : IExprVisitor
return result;
}
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void* extra) override \
- { *(Result*)extra = ((Derived*) this)->visit##NAME(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-expr-defs.h"
-#include "slang-object-meta-end.h"
-
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE)
-#define SYNTAX_CLASS(NAME, BASE) \
- Result visit##NAME(NAME* obj) \
- { return ((Derived*) this)->visit##BASE(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-expr-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_Expr(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL)
+ SLANG_CHILDREN_ASTNode_Expr(SLANG_VISITOR_RESULT_VISIT_IMPL, _)
};
template<typename Derived>
@@ -171,23 +136,8 @@ struct ExprVisitor<Derived,void> : IExprVisitor
expr->accept(this, 0);
}
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void*) override \
- { ((Derived*) this)->visit##NAME(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-expr-defs.h"
-#include "slang-object-meta-end.h"
-
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE)
-#define SYNTAX_CLASS(NAME, BASE) \
- void visit##NAME(NAME* obj) \
- { ((Derived*) this)->visit##BASE(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-expr-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_Expr(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL)
+ SLANG_CHILDREN_ASTNode_Expr(SLANG_VISITOR_VOID_VISIT_IMPL, _)
};
template<typename Derived, typename Arg>
@@ -198,23 +148,8 @@ struct ExprVisitorWithArg : IExprVisitor
obj->accept(this, (void*)&arg);
}
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void* arg) override \
- { ((Derived*) this)->visit##NAME(obj, *(Arg*)arg); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-expr-defs.h"
-#include "slang-object-meta-end.h"
-
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE)
-#define SYNTAX_CLASS(NAME, BASE) \
- void visit##NAME(NAME* obj, Arg const& arg) \
- { ((Derived*) this)->visit##BASE(obj, arg); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-expr-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_Expr(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_ARG_IMPL)
+ SLANG_CHILDREN_ASTNode_Expr(SLANG_VISITOR_VOID_VISIT_ARG_IMPL, _)
};
//
@@ -223,13 +158,7 @@ struct ExprVisitorWithArg : IExprVisitor
struct IStmtVisitor
{
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void* extra) = 0;
-
-#include "slang-object-meta-begin.h"
-#include "slang-stmt-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_Stmt(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL)
};
template<typename Derived, typename Result = void>
@@ -242,23 +171,8 @@ struct StmtVisitor : IStmtVisitor
return result;
}
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void* extra) override \
- { *(Result*)extra = ((Derived*) this)->visit##NAME(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-stmt-defs.h"
-#include "slang-object-meta-end.h"
-
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE)
-#define SYNTAX_CLASS(NAME, BASE) \
- Result visit##NAME(NAME* obj) \
- { return ((Derived*) this)->visit##BASE(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-stmt-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_Stmt(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL)
+ SLANG_CHILDREN_ASTNode_Stmt(SLANG_VISITOR_RESULT_VISIT_IMPL, _)
};
template<typename Derived>
@@ -269,23 +183,8 @@ struct StmtVisitor<Derived,void> : IStmtVisitor
stmt->accept(this, 0);
}
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void*) override \
- { ((Derived*) this)->visit##NAME(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-stmt-defs.h"
-#include "slang-object-meta-end.h"
-
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE)
-#define SYNTAX_CLASS(NAME, BASE) \
- void visit##NAME(NAME* obj) \
- { ((Derived*) this)->visit##BASE(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-stmt-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_Stmt(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL)
+ SLANG_CHILDREN_ASTNode_Stmt(SLANG_VISITOR_VOID_VISIT_IMPL, _)
};
//
@@ -294,13 +193,7 @@ struct StmtVisitor<Derived,void> : IStmtVisitor
struct IDeclVisitor
{
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void* extra) = 0;
-
-#include "slang-object-meta-begin.h"
-#include "slang-decl-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_DeclBase(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL)
};
template<typename Derived, typename Result = void>
@@ -313,23 +206,8 @@ struct DeclVisitor : IDeclVisitor
return result;
}
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void* extra) override \
- { *(Result*)extra = ((Derived*) this)->visit##NAME(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-decl-defs.h"
-#include "slang-object-meta-end.h"
-
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE)
-#define SYNTAX_CLASS(NAME, BASE) \
- Result visit##NAME(NAME* obj) \
- { return ((Derived*) this)->visit##BASE(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-decl-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_DeclBase(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL)
+ SLANG_CHILDREN_ASTNode_DeclBase(SLANG_VISITOR_RESULT_VISIT_IMPL, _)
};
template<typename Derived>
@@ -340,23 +218,8 @@ struct DeclVisitor<Derived,void> : IDeclVisitor
decl->accept(this, 0);
}
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void*) override \
- { ((Derived*) this)->visit##NAME(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-decl-defs.h"
-#include "slang-object-meta-end.h"
-
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE)
-#define SYNTAX_CLASS(NAME, BASE) \
- void visit##NAME(NAME* obj) \
- { ((Derived*) this)->visit##BASE(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-decl-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_DeclBase(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL)
+ SLANG_CHILDREN_ASTNode_DeclBase(SLANG_VISITOR_VOID_VISIT_IMPL, _)
};
template<typename Derived, typename Arg>
@@ -367,23 +230,8 @@ struct DeclVisitorWithArg : IDeclVisitor
obj->accept(this, (void*)&arg);
}
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void* arg) override \
- { ((Derived*) this)->visit##NAME(obj, *(Arg*)arg); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-decl-defs.h"
-#include "slang-object-meta-end.h"
-
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE)
-#define SYNTAX_CLASS(NAME, BASE) \
- void visit##NAME(NAME* obj, Arg const& arg) \
- { ((Derived*) this)->visit##BASE(obj, arg); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-decl-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_DeclBase(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_ARG_IMPL)
+ SLANG_CHILDREN_ASTNode_DeclBase(SLANG_VISITOR_VOID_VISIT_ARG_IMPL, _)
};
@@ -393,13 +241,7 @@ struct DeclVisitorWithArg : IDeclVisitor
struct IModifierVisitor
{
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void* extra) = 0;
-
-#include "slang-object-meta-begin.h"
-#include "slang-modifier-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_Modifier(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL)
};
template<typename Derived, typename Result = void>
@@ -412,23 +254,8 @@ struct ModifierVisitor : IModifierVisitor
return result;
}
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void* extra) override \
- { *(Result*)extra = ((Derived*) this)->visit##NAME(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-modifier-defs.h"
-#include "slang-object-meta-end.h"
-
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE)
-#define SYNTAX_CLASS(NAME, BASE) \
- Result visit##NAME(NAME* obj) \
- { return ((Derived*) this)->visit##BASE(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-modifier-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_Modifier(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL)
+ SLANG_CHILDREN_ASTNode_Modifier(SLANG_VISITOR_RESULT_VISIT_IMPL, _)
};
template<typename Derived>
@@ -439,23 +266,8 @@ struct ModifierVisitor<Derived, void> : IModifierVisitor
modifier->accept(this, 0);
}
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void*) override \
- { ((Derived*) this)->visit##NAME(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-modifier-defs.h"
-#include "slang-object-meta-end.h"
-
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE)
-#define SYNTAX_CLASS(NAME, BASE) \
- void visit##NAME(NAME* obj) \
- { ((Derived*) this)->visit##BASE(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-modifier-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_Modifier(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL)
+ SLANG_CHILDREN_ASTNode_Modifier(SLANG_VISITOR_VOID_VISIT_IMPL, _)
};
//
@@ -464,13 +276,7 @@ struct ModifierVisitor<Derived, void> : IModifierVisitor
struct IValVisitor : ITypeVisitor
{
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void* extra) = 0;
-
-#include "slang-object-meta-begin.h"
-#include "slang-val-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_Val(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL)
};
template<typename Derived, typename Result = void, typename TypeResult = void>
@@ -483,23 +289,8 @@ struct ValVisitor : TypeVisitor<Derived, TypeResult, IValVisitor>
return result;
}
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void* extra) override \
- { *(Result*)extra = ((Derived*) this)->visit##NAME(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-val-defs.h"
-#include "slang-object-meta-end.h"
-
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE)
-#define SYNTAX_CLASS(NAME, BASE) \
- Result visit##NAME(NAME* obj) \
- { return ((Derived*) this)->visit##BASE(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-val-defs.h"
-#include "slang-object-meta-end.h"
+ SLANG_CHILDREN_ASTNode_Val(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL)
+ SLANG_CHILDREN_ASTNode_Val(SLANG_VISITOR_RESULT_VISIT_IMPL, _)
};
template<typename Derived>
@@ -510,24 +301,8 @@ struct ValVisitor<Derived, void, void> : TypeVisitor<Derived, void, IValVisitor>
val->accept(this, 0);
}
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
-#define SYNTAX_CLASS(NAME, BASE) \
- virtual void dispatch_##NAME(NAME* obj, void*) override \
- { ((Derived*) this)->visit##NAME(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-val-defs.h"
-#include "slang-object-meta-end.h"
-
-#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE)
-#define SYNTAX_CLASS(NAME, BASE) \
- void visit##NAME(NAME* obj) \
- { ((Derived*) this)->visit##BASE(obj); }
-
-#include "slang-object-meta-begin.h"
-#include "slang-val-defs.h"
-#include "slang-object-meta-end.h"
-
+ SLANG_CHILDREN_ASTNode_Val(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL)
+ SLANG_CHILDREN_ASTNode_Val(SLANG_VISITOR_VOID_VISIT_IMPL, _)
};
}
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 1f8f79af2..34f1402b5 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -116,19 +116,19 @@ void Session::init()
// Set all the shared library function pointers to nullptr
::memset(m_sharedLibraryFunctions, 0, sizeof(m_sharedLibraryFunctions));
- {
- static auto res = SyntaxClassBase::ClassInfo::initRanges();
- }
-
+
// Initialize the lookup table of syntax classes:
// We can just iterate over the class pointers.
// NOTE! That this adds the names of the abstract classes too(!)
{
- const SyntaxClassBase::ClassInfo* info = SyntaxClassBase::ClassInfo::s_first;
- for (; info; info = info->m_next)
+ for (Index i = 0; i < Index(ASTNodeType::CountOf); ++i)
{
- mapNameToSyntaxClass.Add(getNamePool()->getName(info->m_name), SyntaxClass<Slang::RefObject>(info));
+ const ReflectClassInfo* info = ReflectClassInfo::getInfo(ASTNodeType(i));
+ if (info)
+ {
+ mapNameToSyntaxClass.Add(getNamePool()->getName(info->m_name), SyntaxClass<Slang::RefObject>(info));
+ }
}
}
diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj
index e97d38256..cf5a81499 100644
--- a/source/slang/slang.vcxproj
+++ b/source/slang/slang.vcxproj
@@ -189,10 +189,20 @@
<ClInclude Include="..\..\slang.h" />
<ClInclude Include="core.meta.slang.h" />
<ClInclude Include="hlsl.meta.slang.h" />
+ <ClInclude Include="slang-ast-all.h" />
+ <ClInclude Include="slang-ast-base.h" />
+ <ClInclude Include="slang-ast-decl.h" />
+ <ClInclude Include="slang-ast-expr.h" />
+ <ClInclude Include="slang-ast-generated-macro.h" />
+ <ClInclude Include="slang-ast-generated.h" />
+ <ClInclude Include="slang-ast-modifier.h" />
+ <ClInclude Include="slang-ast-stmt.h" />
+ <ClInclude Include="slang-ast-support-types.h" />
+ <ClInclude Include="slang-ast-type.h" />
+ <ClInclude Include="slang-ast-val.h" />
<ClInclude Include="slang-check-impl.h" />
<ClInclude Include="slang-check.h" />
<ClInclude Include="slang-compiler.h" />
- <ClInclude Include="slang-decl-defs.h" />
<ClInclude Include="slang-diagnostic-defs.h" />
<ClInclude Include="slang-diagnostics.h" />
<ClInclude Include="slang-emit-c-like.h" />
@@ -203,7 +213,6 @@
<ClInclude Include="slang-emit-precedence.h" />
<ClInclude Include="slang-emit-source-writer.h" />
<ClInclude Include="slang-emit.h" />
- <ClInclude Include="slang-expr-defs.h" />
<ClInclude Include="slang-file-system.h" />
<ClInclude Include="slang-glsl-extension-tracker.h" />
<ClInclude Include="slang-hlsl-intrinsic-set.h" />
@@ -244,10 +253,7 @@
<ClInclude Include="slang-lower-to-ir.h" />
<ClInclude Include="slang-mangle.h" />
<ClInclude Include="slang-mangled-lexer.h" />
- <ClInclude Include="slang-modifier-defs.h" />
<ClInclude Include="slang-name.h" />
- <ClInclude Include="slang-object-meta-begin.h" />
- <ClInclude Include="slang-object-meta-end.h" />
<ClInclude Include="slang-options.h" />
<ClInclude Include="slang-parameter-binding.h" />
<ClInclude Include="slang-parser.h" />
@@ -257,19 +263,15 @@
<ClInclude Include="slang-reflection.h" />
<ClInclude Include="slang-source-loc.h" />
<ClInclude Include="slang-state-serialize.h" />
- <ClInclude Include="slang-stmt-defs.h" />
- <ClInclude Include="slang-syntax-base-defs.h" />
- <ClInclude Include="slang-syntax-defs.h" />
<ClInclude Include="slang-syntax.h" />
<ClInclude Include="slang-token-defs.h" />
<ClInclude Include="slang-token.h" />
- <ClInclude Include="slang-type-defs.h" />
<ClInclude Include="slang-type-layout.h" />
<ClInclude Include="slang-type-system-shared.h" />
- <ClInclude Include="slang-val-defs.h" />
<ClInclude Include="slang-visitor.h" />
</ItemGroup>
<ItemGroup>
+ <ClCompile Include="slang-ast-reflect.cpp" />
<ClCompile Include="slang-check-conformance.cpp" />
<ClCompile Include="slang-check-constraint.cpp" />
<ClCompile Include="slang-check-conversion.cpp" />
@@ -378,6 +380,19 @@
<ItemGroup>
<Natvis Include="..\core\core.natvis" />
<Natvis Include="slang.natvis" />
+ <CustomBuild Include="slang-ast-reflect.h">
+ <FileType>Document</FileType>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"../../bin/windows-x86/debug/slang-cpp-extractor" -d %(RootDir)%(Directory)/ slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast- -o slang-ast-generated</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"../../bin/windows-x64/debug/slang-cpp-extractor" -d %(RootDir)%(Directory)/ slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast- -o slang-ast-generated</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"../../bin/windows-x86/release/slang-cpp-extractor" -d %(RootDir)%(Directory)/ slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast- -o slang-ast-generated</Command>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"../../bin/windows-x64/release/slang-cpp-extractor" -d %(RootDir)%(Directory)/ slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast- -o slang-ast-generated</Command>
+ <Outputs>%(RootDir)%(Directory)/slang-ast-generated.h;%(RootDir)%(Directory)/slang-ast-generated-macro.h</Outputs>
+ <Message>slang-cpp-extractor AST %(Identity)</Message>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../bin/windows-x86/debug/slang-cpp-extractor.exe;%(RootDir)%(Directory)/slang-ast-base.h;%(RootDir)%(Directory)/slang-ast-decl.h;%(RootDir)%(Directory)/slang-ast-expr.h;%(RootDir)%(Directory)/slang-ast-modifier.h;%(RootDir)%(Directory)/slang-ast-stmt.h;%(RootDir)%(Directory)/slang-ast-type.h;%(RootDir)%(Directory)/slang-ast-val.h</AdditionalInputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../bin/windows-x64/debug/slang-cpp-extractor.exe;%(RootDir)%(Directory)/slang-ast-base.h;%(RootDir)%(Directory)/slang-ast-decl.h;%(RootDir)%(Directory)/slang-ast-expr.h;%(RootDir)%(Directory)/slang-ast-modifier.h;%(RootDir)%(Directory)/slang-ast-stmt.h;%(RootDir)%(Directory)/slang-ast-type.h;%(RootDir)%(Directory)/slang-ast-val.h</AdditionalInputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../bin/windows-x86/release/slang-cpp-extractor.exe;%(RootDir)%(Directory)/slang-ast-base.h;%(RootDir)%(Directory)/slang-ast-decl.h;%(RootDir)%(Directory)/slang-ast-expr.h;%(RootDir)%(Directory)/slang-ast-modifier.h;%(RootDir)%(Directory)/slang-ast-stmt.h;%(RootDir)%(Directory)/slang-ast-type.h;%(RootDir)%(Directory)/slang-ast-val.h</AdditionalInputs>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../bin/windows-x64/release/slang-cpp-extractor.exe;%(RootDir)%(Directory)/slang-ast-base.h;%(RootDir)%(Directory)/slang-ast-decl.h;%(RootDir)%(Directory)/slang-ast-expr.h;%(RootDir)%(Directory)/slang-ast-modifier.h;%(RootDir)%(Directory)/slang-ast-stmt.h;%(RootDir)%(Directory)/slang-ast-type.h;%(RootDir)%(Directory)/slang-ast-val.h</AdditionalInputs>
+ </CustomBuild>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\core\core.vcxproj">
diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters
index f46e77ebc..4060a6019 100644
--- a/source/slang/slang.vcxproj.filters
+++ b/source/slang/slang.vcxproj.filters
@@ -18,6 +18,39 @@
<ClInclude Include="hlsl.meta.slang.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="slang-ast-all.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="slang-ast-base.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="slang-ast-decl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="slang-ast-expr.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="slang-ast-generated-macro.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="slang-ast-generated.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="slang-ast-modifier.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="slang-ast-stmt.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="slang-ast-support-types.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="slang-ast-type.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="slang-ast-val.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="slang-check-impl.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -27,9 +60,6 @@
<ClInclude Include="slang-compiler.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="slang-decl-defs.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="slang-diagnostic-defs.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -60,9 +90,6 @@
<ClInclude Include="slang-emit.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="slang-expr-defs.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="slang-file-system.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -183,18 +210,9 @@
<ClInclude Include="slang-mangled-lexer.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="slang-modifier-defs.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="slang-name.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="slang-object-meta-begin.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="slang-object-meta-end.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="slang-options.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -222,15 +240,6 @@
<ClInclude Include="slang-state-serialize.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="slang-stmt-defs.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="slang-syntax-base-defs.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="slang-syntax-defs.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="slang-syntax.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -240,23 +249,20 @@
<ClInclude Include="slang-token.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="slang-type-defs.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="slang-type-layout.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="slang-type-system-shared.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="slang-val-defs.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="slang-visitor.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
+ <ClCompile Include="slang-ast-reflect.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="slang-check-conformance.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -501,5 +507,11 @@
<Natvis Include="slang.natvis">
<Filter>Source Files</Filter>
</Natvis>
+ <CustomBuild Include="hlsl.meta.slang">
+ <Filter>Source Files</Filter>
+ </CustomBuild>
+ <CustomBuild Include="slang-ast-reflect.h">
+ <Filter>Header Files</Filter>
+ </CustomBuild>
</ItemGroup>
</Project> \ No newline at end of file