12 #include "utils/logger.hpp"
19 const std::map<ast::AstNodeType, CodegenCompatibilityVisitor::FunctionPointer>
21 {{AstNodeType::DISCRETE_BLOCK,
22 &CodegenCompatibilityVisitor::return_error_with_name<DiscreteBlock>},
23 {AstNodeType::SOLVE_BLOCK,
27 {AstNodeType::BBCORE_POINTER_VAR,
34 const std::shared_ptr<ast::Ast>& ast_node)
const {
35 auto solve_block_ast_node = std::dynamic_pointer_cast<ast::SolveBlock>(ast_node);
36 std::stringstream unhandled_method_error_message;
37 auto method = solve_block_ast_node->get_method();
41 auto unhandled_solver_method =
handled_solvers.find(method->get_node_name()) ==
43 if (unhandled_solver_method) {
44 unhandled_method_error_message << fmt::format(
45 "\"{}\" solving method used at [{}] not handled. Supported methods are cnexp, euler, "
46 "derivimplicit and sparse\n",
47 method->get_node_name(),
48 method->get_token()->position());
50 return unhandled_method_error_message.str();
56 const std::shared_ptr<ast::Ast>& ast_node)
const {
64 auto external = std::dynamic_pointer_cast<ast::External>(ast_node);
65 return fmt::format(
"Found EXTERNAL at [{}] while generating code for CoreNEURON.\n",
66 external->get_token()->position());
72 const std::shared_ptr<ast::Ast>& ast_node)
const {
81 auto global_var = std::dynamic_pointer_cast<ast::GlobalVar>(ast_node);
82 std::stringstream error_message_global_var;
83 if (
node.get_symbol_table()->lookup(global_var->get_node_name())->get_write_count() > 0) {
84 error_message_global_var << fmt::format(
85 "\"{}\" variable found at [{}] should be defined as a RANGE variable instead of GLOBAL "
86 "to enable backend transformations\n",
87 global_var->get_node_name(),
88 global_var->get_token()->position());
90 return error_message_global_var.str();
96 const std::shared_ptr<ast::Ast>& ast_node)
const {
97 auto param_assign = std::dynamic_pointer_cast<ast::ParamAssign>(ast_node);
98 std::stringstream error_message_global_var;
99 auto symbol =
node.get_symbol_table()->lookup(param_assign->get_node_name());
100 if (!symbol->is_writable() && symbol->get_write_count() > 0) {
101 error_message_global_var << fmt::format(
102 "\"{}\" variable found at [{}] should be writable if it needs to be written\n",
104 symbol->get_token().position());
106 return error_message_global_var.str();
112 const std::shared_ptr<ast::Ast>& )
const {
113 std::stringstream error_message_no_bbcore_read_write;
115 auto found_bbcore_read =
false;
116 auto found_bbcore_write =
false;
117 for (
const auto& it: verbatim_nodes) {
118 auto verbatim = std::dynamic_pointer_cast<ast::Verbatim>(it);
120 auto verbatim_statement_string = verbatim->get_statement()->get_value();
127 driver.scan_string(verbatim_statement_string);
128 auto tokens =
driver.all_tokens();
130 for (
const auto& token: tokens) {
131 if (token ==
"bbcore_read") {
132 found_bbcore_read =
true;
134 if (token ==
"bbcore_write") {
135 found_bbcore_write =
true;
139 if (!found_bbcore_read) {
140 error_message_no_bbcore_read_write
141 <<
"\"bbcore_read\" function not defined in any VERBATIM block\n";
143 if (!found_bbcore_write) {
144 error_message_no_bbcore_read_write
145 <<
"\"bbcore_write\" function not defined in any VERBATIM block\n";
147 return error_message_no_bbcore_read_write.str();
157 std::vector<ast::AstNodeType> unhandled_ast_types;
160 unhandled_ast_types.push_back(node_type);
164 std::ostringstream ss;
165 for (
const auto& it: unhandled_ast_nodes) {
166 auto node_type = it->get_node_type();
167 ss << (this->*unhandled_ast_types_func.find(node_type)->second)(
node, it);
169 if (!ss.str().empty()) {
170 logger->error(
"Code incompatibility detected");
171 logger->error(
"Cannot translate mod file to .cpp file");
172 logger->error(
"Fix the following errors and try again");
174 std::istringstream ss_stringstream(ss.str());
175 while (std::getline(ss_stringstream, line)) {
177 logger->error(fmt::format(
"Code Incompatibility :: {}", line));
Auto generated AST classes declaration.
const std::string simulator
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_param_var(ast::Ast &node, const std::shared_ptr< ast::Ast > &ast_node) const
std::string return_error_extern(ast::Ast &node, const std::shared_ptr< ast::Ast > &ast_node) const
Callback when detecting EXTERNAL.
std::string return_error_if_no_bbcore_read_write(ast::Ast &node, const std::shared_ptr< ast::Ast > &ast_node) const
Takes as parameter the ast::Ast and checks if the functions "bbcore_read" and "bbcore_write" are defi...
std::string return_error_if_solve_method_is_unhandled(ast::Ast &node, const std::shared_ptr< ast::Ast > &ast_node) const
Takes as parameter an std::shared_ptr<ast::Ast>, searches if the method used for solving is supported...
static const std::set< std::string > handled_solvers
Set of handled solvers by the NMODL C++ code generator.
std::string return_error_global_var(ast::Ast &node, const std::shared_ptr< ast::Ast > &ast_node) const
Takes as parameter the ast::Ast to read the symbol table and an std::shared_ptr<ast::Ast> node and re...
bool find_unhandled_ast_nodes(Ast &node) const
Search the ast::Ast for nodes that are incompatible with NMODL C++ code generator.
Class that binds all pieces together for parsing C verbatim blocks.
Visitor for printing compatibility issues of the mod file
encapsulates code generation backend implementations
std::vector< std::shared_ptr< const ast::Ast > > collect_nodes(const ast::Ast &node, const std::vector< ast::AstNodeType > &types)
traverse node recursively and collect nodes of given types
static Node * node(Object *)
Base class for all Abstract Syntax Tree node types.
nmodl::parser::UnitDriver driver
Utility functions for visitors implementation.