// slang-visitor.h #ifndef SLANG_VISITOR_H_INCLUDED #define SLANG_VISITOR_H_INCLUDED // This file defines the basic "Visitor" pattern for doing dispatch // over the various categories of syntax node. #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 { SLANG_CHILDREN_ASTNode_Type(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL) }; template struct TypeVisitor : Base { Result dispatch(Type* type) { Result result; type->accept(this, &result); return result; } Result dispatchType(Type* type) { Result result; type->accept(this, &result); return result; } SLANG_CHILDREN_ASTNode_Type(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL) SLANG_CHILDREN_ASTNode_Type(SLANG_VISITOR_RESULT_VISIT_IMPL, _) }; template struct TypeVisitor : Base { void dispatch(Type* type) { type->accept(this, 0); } void dispatchType(Type* type) { type->accept(this, 0); } SLANG_CHILDREN_ASTNode_Type(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL) SLANG_CHILDREN_ASTNode_Type(SLANG_VISITOR_VOID_VISIT_IMPL, _) }; template struct TypeVisitorWithArg : Base { void dispatch(Type* type, Arg const& arg) { type->accept(this, (void*)&arg); } SLANG_CHILDREN_ASTNode_Type(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_ARG_IMPL) SLANG_CHILDREN_ASTNode_Type(SLANG_VISITOR_VOID_VISIT_ARG_IMPL, _) }; // // Expression Visitors // struct IExprVisitor { SLANG_CHILDREN_ASTNode_Expr(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL) }; template struct ExprVisitor : IExprVisitor { Result dispatch(Expr* expr) { Result result; expr->accept(this, &result); return result; } SLANG_CHILDREN_ASTNode_Expr(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL) SLANG_CHILDREN_ASTNode_Expr(SLANG_VISITOR_RESULT_VISIT_IMPL, _) }; template struct ExprVisitor : IExprVisitor { void dispatch(Expr* expr) { expr->accept(this, 0); } SLANG_CHILDREN_ASTNode_Expr(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL) SLANG_CHILDREN_ASTNode_Expr(SLANG_VISITOR_VOID_VISIT_IMPL, _) }; template struct ExprVisitorWithArg : IExprVisitor { void dispatch(Expr* obj, Arg const& arg) { obj->accept(this, (void*)&arg); } SLANG_CHILDREN_ASTNode_Expr(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_ARG_IMPL) SLANG_CHILDREN_ASTNode_Expr(SLANG_VISITOR_VOID_VISIT_ARG_IMPL, _) }; // // Statement Visitors // struct IStmtVisitor { SLANG_CHILDREN_ASTNode_Stmt(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL) }; template struct StmtVisitor : IStmtVisitor { Result dispatch(Stmt* stmt) { Result result; stmt->accept(this, &result); return result; } SLANG_CHILDREN_ASTNode_Stmt(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL) SLANG_CHILDREN_ASTNode_Stmt(SLANG_VISITOR_RESULT_VISIT_IMPL, _) }; template struct StmtVisitor : IStmtVisitor { void dispatch(Stmt* stmt) { stmt->accept(this, 0); } SLANG_CHILDREN_ASTNode_Stmt(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL) SLANG_CHILDREN_ASTNode_Stmt(SLANG_VISITOR_VOID_VISIT_IMPL, _) }; // // Declaration Visitors // struct IDeclVisitor { SLANG_CHILDREN_ASTNode_DeclBase(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL) }; template struct DeclVisitor : IDeclVisitor { Result dispatch(DeclBase* decl) { Result result; decl->accept(this, &result); return result; } SLANG_CHILDREN_ASTNode_DeclBase(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL) SLANG_CHILDREN_ASTNode_DeclBase(SLANG_VISITOR_RESULT_VISIT_IMPL, _) }; template struct DeclVisitor : IDeclVisitor { void dispatch(DeclBase* decl) { decl->accept(this, 0); } SLANG_CHILDREN_ASTNode_DeclBase(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL) SLANG_CHILDREN_ASTNode_DeclBase(SLANG_VISITOR_VOID_VISIT_IMPL, _) }; template struct DeclVisitorWithArg : IDeclVisitor { void dispatch(DeclBase* obj, Arg const& arg) { obj->accept(this, (void*)&arg); } SLANG_CHILDREN_ASTNode_DeclBase(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_ARG_IMPL) SLANG_CHILDREN_ASTNode_DeclBase(SLANG_VISITOR_VOID_VISIT_ARG_IMPL, _) }; // // Modifier Visitors // struct IModifierVisitor { SLANG_CHILDREN_ASTNode_Modifier(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL) }; template struct ModifierVisitor : IModifierVisitor { Result dispatch(Modifier* modifier) { Result result; modifier->accept(this, &result); return result; } SLANG_CHILDREN_ASTNode_Modifier(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL) SLANG_CHILDREN_ASTNode_Modifier(SLANG_VISITOR_RESULT_VISIT_IMPL, _) }; template struct ModifierVisitor : IModifierVisitor { void dispatch(Modifier* modifier) { modifier->accept(this, 0); } SLANG_CHILDREN_ASTNode_Modifier(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL) SLANG_CHILDREN_ASTNode_Modifier(SLANG_VISITOR_VOID_VISIT_IMPL, _) }; // // Val Visitors // struct IValVisitor : ITypeVisitor { SLANG_CHILDREN_ASTNode_Val(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL) }; template struct ValVisitor : TypeVisitor { Result dispatch(Val* val) { Result result; val->accept(this, &result); return result; } SLANG_CHILDREN_ASTNode_Val(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL) SLANG_CHILDREN_ASTNode_Val(SLANG_VISITOR_RESULT_VISIT_IMPL, _) }; template struct ValVisitor : TypeVisitor { void dispatch(Val* val) { val->accept(this, 0); } SLANG_CHILDREN_ASTNode_Val(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL) SLANG_CHILDREN_ASTNode_Val(SLANG_VISITOR_VOID_VISIT_IMPL, _) }; } #endif