//===--- ASTVisitor.h - Decl, Expr and Stmt Visitor -------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file defines the ASTVisitor class, and the DeclVisitor, ExprVisitor, and // StmtVisitor template typedefs. // //===----------------------------------------------------------------------===// #ifndef SWIFT_AST_ASTVISITOR_H #define SWIFT_AST_ASTVISITOR_H #include "swift/AST/Decl.h" #include "swift/AST/Expr.h" #include "swift/AST/Module.h" #include "swift/AST/Pattern.h" #include "swift/AST/Stmt.h" #include "swift/AST/TypeRepr.h" #include "llvm/Support/ErrorHandling.h" namespace swift { class ParameterList; /// ASTVisitor - This is a simple visitor class for Swift expressions. template class ASTVisitor { public: typedef ASTVisitor ASTVisitorType; DeclRetTy visit(Decl *D, Args... AA) { switch (D->getKind()) { #define DECL(CLASS, PARENT) \ case DeclKind::CLASS: \ return static_cast(this) \ ->visit##CLASS##Decl(static_cast(D), \ ::std::forward(AA)...); #include "swift/AST/DeclNodes.def" } llvm_unreachable("Not reachable, all cases handled"); } ExprRetTy visit(Expr *E, Args... AA) { switch (E->getKind()) { #define EXPR(CLASS, PARENT) \ case ExprKind::CLASS: \ return static_cast(this) \ ->visit##CLASS##Expr(static_cast(E), \ ::std::forward(AA)...); #include "swift/AST/ExprNodes.def" } llvm_unreachable("Not reachable, all cases handled"); } // Provide default implementations of abstract "visit" implementations that // just chain to their base class. This allows visitors to just implement // the base behavior and handle all subclasses if they desire. Since this is // a template, it will only instantiate cases that are used and thus we still // require full coverage of the AST nodes by the visitor. #define ABSTRACT_EXPR(CLASS, PARENT) \ ExprRetTy visit##CLASS##Expr(CLASS##Expr *E, Args... AA) { \ return static_cast(this)->visit##PARENT(E, \ ::std::forward(AA)...); \ } #define EXPR(CLASS, PARENT) ABSTRACT_EXPR(CLASS, PARENT) #include "swift/AST/ExprNodes.def" StmtRetTy visit(Stmt *S, Args... AA) { switch (S->getKind()) { #define STMT(CLASS, PARENT) \ case StmtKind::CLASS: \ return static_cast(this) \ ->visit##CLASS##Stmt(static_cast(S), \ ::std::forward(AA)...); #include "swift/AST/StmtNodes.def" } llvm_unreachable("Not reachable, all cases handled"); } #define DECL(CLASS, PARENT) \ DeclRetTy visit##CLASS##Decl(CLASS##Decl *D, Args... AA) {\ return static_cast(this)->visit##PARENT(D, \ ::std::forward(AA)...); \ } #define ABSTRACT_DECL(CLASS, PARENT) DECL(CLASS, PARENT) #include "swift/AST/DeclNodes.def" PatternRetTy visit(Pattern *P, Args... AA) { switch (P->getKind()) { #define PATTERN(CLASS, PARENT) \ case PatternKind::CLASS: \ return static_cast(this) \ ->visit##CLASS##Pattern(static_cast(P), \ ::std::forward(AA)...); #include "swift/AST/PatternNodes.def" } llvm_unreachable("Not reachable, all cases handled"); } TypeReprRetTy visit(TypeRepr *T, Args... AA) { switch (T->getKind()) { #define TYPEREPR(CLASS, PARENT) \ case TypeReprKind::CLASS: \ return static_cast(this) \ ->visit##CLASS##TypeRepr(static_cast(T), \ ::std::forward(AA)...); #include "swift/AST/TypeReprNodes.def" } llvm_unreachable("Not reachable, all cases handled"); } TypeReprRetTy visitTypeRepr(TypeRepr *T, Args... AA) { return TypeReprRetTy(); } #define TYPEREPR(CLASS, PARENT) \ TypeReprRetTy visit##CLASS##TypeRepr(CLASS##TypeRepr *T, Args... AA) {\ return static_cast(this)->visit##PARENT(T, \ ::std::forward(AA)...); \ } #define ABSTRACT_TYPEREPR(CLASS, PARENT) TYPEREPR(CLASS, PARENT) #include "swift/AST/TypeReprNodes.def" AttributeRetTy visit(DeclAttribute *A, Args... AA) { switch (A->getKind()) { #define DECL_ATTR(_, CLASS, ...) \ case DAK_##CLASS: \ return static_cast(this) \ ->visit##CLASS##Attr(static_cast(A), \ ::std::forward(AA)...); #include "swift/AST/Attr.def" case DAK_Count: llvm_unreachable("Not an attribute kind"); } } #define DECL_ATTR(NAME,CLASS,...) \ AttributeRetTy visit##CLASS##Attr(CLASS##Attr *A, Args... AA) { \ return static_cast(this)->visitDeclAttribute( \ A, ::std::forward(AA)...); \ } #include "swift/AST/Attr.def" bool visit(ParameterList *PL) { return static_cast(this)->visitParameterList(PL); } bool visitParameterList(ParameterList *PL) { return false; } }; template using ExprVisitor = ASTVisitor; template using StmtVisitor = ASTVisitor; template using DeclVisitor = ASTVisitor; template using PatternVisitor = ASTVisitor; template using TypeReprVisitor = ASTVisitor; template using AttributeVisitor = ASTVisitor; } // end namespace swift #endif