diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2020-05-08 14:31:40 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-05-08 14:31:40 -0400 |
| commit | 798f3bc2236ce81499b05662dc11e7c071e7cde8 (patch) | |
| tree | fbfa2ef90d4cfdace9ce3667cf441e22137792fb /source | |
| parent | c16abd4fe1bda5ebcd50dbb22f30c6be43bb885f (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')
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 |
