From daf53bb2708982a2bcc6d6cc08fe88790ccf0bc2 Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Thu, 21 May 2020 15:36:02 -0400 Subject: Non virtual accept implementation on AST types (#1351) * First pass impl of making accept on AST node types non virtual. * A single switch for ITypeVistor on Val type. * Use ORIGIN to choose ITypeVisitor dispatch. * Don't use ORIGIN - we don't need special handling for ITypeVisitor on Val derived types. --- source/slang/slang-ast-base.h | 13 +++--- source/slang/slang-ast-reflect.cpp | 79 ++++++++++++++++++++++++++++++++++ source/slang/slang-ast-reflect.h | 29 +------------ source/slang/slang-ast-support-types.h | 6 +++ source/slang/slang-syntax.cpp | 12 ------ 5 files changed, 92 insertions(+), 47 deletions(-) diff --git a/source/slang/slang-ast-base.h b/source/slang/slang-ast-base.h index b25c8a371..66afece19 100644 --- a/source/slang/slang-ast-base.h +++ b/source/slang/slang-ast-base.h @@ -74,7 +74,7 @@ class Val : public NodeBase typedef IValVisitor Visitor; - virtual void accept(IValVisitor* visitor, void* extra) = 0; + void accept(IValVisitor* visitor, void* extra); // construct a new value by applying a set of parameter // substitutions to this one @@ -122,8 +122,7 @@ class Type: public Val typedef ITypeVisitor Visitor; - virtual void accept(IValVisitor* visitor, void* extra) override; - virtual void accept(ITypeVisitor* visitor, void* extra) = 0; + void accept(ITypeVisitor* visitor, void* extra); public: Session* getSession() { return this->session; } @@ -271,7 +270,7 @@ class Modifier : public SyntaxNode SLANG_ABSTRACT_CLASS(Modifier) typedef IModifierVisitor Visitor; - virtual void accept(IModifierVisitor* visitor, void* extra) = 0; + void accept(IModifierVisitor* visitor, void* extra); // Next modifier in linked list of modifiers on same piece of syntax RefPtr next; @@ -312,7 +311,7 @@ class DeclBase : public ModifiableSyntaxNode typedef IDeclVisitor Visitor; - virtual void accept(IDeclVisitor* visitor, void* extra) = 0; + void accept(IDeclVisitor* visitor, void* extra); }; class Decl : public DeclBase @@ -350,7 +349,7 @@ class Expr : public SyntaxNode QualType type; - virtual void accept(IExprVisitor* visitor, void* extra) = 0; + void accept(IExprVisitor* visitor, void* extra); }; class Stmt : public ModifiableSyntaxNode @@ -359,7 +358,7 @@ class Stmt : public ModifiableSyntaxNode typedef IStmtVisitor Visitor; - virtual void accept(IStmtVisitor* visitor, void* extra) = 0; + void accept(IStmtVisitor* visitor, void* extra); }; } // namespace Slang diff --git a/source/slang/slang-ast-reflect.cpp b/source/slang/slang-ast-reflect.cpp index 471daf92b..eb511689d 100644 --- a/source/slang/slang-ast-reflect.cpp +++ b/source/slang/slang-ast-reflect.cpp @@ -9,6 +9,8 @@ #include #include +#include "slang-visitor.h" + #include "slang-ast-generated-macro.h" namespace Slang @@ -66,5 +68,82 @@ struct CreateImpl SLANG_ALL_ASTNode_NodeBase(SLANG_REFLECT_CLASS_INFO, _) SLANG_ALL_ASTNode_Substitutions(SLANG_REFLECT_CLASS_INFO, _) +// We dispatch to non 'abstract' types +#define SLANG_CASE_NONE(NAME) case ASTNodeType::NAME: return visitor->dispatch_##NAME(static_cast(this), extra); +#define SLANG_CASE_ABSTRACT(NAME) + +#define SLANG_CASE_DISPATCH(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) SLANG_CASE_##MARKER(NAME) + +void Val::accept(IValVisitor* visitor, void* extra) +{ + const ReflectClassInfo& classInfo = getClassInfo(); + const ASTNodeType astType = ASTNodeType(classInfo.m_classId); + + switch (astType) + { + SLANG_CHILDREN_ASTNode_Val(SLANG_CASE_DISPATCH, _) + default: SLANG_ASSERT(!"Unknown type"); + } +} + +void Type::accept(ITypeVisitor* visitor, void* extra) +{ + const ReflectClassInfo& classInfo = getClassInfo(); + const ASTNodeType astType = ASTNodeType(classInfo.m_classId); + + switch (astType) + { + SLANG_CHILDREN_ASTNode_Type(SLANG_CASE_DISPATCH, _) + default: SLANG_ASSERT(!"Unknown type"); + } +} + +void Modifier::accept(IModifierVisitor* visitor, void* extra) +{ + const ReflectClassInfo& classInfo = getClassInfo(); + const ASTNodeType astType = ASTNodeType(classInfo.m_classId); + + switch (astType) + { + SLANG_CHILDREN_ASTNode_Modifier(SLANG_CASE_DISPATCH, _) + default: SLANG_ASSERT(!"Unknown type"); + } +} + +void DeclBase::accept(IDeclVisitor* visitor, void* extra) +{ + const ReflectClassInfo& classInfo = getClassInfo(); + const ASTNodeType astType = ASTNodeType(classInfo.m_classId); + + switch (astType) + { + SLANG_CHILDREN_ASTNode_DeclBase(SLANG_CASE_DISPATCH, _) + default: SLANG_ASSERT(!"Unknown type"); + } +} + +void Expr::accept(IExprVisitor* visitor, void* extra) +{ + const ReflectClassInfo& classInfo = getClassInfo(); + const ASTNodeType astType = ASTNodeType(classInfo.m_classId); + + switch (astType) + { + SLANG_CHILDREN_ASTNode_Expr(SLANG_CASE_DISPATCH, _) + default: SLANG_ASSERT(!"Unknown type"); + } +} + +void Stmt::accept(IStmtVisitor* visitor, void* extra) +{ + const ReflectClassInfo& classInfo = getClassInfo(); + const ASTNodeType astType = ASTNodeType(classInfo.m_classId); + + switch (astType) + { + SLANG_CHILDREN_ASTNode_Stmt(SLANG_CASE_DISPATCH, _) + default: SLANG_ASSERT(!"Unknown type"); + } +} } // namespace Slang diff --git a/source/slang/slang-ast-reflect.h b/source/slang/slang-ast-reflect.h index 0c57dc757..5384e4afd 100644 --- a/source/slang/slang-ast-reflect.h +++ b/source/slang/slang-ast-reflect.h @@ -10,33 +10,7 @@ #define SLANG_AST_OVERRIDE_INNER override #define SLANG_AST_OVERRIDE_LEAF override -// Switch based on the origin - classes defined in slang-ast-base.h do not have accept defined on them -// The 'origin' is based on the file where the class definition is located. - -// Define what the accept method looks like, so don't have to repeat -#define SLANG_AST_ACCEPT_IMPL(NAME) virtual void accept(NAME::Visitor* visitor, void* extra) override; - -// A macro for *all* of the different origin/files where AST files are defined. -#define SLANG_AST_ACCEPT_BASE(NAME) -#define SLANG_AST_ACCEPT_DECL(NAME) SLANG_AST_ACCEPT_IMPL(NAME) -#define SLANG_AST_ACCEPT_EXPR(NAME) SLANG_AST_ACCEPT_IMPL(NAME) -#define SLANG_AST_ACCEPT_MODIFIER(NAME) SLANG_AST_ACCEPT_IMPL(NAME) -#define SLANG_AST_ACCEPT_TYPE(NAME) SLANG_AST_ACCEPT_IMPL(NAME) -#define SLANG_AST_ACCEPT_VAL(NAME) SLANG_AST_ACCEPT_IMPL(NAME) -#define SLANG_AST_ACCEPT_STMT(NAME) SLANG_AST_ACCEPT_IMPL(NAME) - // Implementation for SLANG_ABSTRACT_CLASS(x) using reflection from C++ extractor in slang-ast-generated.h -#define SLANG_ABSTRACT_CLASS_REFLECT_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \ - public: \ - typedef SUPER Super; \ - static const ASTNodeType kType = ASTNodeType::NAME; \ - static const ReflectClassInfo kReflectClassInfo; \ - 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; } \ - -// Implementation for SLANG_CLASS(x) using reflection from C++ extractor in slang-ast-generated.h. -// This implementation is the same as for SLANG_ABSTRACT_CLASS_REFLECT_IMPL, except for the SLANG_AST_ACCEPT_ line which inserts the accept -// method for non 'BASE' origin classes. #define SLANG_CLASS_REFLECT_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \ public: \ typedef SUPER Super; \ @@ -44,11 +18,10 @@ static const ReflectClassInfo kReflectClassInfo; \ 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; } \ - SLANG_AST_ACCEPT_##ORIGIN(NAME) // Macro definitions - use the SLANG_ASTNode_ definitions to invoke the IMPL to produce the code // injected into AST classes -#define SLANG_ABSTRACT_CLASS(NAME) SLANG_ASTNode_##NAME(SLANG_ABSTRACT_CLASS_REFLECT_IMPL, _) +#define SLANG_ABSTRACT_CLASS(NAME) SLANG_ASTNode_##NAME(SLANG_CLASS_REFLECT_IMPL, _) #define SLANG_CLASS(NAME) SLANG_ASTNode_##NAME(SLANG_CLASS_REFLECT_IMPL, _) // Does nothing - just a mark to the C++ extractor diff --git a/source/slang/slang-ast-support-types.h b/source/slang/slang-ast-support-types.h index c1072c923..9b8cfbea2 100644 --- a/source/slang/slang-ast-support-types.h +++ b/source/slang/slang-ast-support-types.h @@ -491,6 +491,12 @@ namespace Slang // We include super.m_classId, because it's a subclass of itself. return m_classId >= super.m_classId && m_classId <= super.m_lastClassId; } + // True if typeId derives from this type + SLANG_FORCE_INLINE bool isDerivedFrom(uint32_t typeId) const + { + return typeId >= m_classId && typeId <= 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; diff --git a/source/slang/slang-syntax.cpp b/source/slang/slang-syntax.cpp index cb75622bc..486466718 100644 --- a/source/slang/slang-syntax.cpp +++ b/source/slang/slang-syntax.cpp @@ -9,11 +9,6 @@ namespace Slang { -#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); } - -SLANG_ALL_ASTNode_NodeBase(SLANG_CLASS_ONLY, SLANG_CLASS_ACCEPT_IMPL) - // !!!!!!!!!!!!!!!!!!!!!!!!!!!!! DiagnosticSink impls !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! void printDiagnosticArg(StringBuilder& sb, Decl* decl) @@ -209,13 +204,6 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt return count; } - // Type - - void Type::accept(IValVisitor* visitor, void* extra) - { - accept((ITypeVisitor*)visitor, extra); - } - // TypeExp bool TypeExp::Equals(Type* other) -- cgit v1.2.3