diff options
| author | Tim Foley <tfoley@nvidia.com> | 2017-06-29 08:55:09 -0700 |
|---|---|---|
| committer | Tim Foley <tfoley@nvidia.com> | 2017-06-30 12:22:33 -0700 |
| commit | cab694dcead92a554654d7fa3f08909d519425f0 (patch) | |
| tree | 6c2c07c3930ff68b5518e562b0b507d5ec54d0bf /source/slang/syntax-base-defs.h | |
| parent | b2b08679a32506d629df84730f36639dab9f9593 (diff) | |
Add meta-definitions for AST types
- The big change here is that all the definitions for syntax-node classes have been macro-ized, to that we can do light metaprogramming over them
- The use of macros for this has big down-sides, but I'm not quite ready to do anything more heavy-weight right now
- The macro-ized definitions can be included multiple times, to generate different declarations/code as needed
- The first example of using this meta-programming facility is a new visitor system
- The actual visitor base classes and the dispatch logic are all generated from the meta-files
- There was only one visitor left in the code: the semantics checker, so that was ported to the new system.
- All current test cases pass, so *of course* that means all is well.
Diffstat (limited to 'source/slang/syntax-base-defs.h')
| -rw-r--r-- | source/slang/syntax-base-defs.h | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/source/slang/syntax-base-defs.h b/source/slang/syntax-base-defs.h new file mode 100644 index 000000000..11ec30e62 --- /dev/null +++ b/source/slang/syntax-base-defs.h @@ -0,0 +1,261 @@ +// syntax-base-defs.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. + +// Base class for all nodes representing actual syntax +// (thus having a location in the source code) +ABSTRACT_SYNTAX_CLASS(SyntaxNodeBase, RefObject) + + // The primary source location associated with this AST node + FIELD(CodePosition, Position) +END_SYNTAX_CLASS() + +// 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, RefObject) + RAW(typedef IValVisitor Visitor;) + + RAW(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(Substitutions* subst); + + // Lower-level interface for substition. Like the basic + // `Substitute` above, but also takes a by-reference + // integer parameter that should be incremented when + // returning a modified value (this can help the caller + // decide whether they need to do anything). + virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff); + + virtual bool EqualsVal(Val* val) = 0; + virtual String ToString() = 0; + virtual int GetHashCode() = 0; + bool operator == (const Val & v) + { + return EqualsVal(const_cast<Val*>(&v)); + } + ) +END_SYNTAX_CLASS() + +// A type, representing a classifier for some term in the AST. +// +// Types can include "sugar" in that they may refer to a +// `typedef` which gives them a good name when printed as +// part of diagnostic messages. +// +// In order to operation on types, though, we often want +// to look past any sugar, and operate on an underlying +// "canonical" type. The reprsentation caches a pointer to +// a canonical type on every type, so we can easily +// operate on the raw representation when needed. +ABSTRACT_SYNTAX_CLASS(ExpressionType, Val) + RAW(typedef ITypeVisitor Visitor;) + + RAW(virtual void accept(IValVisitor* visitor, void* extra) override;) + RAW(virtual void accept(ITypeVisitor* visitor, void* extra) = 0;) + +RAW( +public: + static RefPtr<ExpressionType> Error; + static RefPtr<ExpressionType> initializerListType; + static RefPtr<ExpressionType> Overloaded; + + static Dictionary<int, RefPtr<ExpressionType>> sBuiltinTypes; + static Dictionary<String, Decl*> sMagicDecls; + + // Note: just exists to make sure we can clean up + // canonical types we create along the way + static List<RefPtr<ExpressionType>> sCanonicalTypes; + + + + static ExpressionType* GetBool(); + static ExpressionType* GetFloat(); + static ExpressionType* getDoubleType(); + static ExpressionType* GetInt(); + static ExpressionType* GetUInt(); + static ExpressionType* GetVoid(); + static ExpressionType* getInitializerListType(); + static ExpressionType* GetError(); + +public: + virtual String ToString() = 0; + + bool Equals(ExpressionType * type); + bool Equals(RefPtr<ExpressionType> type); + + bool IsVectorType() { return As<VectorExpressionType>() != nullptr; } + bool IsArray() { return As<ArrayExpressionType>() != nullptr; } + + template<typename T> + T* As() + { + return dynamic_cast<T*>(GetCanonicalType()); + } + + // Convenience/legacy wrappers for `As<>` + ArithmeticExpressionType * AsArithmeticType() { return As<ArithmeticExpressionType>(); } + BasicExpressionType * AsBasicType() { return As<BasicExpressionType>(); } + VectorExpressionType * AsVectorType() { return As<VectorExpressionType>(); } + MatrixExpressionType * AsMatrixType() { return As<MatrixExpressionType>(); } + ArrayExpressionType * AsArrayType() { return As<ArrayExpressionType>(); } + + DeclRefType* AsDeclRefType() { return As<DeclRefType>(); } + + NamedExpressionType* AsNamedType(); + + bool IsTextureOrSampler(); + bool IsTexture() { return As<TextureType>() != nullptr; } + bool IsSampler() { return As<SamplerStateType>() != nullptr; } + bool IsStruct(); + bool IsClass(); + static void Init(); + static void Finalize(); + ExpressionType* GetCanonicalType(); + + virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff) override; + + virtual bool EqualsVal(Val* val) override; +protected: + virtual bool EqualsImpl(ExpressionType * type) = 0; + + virtual ExpressionType* CreateCanonicalType() = 0; + ExpressionType* canonicalType = nullptr; + ) +END_SYNTAX_CLASS() + +// A substitution represents a binding of certain +// type-level variables to concrete argument values +SYNTAX_CLASS(Substitutions, RefObject) + + // The generic declaration that defines the + // parametesr we are binding to arguments + DECL_FIELD(GenericDecl*, genericDecl) + + // The actual values of the arguments + SYNTAX_FIELD(List<RefPtr<Val>>, args) + + // Any further substitutions, relating to outer generic declarations + SYNTAX_FIELD(RefPtr<Substitutions>, outer) + + RAW( + // Apply a set of substitutions to the bindings in this substitution + RefPtr<Substitutions> SubstituteImpl(Substitutions* subst, int* ioDiff); + + // Check if these are equivalent substitutiosn to another set + bool Equals(Substitutions* subst); + bool operator == (const Substitutions & subst) + { + return Equals(const_cast<Substitutions*>(&subst)); + } + int GetHashCode() const + { + int rs = 0; + for (auto && v : args) + { + rs ^= v->GetHashCode(); + rs *= 16777619; + } + return rs; + } + ) +END_SYNTAX_CLASS() + +ABSTRACT_SYNTAX_CLASS(SyntaxNode, SyntaxNodeBase) +END_SYNTAX_CLASS() + +// +// 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, SyntaxNodeBase) + RAW(typedef IModifierVisitor Visitor;) + + RAW(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) + + // The token that was used to name this modifier. + FIELD(Token, nameToken) +END_SYNTAX_CLASS() + +// A syntax node which can have modifiers appled +ABSTRACT_SYNTAX_CLASS(ModifiableSyntaxNode, SyntaxNode) + + SYNTAX_FIELD(Modifiers, modifiers) + + RAW( + template<typename T> + FilteredModifierList<T> GetModifiersOfType() { return FilteredModifierList<T>(modifiers.first.Ptr()); } + + // Find the first modifier of a given type, or return `nullptr` if none is found. + template<typename T> + T* FindModifier() + { + return *GetModifiersOfType<T>().begin(); + } + + template<typename T> + bool HasModifier() { return FindModifier<T>() != nullptr; } + ) +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;) + + RAW(virtual void accept(IDeclVisitor* visitor, void* extra) = 0;) + + +END_SYNTAX_CLASS() + +ABSTRACT_SYNTAX_CLASS(Decl, DeclBase) + DECL_FIELD(ContainerDecl*, ParentDecl RAW(=nullptr)) + + FIELD(Token, Name) + + RAW( + String const& getName() { return Name.Content; } + Token const& getNameToken() { return Name; } + ) + + + FIELD_INIT(DeclCheckState, checkState, DeclCheckState::Unchecked) + + // The next declaration defined in the same container with the same name + DECL_FIELD(Decl*, nextInContainerWithSameName RAW(= nullptr)) + + RAW( + bool IsChecked(DeclCheckState state) { return checkState >= state; } + void SetCheckState(DeclCheckState state) + { + assert(state >= checkState); + checkState = state; + } + ) +END_SYNTAX_CLASS() + +ABSTRACT_SYNTAX_CLASS(ExpressionSyntaxNode, SyntaxNode) + RAW(typedef IExprVisitor Visitor;) + + FIELD(QualType, Type) + + RAW(virtual void accept(IExprVisitor* visitor, void* extra) = 0;) + +END_SYNTAX_CLASS() + +ABSTRACT_SYNTAX_CLASS(StatementSyntaxNode, ModifiableSyntaxNode) + RAW(typedef IStmtVisitor Visitor;) + + RAW(virtual void accept(IStmtVisitor* visitor, void* extra) = 0;) + +END_SYNTAX_CLASS() |
