summaryrefslogtreecommitdiffstats
path: root/source/slang/syntax.h
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/syntax.h')
-rw-r--r--source/slang/syntax.h2771
1 files changed, 2771 insertions, 0 deletions
diff --git a/source/slang/syntax.h b/source/slang/syntax.h
new file mode 100644
index 000000000..9e4486d4e
--- /dev/null
+++ b/source/slang/syntax.h
@@ -0,0 +1,2771 @@
+#ifndef RASTER_RENDERER_SYNTAX_H
+#define RASTER_RENDERER_SYNTAX_H
+
+#include "../core/basic.h"
+#include "Lexer.h"
+#include "Profile.h"
+
+#include "../../Slang.h"
+
+#include <assert.h>
+
+namespace Slang
+{
+ namespace Compiler
+ {
+ using namespace CoreLib::Basic;
+ class SyntaxVisitor;
+ class FunctionSyntaxNode;
+
+ class SyntaxNodeBase : public RefObject
+ {
+ public:
+ CodePosition Position;
+ };
+
+
+
+
+ //
+ // Other modifiers may have more elaborate data, and so
+ // are represented as heap-allocated objects, in a linked
+ // list.
+ //
+ class Modifier : public SyntaxNodeBase
+ {
+ public:
+ // Next modifier in linked list of modifiers on same piece of syntax
+ RefPtr<Modifier> next;
+
+ // The token that was used to name this modifier.
+ Token nameToken;
+ };
+
+#define SIMPLE_MODIFIER(NAME) \
+ class NAME##Modifier : public Modifier {}
+
+ SIMPLE_MODIFIER(Uniform);
+ 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);
+
+#undef SIMPLE_MODIFIER
+
+ enum class IntrinsicOp
+ {
+ Unknown = 0,
+#define INTRINSIC(NAME) NAME,
+#include "intrinsic-defs.h"
+ };
+
+ IntrinsicOp findIntrinsicOp(char const* name);
+
+ class IntrinsicModifier : public Modifier
+ {
+ public:
+ // token that names the intrinsic op
+ Token opToken;
+
+ // The opcode for the intrinsic operation
+ IntrinsicOp op = IntrinsicOp::Unknown;
+ };
+
+
+ class InOutModifier : public OutModifier {};
+
+ // 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 {};
+
+ // 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
+ {
+ public:
+ // THe token used to introduce the modifier is stored
+ // as the `nameToken` field.
+
+ // TODO: may want to accept a full expression here
+ Token valToken;
+ };
+
+ // 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 {};
+ class GLSLUnparsedLayoutModifier : public GLSLLayoutModifier {};
+
+ // Specific cases for known GLSL `layout` modifiers that we need to work with
+ class GLSLConstantIDLayoutModifier : public GLSLParsedLayoutModifier {};
+ class GLSLBindingLayoutModifier : public GLSLParsedLayoutModifier {};
+ class GLSLSetLayoutModifier : public GLSLParsedLayoutModifier {};
+ class GLSLLocationLayoutModifier : public GLSLParsedLayoutModifier {};
+
+ // A catch-all for single-keyword modifiers
+ class SimpleModifier : public Modifier {};
+
+ // Some GLSL-specific modifiers
+ class GLSLBufferModifier : public SimpleModifier {};
+ class GLSLWriteOnlyModifier : public SimpleModifier {};
+ class GLSLReadOnlyModifier : public SimpleModifier {};
+ class GLSLPatchModifier : public SimpleModifier {};
+
+ // Indicates that this is a variable declaration that corresponds to
+ // a parameter block declaration in the source program.
+ class ImplicitParameterBlockVariableModifier : public Modifier {};
+
+ // Indicates that this is a type that corresponds to the element
+ // type of a parameter block declaration in the source program.
+ class ImplicitParameterBlockElementTypeModifier : public Modifier {};
+
+ // An HLSL semantic
+ class HLSLSemantic : public Modifier
+ {
+ public:
+ Token name;
+ };
+
+
+ // An HLSL semantic that affects layout
+ class HLSLLayoutSemantic : public HLSLSemantic
+ {
+ public:
+ Token registerName;
+ Token componentMask;
+ };
+
+ // An HLSL `register` semantic
+ class HLSLRegisterSemantic : public HLSLLayoutSemantic
+ {
+ };
+
+ // TODO(tfoley): `packoffset`
+ class HLSLPackOffsetSemantic : public HLSLLayoutSemantic
+ {
+ };
+
+ // An HLSL semantic that just associated a declaration with a semantic name
+ class HLSLSimpleSemantic : public HLSLSemantic
+ {
+ };
+
+ // GLSL
+
+ // Directives that came in via the preprocessor, but
+ // that we need to keep around for later steps
+ class GLSLPreprocessorDirective : public Modifier
+ {
+ };
+
+ // A GLSL `#version` directive
+ class GLSLVersionDirective : public GLSLPreprocessorDirective
+ {
+ public:
+ // 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
+ {
+ public:
+ // Token giving the version number to use
+ Token extensionNameToken;
+
+ // Optional token giving the sub-profile to be used
+ Token dispositionToken;
+ };
+
+ class ParameterBlockReflectionName : public Modifier
+ {
+ public:
+ Token nameToken;
+ };
+
+ // Helper class for iterating over a list of heap-allocated modifiers
+ struct ModifierList
+ {
+ struct Iterator
+ {
+ Modifier* current;
+
+ Modifier* operator*()
+ {
+ return current;
+ }
+
+ void operator++()
+ {
+ current = current->next.Ptr();
+ }
+
+ 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++()
+ {
+ current = Adjust(current->next.Ptr());
+ }
+
+ 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)
+ {
+ Modifier* m = modifier;
+ for (;;)
+ {
+ if (!m) return m;
+ if (dynamic_cast<T*>(m)) return m;
+ m = m->next.Ptr();
+ }
+ }
+
+ 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); }
+ };
+
+
+ enum class BaseType
+ {
+ // Note(tfoley): These are ordered in terms of promotion rank, so be vareful when messing with this
+
+ Void = 0,
+ Bool,
+ Int,
+ UInt,
+ UInt64,
+ Float,
+#if 0
+ Texture2D = 48,
+ TextureCube = 49,
+ Texture2DArray = 50,
+ Texture2DShadow = 51,
+ TextureCubeShadow = 52,
+ Texture2DArrayShadow = 53,
+ Texture3D = 54,
+ SamplerState = 4096, SamplerComparisonState = 4097,
+ Error = 16384,
+#endif
+ };
+
+ class Decl;
+ class StructSyntaxNode;
+ class BasicExpressionType;
+ class ArrayExpressionType;
+ class TypeDefDecl;
+ class DeclRefType;
+ class NamedExpressionType;
+ class TypeType;
+ class GenericDeclRefType;
+ class VectorExpressionType;
+ class MatrixExpressionType;
+ class ArithmeticExpressionType;
+ class GenericDecl;
+ class Substitutions;
+ class TextureType;
+ class SamplerStateType;
+
+ // A compile-time constant value (usually a type)
+ class Val : public RefObject
+ {
+ public:
+ // construct a new value by applying a set of parameter
+ // substitutions to this one
+ RefPtr<Val> Substitute(Substitutions* subst);
+
+ // Lower-level interface for substition. Like the basic
+ // `Substitute` above, but also takes a by-reference
+ // integer parameter that should be incremented when
+ // returning a modified value (this can help the caller
+ // decide whether they need to do anything).
+ virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff);
+
+ virtual bool EqualsVal(Val* val) = 0;
+ virtual String ToString() = 0;
+ virtual int GetHashCode() = 0;
+ bool operator == (const Val & v)
+ {
+ return EqualsVal(const_cast<Val*>(&v));
+ }
+ };
+
+ // A compile-time integer (may not have a specific concrete value)
+ class IntVal : public Val
+ {
+ };
+
+ // Try to extract a simple integer value from an `IntVal`.
+ // This fill assert-fail if the object doesn't represent a literal value.
+ int GetIntVal(RefPtr<IntVal> val);
+
+ // Trivial case of a value that is just a constant integer
+ class ConstantIntVal : public IntVal
+ {
+ public:
+ int value;
+
+ ConstantIntVal(int value)
+ : value(value)
+ {}
+
+ virtual bool EqualsVal(Val* val) override;
+ virtual String ToString() override;
+ virtual int GetHashCode() override;
+ };
+
+ // TODO(tfoley): classes for more general compile-time integers,
+ // including references to template parameters
+
+ // A type, representing a classifier for some term in the AST.
+ //
+ // Types can include "sugar" in that they may refer to a
+ // `typedef` which gives them a good name when printed as
+ // part of diagnostic messages.
+ //
+ // In order to operation on types, though, we often want
+ // to look past any sugar, and operate on an underlying
+ // "canonical" type. The reprsentation caches a pointer to
+ // a canonical type on every type, so we can easily
+ // operate on the raw representation when needed.
+ class ExpressionType : public Val
+ {
+ public:
+ static RefPtr<ExpressionType> Error;
+ static RefPtr<ExpressionType> initializerListType;
+ static RefPtr<ExpressionType> Overloaded;
+
+ static Dictionary<int, RefPtr<ExpressionType>> sBuiltinTypes;
+ static Dictionary<String, Decl*> sMagicDecls;
+
+ // Note: just exists to make sure we can clean up
+ // canonical types we create along the way
+ static List<RefPtr<ExpressionType>> sCanonicalTypes;
+
+
+
+ static ExpressionType* GetBool();
+ static ExpressionType* GetFloat();
+ static ExpressionType* GetInt();
+ static ExpressionType* GetUInt();
+ static ExpressionType* GetVoid();
+ static ExpressionType* getInitializerListType();
+ static ExpressionType* GetError();
+
+ public:
+ virtual String ToString() = 0;
+
+ bool Equals(ExpressionType * type);
+ bool Equals(RefPtr<ExpressionType> type);
+
+ bool IsVectorType() { return As<VectorExpressionType>() != nullptr; }
+ bool IsArray() { return As<ArrayExpressionType>() != nullptr; }
+
+ template<typename T>
+ T* As()
+ {
+ return dynamic_cast<T*>(GetCanonicalType());
+ }
+
+ // Convenience/legacy wrappers for `As<>`
+ ArithmeticExpressionType * AsArithmeticType() { return As<ArithmeticExpressionType>(); }
+ BasicExpressionType * AsBasicType() { return As<BasicExpressionType>(); }
+ VectorExpressionType * AsVectorType() { return As<VectorExpressionType>(); }
+ MatrixExpressionType * AsMatrixType() { return As<MatrixExpressionType>(); }
+ ArrayExpressionType * AsArrayType() { return As<ArrayExpressionType>(); }
+
+ DeclRefType* AsDeclRefType() { return As<DeclRefType>(); }
+
+ NamedExpressionType* AsNamedType();
+
+ bool IsTextureOrSampler();
+ bool IsTexture() { return As<TextureType>() != nullptr; }
+ bool IsSampler() { return As<SamplerStateType>() != nullptr; }
+ bool IsStruct();
+ bool IsClass();
+ static void Init();
+ static void Finalize();
+ ExpressionType* GetCanonicalType();
+
+ virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff) override;
+
+ virtual bool EqualsVal(Val* val) override;
+ protected:
+ virtual bool EqualsImpl(ExpressionType * type) = 0;
+
+ virtual ExpressionType* CreateCanonicalType() = 0;
+ ExpressionType* canonicalType = nullptr;
+ };
+
+ // A substitution represents a binding of certain
+ // type-level variables to concrete argument values
+ class Substitutions : public RefObject
+ {
+ public:
+ // The generic declaration that defines the
+ // parametesr we are binding to arguments
+ GenericDecl* genericDecl;
+
+ // The actual values of the arguments
+ List<RefPtr<Val>> args;
+
+ // Any further substitutions, relating to outer generic declarations
+ RefPtr<Substitutions> outer;
+
+ // Apply a set of substitutions to the bindings in this substitution
+ RefPtr<Substitutions> SubstituteImpl(Substitutions* subst, int* ioDiff);
+
+ // Check if these are equivalent substitutiosn to another set
+ bool Equals(Substitutions* subst);
+ bool operator == (const Substitutions & subst)
+ {
+ return Equals(const_cast<Substitutions*>(&subst));
+ }
+ int GetHashCode() const
+ {
+ int rs = 0;
+ for (auto && v : args)
+ {
+ rs ^= v->GetHashCode();
+ rs *= 16777619;
+ }
+ return rs;
+ }
+ };
+
+ class SyntaxNode : public SyntaxNodeBase
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) = 0;
+ };
+
+ class ContainerDecl;
+ class SpecializeModifier;
+
+ // Represents how much checking has been applied to a declaration.
+ enum class DeclCheckState : uint8_t
+ {
+ // The declaration has been parsed, but not checked
+ Unchecked,
+
+ // We are in the process of checking the declaration "header"
+ // (those parts of the declaration needed in order to
+ // reference it)
+ CheckingHeader,
+
+ // We are done checking the declaration header.
+ CheckedHeader,
+
+ // We have checked the declaration fully.
+ Checked,
+ };
+
+ // A syntax node which can have modifiers appled
+ class ModifiableSyntaxNode : public SyntaxNode
+ {
+ public:
+ Modifiers modifiers;
+
+ template<typename T>
+ FilteredModifierList<T> GetModifiersOfType() { return FilteredModifierList<T>(modifiers.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; }
+ };
+
+ void addModifier(
+ RefPtr<ModifiableSyntaxNode> syntax,
+ RefPtr<Modifier> modifier);
+
+
+ // An intermediate type to represent either a single declaration, or a group of declarations
+ class DeclBase : public ModifiableSyntaxNode
+ {
+ public:
+ };
+
+ class Decl : public DeclBase
+ {
+ public:
+ ContainerDecl* ParentDecl;
+
+ Token Name;
+ String const& getName() { return Name.Content; }
+ Token const& getNameToken() { return Name; }
+
+
+ DeclCheckState checkState = DeclCheckState::Unchecked;
+
+ // The next declaration defined in the same container with the same name
+ Decl* nextInContainerWithSameName = nullptr;
+
+ bool IsChecked(DeclCheckState state) { return checkState >= state; }
+ void SetCheckState(DeclCheckState state)
+ {
+ assert(state >= checkState);
+ checkState = state;
+ }
+ };
+
+ struct QualType
+ {
+ RefPtr<ExpressionType> type;
+ bool IsLeftValue;
+
+ QualType()
+ : IsLeftValue(false)
+ {}
+
+ QualType(RefPtr<ExpressionType> type)
+ : type(type)
+ , IsLeftValue(false)
+ {}
+
+ QualType(ExpressionType* type)
+ : type(type)
+ , IsLeftValue(false)
+ {}
+
+ void operator=(RefPtr<ExpressionType> t)
+ {
+ *this = QualType(t);
+ }
+
+ void operator=(ExpressionType* t)
+ {
+ *this = QualType(t);
+ }
+
+ ExpressionType* Ptr() { return type.Ptr(); }
+
+ operator RefPtr<ExpressionType>() { return type; }
+ RefPtr<ExpressionType> operator->() { return type; }
+ };
+
+ class ExpressionSyntaxNode : public SyntaxNode
+ {
+ public:
+ QualType Type;
+ ExpressionSyntaxNode()
+ {}
+ };
+
+
+
+
+ // A reference to a declaration, which may include
+ // substitutions for generic parameters.
+ struct DeclRef
+ {
+ typedef Decl DeclType;
+
+ // The underlying declaration
+ Decl* decl = nullptr;
+ Decl* GetDecl() const { return decl; }
+
+ // Optionally, a chain of substititions to perform
+ RefPtr<Substitutions> substitutions;
+
+ DeclRef()
+ {}
+
+ DeclRef(Decl* decl, RefPtr<Substitutions> substitutions)
+ : decl(decl)
+ , substitutions(substitutions)
+ {}
+
+ // Apply substitutions to a type or ddeclaration
+ RefPtr<ExpressionType> Substitute(RefPtr<ExpressionType> type) const;
+ DeclRef Substitute(DeclRef declRef) const;
+
+ // Apply substitutions to an expression
+ RefPtr<ExpressionSyntaxNode> Substitute(RefPtr<ExpressionSyntaxNode> expr) const;
+
+ // Apply substitutions to this declaration reference
+ DeclRef SubstituteImpl(Substitutions* subst, int* ioDiff);
+
+ // Check if this is an equivalent declaration reference to another
+ bool Equals(DeclRef const& declRef) const;
+ bool operator == (const DeclRef& other) const
+ {
+ return Equals(other);
+ }
+
+ // Convenience accessors for common properties of declarations
+ String const& GetName() const;
+ DeclRef GetParent() const;
+
+ // "dynamic cast" to a more specific declaration reference type
+ template<typename T>
+ T As() const
+ {
+ T result;
+ result.decl = dynamic_cast<T::DeclType*>(decl);
+ result.substitutions = substitutions;
+ return result;
+ }
+
+ // Implicit conversion mostly so we can use a `DeclRef`
+ // in a conditional context
+ operator Decl*() const
+ {
+ return decl;
+ }
+
+ int GetHashCode() const;
+ };
+
+ // Helper macro for defining `DeclRef` subtypes
+ #define SLANG_DECLARE_DECL_REF(D) \
+ typedef D DeclType; \
+ D* GetDecl() const { return (D*) decl; } \
+ /* */
+
+
+
+ // The type of a reference to an overloaded name
+ class OverloadGroupType : public ExpressionType
+ {
+ public:
+ virtual String ToString() override;
+
+ protected:
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ virtual int GetHashCode() override;
+ };
+
+ // The type of an initializer-list expression (before it has
+ // been coerced to some other type)
+ class InitializerListType : public ExpressionType
+ {
+ public:
+ virtual String ToString() override;
+
+ protected:
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ virtual int GetHashCode() override;
+ };
+
+ // The type of an expression that was erroneous
+ class ErrorType : public ExpressionType
+ {
+ public:
+ virtual String ToString() override;
+
+ protected:
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ virtual int GetHashCode() override;
+ };
+
+ // A type that takes the form of a reference to some declaration
+ class DeclRefType : public ExpressionType
+ {
+ public:
+ DeclRef declRef;
+
+ virtual String ToString() override;
+ virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff) override;
+
+ static DeclRefType* Create(DeclRef declRef);
+
+ protected:
+ DeclRefType()
+ {}
+ DeclRefType(DeclRef declRef)
+ : declRef(declRef)
+ {}
+ virtual int GetHashCode() override;
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ };
+
+ // Base class for types that can be used in arithmetic expressions
+ class ArithmeticExpressionType : public DeclRefType
+ {
+ public:
+ virtual BasicExpressionType* GetScalarType() = 0;
+ };
+
+ class FunctionDeclBase;
+
+ class BasicExpressionType : public ArithmeticExpressionType
+ {
+ public:
+ BaseType BaseType;
+
+ BasicExpressionType()
+ {
+ BaseType = Compiler::BaseType::Int;
+ }
+ BasicExpressionType(Compiler::BaseType baseType)
+ {
+ BaseType = baseType;
+ }
+ virtual CoreLib::Basic::String ToString() override;
+ protected:
+ virtual BasicExpressionType* GetScalarType() override;
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ };
+
+
+ class TextureTypeBase : public DeclRefType
+ {
+ public:
+ // The type that results from fetching an element from this texture
+ RefPtr<ExpressionType> elementType;
+
+ // Bits representing the kind of texture type we are looking at
+ // (e.g., `Texture2DMS` vs. `TextureCubeArray`)
+ typedef uint16_t Flavor;
+ Flavor flavor;
+
+ enum
+ {
+ // Mask for the overall "shape" of the texture
+ ShapeMask = SLANG_RESOURCE_BASE_SHAPE_MASK,
+
+ // Flag for whether the shape has "array-ness"
+ ArrayFlag = SLANG_TEXTURE_ARRAY_FLAG,
+
+ // Whether or not the texture stores multiple samples per pixel
+ MultisampleFlag = SLANG_TEXTURE_MULTISAMPLE_FLAG,
+
+ // Whether or not this is a shadow texture
+ //
+ // TODO(tfoley): is this even meaningful/used?
+ // ShadowFlag = 0x80,
+ };
+
+ enum Shape : uint8_t
+ {
+ Shape1D = SLANG_TEXTURE_1D,
+ Shape2D = SLANG_TEXTURE_2D,
+ Shape3D = SLANG_TEXTURE_3D,
+ ShapeCube = SLANG_TEXTURE_CUBE,
+
+ Shape1DArray = Shape1D | ArrayFlag,
+ Shape2DArray = Shape2D | ArrayFlag,
+ // No Shape3DArray
+ ShapeCubeArray = ShapeCube | ArrayFlag,
+ };
+
+
+ Shape GetBaseShape() const { return Shape(flavor & ShapeMask); }
+ bool isArray() const { return (flavor & ArrayFlag) != 0; }
+ bool isMultisample() const { return (flavor & MultisampleFlag) != 0; }
+// bool isShadow() const { return (flavor & ShadowFlag) != 0; }
+
+ SlangResourceShape getShape() const { return flavor & 0xFF; }
+ SlangResourceAccess getAccess() const { return (flavor >> 8) & 0xFF; }
+
+ TextureTypeBase(
+ Flavor flavor,
+ RefPtr<ExpressionType> elementType)
+ : elementType(elementType)
+ , flavor(flavor)
+ {}
+ };
+
+ class TextureType : public TextureTypeBase
+ {
+ public:
+ TextureType(
+ Flavor flavor,
+ RefPtr<ExpressionType> elementType)
+ : TextureTypeBase(flavor, elementType)
+ {}
+ };
+
+ // This is a base type for texture/sampler pairs,
+ // as they exist in, e.g., GLSL
+ class TextureSamplerType : public TextureTypeBase
+ {
+ public:
+ TextureSamplerType(
+ Flavor flavor,
+ RefPtr<ExpressionType> elementType)
+ : TextureTypeBase(flavor, elementType)
+ {}
+ };
+
+ // This is a base type for `image*` types, as they exist in GLSL
+ class GLSLImageType : public TextureTypeBase
+ {
+ public:
+ GLSLImageType(
+ Flavor flavor,
+ RefPtr<ExpressionType> elementType)
+ : TextureTypeBase(flavor, elementType)
+ {}
+ };
+
+ class SamplerStateType : public DeclRefType
+ {
+ public:
+ // What flavor of sampler state is this
+ enum class Flavor : uint8_t
+ {
+ SamplerState,
+ SamplerComparisonState,
+ };
+ Flavor flavor;
+ };
+
+ // Other cases of generic types known to the compiler
+ class BuiltinGenericType : public DeclRefType
+ {
+ public:
+ RefPtr<ExpressionType> elementType;
+ };
+
+ // Types that behave like pointers, in that they can be
+ // dereferenced (implicitly) to access members defined
+ // in the element type.
+ class PointerLikeType : public BuiltinGenericType
+ {};
+
+ // Generic types used in existing Slang code
+ // TODO(tfoley): check that these are actually working right...
+ class PatchType : public PointerLikeType {};
+ class StorageBufferType : public BuiltinGenericType {};
+ class UniformBufferType : public PointerLikeType {};
+ class PackedBufferType : public BuiltinGenericType {};
+
+ // HLSL buffer-type resources
+
+ class HLSLBufferType : public BuiltinGenericType {};
+ class HLSLRWBufferType : public BuiltinGenericType {};
+ class HLSLStructuredBufferType : public BuiltinGenericType {};
+ class HLSLRWStructuredBufferType : public BuiltinGenericType {};
+
+ class UntypedBufferResourceType : public DeclRefType {};
+ class HLSLByteAddressBufferType : public UntypedBufferResourceType {};
+ class HLSLRWByteAddressBufferType : public UntypedBufferResourceType {};
+
+ class HLSLAppendStructuredBufferType : public BuiltinGenericType {};
+ class HLSLConsumeStructuredBufferType : public BuiltinGenericType {};
+
+ class HLSLInputPatchType : public BuiltinGenericType {};
+ class HLSLOutputPatchType : public BuiltinGenericType {};
+
+ // HLSL geometry shader output stream types
+
+ class HLSLStreamOutputType : public BuiltinGenericType {};
+ class HLSLPointStreamType : public HLSLStreamOutputType {};
+ class HLSLLineStreamType : public HLSLStreamOutputType {};
+ class HLSLTriangleStreamType : public HLSLStreamOutputType {};
+
+ //
+ class GLSLInputAttachmentType : public DeclRefType {};
+
+ // Base class for types used when desugaring parameter block
+ // declarations, includeing HLSL `cbuffer` or GLSL `uniform` blocks.
+ class ParameterBlockType : public PointerLikeType {};
+
+ class UniformParameterBlockType : public ParameterBlockType {};
+ class VaryingParameterBlockType : public ParameterBlockType {};
+
+ // Type for HLSL `cbuffer` declarations, and `ConstantBuffer<T>`
+ // ALso used for GLSL `uniform` blocks.
+ class ConstantBufferType : public UniformParameterBlockType {};
+
+ // Type for HLSL `tbuffer` declarations, and `TextureBuffer<T>`
+ class TextureBufferType : public UniformParameterBlockType {};
+
+ // Type for GLSL `in` and `out` blocks
+ class GLSLInputParameterBlockType : public VaryingParameterBlockType {};
+ class GLSLOutputParameterBlockType : public VaryingParameterBlockType {};
+
+ // Type for GLLSL `buffer` blocks
+ class GLSLShaderStorageBufferType : public UniformParameterBlockType {};
+
+ class ArrayExpressionType : public ExpressionType
+ {
+ public:
+ RefPtr<ExpressionType> BaseType;
+ RefPtr<IntVal> ArrayLength;
+ virtual CoreLib::Basic::String ToString() override;
+ protected:
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ virtual int GetHashCode() override;
+ };
+
+ // 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)`.
+ class TypeType : public ExpressionType
+ {
+ public:
+ TypeType(RefPtr<ExpressionType> type)
+ : type(type)
+ {}
+
+ // The type that this is the type of...
+ RefPtr<ExpressionType> type;
+
+
+ virtual String ToString() override;
+
+ protected:
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ virtual int GetHashCode() override;
+ };
+
+ class GenericDecl;
+
+ // A vector type, e.g., `vector<T,N>`
+ class VectorExpressionType : public ArithmeticExpressionType
+ {
+ public:
+#if 0
+ VectorExpressionType(
+ RefPtr<ExpressionType> elementType,
+ RefPtr<IntVal> elementCount)
+ : elementType(elementType)
+ , elementCount(elementCount)
+ {}
+#endif
+
+ // The type of vector elements.
+ // As an invariant, this should be a basic type or an alias.
+ RefPtr<ExpressionType> elementType;
+
+ // The number of elements
+ RefPtr<IntVal> elementCount;
+
+ virtual String ToString() override;
+
+ protected:
+ virtual BasicExpressionType* GetScalarType() override;
+ };
+
+ // A matrix type, e.g., `matrix<T,R,C>`
+ class MatrixExpressionType : public ArithmeticExpressionType
+ {
+ public:
+ // TODO: consider adding these back for convenience,
+ // with a way to initialize them on-demand from the
+ // real storage (which is in the `DeclRefType`
+#if 0
+ // The type of vector elements.
+ // As an invariant, this should be a basic type or an alias.
+ RefPtr<ExpressionType> elementType;
+
+ // The type of the matrix rows
+ RefPtr<VectorExpressionType> rowType;
+
+ // The number of rows and columns
+ RefPtr<IntVal> rowCount;
+ RefPtr<IntVal> colCount;
+#endif
+ ExpressionType* getElementType();
+ IntVal* getRowCount();
+ IntVal* getColumnCount();
+
+
+ virtual String ToString() override;
+
+ protected:
+ virtual BasicExpressionType* GetScalarType() override;
+ };
+
+ inline BaseType GetVectorBaseType(VectorExpressionType* vecType) {
+ return vecType->elementType->AsBasicType()->BaseType;
+ }
+
+ inline int GetVectorSize(VectorExpressionType* vecType)
+ {
+ auto constantVal = vecType->elementCount.As<ConstantIntVal>();
+ if (constantVal)
+ return constantVal->value;
+ // TODO: what to do in this case?
+ return 0;
+ }
+
+ class Type
+ {
+ public:
+ RefPtr<ExpressionType> DataType;
+ // ContrainedWorlds: Implementation must be defined at at least one of of these worlds in order to satisfy global dependency
+ // FeasibleWorlds: The component can be computed at any of these worlds
+ EnumerableHashSet<String> ConstrainedWorlds, FeasibleWorlds;
+ EnumerableHashSet<String> PinnedWorlds;
+ };
+
+ class ContainerDecl;
+
+
+ // A group of declarations that should be treated as a unit
+ class DeclGroup : public DeclBase
+ {
+ public:
+ List<RefPtr<Decl>> decls;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ template<typename T>
+ struct FilteredMemberList
+ {
+ typedef RefPtr<Decl> Element;
+
+ FilteredMemberList()
+ : mBegin(NULL)
+ , mEnd(NULL)
+ {}
+
+ explicit FilteredMemberList(
+ List<Element> const& list)
+ : mBegin(Adjust(list.begin(), list.end()))
+ , mEnd(list.end())
+ {}
+
+ struct Iterator
+ {
+ Element* mCursor;
+ Element* mEnd;
+
+ bool operator!=(Iterator const& other)
+ {
+ return mCursor != other.mCursor;
+ }
+
+ void operator++()
+ {
+ mCursor = Adjust(mCursor + 1, mEnd);
+ }
+
+ RefPtr<T>& operator*()
+ {
+ return *(RefPtr<T>*)mCursor;
+ }
+ };
+
+ Iterator begin()
+ {
+ Iterator iter = { mBegin, mEnd };
+ return iter;
+ }
+
+ Iterator end()
+ {
+ Iterator iter = { mEnd, mEnd };
+ return iter;
+ }
+
+ static Element* Adjust(Element* cursor, Element* end)
+ {
+ while (cursor != end)
+ {
+ if ((*cursor).As<T>())
+ return cursor;
+ cursor++;
+ }
+ return cursor;
+ }
+
+ // TODO(tfoley): It is ugly to have these.
+ // We should probably fix the call sites instead.
+ RefPtr<T>& First() { return *begin(); }
+ int Count()
+ {
+ int count = 0;
+ for (auto iter : (*this))
+ {
+ (void)iter;
+ count++;
+ }
+ return count;
+ }
+
+ List<RefPtr<T>> ToArray()
+ {
+ List<RefPtr<T>> result;
+ for (auto element : (*this))
+ {
+ result.Add(element);
+ }
+ return result;
+ }
+
+ Element* mBegin;
+ Element* mEnd;
+ };
+
+ struct TransparentMemberInfo
+ {
+ // The declaration of the transparent member
+ Decl* decl;
+ };
+
+ // A "container" decl is a parent to other declarations
+ class ContainerDecl : public Decl
+ {
+ public:
+ List<RefPtr<Decl>> Members;
+
+ template<typename T>
+ FilteredMemberList<T> GetMembersOfType()
+ {
+ return FilteredMemberList<T>(Members);
+ }
+
+
+ // Dictionary for looking up members by name.
+ // This is built on demand before performing lookup.
+ Dictionary<String, Decl*> memberDictionary;
+
+ // Whether the `memberDictionary` is valid.
+ // Should be set to `false` if any members get added/remoed.
+ bool memberDictionaryIsValid = false;
+
+ // A list of transparent members, to be used in lookup
+ // Note: this is only valid if `memberDictionaryIsValid` is true
+ List<TransparentMemberInfo> transparentMembers;
+ };
+
+ template<typename T>
+ struct FilteredMemberRefList
+ {
+ List<RefPtr<Decl>> const& decls;
+ RefPtr<Substitutions> substitutions;
+
+ FilteredMemberRefList(
+ List<RefPtr<Decl>> const& decls,
+ RefPtr<Substitutions> substitutions)
+ : decls(decls)
+ , substitutions(substitutions)
+ {}
+
+ int Count() const
+ {
+ int count = 0;
+ for (auto d : *this)
+ count++;
+ return count;
+ }
+
+ List<T> ToArray() const
+ {
+ List<T> result;
+ for (auto d : *this)
+ result.Add(d);
+ return result;
+ }
+
+ struct Iterator
+ {
+ FilteredMemberRefList const* list;
+ RefPtr<Decl>* ptr;
+ RefPtr<Decl>* end;
+
+ Iterator() : list(nullptr), ptr(nullptr) {}
+ Iterator(
+ FilteredMemberRefList const* list,
+ RefPtr<Decl>* ptr,
+ RefPtr<Decl>* end)
+ : list(list)
+ , ptr(ptr)
+ , end(end)
+ {}
+
+ bool operator!=(Iterator other)
+ {
+ return ptr != other.ptr;
+ }
+
+ void operator++()
+ {
+ ptr = list->Adjust(ptr + 1, end);
+ }
+
+ T operator*()
+ {
+ return DeclRef(ptr->Ptr(), list->substitutions).As<T>();
+ }
+ };
+
+ Iterator begin() const { return Iterator(this, Adjust(decls.begin(), decls.end()), decls.end()); }
+ Iterator end() const { return Iterator(this, decls.end(), decls.end()); }
+
+ RefPtr<Decl>* Adjust(RefPtr<Decl>* ptr, RefPtr<Decl>* end) const
+ {
+ while (ptr != end)
+ {
+ DeclRef declRef(ptr->Ptr(), substitutions);
+ if (declRef.As<T>())
+ return ptr;
+ ptr++;
+ }
+ return end;
+ }
+ };
+
+ struct ContainerDeclRef : DeclRef
+ {
+ SLANG_DECLARE_DECL_REF(ContainerDecl);
+
+ FilteredMemberRefList<DeclRef> GetMembers() const
+ {
+ return FilteredMemberRefList<DeclRef>(GetDecl()->Members, substitutions);
+ }
+
+ template<typename T>
+ FilteredMemberRefList<T> GetMembersOfType() const
+ {
+ return FilteredMemberRefList<T>(GetDecl()->Members, substitutions);
+ }
+
+ };
+
+ //
+ // 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<ExpressionSyntaxNode> exp)
+ : exp(exp)
+ {}
+ TypeExp(RefPtr<ExpressionSyntaxNode> exp, RefPtr<ExpressionType> type)
+ : exp(exp)
+ , type(type)
+ {}
+
+ RefPtr<ExpressionSyntaxNode> exp;
+ RefPtr<ExpressionType> type;
+
+ bool Equals(ExpressionType* other) {
+ return type->Equals(other);
+ }
+ bool Equals(RefPtr<ExpressionType> other) {
+ return type->Equals(other.Ptr());
+ }
+ ExpressionType* Ptr() { return type.Ptr(); }
+ operator RefPtr<ExpressionType>()
+ {
+ return type;
+ }
+ ExpressionType* operator->() { return Ptr(); }
+
+ TypeExp Accept(SyntaxVisitor* visitor);
+ };
+
+
+ //
+ // Declarations
+ //
+
+ // Base class for all variable-like declarations
+ class VarDeclBase : public Decl
+ {
+ public:
+ // Type of the variable
+ TypeExp Type;
+
+ ExpressionType* getType() { return Type.type.Ptr(); }
+
+ // Initializer expression (optional)
+ RefPtr<ExpressionSyntaxNode> Expr;
+ };
+
+ struct VarDeclBaseRef : DeclRef
+ {
+ SLANG_DECLARE_DECL_REF(VarDeclBase);
+
+ RefPtr<ExpressionType> GetType() const { return Substitute(GetDecl()->Type); }
+
+ RefPtr<ExpressionSyntaxNode> getInitExpr() const { return Substitute(GetDecl()->Expr); }
+ };
+
+ // A field of a `struct` type
+ class StructField : public VarDeclBase
+ {
+ public:
+ StructField()
+ {}
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ struct FieldDeclRef : VarDeclBaseRef
+ {
+ SLANG_DECLARE_DECL_REF(StructField)
+ };
+
+ // An extension to apply to an existing type
+ class ExtensionDecl : public ContainerDecl
+ {
+ public:
+ TypeExp targetType;
+
+ // next extension attached to the same nominal type
+ ExtensionDecl* nextCandidateExtension = nullptr;
+
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ struct ExtensionDeclRef : ContainerDeclRef
+ {
+ SLANG_DECLARE_DECL_REF(ExtensionDecl);
+
+ RefPtr<ExpressionType> GetTargetType() const { return Substitute(GetDecl()->targetType); }
+ };
+
+ // Declaration of a type that represents some sort of aggregate
+ class AggTypeDecl : public ContainerDecl
+ {
+ public:
+ // extensions that might apply to this declaration
+ ExtensionDecl* candidateExtensions = nullptr;
+ FilteredMemberList<StructField> GetFields()
+ {
+ return GetMembersOfType<StructField>();
+ }
+ StructField* FindField(String name)
+ {
+ for (auto field : GetFields())
+ {
+ if (field->Name.Content == name)
+ return field.Ptr();
+ }
+ return nullptr;
+ }
+ int FindFieldIndex(String name)
+ {
+ int index = 0;
+ for (auto field : GetFields())
+ {
+ if (field->Name.Content == name)
+ return index;
+ index++;
+ }
+ return -1;
+ }
+ };
+
+ struct AggTypeDeclRef : public ContainerDeclRef
+ {
+ SLANG_DECLARE_DECL_REF(AggTypeDecl);
+
+ ExtensionDecl* GetCandidateExtensions() const { return GetDecl()->candidateExtensions; }
+ };
+
+ class StructSyntaxNode : public AggTypeDecl
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ struct StructDeclRef : public AggTypeDeclRef
+ {
+ SLANG_DECLARE_DECL_REF(StructSyntaxNode);
+
+ FilteredMemberRefList<FieldDeclRef> GetFields() const { return GetMembersOfType<FieldDeclRef>(); }
+ };
+
+ class ClassSyntaxNode : public AggTypeDecl
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ struct ClassDeclRef : public AggTypeDeclRef
+ {
+ SLANG_DECLARE_DECL_REF(ClassSyntaxNode);
+
+ FilteredMemberRefList<FieldDeclRef> GetFields() const { return GetMembersOfType<FieldDeclRef>(); }
+ };
+
+ // A trait which other types can conform to
+ class TraitDecl : public AggTypeDecl
+ {
+ public:
+ List<TypeExp> bases;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ struct TraitDeclRef : public AggTypeDeclRef
+ {
+ SLANG_DECLARE_DECL_REF(TraitDecl);
+ };
+
+
+ // A declaration that states that the enclosing type supports a given trait
+ //
+ // TODO: this same construct might be used for represent other inheritance-like cases
+ class TraitConformanceDecl : public Decl
+ {
+ public:
+ // The type expression as written
+ TypeExp base;
+
+ // The trait that we found we conform to...
+ TraitDeclRef traitDeclRef;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ struct TraitConformanceDeclRef : public DeclRef
+ {
+ SLANG_DECLARE_DECL_REF(TraitConformanceDecl);
+
+ TraitDeclRef GetTraitDeclRef() { return Substitute(GetDecl()->traitDeclRef).As<TraitDeclRef>(); }
+ };
+
+ // A declaration that represents a simple (non-aggregate) type
+ class SimpleTypeDecl : public Decl
+ {
+ };
+
+ struct SimpleTypeDeclRef : DeclRef
+ {
+ SLANG_DECLARE_DECL_REF(SimpleTypeDecl)
+ };
+
+ // A `typedef` declaration
+ class TypeDefDecl : public SimpleTypeDecl
+ {
+ public:
+ TypeExp Type;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ struct TypeDefDeclRef : SimpleTypeDeclRef
+ {
+ SLANG_DECLARE_DECL_REF(TypeDefDecl);
+
+ RefPtr<ExpressionType> GetType() const { return Substitute(GetDecl()->Type); }
+ };
+
+ // A type alias of some kind (e.g., via `typedef`)
+ class NamedExpressionType : public ExpressionType
+ {
+ public:
+ NamedExpressionType(TypeDefDeclRef declRef)
+ : declRef(declRef)
+ {}
+
+ TypeDefDeclRef declRef;
+
+ virtual String ToString() override;
+
+ protected:
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ virtual int GetHashCode() override;
+ };
+
+
+ class StatementSyntaxNode : public ModifiableSyntaxNode
+ {
+ public:
+ };
+
+ // A scope for local declarations (e.g., as part of a statement)
+ class ScopeDecl : public ContainerDecl
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class ScopeStmt : public StatementSyntaxNode
+ {
+ public:
+ RefPtr<ScopeDecl> scopeDecl;
+ };
+
+ class BlockStatementSyntaxNode : public ScopeStmt
+ {
+ public:
+ List<RefPtr<StatementSyntaxNode>> Statements;
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class UnparsedStmt : public StatementSyntaxNode
+ {
+ public:
+ // The tokens that were contained between `{` and `}`
+ List<Token> tokens;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class ParameterSyntaxNode : public VarDeclBase
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ struct ParamDeclRef : VarDeclBaseRef
+ {
+ SLANG_DECLARE_DECL_REF(ParameterSyntaxNode);
+ };
+
+ // Base class for things that have parameter lists and can thus be applied to arguments ("called")
+ class CallableDecl : public ContainerDecl
+ {
+ public:
+ FilteredMemberList<ParameterSyntaxNode> GetParameters()
+ {
+ return GetMembersOfType<ParameterSyntaxNode>();
+ }
+ TypeExp ReturnType;
+ };
+
+ struct CallableDeclRef : ContainerDeclRef
+ {
+ SLANG_DECLARE_DECL_REF(CallableDecl);
+
+ RefPtr<ExpressionType> GetResultType() const
+ {
+ return Substitute(GetDecl()->ReturnType.type.Ptr());
+ }
+
+ FilteredMemberRefList<ParamDeclRef> GetParameters()
+ {
+ return GetMembersOfType<ParamDeclRef>();
+ }
+ };
+
+ // Base class for callable things that may also have a body that is evaluated to produce their result
+ class FunctionDeclBase : public CallableDecl
+ {
+ public:
+ RefPtr<StatementSyntaxNode> Body;
+ };
+
+ struct FuncDeclBaseRef : CallableDeclRef
+ {
+ SLANG_DECLARE_DECL_REF(FunctionDeclBase);
+ };
+
+ // Function types are currently used for references to symbols that name
+ // either ordinary functions, or "component functions."
+ // We do not directly store a representation of the type, and instead
+ // use a reference to the symbol to stand in for its logical type
+ class FuncType : public ExpressionType
+ {
+ public:
+ CallableDeclRef declRef;
+
+ virtual String ToString() override;
+ protected:
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ virtual int GetHashCode() override;
+ };
+
+ // A constructor/initializer to create instances of a type
+ class ConstructorDecl : public FunctionDeclBase
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ struct ConstructorDeclRef : FuncDeclBaseRef
+ {
+ SLANG_DECLARE_DECL_REF(ConstructorDecl);
+ };
+
+ // A subscript operation used to index instances of a type
+ class SubscriptDecl : public CallableDecl
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ struct SubscriptDeclRef : CallableDeclRef
+ {
+ SLANG_DECLARE_DECL_REF(SubscriptDecl);
+ };
+
+ // An "accessor" for a subscript or property
+ class AccessorDecl : public FunctionDeclBase
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class GetterDecl : public AccessorDecl
+ {
+ };
+
+ class SetterDecl : public AccessorDecl
+ {
+ };
+
+ //
+
+ class FunctionSyntaxNode : public FunctionDeclBase
+ {
+ public:
+ String InternalName;
+ bool IsInline() { return HasModifier<InlineModifier>(); }
+ bool IsExtern() { return HasModifier<ExternModifier>(); }
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ FunctionSyntaxNode()
+ {
+ }
+ };
+
+ struct FuncDeclRef : FuncDeclBaseRef
+ {
+ SLANG_DECLARE_DECL_REF(FunctionSyntaxNode);
+ };
+
+
+ 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;
+ };
+
+ // Base class for expressions that will reference declarations
+ class DeclRefExpr : public ExpressionSyntaxNode
+ {
+ public:
+ // The scope in which to perform lookup
+ RefPtr<Scope> scope;
+
+ // The declaration of the symbol being referenced
+ DeclRef declRef;
+ };
+
+ class VarExpressionSyntaxNode : public DeclRefExpr
+ {
+ public:
+ // The name of the symbol being referenced
+ String Variable;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ // Masks to be applied when lookup up declarations
+ enum class LookupMask : uint8_t
+ {
+ Type = 0x1,
+ Function = 0x2,
+ Value = 0x4,
+
+ All = 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.
+ class Breadcrumb : public RefObject
+ {
+ public:
+ enum class Kind
+ {
+ Member, // A member was references
+ Deref, // A value with pointer(-like) type was dereferenced
+ };
+
+ Kind kind;
+ DeclRef declRef;
+ RefPtr<Breadcrumb> next;
+
+ Breadcrumb(Kind kind, DeclRef declRef, RefPtr<Breadcrumb> next)
+ : kind(kind)
+ , declRef(declRef)
+ , next(next)
+ {}
+ };
+
+ // A properly-specialized reference to the declaration that was found.
+ DeclRef 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 declRef)
+ : declRef(declRef)
+ {}
+ LookupResultItem(DeclRef 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.Count() > 1; }
+ };
+
+ struct LookupRequest
+ {
+ RefPtr<Scope> scope = nullptr;
+ RefPtr<Scope> endScope = nullptr;
+
+ LookupMask mask = LookupMask::All;
+ };
+
+ // An expression that references an overloaded set of declarations
+ // having the same name.
+ class OverloadedExpr : public ExpressionSyntaxNode
+ {
+ public:
+ // Optional: the base expression is this overloaded result
+ // arose from a member-reference expression.
+ RefPtr<ExpressionSyntaxNode> base;
+
+ // The lookup result that was ambiguous
+ LookupResult lookupResult2;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ typedef double FloatingPointLiteralValue;
+
+ class ConstantExpressionSyntaxNode : public ExpressionSyntaxNode
+ {
+ public:
+ enum class ConstantType
+ {
+ Int, Bool, Float
+ };
+ ConstantType ConstType;
+ union
+ {
+ int IntValue;
+ FloatingPointLiteralValue FloatValue;
+ };
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ enum class Operator
+ {
+ Neg, Not, BitNot, PreInc, PreDec, PostInc, PostDec,
+ Mul, Div, Mod,
+ Add, Sub,
+ Lsh, Rsh,
+ Eql, Neq, Greater, Less, Geq, Leq,
+ BitAnd, BitXor, BitOr,
+ And,
+ Or,
+ Sequence,
+ Select,
+ Assign = 200, AddAssign, SubAssign, MulAssign, DivAssign, ModAssign,
+ LshAssign, RshAssign, OrAssign, AndAssign, XorAssign,
+ };
+ String GetOperatorFunctionName(Operator op);
+ String OperatorToString(Operator op);
+
+ // An initializer list, e.g. `{ 1, 2, 3 }`
+ class InitializerListExpr : public ExpressionSyntaxNode
+ {
+ public:
+ List<RefPtr<ExpressionSyntaxNode>> args;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ // A base expression being applied to arguments: covers
+ // both ordinary `()` function calls and `<>` generic application
+ class AppExprBase : public ExpressionSyntaxNode
+ {
+ public:
+ RefPtr<ExpressionSyntaxNode> FunctionExpr;
+ List<RefPtr<ExpressionSyntaxNode>> Arguments;
+ };
+
+
+ class InvokeExpressionSyntaxNode : public AppExprBase
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class OperatorExpressionSyntaxNode : public InvokeExpressionSyntaxNode
+ {
+ public:
+// Operator Operator;
+// void SetOperator(RefPtr<Scope> scope, Slang::Compiler::Operator op);
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class InfixExpr : public OperatorExpressionSyntaxNode {};
+ class PrefixExpr : public OperatorExpressionSyntaxNode {};
+ class PostfixExpr : public OperatorExpressionSyntaxNode {};
+
+ class IndexExpressionSyntaxNode : public ExpressionSyntaxNode
+ {
+ public:
+ RefPtr<ExpressionSyntaxNode> BaseExpression;
+ RefPtr<ExpressionSyntaxNode> IndexExpression;
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class MemberExpressionSyntaxNode : public DeclRefExpr
+ {
+ public:
+ RefPtr<ExpressionSyntaxNode> BaseExpression;
+ String MemberName;
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class SwizzleExpr : public ExpressionSyntaxNode
+ {
+ public:
+ RefPtr<ExpressionSyntaxNode> base;
+ int elementCount;
+ int elementIndices[4];
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ // A dereference of a pointer or pointer-like type
+ class DerefExpr : public ExpressionSyntaxNode
+ {
+ public:
+ RefPtr<ExpressionSyntaxNode> base;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class TypeCastExpressionSyntaxNode : public ExpressionSyntaxNode
+ {
+ public:
+ TypeExp TargetType;
+ RefPtr<ExpressionSyntaxNode> Expression;
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class SelectExpressionSyntaxNode : public OperatorExpressionSyntaxNode
+ {
+ public:
+ };
+
+
+ class EmptyStatementSyntaxNode : public StatementSyntaxNode
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class DiscardStatementSyntaxNode : public StatementSyntaxNode
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ struct Variable : public VarDeclBase
+ {
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class VarDeclrStatementSyntaxNode : public StatementSyntaxNode
+ {
+ public:
+ RefPtr<DeclBase> decl;
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class UsingFileDecl : public Decl
+ {
+ public:
+ Token fileName;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class ProgramSyntaxNode : public ContainerDecl
+ {
+ public:
+ // Access members of specific types
+ FilteredMemberList<UsingFileDecl> GetUsings()
+ {
+ return GetMembersOfType<UsingFileDecl>();
+ }
+ FilteredMemberList<FunctionSyntaxNode> GetFunctions()
+ {
+ return GetMembersOfType<FunctionSyntaxNode>();
+ }
+
+ FilteredMemberList<ClassSyntaxNode> GetClasses()
+ {
+ return GetMembersOfType<ClassSyntaxNode>();
+ }
+ FilteredMemberList<StructSyntaxNode> GetStructs()
+ {
+ return GetMembersOfType<StructSyntaxNode>();
+ }
+ FilteredMemberList<TypeDefDecl> GetTypeDefs()
+ {
+ return GetMembersOfType<TypeDefDecl>();
+ }
+#if 0
+ void Include(ProgramSyntaxNode * other)
+ {
+ Members.AddRange(other->Members);
+ }
+#endif
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class IfStatementSyntaxNode : public StatementSyntaxNode
+ {
+ public:
+ RefPtr<ExpressionSyntaxNode> Predicate;
+ RefPtr<StatementSyntaxNode> PositiveStatement;
+ RefPtr<StatementSyntaxNode> NegativeStatement;
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ // A statement that can be escaped with a `break`
+ class BreakableStmt : public ScopeStmt
+ {};
+
+ class SwitchStmt : public BreakableStmt
+ {
+ public:
+ RefPtr<ExpressionSyntaxNode> condition;
+ RefPtr<StatementSyntaxNode> body;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ // 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 StatementSyntaxNode
+ {
+ public:
+ StatementSyntaxNode* 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
+ {
+ public:
+ };
+
+ // a `case` statement inside a `switch`
+ class CaseStmt : public CaseStmtBase
+ {
+ public:
+ RefPtr<ExpressionSyntaxNode> expr;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ // a `default` statement inside a `switch`
+ class DefaultStmt : public CaseStmtBase
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ // A statement that represents a loop, and can thus be escaped with a `continue`
+ class LoopStmt : public BreakableStmt
+ {};
+
+ class ForStatementSyntaxNode : public LoopStmt
+ {
+ public:
+ RefPtr<StatementSyntaxNode> InitialStatement;
+ RefPtr<ExpressionSyntaxNode> SideEffectExpression, PredicateExpression;
+ RefPtr<StatementSyntaxNode> Statement;
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class WhileStatementSyntaxNode : public LoopStmt
+ {
+ public:
+ RefPtr<ExpressionSyntaxNode> Predicate;
+ RefPtr<StatementSyntaxNode> Statement;
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class DoWhileStatementSyntaxNode : public LoopStmt
+ {
+ public:
+ RefPtr<StatementSyntaxNode> Statement;
+ RefPtr<ExpressionSyntaxNode> Predicate;
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ // The case of child statements that do control flow relative
+ // to their parent statement.
+ class JumpStmt : public ChildStmt
+ {
+ public:
+ StatementSyntaxNode* parentStmt = nullptr;
+ };
+
+ class BreakStatementSyntaxNode : public JumpStmt
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class ContinueStatementSyntaxNode : public JumpStmt
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class ReturnStatementSyntaxNode : public StatementSyntaxNode
+ {
+ public:
+ RefPtr<ExpressionSyntaxNode> Expression;
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ class ExpressionStatementSyntaxNode : public StatementSyntaxNode
+ {
+ public:
+ RefPtr<ExpressionSyntaxNode> Expression;
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ // Note(tfoley): Moved this further down in the file because it depends on
+ // `ExpressionSyntaxNode` and a forward reference just isn't good enough
+ // for `RefPtr`.
+ //
+ class GenericAppExpr : public AppExprBase
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ // An expression representing re-use of the syntax for a type in more
+ // than once conceptually-distinct declaration
+ class SharedTypeExpr : public ExpressionSyntaxNode
+ {
+ public:
+ // The underlying type expression that we want to share
+ TypeExp base;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+
+ // A modifier that indicates a built-in base type (e.g., `float`)
+ class BuiltinTypeModifier : public Modifier
+ {
+ public:
+ 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
+ {
+ public:
+ String name;
+ uint32_t tag;
+ };
+
+ // Modifiers that affect the storage layout for matrices
+ class MatrixLayoutModifier : public Modifier {};
+
+ // Modifiers that specify row- and column-major layout, respectively
+ class RowMajorLayoutModifier : public MatrixLayoutModifier {};
+ class ColumnMajorLayoutModifier : public MatrixLayoutModifier {};
+
+ // The HLSL flavor of those modifiers
+ class HLSLRowMajorLayoutModifier : public RowMajorLayoutModifier {};
+ class HLSLColumnMajorLayoutModifier : public 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.
+ class GLSLRowMajorLayoutModifier : public ColumnMajorLayoutModifier {};
+ class GLSLColumnMajorLayoutModifier : public RowMajorLayoutModifier {};
+
+ // More HLSL Keyword
+
+ // HLSL `nointerpolation` modifier
+ class HLSLNoInterpolationModifier : public Modifier {};
+
+ // HLSL `linear` modifier
+ class HLSLLinearModifier : public Modifier {};
+
+ // HLSL `sample` modifier
+ class HLSLSampleModifier : public Modifier {};
+
+ // HLSL `centroid` modifier
+ class HLSLCentroidModifier : public Modifier {};
+
+ // HLSL `precise` modifier
+ class HLSLPreciseModifier : public Modifier {};
+
+ // HLSL `shared` modifier (which is used by the effect system,
+ // and shouldn't be confused with `groupshared`)
+ class HLSLEffectSharedModifier : public Modifier {};
+
+ // HLSL `groupshared` modifier
+ class HLSLGroupSharedModifier : public Modifier {};
+
+ // HLSL `static` modifier (probably doesn't need to be
+ // treated as HLSL-specific)
+ class HLSLStaticModifier : public Modifier {};
+
+ // HLSL `uniform` modifier (distinct meaning from GLSL
+ // use of the keyword)
+ class HLSLUniformModifier : public Modifier {};
+
+ // HLSL `volatile` modifier (ignored)
+ class HLSLVolatileModifier : public Modifier {};
+
+ // An HLSL `[name(arg0, ...)]` style attribute.
+ class HLSLAttribute : public Modifier
+ {
+ public:
+ Token nameToken;
+ List<RefPtr<ExpressionSyntaxNode>> args;
+ };
+
+ // An HLSL `[name(...)]` attribute that hasn't undergone
+ // any semantic analysis.
+ // After analysis, this might be transformed into a more specific case.
+ class HLSLUncheckedAttribute : public HLSLAttribute
+ {
+ public:
+ };
+
+ // An HLSL `[numthreads(x,y,z)]` attribute
+ class HLSLNumThreadsAttribute : public HLSLAttribute
+ {
+ public:
+ // The number of threads to use along each axis
+ int32_t x;
+ int32_t y;
+ int32_t z;
+ };
+
+ // HLSL modifiers for geometry shader input topology
+ class HLSLGeometryShaderInputPrimitiveTypeModifier : public Modifier {};
+ class HLSLPointModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier {};
+ class HLSLLineModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier {};
+ class HLSLTriangleModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier {};
+ class HLSLLineAdjModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier {};
+ class HLSLTriangleAdjModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier {};
+
+ //
+
+ // A generic declaration, parameterized on types/values
+ class GenericDecl : public ContainerDecl
+ {
+ public:
+ // The decl that is genericized...
+ RefPtr<Decl> inner;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ struct GenericDeclRef : ContainerDeclRef
+ {
+ SLANG_DECLARE_DECL_REF(GenericDecl);
+
+ Decl* GetInner() const { return GetDecl()->inner.Ptr(); }
+ };
+
+ // The "type" of an expression that names a generic declaration.
+ class GenericDeclRefType : public ExpressionType
+ {
+ public:
+ GenericDeclRefType(GenericDeclRef declRef)
+ : declRef(declRef)
+ {}
+
+ GenericDeclRef declRef;
+ GenericDeclRef const& GetDeclRef() const { return declRef; }
+
+ virtual String ToString() override;
+
+ protected:
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual int GetHashCode() override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ };
+
+
+
+ class GenericTypeParamDecl : public SimpleTypeDecl
+ {
+ public:
+ // 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
+ TypeExp initType;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ struct GenericTypeParamDeclRef : SimpleTypeDeclRef
+ {
+ SLANG_DECLARE_DECL_REF(GenericTypeParamDecl);
+ };
+
+ // A constraint placed as part of a generic declaration
+ class GenericTypeConstraintDecl : public Decl
+ {
+ public:
+ // 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.
+ TypeExp sub;
+ TypeExp sup;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ struct GenericTypeConstraintDeclRef : DeclRef
+ {
+ SLANG_DECLARE_DECL_REF(GenericTypeConstraintDecl);
+
+ RefPtr<ExpressionType> GetSub() { return Substitute(GetDecl()->sub); }
+ RefPtr<ExpressionType> GetSup() { return Substitute(GetDecl()->sup); }
+ };
+
+
+ class GenericValueParamDecl : public VarDeclBase
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ struct GenericValueParamDeclRef : VarDeclBaseRef
+ {
+ SLANG_DECLARE_DECL_REF(GenericValueParamDecl);
+ };
+
+ // The logical "value" of a rererence to a generic value parameter
+ class GenericParamIntVal : public IntVal
+ {
+ public:
+ VarDeclBaseRef declRef;
+
+ GenericParamIntVal(VarDeclBaseRef declRef)
+ : declRef(declRef)
+ {}
+
+ virtual bool EqualsVal(Val* val) override;
+ virtual String ToString() override;
+ virtual int GetHashCode() override;
+ virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff) override;
+ };
+
+ // Declaration of a user-defined modifier
+ class ModifierDecl : public Decl
+ {
+ public:
+ // The name of the C++ class to instantiate
+ // (this is a reference to a class in the compiler source code,
+ // and not the user's source code)
+ Token classNameToken;
+
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ // An empty declaration (which might still have modifiers attached).
+ //
+ // An empty declaration is uncommon in HLSL, but
+ // in GLSL it is often used at the global scope
+ // to declare metadata that logically belongs
+ // to the entry point, e.g.:
+ //
+ // layout(local_size_x = 16) in;
+ //
+ class EmptyDecl : public Decl
+ {
+ public:
+ virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
+ };
+
+ //
+
+ class SyntaxVisitor : public Object
+ {
+ protected:
+ DiagnosticSink * sink = nullptr;
+ DiagnosticSink* getSink() { return sink; }
+
+ SourceLanguage sourceLanguage = SourceLanguage::Unknown;
+ public:
+ void setSourceLanguage(SourceLanguage language)
+ {
+ sourceLanguage = language;
+ }
+
+ SyntaxVisitor(DiagnosticSink * sink)
+ : sink(sink)
+ {}
+ virtual RefPtr<ProgramSyntaxNode> VisitProgram(ProgramSyntaxNode* program)
+ {
+ for (auto & m : program->Members)
+ m = m->Accept(this).As<Decl>();
+ return program;
+ }
+
+ virtual RefPtr<UsingFileDecl> VisitUsingFileDecl(UsingFileDecl * decl)
+ {
+ return decl;
+ }
+
+ virtual RefPtr<FunctionSyntaxNode> VisitFunction(FunctionSyntaxNode* func)
+ {
+ func->ReturnType = func->ReturnType.Accept(this);
+ for (auto & member : func->Members)
+ member = member->Accept(this).As<Decl>();
+ if (func->Body)
+ func->Body = func->Body->Accept(this).As<BlockStatementSyntaxNode>();
+ return func;
+ }
+ virtual RefPtr<ScopeDecl> VisitScopeDecl(ScopeDecl* decl)
+ {
+ // By default don't visit children, because they will always
+ // be encountered in the ordinary flow of the corresponding statement.
+ return decl;
+ }
+ virtual RefPtr<StructSyntaxNode> VisitStruct(StructSyntaxNode * s)
+ {
+ for (auto & f : s->Members)
+ f = f->Accept(this).As<Decl>();
+ return s;
+ }
+ virtual RefPtr<ClassSyntaxNode> VisitClass(ClassSyntaxNode * s)
+ {
+ for (auto & f : s->Members)
+ f = f->Accept(this).As<Decl>();
+ return s;
+ }
+ virtual RefPtr<GenericDecl> VisitGenericDecl(GenericDecl * decl)
+ {
+ for (auto & m : decl->Members)
+ m = m->Accept(this).As<Decl>();
+ decl->inner = decl->inner->Accept(this).As<Decl>();
+ return decl;
+ }
+ virtual RefPtr<TypeDefDecl> VisitTypeDefDecl(TypeDefDecl* decl)
+ {
+ decl->Type = decl->Type.Accept(this);
+ return decl;
+ }
+ virtual RefPtr<StatementSyntaxNode> VisitDiscardStatement(DiscardStatementSyntaxNode * stmt)
+ {
+ return stmt;
+ }
+ virtual RefPtr<StructField> VisitStructField(StructField * f)
+ {
+ f->Type = f->Type.Accept(this);
+ return f;
+ }
+ virtual RefPtr<StatementSyntaxNode> VisitBlockStatement(BlockStatementSyntaxNode* stmt)
+ {
+ for (auto & s : stmt->Statements)
+ s = s->Accept(this).As<StatementSyntaxNode>();
+ return stmt;
+ }
+ virtual RefPtr<StatementSyntaxNode> VisitBreakStatement(BreakStatementSyntaxNode* stmt)
+ {
+ return stmt;
+ }
+ virtual RefPtr<StatementSyntaxNode> VisitContinueStatement(ContinueStatementSyntaxNode* stmt)
+ {
+ return stmt;
+ }
+
+ virtual RefPtr<StatementSyntaxNode> VisitDoWhileStatement(DoWhileStatementSyntaxNode* stmt)
+ {
+ if (stmt->Predicate)
+ stmt->Predicate = stmt->Predicate->Accept(this).As<ExpressionSyntaxNode>();
+ if (stmt->Statement)
+ stmt->Statement = stmt->Statement->Accept(this).As<StatementSyntaxNode>();
+ return stmt;
+ }
+ virtual RefPtr<StatementSyntaxNode> VisitEmptyStatement(EmptyStatementSyntaxNode* stmt)
+ {
+ return stmt;
+ }
+ virtual RefPtr<StatementSyntaxNode> VisitForStatement(ForStatementSyntaxNode* stmt)
+ {
+ if (stmt->InitialStatement)
+ stmt->InitialStatement = stmt->InitialStatement->Accept(this).As<StatementSyntaxNode>();
+ if (stmt->PredicateExpression)
+ stmt->PredicateExpression = stmt->PredicateExpression->Accept(this).As<ExpressionSyntaxNode>();
+ if (stmt->SideEffectExpression)
+ stmt->SideEffectExpression = stmt->SideEffectExpression->Accept(this).As<ExpressionSyntaxNode>();
+ if (stmt->Statement)
+ stmt->Statement = stmt->Statement->Accept(this).As<StatementSyntaxNode>();
+ return stmt;
+ }
+ virtual RefPtr<StatementSyntaxNode> VisitIfStatement(IfStatementSyntaxNode* stmt)
+ {
+ if (stmt->Predicate)
+ stmt->Predicate = stmt->Predicate->Accept(this).As<ExpressionSyntaxNode>();
+ if (stmt->PositiveStatement)
+ stmt->PositiveStatement = stmt->PositiveStatement->Accept(this).As<StatementSyntaxNode>();
+ if (stmt->NegativeStatement)
+ stmt->NegativeStatement = stmt->NegativeStatement->Accept(this).As<StatementSyntaxNode>();
+ return stmt;
+ }
+ virtual RefPtr<SwitchStmt> VisitSwitchStmt(SwitchStmt* stmt)
+ {
+ if (stmt->condition)
+ stmt->condition = stmt->condition->Accept(this).As<ExpressionSyntaxNode>();
+ if (stmt->body)
+ stmt->body = stmt->body->Accept(this).As<BlockStatementSyntaxNode>();
+ return stmt;
+ }
+ virtual RefPtr<CaseStmt> VisitCaseStmt(CaseStmt* stmt)
+ {
+ if (stmt->expr)
+ stmt->expr = stmt->expr->Accept(this).As<ExpressionSyntaxNode>();
+ return stmt;
+ }
+ virtual RefPtr<DefaultStmt> VisitDefaultStmt(DefaultStmt* stmt)
+ {
+ return stmt;
+ }
+ virtual RefPtr<StatementSyntaxNode> VisitReturnStatement(ReturnStatementSyntaxNode* stmt)
+ {
+ if (stmt->Expression)
+ stmt->Expression = stmt->Expression->Accept(this).As<ExpressionSyntaxNode>();
+ return stmt;
+ }
+ virtual RefPtr<StatementSyntaxNode> VisitVarDeclrStatement(VarDeclrStatementSyntaxNode* stmt)
+ {
+ stmt->decl = stmt->decl->Accept(this).As<DeclBase>();
+ return stmt;
+ }
+ virtual RefPtr<StatementSyntaxNode> VisitWhileStatement(WhileStatementSyntaxNode* stmt)
+ {
+ if (stmt->Predicate)
+ stmt->Predicate = stmt->Predicate->Accept(this).As<ExpressionSyntaxNode>();
+ if (stmt->Statement)
+ stmt->Statement = stmt->Statement->Accept(this).As<StatementSyntaxNode>();
+ return stmt;
+ }
+ virtual RefPtr<StatementSyntaxNode> VisitExpressionStatement(ExpressionStatementSyntaxNode* stmt)
+ {
+ if (stmt->Expression)
+ stmt->Expression = stmt->Expression->Accept(this).As<ExpressionSyntaxNode>();
+ return stmt;
+ }
+
+ virtual RefPtr<ExpressionSyntaxNode> VisitOperatorExpression(OperatorExpressionSyntaxNode* expr)
+ {
+ for (auto && child : expr->Arguments)
+ child->Accept(this);
+ return expr;
+ }
+ virtual RefPtr<ExpressionSyntaxNode> VisitConstantExpression(ConstantExpressionSyntaxNode* expr)
+ {
+ return expr;
+ }
+ virtual RefPtr<ExpressionSyntaxNode> VisitIndexExpression(IndexExpressionSyntaxNode* expr)
+ {
+ if (expr->BaseExpression)
+ expr->BaseExpression = expr->BaseExpression->Accept(this).As<ExpressionSyntaxNode>();
+ if (expr->IndexExpression)
+ expr->IndexExpression = expr->IndexExpression->Accept(this).As<ExpressionSyntaxNode>();
+ return expr;
+ }
+ virtual RefPtr<ExpressionSyntaxNode> VisitMemberExpression(MemberExpressionSyntaxNode * stmt)
+ {
+ if (stmt->BaseExpression)
+ stmt->BaseExpression = stmt->BaseExpression->Accept(this).As<ExpressionSyntaxNode>();
+ return stmt;
+ }
+ virtual RefPtr<ExpressionSyntaxNode> VisitSwizzleExpression(SwizzleExpr * expr)
+ {
+ if (expr->base)
+ expr->base->Accept(this);
+ return expr;
+ }
+ virtual RefPtr<ExpressionSyntaxNode> VisitInvokeExpression(InvokeExpressionSyntaxNode* stmt)
+ {
+ stmt->FunctionExpr->Accept(this);
+ for (auto & arg : stmt->Arguments)
+ arg = arg->Accept(this).As<ExpressionSyntaxNode>();
+ return stmt;
+ }
+ virtual RefPtr<ExpressionSyntaxNode> VisitTypeCastExpression(TypeCastExpressionSyntaxNode * stmt)
+ {
+ if (stmt->Expression)
+ stmt->Expression = stmt->Expression->Accept(this).As<ExpressionSyntaxNode>();
+ return stmt->Expression;
+ }
+ virtual RefPtr<ExpressionSyntaxNode> VisitVarExpression(VarExpressionSyntaxNode* expr)
+ {
+ return expr;
+ }
+
+ virtual RefPtr<ParameterSyntaxNode> VisitParameter(ParameterSyntaxNode* param)
+ {
+ return param;
+ }
+ virtual RefPtr<ExpressionSyntaxNode> VisitGenericApp(GenericAppExpr* type)
+ {
+ return type;
+ }
+
+ virtual RefPtr<Variable> VisitDeclrVariable(Variable* dclr)
+ {
+ if (dclr->Expr)
+ dclr->Expr = dclr->Expr->Accept(this).As<ExpressionSyntaxNode>();
+ return dclr;
+ }
+
+ virtual TypeExp VisitTypeExp(TypeExp const& typeExp)
+ {
+ TypeExp result = typeExp;
+ result.exp = typeExp.exp->Accept(this).As<ExpressionSyntaxNode>();
+ if (auto typeType = result.exp->Type.type.As<TypeType>())
+ {
+ result.type = typeType->type;
+ }
+ return result;
+ }
+
+ virtual void VisitExtensionDecl(ExtensionDecl* /*decl*/)
+ {}
+
+ virtual void VisitConstructorDecl(ConstructorDecl* /*decl*/)
+ {}
+
+ virtual void visitSubscriptDecl(SubscriptDecl* decl) = 0;
+
+ virtual void visitAccessorDecl(AccessorDecl* decl) = 0;
+
+ virtual void VisitTraitDecl(TraitDecl* /*decl*/)
+ {}
+
+ virtual void VisitTraitConformanceDecl(TraitConformanceDecl* /*decl*/)
+ {}
+
+ virtual RefPtr<ExpressionSyntaxNode> VisitSharedTypeExpr(SharedTypeExpr* typeExpr)
+ {
+ return typeExpr;
+ }
+
+ virtual void VisitDeclGroup(DeclGroup* declGroup)
+ {
+ for (auto decl : declGroup->decls)
+ {
+ decl->Accept(this);
+ }
+ }
+
+ virtual RefPtr<ExpressionSyntaxNode> visitInitializerListExpr(InitializerListExpr* expr) = 0;
+ };
+
+ // Note(tfoley): These logically belong to `ExpressionType`,
+ // but order-of-declaration stuff makes that tricky
+ //
+ // TODO(tfoley): These should really belong to the compilation context!
+ //
+ void RegisterBuiltinDecl(
+ RefPtr<Decl> decl,
+ RefPtr<BuiltinTypeModifier> modifier);
+ void RegisterMagicDecl(
+ RefPtr<Decl> decl,
+ RefPtr<MagicTypeModifier> modifier);
+
+ // Look up a magic declaration by its name
+ RefPtr<Decl> findMagicDecl(
+ String const& name);
+
+ // Create an instance of a syntax class by name
+ SyntaxNodeBase* createInstanceOfSyntaxClassByName(
+ String const& name);
+
+ }
+}
+
+#endif \ No newline at end of file