User Guide
sympy_replace_solutions_visitor.cpp
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 
10 
11 #include "ast/all.hpp"
12 #include "utils/logger.hpp"
14 
15 namespace nmodl {
16 namespace visitor {
17 
18 /**
19  * \details SympyReplaceSolutionsVisitor tells us that a new equation appear and, depending where
20  * it is located, it can determine if it is part of the main system of equations or is something
21  * else. Every time we are out of the system and we print a new equation that is in the system
22  * we update the counter. \ref in_system follows, with lag, \param is_in_system and every time
23  * they are false and true respectively we detect a switch.
24  *
25  * \param is_in_system is a bool provided from outside that tells us if a new equation is indeed
26  * part of the main system of equations
27  */
29  n_interleaves += (!in_system && is_in_system); // count an interleave only if in_system ==
30  // false and is_in_system == true
31  in_system = is_in_system; // update in_system
32 }
33 
35  const std::vector<std::string>& pre_solve_statements,
36  const std::vector<std::string>& solutions,
37  const std::unordered_set<ast::Statement*>& to_be_removed,
38  const ReplacePolicy policy,
39  const size_t n_next_equations,
40  const std::string& tmp_unique_prefix)
43  , to_be_removed(&to_be_removed)
44  , policy(policy)
45  , n_next_equations(n_next_equations)
46  , replaced_statements_range(-1, -1) {
47  // if tmp_unique_prefix we do not expect tmp_statements
48  const auto ss_tmp_delimeter =
49  tmp_unique_prefix.empty()
50  ? solutions.begin()
51  : std::find_if(solutions.begin(),
52  solutions.end(),
53  [&tmp_unique_prefix](const std::string& statement) {
54  return statement.substr(0, tmp_unique_prefix.size()) !=
55  tmp_unique_prefix;
56  });
57  tmp_statements = StatementDispenser(solutions.begin(), ss_tmp_delimeter, -1);
58  solution_statements = StatementDispenser(ss_tmp_delimeter, solutions.end(), -1);
59 
60  replacements.clear();
61 }
62 
63 // NOLINTNEXTLINE(readability-function-cognitive-complexity)
65  const bool current_is_top_level_statement_block =
66  is_top_level_statement_block; // we mark it down since we are going to change it for
67  // visiting the children
69 
70  if (current_is_top_level_statement_block) {
71  logger->debug("SympyReplaceSolutionsVisitor :: visit statements. Matching policy: {}",
72  (policy == ReplacePolicy::VALUE ? "VALUE" : "GREEDY"));
74  node.visit_children(*this);
75 
77  logger->debug(
78  "SympyReplaceSolutionsVisitor :: not all solutions were replaced. Policy: GREEDY");
81  node.visit_children(*this);
82 
83  if (interleaves_counter.n() > 0) {
84  logger->warn(
85  "SympyReplaceSolutionsVisitor :: Found ambiguous system of equations "
86  "interleaved with {} assignment statements. I do not know what equations go "
87  "before and what "
88  "equations go after the assignment statements. Either put all the equations "
89  "that need to be solved "
90  "in the form: x = f(...) and with distinct variable assignments or do not "
91  "interleave the system with assignments.",
93  }
94  }
95  } else {
96  node.visit_children(*this);
97  }
98 
99  auto const& old_statements = node.get_statements();
100 
101  ast::StatementVector new_statements;
102  new_statements.reserve(2 * old_statements.size());
103  for (auto& old_statement: old_statements) {
104  const auto& replacement_ptr = replacements.find(old_statement);
105  if (replacement_ptr != replacements.end()) {
106  if (replaced_statements_range.first == -1) {
107  replaced_statements_range.first = static_cast<int>(new_statements.size());
108  }
109 
110  new_statements.insert(new_statements.end(),
111  replacement_ptr->second.begin(),
112  replacement_ptr->second.end());
113 
114  replaced_statements_range.second = static_cast<int>(new_statements.size());
115 
116  logger->debug("SympyReplaceSolutionsVisitor :: erasing {}", to_nmodl(old_statement));
117  for (const auto& replacement: replacement_ptr->second) {
118  logger->debug("SympyReplaceSolutionsVisitor :: adding {}", to_nmodl(replacement));
119  }
120  } else if (to_be_removed == nullptr ||
121  to_be_removed->find(&(*old_statement)) == to_be_removed->end()) {
122  logger->debug("SympyReplaceSolutionsVisitor :: found {}, nothing to do",
123  to_nmodl(old_statement));
124  new_statements.emplace_back(old_statement);
125  } else {
126  logger->debug("SympyReplaceSolutionsVisitor :: erasing {}", to_nmodl(old_statement));
127  }
128  }
129 
130  if (current_is_top_level_statement_block) {
131  if (!solution_statements.tags.empty()) {
132  std::ostringstream ss;
133  for (const auto ii: solution_statements.tags) {
134  ss << to_nmodl(solution_statements.statements[ii]) << '\n';
135  }
136  throw std::runtime_error(fmt::format(
137  "Not all solutions were replaced! Sympy returned {} equations but I could not find "
138  "a place "
139  "for all of them. In particular, the following equations remain to be replaced "
140  "somewhere:\n{}This is "
141  "probably a bug and I invite you to report it to a developer. Possible causes:\n"
142  " - I did not do a GREEDY pass and some solutions could not be replaced by VALUE\n "
143  "sympy "
144  "returned more equations than what we expected\n - There is a bug in the GREEDY "
145  "pass\n - some "
146  "solutions were replaced but not untagged",
148  ss.str()));
149  }
150 
151  if (replaced_statements_range.first == -1) {
152  replaced_statements_range.first = static_cast<int>(new_statements.size());
153  }
154  if (replaced_statements_range.second == -1) {
155  replaced_statements_range.second = static_cast<int>(new_statements.size());
156  }
157  }
158 
159  node.set_statements(std::move(new_statements));
160 }
161 
163  const ast::Node& node,
164  std::shared_ptr<ast::Expression> get_lhs(const ast::Node& node),
165  std::shared_ptr<ast::Expression> get_rhs(const ast::Node& node)) {
167 
168  const auto& statement = std::static_pointer_cast<ast::Statement>(
169  node.get_parent()->get_shared_ptr());
170 
171  // do not visit if already marked
172  if (replacements.find(statement) != replacements.end()) {
173  return;
174  }
175 
176 
177  switch (policy) {
178  case ReplacePolicy::VALUE: {
179  const auto dependencies = statement_dependencies(get_lhs(node), get_rhs(node));
180  const auto& key = dependencies.first;
181 
183  logger->debug("SympyReplaceSolutionsVisitor :: marking for replacement {}",
184  to_nmodl(statement));
185 
186  ast::StatementVector new_statements;
187 
191 
192  replacements.emplace(statement, new_statements);
193  }
194  break;
195  }
196  case ReplacePolicy::GREEDY: {
197  logger->debug("SympyReplaceSolutionsVisitor :: marking for replacement {}",
198  to_nmodl(statement));
199 
200  ast::StatementVector new_statements;
201 
205 
206  replacements.emplace(statement, new_statements);
207  break;
208  }
209  }
210 }
211 
212 
214  logger->debug("SympyReplaceSolutionsVisitor :: visit {}", to_nmodl(node));
215  auto get_lhs = [](const ast::Node& node) -> std::shared_ptr<ast::Expression> {
216  return dynamic_cast<const ast::DiffEqExpression&>(node).get_expression()->get_lhs();
217  };
218 
219  auto get_rhs = [](const ast::Node& node) -> std::shared_ptr<ast::Expression> {
220  return dynamic_cast<const ast::DiffEqExpression&>(node).get_expression()->get_rhs();
221  };
222 
223  try_replace_tagged_statement(node, get_lhs, get_rhs);
224 }
225 
227  logger->debug("SympyReplaceSolutionsVisitor :: visit {}", to_nmodl(node));
228  auto get_lhs = [](const ast::Node& node) -> std::shared_ptr<ast::Expression> {
229  return dynamic_cast<const ast::LinEquation&>(node).get_left_linxpression();
230  };
231 
232  auto get_rhs = [](const ast::Node& node) -> std::shared_ptr<ast::Expression> {
233  return dynamic_cast<const ast::LinEquation&>(node).get_left_linxpression();
234  };
235 
236  try_replace_tagged_statement(node, get_lhs, get_rhs);
237 }
238 
239 
241  logger->debug("SympyReplaceSolutionsVisitor :: visit {}", to_nmodl(node));
242  auto get_lhs = [](const ast::Node& node) -> std::shared_ptr<ast::Expression> {
243  return dynamic_cast<const ast::NonLinEquation&>(node).get_lhs();
244  };
245 
246  auto get_rhs = [](const ast::Node& node) -> std::shared_ptr<ast::Expression> {
247  return dynamic_cast<const ast::NonLinEquation&>(node).get_rhs();
248  };
249 
250  try_replace_tagged_statement(node, get_lhs, get_rhs);
251 }
252 
253 
255  logger->debug("SympyReplaceSolutionsVisitor :: visit {}", to_nmodl(node));
256  if (node.get_op().get_value() == ast::BinaryOp::BOP_ASSIGN && node.get_lhs()->is_var_name()) {
258 
259  const auto& var =
260  std::static_pointer_cast<ast::VarName>(node.get_lhs())->get_name()->get_node_name();
263  }
264 }
265 
266 
268  const std::vector<std::string>::const_iterator& statements_str_beg,
269  const std::vector<std::string>::const_iterator& statements_str_end,
270  const int error_on_n_flushes)
271  : statements(create_statements(statements_str_beg, statements_str_end))
272  , error_on_n_flushes(error_on_n_flushes) {
274  build_maps();
275 }
276 
277 
278 /**
279  * \details CHere we construct a map variable -> affected equations. In other words this map tells
280  * me what equations need to be updated when I change a particular variable. To do that we build a a
281  * graph of dependencies var -> vars and in the mean time we reduce it to the root variables. This
282  * is ensured by the fact that the tmp variables are sorted so that the next tmp variable may depend
283  * on the previous one. Since it is a relation of equivalence (if an equation depends on a variable,
284  * it needs to be updated if the variable changes), we build the two maps at the same time.
285  *
286  * An example:
287  *
288  * \code{.mod}
289  * tmp0 = x + a
290  * tmp1 = tmp0 + b
291  * tmp2 = y
292  * \endcode
293  *
294  * dependency_map should be (the order of the equation is unimportant since we are building
295  * a map):
296  *
297  * - tmp0 : x, a
298  * - tmp1 : x, a, b
299  * - tmp2 : y
300  *
301  * and the var2statement map should be (the order of the following equations is unimportant
302  * since we are building a map. The number represents the index of the original equations):
303  *
304  * - x : 0, 1
305  * - y : 2
306  * - a : 0, 1
307  * - b : 1
308  *
309  */
310 // NOLINTNEXTLINE(readability-function-cognitive-complexity)
312  for (size_t ii = 0; ii < statements.size(); ++ii) {
313  const auto& statement = statements[ii];
314 
315  if (statement->is_expression_statement()) {
316  const auto& e_statement =
317  std::static_pointer_cast<ast::ExpressionStatement>(statement)->get_expression();
318  if (e_statement->is_binary_expression()) {
319  const auto& bin_exp = std::static_pointer_cast<ast::BinaryExpression>(e_statement);
320  const auto& dependencies = statement_dependencies(bin_exp->get_lhs(),
321  bin_exp->get_rhs());
322 
323  const auto& key = dependencies.first;
324  const auto& vars = dependencies.second;
325  if (!key.empty()) {
326  var2statement.emplace(key, ii);
327  for (const auto& var: vars) {
328  const auto& var_already_inserted = dependency_map.find(var);
329  if (var_already_inserted != dependency_map.end()) {
330  dependency_map[key].insert(var_already_inserted->second.begin(),
331  var_already_inserted->second.end());
332  for (const auto& root_var: var_already_inserted->second) {
333  var2dependants[root_var].insert(ii);
334  }
335  } else {
336  dependency_map[key].insert(var);
337  var2dependants[var].insert(ii);
338  }
339  }
340  }
341  }
342  }
343  }
344 
345  logger->debug("SympyReplaceSolutionsVisitor::StatementDispenser :: var2dependants map");
346  for (const auto& entry: var2dependants) {
347  logger->debug("SympyReplaceSolutionsVisitor::StatementDispenser :: var `{}` used in:",
348  entry.first);
349  for (const auto ii: entry.second) {
350  logger->debug("SympyReplaceSolutionsVisitor::StatementDispenser :: -> {}",
351  to_nmodl(statements[ii]));
352  }
353  }
354  logger->debug("SympyReplaceSolutionsVisitor::StatementDispenser :: var2statement map");
355  for (const auto& entry: var2statement) {
356  logger->debug("SympyReplaceSolutionsVisitor::StatementDispenser :: var `{}` defined in:",
357  entry.first);
358  logger->debug("SympyReplaceSolutionsVisitor::StatementDispenser :: -> {}",
359  to_nmodl(statements[entry.second]));
360  }
361 }
362 
364  ast::StatementVector& new_statements,
365  const std::string& var) {
366  auto ptr = var2statement.find(var);
367  bool emplaced = false;
368  if (ptr != var2statement.end()) {
369  const auto ii = ptr->second;
370  const auto tag_ptr = tags.find(ii);
371  if (tag_ptr != tags.end()) {
372  new_statements.emplace_back(statements[ii]->clone());
373  tags.erase(tag_ptr);
374  emplaced = true;
375 
376  logger->debug(
377  "SympyReplaceSolutionsVisitor::StatementDispenser :: adding to replacement rule {}",
378  to_nmodl(statements[ii]));
379  } else {
380  logger->error(
381  "SympyReplaceSolutionsVisitor::StatementDispenser :: tried adding to replacement "
382  "rule {} but statement is not "
383  "tagged",
384  to_nmodl(statements[ii]));
385  }
386  }
387  return emplaced;
388 }
389 
391  ast::StatementVector& new_statements,
392  const size_t n_next_statements) {
393  size_t counter = 0;
394  for (size_t next_statement_ii = 0;
395  next_statement_ii < statements.size() && counter < n_next_statements;
396  ++next_statement_ii) {
397  const auto tag_ptr = tags.find(next_statement_ii);
398  if (tag_ptr != tags.end()) {
399  logger->debug(
400  "SympyReplaceSolutionsVisitor::StatementDispenser :: adding to replacement rule {}",
401  to_nmodl(statements[next_statement_ii]));
402  new_statements.emplace_back(statements[next_statement_ii]->clone());
403  tags.erase(tag_ptr);
404  ++counter;
405  }
406  }
407  return counter;
408 }
409 
411  ast::StatementVector& new_statements) {
412  for (const auto ii: tags) {
413  new_statements.emplace_back(statements[ii]->clone());
414  logger->debug(
415  "SympyReplaceSolutionsVisitor::StatementDispenser :: adding to replacement rule {}",
416  to_nmodl(statements[ii]));
417  }
418 
419  n_flushes += (!tags.empty());
420  if (error_on_n_flushes > 0 && n_flushes >= error_on_n_flushes) {
421  throw std::runtime_error(
422  "SympyReplaceSolutionsVisitor::StatementDispenser :: State variable assignment(s) "
423  "interleaved in system "
424  "of "
425  "equations/differential equations. It is not allowed due to possible numerical "
426  "instability and undefined "
427  "behavior. Erase the assignment statement(s) or move them before/after the"
428  " set of equations/differential equations.");
429  }
430 
431  const auto n_replacements = tags.size();
432 
433  tags.clear();
434 
435  return n_replacements;
436 }
437 
439  const std::string& var) {
440  auto ptr = var2dependants.find(var);
441  size_t n = 0;
442  if (ptr != var2dependants.end()) {
443  for (const auto ii: ptr->second) {
444  const auto pos = tags.insert(ii);
445  if (pos.second) {
446  logger->debug("SympyReplaceSolutionsVisitor::StatementDispenser :: tagging {}",
447  to_nmodl(statements[ii]));
448  }
449  ++n;
450  }
451  }
452  return n;
453 }
454 
456  logger->debug("SympyReplaceSolutionsVisitor::StatementDispenser :: tagging all statements");
457  for (size_t i = 0; i < statements.size(); ++i) {
458  tags.insert(i);
459  logger->debug("SympyReplaceSolutionsVisitor::StatementDispenser :: tagging {}",
460  to_nmodl(statements[i]));
461  }
462 }
463 
464 
465 } // namespace visitor
466 } // namespace nmodl
nmodl::visitor::SympyReplaceSolutionsVisitor::to_be_removed
const std::unordered_set< ast::Statement * > * to_be_removed
group of old statements that need replacing
Definition: sympy_replace_solutions_visitor.hpp:490
nmodl::visitor::SympyReplaceSolutionsVisitor::ReplacePolicy
ReplacePolicy
Definition: sympy_replace_solutions_visitor.hpp:214
nmodl::ast::Node
Base class for all AST node.
Definition: node.hpp:40
nmodl::to_nmodl
std::string to_nmodl(const ast::Ast &node, const std::set< ast::AstNodeType > &exclude_types)
Given AST node, return the NMODL string representation.
Definition: visitor_utils.cpp:227
nmodl::visitor::SympyReplaceSolutionsVisitor::pre_solve_statements
StatementDispenser pre_solve_statements
Update state variable statements (i.e. )
Definition: sympy_replace_solutions_visitor.hpp:462
nmodl::ast::DiffEqExpression
Represents differential equation in DERIVATIVE block.
Definition: diff_eq_expression.hpp:38
nmodl::visitor::SympyReplaceSolutionsVisitor::StatementDispenser::tag_all_statements
void tag_all_statements()
Mark that all the statements need updating (probably unused)
Definition: sympy_replace_solutions_visitor.cpp:455
nmodl::visitor::create_statements
std::vector< std::shared_ptr< Statement > > create_statements(const std::vector< std::string >::const_iterator &code_statements_beg, const std::vector< std::string >::const_iterator &code_statements_end)
Same as for create_statement but for vectors of strings.
Definition: visitor_utils.cpp:136
nmodl::ast::NonLinEquation
TODO.
Definition: non_lin_equation.hpp:38
nmodl::visitor::SympyReplaceSolutionsVisitor::StatementDispenser::build_maps
void build_maps()
Construct the maps var2dependants, var2statement and dependency_map for easy access and classificatio...
Definition: sympy_replace_solutions_visitor.cpp:311
nmodl::ast::StatementBlock::visit_children
void visit_children(visitor::Visitor &v) override
visit children i.e.
Definition: ast.cpp:3158
nmodl::visitor::SympyReplaceSolutionsVisitor::StatementDispenser::StatementDispenser
StatementDispenser()=default
Empty ctor.
nmodl::ast::StatementVector
std::vector< std::shared_ptr< Statement > > StatementVector
Definition: ast_decl.hpp:298
nmodl::visitor::SympyReplaceSolutionsVisitor::visit_statement_block
void visit_statement_block(ast::StatementBlock &node) override
visit node of type ast::StatementBlock
Definition: sympy_replace_solutions_visitor.cpp:64
nmodl::visitor::SympyReplaceSolutionsVisitor::InterleavesCounter::n_interleaves
size_t n_interleaves
Number of interleaves of assignment statements in between equations of the system of equations.
Definition: sympy_replace_solutions_visitor.hpp:293
nmodl
encapsulates code generation backend implementations
Definition: ast_common.hpp:26
nmodl::ast::StatementBlock::set_statements
void set_statements(StatementVector &&statements)
Setter for member variable StatementBlock::statements (rvalue reference)
Definition: ast.cpp:3218
nmodl::visitor::SympyReplaceSolutionsVisitor::StatementDispenser::tags
std::set< size_t > tags
Keeps track of what statements need updating.
Definition: sympy_replace_solutions_visitor.hpp:435
nmodl::visitor::SympyReplaceSolutionsVisitor::replaced_statements_range
std::pair< int, int > replaced_statements_range
{begin index, end index} of the added statements. -1 means that it is invalid
Definition: sympy_replace_solutions_visitor.hpp:496
nmodl::visitor::SympyReplaceSolutionsVisitor::tmp_statements
StatementDispenser tmp_statements
tmp statements that appear with –cse (i.e. )
Definition: sympy_replace_solutions_visitor.hpp:465
nmodl::visitor::SympyReplaceSolutionsVisitor::try_replace_tagged_statement
void try_replace_tagged_statement(const ast::Node &node, std::shared_ptr< ast::Expression > get_lhs(const ast::Node &node), std::shared_ptr< ast::Expression > get_rhs(const ast::Node &node))
Try to replace a statement.
Definition: sympy_replace_solutions_visitor.cpp:162
nmodl::ast::BOP_ASSIGN
@ BOP_ASSIGN
=
Definition: ast_common.hpp:59
nmodl::logger
logger_type logger
Definition: logger.cpp:34
sympy_replace_solutions_visitor.hpp
Replace statements in node with pre_solve_statements, tmp_statements, and solutions.
nmodl::statement_dependencies
std::pair< std::string, std::unordered_set< std::string > > statement_dependencies(const std::shared_ptr< ast::Expression > &lhs, const std::shared_ptr< ast::Expression > &rhs)
If lhs and rhs combined represent an assignment (we assume to have an "=" in between them) we extract...
Definition: visitor_utils.cpp:246
nmodl::visitor::SympyReplaceSolutionsVisitor::visit_lin_equation
void visit_lin_equation(ast::LinEquation &node) override
visit node of type ast::LinEquation
Definition: sympy_replace_solutions_visitor.cpp:226
nmodl::ast::StatementBlock::get_statements
const StatementVector & get_statements() const noexcept
Getter for member variable StatementBlock::statements.
Definition: statement_block.hpp:221
visitor_utils.hpp
Utility functions for visitors implementation.
nmodl::visitor::SympyReplaceSolutionsVisitor::InterleavesCounter
Count interleaves of assignment statement inside the system of equations.
Definition: sympy_replace_solutions_visitor.hpp:275
nmodl::visitor::SympyReplaceSolutionsVisitor::InterleavesCounter::new_equation
void new_equation(const bool is_in_system)
Count interleaves defined as a switch false -> true for in_system.
Definition: sympy_replace_solutions_visitor.cpp:28
nmodl::visitor::SympyReplaceSolutionsVisitor::visit_binary_expression
void visit_binary_expression(ast::BinaryExpression &node) override
visit node of type ast::BinaryExpression
Definition: sympy_replace_solutions_visitor.cpp:254
nmodl::visitor::SympyReplaceSolutionsVisitor::visit_diff_eq_expression
void visit_diff_eq_expression(ast::DiffEqExpression &node) override
visit node of type ast::DiffEqExpression
Definition: sympy_replace_solutions_visitor.cpp:213
nmodl::visitor::SympyReplaceSolutionsVisitor::policy
ReplacePolicy policy
Replacement policy used by the various visitors.
Definition: sympy_replace_solutions_visitor.hpp:484
nmodl::visitor::SympyReplaceSolutionsVisitor::interleaves_counter
InterleavesCounter interleaves_counter
counts how many times the solution statements are interleaved with assignment expressions
Definition: sympy_replace_solutions_visitor.hpp:493
nmodl::visitor::SympyReplaceSolutionsVisitor::StatementDispenser::tag_dependant_statements
size_t tag_dependant_statements(const std::string &var)
Tag all the statements that depend on var for updating.
Definition: sympy_replace_solutions_visitor.cpp:438
nmodl::visitor::SympyReplaceSolutionsVisitor::ReplacePolicy::GREEDY
@ GREEDY
Replace statements greedily.
nmodl::ast::BinaryExpression::get_op
const BinaryOperator & get_op() const noexcept
Getter for member variable BinaryExpression::op.
Definition: binary_expression.hpp:170
nmodl::visitor::SympyReplaceSolutionsVisitor::SympyReplaceSolutionsVisitor
SympyReplaceSolutionsVisitor()=delete
Empty ctor.
nmodl::visitor::SympyReplaceSolutionsVisitor::replacements
std::unordered_map< std::shared_ptr< ast::Statement >, ast::StatementVector > replacements
Replacements found by the visitor.
Definition: sympy_replace_solutions_visitor.hpp:477
nmodl::visitor::SympyReplaceSolutionsVisitor::solution_statements
StatementDispenser solution_statements
solutions that we want to replace
Definition: sympy_replace_solutions_visitor.hpp:468
nmodl::visitor::SympyReplaceSolutionsVisitor::StatementDispenser::statements
std::vector< std::shared_ptr< ast::Statement > > statements
Vector of statements.
Definition: sympy_replace_solutions_visitor.hpp:426
nmodl::ast::StatementBlock
Represents block encapsulating list of statements.
Definition: statement_block.hpp:53
nmodl::ast::Ast::get_shared_ptr
virtual std::shared_ptr< Ast > get_shared_ptr()
get std::shared_ptr from this pointer of the AST node
Definition: ast.cpp:52
nmodl::ast::BinaryOperator::get_value
BinaryOp get_value() const noexcept
Getter for member variable BinaryOperator::value.
Definition: binary_operator.hpp:143
logger.hpp
Implement logger based on spdlog library.
nmodl::visitor::SympyReplaceSolutionsVisitor::StatementDispenser::emplace_back_all_tagged_statements
size_t emplace_back_all_tagged_statements(ast::StatementVector &new_statements)
Emplace back all the statements that are marked for updating in tags.
Definition: sympy_replace_solutions_visitor.cpp:410
nmodl::ast::LinEquation
TODO.
Definition: lin_equation.hpp:38
nmodl::visitor::SympyReplaceSolutionsVisitor::StatementDispenser::try_emplace_back_tagged_statement
bool try_emplace_back_tagged_statement(ast::StatementVector &new_statements, const std::string &var)
Look for var in var2statement and emplace back that statement in new_statements.
Definition: sympy_replace_solutions_visitor.cpp:363
nmodl::visitor::SympyReplaceSolutionsVisitor::StatementDispenser::is_var_assigned_here
bool is_var_assigned_here(const std::string &var) const
Check if one of the statements assigns this variable (i.e.
Definition: sympy_replace_solutions_visitor.hpp:328
nmodl::ast::BinaryExpression::get_lhs
std::shared_ptr< Expression > get_lhs() const noexcept
Getter for member variable BinaryExpression::lhs.
Definition: binary_expression.hpp:161
nmodl::visitor::SympyReplaceSolutionsVisitor::is_top_level_statement_block
bool is_top_level_statement_block
Used to notify to visit_statement_block was called by the user (or another visitor) or re-called in a...
Definition: sympy_replace_solutions_visitor.hpp:481
nmodl::visitor::SympyReplaceSolutionsVisitor::n_next_equations
size_t n_next_equations
Number of solutions that match each old_statement with the greedy policy.
Definition: sympy_replace_solutions_visitor.hpp:487
nmodl::visitor::SympyReplaceSolutionsVisitor::StatementDispenser::emplace_back_next_tagged_statements
size_t emplace_back_next_tagged_statements(ast::StatementVector &new_statements, const size_t n_next_statements)
Emplace back the next n_next_statements solutions in statements that is marked for updating in tags.
Definition: sympy_replace_solutions_visitor.cpp:390
lookup_visitor.hpp
THIS FILE IS GENERATED AT BUILD TIME AND SHALL NOT BE EDITED.
nmodl::ast::BinaryExpression
Represents binary expression in the NMODL.
Definition: binary_expression.hpp:52
nmodl::visitor::SympyReplaceSolutionsVisitor::ReplacePolicy::VALUE
@ VALUE
Replace statements matching by lhs varName.
nmodl::visitor::SympyReplaceSolutionsVisitor::visit_non_lin_equation
void visit_non_lin_equation(ast::NonLinEquation &node) override
visit node of type ast::NonLinEquation
Definition: sympy_replace_solutions_visitor.cpp:240
nmodl::ast::Ast::get_parent
virtual Ast * get_parent() const
Parent getter.
Definition: ast.cpp:307
nmodl::visitor::SympyReplaceSolutionsVisitor::InterleavesCounter::in_system
bool in_system
Bool that keeps track if just wrote an equation of the system of equations (true) or not (false)
Definition: sympy_replace_solutions_visitor.hpp:297
all.hpp
Auto generated AST classes declaration.
nmodl::visitor::SympyReplaceSolutionsVisitor::InterleavesCounter::n
size_t n() const
Number of interleaves.
Definition: sympy_replace_solutions_visitor.hpp:281