/* This file is part of TON Blockchain Library. TON Blockchain Library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. TON Blockchain Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with TON Blockchain Library. If not, see . */ #pragma once #include "ast.h" #include "platform-utils.h" /* * A module implementing base functionality of read-only traversing a vertex tree. * Since a vertex in general doesn't store a vector of children, iterating is possible only for concrete node_type. * E.g., for ast_if_statement, visit nodes cond, if-body and else-body. For ast_string_const, nothing. And so on. * Visitors below are helpers to inherit from and handle specific vertex types. * * Note, that absence of "children" in ASTNodeBase is not a drawback. Instead, it encourages you to think * about types and match the type system. * * The visitor is read-only, it does not modify visited nodes (except if you purposely call mutating methods). * For example, if you want to replace "beginCell()" call with "begin_cell", a visitor isn't enough for you. * To replace vertices, consider another API: ast-replacer.h. */ namespace tolk { class ASTVisitor { protected: GNU_ATTRIBUTE_ALWAYS_INLINE static void visit_children(const ASTNodeLeaf* v) { static_cast(v); } GNU_ATTRIBUTE_ALWAYS_INLINE void visit_children(const ASTNodeUnary* v) { visit(v->child); } GNU_ATTRIBUTE_ALWAYS_INLINE void visit_children(const ASTNodeBinary* v) { visit(v->lhs); visit(v->rhs); } GNU_ATTRIBUTE_ALWAYS_INLINE void visit_children(const ASTNodeVararg* v) { for (AnyV child : v->children) { visit(child); } } virtual void visit(AnyV v) = 0; public: virtual ~ASTVisitor() = default; }; class ASTVisitorFunctionBody : public ASTVisitor { protected: using parent = ASTVisitorFunctionBody; virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } virtual void visit(V v) { return visit_children(v); } void visit(AnyV v) final { switch (v->type) { case ast_empty: return visit(v->as()); case ast_identifier: return visit(v->as()); case ast_int_const: return visit(v->as()); case ast_string_const: return visit(v->as()); case ast_bool_const: return visit(v->as()); case ast_nil_tuple: return visit(v->as()); case ast_function_call: return visit(v->as()); case ast_parenthesized_expr: return visit(v->as()); case ast_underscore: return visit(v->as()); case ast_type_expression: return visit(v->as()); case ast_variable_declaration: return visit(v->as()); case ast_tensor: return visit(v->as()); case ast_tensor_square: return visit(v->as()); case ast_dot_tilde_call: return visit(v->as()); case ast_unary_operator: return visit(v->as()); case ast_binary_operator: return visit(v->as()); case ast_ternary_operator: return visit(v->as()); case ast_return_statement: return visit(v->as()); case ast_sequence: return visit(v->as()); case ast_repeat_statement: return visit(v->as()); case ast_while_statement: return visit(v->as()); case ast_do_until_statement: return visit(v->as()); case ast_try_catch_statement: return visit(v->as()); case ast_if_statement: return visit(v->as()); case ast_asm_body: return visit(v->as()); default: throw UnexpectedASTNodeType(v, "ASTVisitorFunctionBody::visit"); } } public: void start_visiting_function(V v_function) { visit(v_function->get_body()); } }; class ASTVisitorAllFunctionsInFile : public ASTVisitorFunctionBody { protected: using parent = ASTVisitorAllFunctionsInFile; virtual bool should_enter_function(V v) = 0; public: void start_visiting_file(V v_file) { for (AnyV v : v_file->get_toplevel_declarations()) { if (auto v_func = v->try_as()) { if (should_enter_function(v_func)) { visit(v_func->get_body()); } } } } }; } // namespace tolk