summaryrefslogtreecommitdiff
path: root/source/slang/syntax-base-defs.h
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-06-29 08:55:09 -0700
committerTim Foley <tfoley@nvidia.com>2017-06-30 12:22:33 -0700
commitcab694dcead92a554654d7fa3f08909d519425f0 (patch)
tree6c2c07c3930ff68b5518e562b0b507d5ec54d0bf /source/slang/syntax-base-defs.h
parentb2b08679a32506d629df84730f36639dab9f9593 (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.h261
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()