NEURON
codegen_compatibility_visitor.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2023 Blue Brain Project, EPFL.
3  * See the top-level LICENSE file for details.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #pragma once
9 
10 /**
11  * \file
12  * \brief \copybrief nmodl::codegen::CodegenCompatibilityVisitor
13  */
14 
15 #include <map>
16 #include <set>
17 
18 #include "ast/ast.hpp"
19 #include "codegen_naming.hpp"
20 #include "lexer/modtoken.hpp"
21 #include "symtab/symbol_table.hpp"
22 #include "utils/logger.hpp"
23 #include "visitors/ast_visitor.hpp"
24 
25 namespace nmodl {
26 namespace codegen {
27 
28 using namespace ast;
29 
30 /**
31  * \addtogroup codegen_backends
32  * \{
33  */
34 
35 /**
36  * \class CodegenCompatibilityVisitor
37  * \brief %Visitor for printing compatibility issues of the mod file
38  *
39  * INDEPENDENT_BLOCK is ignored (no error raised) as stated in:
40  * https://nrn.readthedocs.io/en/latest/nmodl/language/nmodl.html#independent
41  */
43  /// Typedef for defining FunctionPointer that points to the
44  /// function needed to be called for every kind of error
45  typedef std::string (CodegenCompatibilityVisitor::*FunctionPointer)(
46  ast::Ast& node,
47  const std::shared_ptr<ast::Ast>&) const;
48 
49  /// associated container to find the function needed to be called in
50  /// for every ast::AstNodeType that is unsupported
51  static const std::map<ast::AstNodeType, FunctionPointer> unhandled_ast_types_func;
52 
53  /// Set of handled solvers by the NMODL \c C++ code generator
54  static const inline std::set<std::string> handled_solvers{codegen::naming::CNEXP_METHOD,
60 
61  const std::string simulator = "coreneuron";
62 
63  public:
64  /// \name Ctor & dtor
65  /// \{
66 
67  /// Default CodegenCompatibilityVisitor constructor
68  ///
69  /// The argument `simulator` must be `"neuron"` for NEURON, everything else
70  /// refers to CoreNEURON. The compatibility will be checked as if
71  /// generating code for the specified simulator.
72  CodegenCompatibilityVisitor(const std::string& simulator = "coreneuron")
73  : simulator(simulator) {}
74 
75  /// \}
76 
77  /// Search the ast::Ast for nodes that
78  /// are incompatible with NMODL \c C++ code generator
79  ///
80  /// \param node Ast
81  /// \return bool if there are unhandled nodes or not
82  bool find_unhandled_ast_nodes(Ast& node) const;
83 
84  private:
85  /// Takes as parameter an std::shared_ptr<ast::Ast>,
86  /// searches if the method used for solving is supported
87  /// and if it is not it returns a relative error message
88  ///
89  /// \param node Not used by the function
90  /// \param ast_node Ast node which is checked
91  /// \return std::string error
92  std::string return_error_if_solve_method_is_unhandled(
93  ast::Ast& node,
94  const std::shared_ptr<ast::Ast>& ast_node) const;
95 
96  /// Takes as parameter an std::shared_ptr<ast::Ast> node
97  /// and returns a relative error with the name, the type
98  /// and the location of the unhandled statement
99  ///
100  /// \tparam T Type of node parameter in the ast::Ast
101  /// \param node Not used by the function
102  /// \param ast_node Ast node which is checked
103  /// \return std::string error
104  template <typename T>
105  std::string return_error_with_name(ast::Ast& /* node */,
106  const std::shared_ptr<ast::Ast>& ast_node) const {
107  auto real_type_block = std::dynamic_pointer_cast<T>(ast_node);
108  auto token = real_type_block->get_token();
109  try {
110  return fmt::format("\"{}\" {}construct found at [{}] is not handled\n",
111  ast_node->get_node_name(),
112  real_type_block->get_nmodl_name(),
113  token ? token->position() : "unknown location");
114  } catch (const std::logic_error&) {
115  return fmt::format("{}construct found at [{}] is not handled\n",
116  real_type_block->get_nmodl_name(),
117  token ? token->position() : "unknown location");
118  }
119  }
120 
121  /// Takes as parameter an std::shared_ptr<ast::Ast> node
122  /// and returns a relative error with the type and the
123  /// location of the unhandled statement
124  ///
125  /// \tparam T Type of node parameter in the ast::Ast
126  /// \param node Not used by the function
127  /// \param ast_node Ast node which is checked
128  /// \return std::string error
129  template <typename T>
130  std::string return_error_without_name(ast::Ast& /* node */,
131  const std::shared_ptr<ast::Ast>& ast_node) const {
132  auto real_type_block = std::dynamic_pointer_cast<T>(ast_node);
133  return fmt::format("{}construct found at [{}] is not handled\n",
134  real_type_block->get_nmodl_name(),
135  real_type_block->get_token()->position());
136  }
137 
138  /// Callback when detecting EXTERNAL.
139  std::string return_error_extern(ast::Ast& node,
140  const std::shared_ptr<ast::Ast>& ast_node) const;
141 
142  /// Takes as parameter the ast::Ast to read the symbol table
143  /// and an std::shared_ptr<ast::Ast> node and returns relative
144  /// error if a variable that is writen in the mod file is
145  /// defined as GLOBAL instead of RANGE
146  ///
147  /// \param node Ast
148  /// \param ast_node Ast node which is checked
149  /// \return std::string error
150  std::string return_error_global_var(ast::Ast& node,
151  const std::shared_ptr<ast::Ast>& ast_node) const;
152 
153  std::string return_error_param_var(ast::Ast& node,
154  const std::shared_ptr<ast::Ast>& ast_node) const;
155 
156  /// Takes as parameter the ast::Ast and checks if the
157  /// functions "bbcore_read" and "bbcore_write" are defined
158  /// in any of the ast::Ast VERBATIM blocks. The function is
159  /// called if there is a BBCORE_POINTER defined in the mod
160  /// file
161  ///
162  /// \param node Ast
163  /// \param ast_node Not used by the function
164  /// \return std::string error
165  std::string return_error_if_no_bbcore_read_write(
166  ast::Ast& node,
167  const std::shared_ptr<ast::Ast>& ast_node) const;
168 };
169 
170 /** \} */ // end of codegen_backends
171 
172 } // namespace codegen
173 } // namespace nmodl
Auto generated AST classes declaration.
Concrete visitor for all AST classes.
Visitor for printing compatibility issues of the mod file
CodegenCompatibilityVisitor(const std::string &simulator="coreneuron")
Default CodegenCompatibilityVisitor constructor.
static const std::map< ast::AstNodeType, FunctionPointer > unhandled_ast_types_func
associated container to find the function needed to be called in for every ast::AstNodeType that is u...
std::string return_error_without_name(ast::Ast &, const std::shared_ptr< ast::Ast > &ast_node) const
Takes as parameter an std::shared_ptr<ast::Ast> node and returns a relative error with the type and t...
std::string return_error_with_name(ast::Ast &, const std::shared_ptr< ast::Ast > &ast_node) const
Takes as parameter an std::shared_ptr<ast::Ast> node and returns a relative error with the name,...
Concrete visitor for all AST classes.
Definition: ast_visitor.hpp:37
static constexpr char DERIVIMPLICIT_METHOD[]
derivimplicit method in nmodl
static constexpr char MATEXP_METHOD[]
matexp method in nmodl
static constexpr char CNEXP_METHOD[]
cnexp method in nmodl
static constexpr char EULER_METHOD[]
euler method in nmodl
static constexpr char SPARSE_METHOD[]
sparse method in nmodl
static constexpr char AFTER_CVODE_METHOD[]
cvode method in nmodl
encapsulates code generation backend implementations
Definition: ast_common.hpp:26
static Node * node(Object *)
Definition: netcvode.cpp:291
Base class for all Abstract Syntax Tree node types.
Definition: ast.hpp:52
Implement classes for representing symbol table at block and file scope.