User Guide
kinetic_block_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 
9 
10 #include "ast/all.hpp"
11 #include "symtab/symbol.hpp"
12 #include "utils/logger.hpp"
13 #include "utils/string_utils.hpp"
14 #include "visitor_utils.hpp"
15 
16 
17 namespace nmodl {
18 namespace visitor {
19 
21 
22 void KineticBlockVisitor::process_reac_var(const std::string& varname, int count) {
23  // lookup index of state var
24  const auto it = state_var_index.find(varname);
25  if (it == state_var_index.cend()) {
26  // not a state var
27  // so this is a constant variable in the reaction statement
28  // this should be included in the fluxes:
31  logger->debug("KineticBlockVisitor :: adding non-state fflux[{}] \"{}\"",
33  varname);
34  } else {
36  logger->debug("KineticBlockVisitor :: adding non-state bflux[{}] \"{}\"",
38  varname);
39  }
40  // but as it is not a state var, no ODE should be generated for it, i.e. no nu_L or nu_R
41  // entry.
42  } else {
43  // found state var index
44  int i_statevar = it->second;
46  // set element of nu_L matrix
47  rate_eqs.nu_L[i_statement][i_statevar] += count;
48  logger->debug("KineticBlockVisitor :: nu_L[{}][{}] += {}",
50  i_statevar,
51  count);
52  } else {
53  // set element of nu_R matrix
54  rate_eqs.nu_R[i_statement][i_statevar] += count;
55  logger->debug("KineticBlockVisitor :: nu_R[{}][{}] += {}",
57  i_statevar,
58  count);
59  }
60  }
61 }
62 
63 void KineticBlockVisitor::process_conserve_reac_var(const std::string& varname, int count) {
64  // subtract previous term from both sides of equation
65  if (!conserve_equation_statevar.empty()) {
66  if (conserve_equation_factor.empty()) {
68 
69  } else {
72  }
73  }
74  // construct new term
75  auto compartment_factor = compartment_factors[state_var_index[varname]];
76  if (compartment_factor.empty()) {
77  if (count == 1) {
79  } else {
81  }
82  } else {
83  conserve_equation_factor = compartment_factor + "*" + std::to_string(count);
84  }
85  // if new term is not a state var raise error
86  if (state_var_index.find(varname) == state_var_index.cend()) {
87  logger->error(
88  "KineticBlockVisitor :: Error : CONSERVE statement should only contain state vars "
89  "on LHS, but found {}",
90  varname);
91  } else {
93  }
94 }
95 
96 std::shared_ptr<ast::Expression> create_expr(const std::string& str_expr) {
97  auto statement = create_statement("dummy = " + str_expr);
98  auto expr = std::dynamic_pointer_cast<ast::ExpressionStatement>(statement)->get_expression();
99  return std::dynamic_pointer_cast<ast::BinaryExpression>(expr)->get_rhs();
100 }
101 
104  // rewrite CONSERVE statement in form x = ...
105  // where x was the last state var on LHS, and whose ODE should later be replaced with this
106  // equation note: CONSERVE statement "implicitly takes into account COMPARTMENT factors on LHS"
107  // this means that each state var on LHS must be multiplied by its compartment factor
108  // the RHS is just an expression, no compartment factors are taken into account
109  // see p244 of NEURON book
110  logger->debug("KineticBlockVisitor :: CONSERVE statement: {}", to_nmodl(node));
114 
115  in_conserve_statement = true;
116  // construct equation to replace ODE in conserve_equation_str
117  node.visit_children(*this);
118  in_conserve_statement = false;
119 
121  if (!conserve_equation_factor.empty()) {
122  // divide by compartment factor of conserve_equation_statevar
124  ")";
125  }
126 
127  // note: The following 4 lines result in a still valid (and equivalent) CONSERVE statement.
128  // later this block will become a DERIVATIVE block where it is no longer valid
129  // to have a CONSERVE statement. Parsing the equivalent nmodl in between the
130  // kinetic visitor and the sympysolvervisitor in presence of a conserve statement
131  // should result in an error since we do not want to add new functionalities to the language.
132  // the SympySolver will use to it replace the ODE (to replicate what neuron does)
133  auto statement = create_statement("CONSERVE " + conserve_equation_statevar + " = " +
135  auto expr = std::dynamic_pointer_cast<ast::Conserve>(statement);
136  // set react (lhs) of CONSERVE to the state variable whose ODE should be replaced
137  node.set_react(expr->get_react());
138  // set expr (rhs) of CONSERVE to the equation that should replace the ODE
139  node.set_expr(expr->get_expr());
140 
141  logger->debug("KineticBlockVisitor :: --> {}", to_nmodl(node));
142 }
143 
145  // COMPARTMENT block has an expression, and a list of state vars it applies to.
146  // For each state var, the rhs of the differential eq should be divided by the expression.
147  // Here we store the expressions in the compartment_factors vector
148  auto expr = node.get_expression();
149  std::string expression = to_nmodl(expr);
150  logger->debug("KineticBlockVisitor :: COMPARTMENT expr: {}", expression);
151  for (const auto& name_ptr: node.get_names()) {
152  const auto& var_name = name_ptr->get_node_name();
153  const auto it = state_var_index.find(var_name);
154  if (it != state_var_index.cend()) {
155  int var_index = it->second;
156  compartment_factors[var_index] = expression;
157  logger->debug(
158  "KineticBlockVisitor :: COMPARTMENT factor {} for state var {} (index {})",
159  expression,
160  var_name,
161  var_index);
162  }
163  }
164  // add COMPARTMENT state to list of statements to remove
165  // since we don't want this statement to be present in the final DERIVATIVE block
166  statements_to_remove.insert(&node);
167 }
168 
170  auto reaction_op = node.get_value();
171  if (reaction_op == ast::ReactionOp::LTMINUSGT) {
172  // <->
173  // reversible reaction
174  // we go from visiting the lhs to visiting the rhs of the reaction statement
176  }
177 }
178 
180  ast::ReactVarName& node) { // NOLINT(readability-function-cognitive-complexity)
181  // ReactVarName node contains a VarName and an Integer
182  // the VarName is the state variable which we convert to an index
183  // the Integer is the value to be added to the stoichiometric matrix at this index
184  auto varname = to_nmodl(node.get_name());
185  int count = node.get_value() ? node.get_value()->eval() : 1;
186  if (in_reaction_statement) {
187  process_reac_var(varname, count);
188  } else if (in_conserve_statement) {
189  if (array_state_var_size.find(varname) != array_state_var_size.cend()) {
190  // state var is an array: need to sum over each element
191  for (int i = 0; i < array_state_var_size[varname]; ++i) {
192  process_conserve_reac_var(varname + "[" + std::to_string(i) + "]", count);
193  }
194  } else {
195  process_conserve_reac_var(varname, count);
196  }
197  }
198 }
199 
200 // NOLINTNEXTLINE(readability-function-cognitive-complexity)
202  statements_to_remove.insert(&node);
203 
204  auto reaction_op = node.get_op().get_value();
205  // special case for << statements
206  if (reaction_op == ast::ReactionOp::LTLT) {
207  logger->debug("KineticBlockVisitor :: '<<' reaction statement: {}", to_nmodl(node));
208  // statements involving the "<<" operator
209  // must have a single state var on lhs
210  // and a single expression on rhs that corresponds to d{state var}/dt
211  // So if x is a state var, then
212  // ~ x << (a*b)
213  // translates to the ODE contribution x' += a*b
214  const auto& lhs = node.get_reaction1();
215 
216  /// check if reaction statement is a single state variable
217  bool single_state_var = true;
218  if (lhs->is_react_var_name()) {
219  auto value = std::dynamic_pointer_cast<ast::ReactVarName>(lhs)->get_value();
220  if (value && (value->eval() != 1)) {
221  single_state_var = false;
222  }
223  }
224  if (!lhs->is_react_var_name() || !single_state_var) {
225  logger->warn(
226  "KineticBlockVisitor :: LHS of \"<<\" reaction statement must be a single state "
227  "var, but instead found {}: ignoring this statement",
228  to_nmodl(lhs));
229  return;
230  }
231  const auto& rhs = node.get_expression1();
232  std::string varname = to_nmodl(lhs);
233  // get index of state var
234  const auto it = state_var_index.find(varname);
235  if (it != state_var_index.cend()) {
236  int var_index = it->second;
237  std::string expr = to_nmodl(rhs);
238  if (!additive_terms[var_index].empty()) {
239  additive_terms[var_index] += " + ";
240  }
241  // add to additive terms for this state var
242  additive_terms[var_index] += fmt::format("({})", expr);
243  logger->debug("KineticBlockVisitor :: '<<' reaction statement: {}' += {}",
244  varname,
245  expr);
246  }
247  return;
248  }
249 
250  // forwards reaction rate
251  const auto& kf = node.get_expression1();
252  // backwards reaction rate
253  const auto& kb = node.get_expression2();
254 
255  // add reaction rates to vectors kf, kb
256  auto kf_str = to_nmodl(kf);
257  logger->debug("KineticBlockVisitor :: k_f[{}] = {}", i_statement, kf_str);
258  rate_eqs.k_f.emplace_back(kf_str);
259 
260  if (kb) {
261  // kf is always defined, but for statements with operator "->" kb is not
262  auto kb_str = to_nmodl(kb);
263  logger->debug("KineticBlockVisitor :: k_b[{}] = {}", i_statement, kb_str);
264  rate_eqs.k_b.emplace_back(kb_str);
265  } else {
266  rate_eqs.k_b.emplace_back();
267  }
268 
269  // add empty non state var fluxes for this statement
270  non_state_var_fflux.emplace_back();
271  non_state_var_bflux.emplace_back();
272 
273  // add a row of zeros to the stoichiometric matrices
274  rate_eqs.nu_L.emplace_back(std::vector<int>(state_var_count, 0));
275  rate_eqs.nu_R.emplace_back(std::vector<int>(state_var_count, 0));
276 
277  // visit each term in reaction statement and
278  // add the corresponding integer to the new row in the matrix
279  in_reaction_statement = true;
281  node.visit_children(*this);
282  in_reaction_statement = false;
283 
284  // generate fluxes
285  modfile_fflux = rate_eqs.k_f.back();
286  modfile_bflux = rate_eqs.k_b.back();
287 
288  // contribution from state vars
289  for (int j = 0; j < state_var_count; ++j) {
290  std::string multiply_var = std::string("*").append(state_var[j]);
291  int nu_L = rate_eqs.nu_L[i_statement][j];
292  while (nu_L-- > 0) {
293  modfile_fflux += multiply_var;
294  }
295  int nu_R = rate_eqs.nu_R[i_statement][j];
296  while (nu_R-- > 0) {
297  modfile_bflux += multiply_var;
298  }
299  }
300  // contribution from non-state vars
301  if (!non_state_var_fflux[i_statement].empty()) {
302  modfile_fflux += std::string("*").append(non_state_var_fflux[i_statement]);
303  }
304  if (!non_state_var_bflux[i_statement].empty()) {
305  modfile_bflux += std::string("*").append(non_state_var_bflux[i_statement]);
306  }
307  fflux.emplace_back(modfile_fflux);
308  bflux.emplace_back(modfile_bflux);
309 
310  // for substituting into modfile, empty flux should be 0
311  if (modfile_fflux.empty()) {
312  modfile_fflux = "0";
313  }
314  if (modfile_bflux.empty()) {
315  modfile_bflux = "0";
316  }
317 
318  logger->debug("KineticBlockVisitor :: fflux[{}] = {}", i_statement, fflux[i_statement]);
319  logger->debug("KineticBlockVisitor :: bflux[{}] = {}", i_statement, bflux[i_statement]);
320 
321  // increment statement counter
322  ++i_statement;
323 }
324 
326  // If a wrapped expression contains a variable with name "f_flux" or "b_flux",
327  // this variable should be replaced by the expression for the corresponding flux
328  // which depends on the previous reaction statement. The current expressions are
329  // stored as strings in "modfile_fflux" and "modfile_bflux"
330  if (node.get_expression()->is_name()) {
331  auto var_name = std::dynamic_pointer_cast<ast::Name>(node.get_expression());
332  if (var_name->get_node_name() == "f_flux") {
333  auto expr = create_expr(modfile_fflux);
334  logger->debug("KineticBlockVisitor :: replacing f_flux with {}", to_nmodl(expr));
335  node.set_expression(std::move(expr));
336  } else if (var_name->get_node_name() == "b_flux") {
337  auto expr = create_expr(modfile_bflux);
338  logger->debug("KineticBlockVisitor :: replacing b_flux with {}", to_nmodl(expr));
339  node.set_expression(std::move(expr));
340  }
341  }
342  node.visit_children(*this);
343 }
344 
346  auto prev_statement_block = current_statement_block;
347  current_statement_block = &node;
348  node.visit_children(*this);
349  // remove processed statements from current statement block
351  current_statement_block = prev_statement_block;
352 }
353 
355  rate_eqs.nu_L.clear();
356  rate_eqs.nu_R.clear();
357  rate_eqs.k_f.clear();
358  rate_eqs.k_b.clear();
359  fflux.clear();
360  bflux.clear();
361  odes.clear();
362  modfile_fflux = "0";
363  modfile_bflux = "0";
364 
365  // allocate these vectors with empty strings
366  compartment_factors = std::vector<std::string>(state_var_count);
367  additive_terms = std::vector<std::string>(state_var_count);
368  i_statement = 0;
369 
370  // construct stochiometric matrices and fluxes
371  node.visit_children(*this);
372 
373  // number of reaction statements
374  int Ni = static_cast<int>(rate_eqs.k_f.size());
375 
376  // number of ODEs (= number of state vars)
377  int Nj = state_var_count;
378 
379  // generate ODEs
380  for (int j = 0; j < Nj; ++j) {
381  // rhs of ODE eq
382  std::string ode_rhs = additive_terms[j];
383  for (int i = 0; i < Ni; ++i) {
384  int delta_nu = rate_eqs.nu_R[i][j] - rate_eqs.nu_L[i][j];
385  if (delta_nu != 0) {
386  // if not the first RHS term, add + sign first
387  if (!ode_rhs.empty()) {
388  ode_rhs += " + ";
389  }
390  if (bflux[i].empty()) {
391  ode_rhs += fmt::format("({}*({}))", delta_nu, fflux[i]);
392  } else if (fflux[i].empty()) {
393  ode_rhs += fmt::format("({}*(-{}))", delta_nu, bflux[i]);
394  } else {
395  ode_rhs += fmt::format("({}*({}-{}))", delta_nu, fflux[i], bflux[i]);
396  }
397  }
398  }
399  // divide by COMPARTMENT factor if present
400  if (!compartment_factors[j].empty() && !ode_rhs.empty()) {
401  ode_rhs = fmt::format("({})/({})", ode_rhs, compartment_factors[j]);
402  }
403  // if rhs of ODE is not empty, add to list of ODEs
404  if (!ode_rhs.empty()) {
405  auto state_var_split = stringutils::split_string(state_var[j], '[');
406  std::string var_str = state_var_split[0];
407  std::string index_str;
408  if (state_var_split.size() > 1) {
409  index_str = "[" + state_var_split[1];
410  }
411  odes.push_back(fmt::format("{}'{} = {}", var_str, index_str, ode_rhs));
412  }
413  }
414 
415  for (const auto& ode: odes) {
416  logger->debug("KineticBlockVisitor :: ode : {}", ode);
417  }
418 
419  const auto& kinetic_statement_block = node.get_statement_block();
420  // remove any remaining kinetic statements
421  kinetic_statement_block->erase_statement(statements_to_remove);
422  // add new statements
423  for (const auto& ode: odes) {
424  logger->debug("KineticBlockVisitor :: -> adding statement: {}", ode);
425  kinetic_statement_block->emplace_back_statement(create_statement(ode));
426  }
427 
428  // store pointer to kinetic block
429  kinetic_blocks.push_back(&node);
430 }
431 
434  statements_to_remove.clear();
435  current_statement_block = nullptr;
436 
437  // get state variables - assign an index to each
438  state_var_index.clear();
439  array_state_var_size.clear();
440  state_var.clear();
441  state_var_count = 0;
442  if (auto symtab = node.get_symbol_table()) {
443  auto statevars = symtab->get_variables_with_properties(NmodlType::state_var);
444  for (const auto& v: statevars) {
445  std::string var_name = v->get_name();
446  if (v->is_array()) {
447  // CONSERVE statement needs to know this is an array state var, and its size:
448  array_state_var_size[var_name] = v->get_length();
449  // for array state vars we need to add each element of the array separately
450  var_name += "[";
451  for (int i = 0; i < v->get_length(); ++i) {
452  std::string var_name_i = var_name + std::to_string(i) + "]";
453  logger->debug("KineticBlockVisitor :: state_var_index[{}] = {}",
454  var_name_i,
456  state_var_index[var_name_i] = state_var_count++;
457  state_var.push_back(var_name_i);
458  }
459  } else {
460  logger->debug("KineticBlockVisitor :: state_var_index[{}] = {}",
461  var_name,
463  state_var_index[var_name] = state_var_count++;
464  state_var.push_back(var_name);
465  }
466  }
467  }
468 
469  const auto& kineticBlockNodes = collect_nodes(node, {ast::AstNodeType::KINETIC_BLOCK});
470  // replace reaction statements within each kinetic block with equivalent ODEs
471  for (const auto& ii: kineticBlockNodes) {
472  ii->accept(*this);
473  }
474 
475  // change KINETIC blocks -> DERIVATIVE blocks
476  auto blocks = node.get_blocks();
477  for (auto* kinetic_block: kinetic_blocks) {
478  for (auto it = blocks.begin(); it != blocks.end(); ++it) {
479  if (it->get() == kinetic_block) {
480  auto dblock =
481  std::make_shared<ast::DerivativeBlock>(kinetic_block->get_name(),
482  kinetic_block->get_statement_block());
483  ModToken tok{};
484  dblock->set_token(tok);
485  *it = dblock;
486  }
487  }
488  }
489  node.set_blocks(std::move(blocks));
490 }
491 
492 } // namespace visitor
493 } // namespace nmodl
nmodl::visitor::KineticBlockVisitor::visit_wrapped_expression
void visit_wrapped_expression(ast::WrappedExpression &node) override
visit node of type ast::WrappedExpression
Definition: kinetic_block_visitor.cpp:325
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::ast::WrappedExpression::get_expression
std::shared_ptr< Expression > get_expression() const noexcept
Getter for member variable WrappedExpression::expression.
Definition: wrapped_expression.hpp:143
nmodl::ast::ReactionStatement::get_expression1
std::shared_ptr< Expression > get_expression1() const noexcept
Getter for member variable ReactionStatement::expression1.
Definition: reaction_statement.hpp:193
nmodl::visitor::KineticBlockVisitor::array_state_var_size
std::unordered_map< std::string, int > array_state_var_size
unordered_map from array state variable to its size (for summing over each element of any array state...
Definition: kinetic_block_visitor.hpp:100
symbol.hpp
Implement class to represent a symbol in Symbol Table.
nmodl::ast::ReactionOperator::get_value
ReactionOp get_value() const noexcept
Getter for member variable ReactionOperator::value.
Definition: reaction_operator.hpp:143
nmodl::ast::AstNodeType::KINETIC_BLOCK
@ KINETIC_BLOCK
type of ast::KineticBlock
nmodl::ast::Compartment::get_expression
std::shared_ptr< Expression > get_expression() const noexcept
Getter for member variable Compartment::expression.
Definition: compartment.hpp:171
nmodl::visitor::KineticBlockVisitor::visit_statement_block
void visit_statement_block(ast::StatementBlock &node) override
visit node of type ast::StatementBlock
Definition: kinetic_block_visitor.cpp:345
nmodl::visitor::KineticBlockVisitor::process_conserve_reac_var
void process_conserve_reac_var(const std::string &varname, int count=1)
update CONSERVE statement with reaction var term
Definition: kinetic_block_visitor.cpp:63
nmodl::ast::StatementBlock::visit_children
void visit_children(visitor::Visitor &v) override
visit children i.e.
Definition: ast.cpp:3158
nmodl::ast::Conserve
Represent CONSERVE statement in NMODL.
Definition: conserve.hpp:38
nmodl::ast::Conserve::get_expr
std::shared_ptr< Expression > get_expr() const noexcept
Getter for member variable Conserve::expr.
Definition: conserve.hpp:168
nmodl::ast::ReactionStatement::get_expression2
std::shared_ptr< Expression > get_expression2() const noexcept
Getter for member variable ReactionStatement::expression2.
Definition: reaction_statement.hpp:202
nmodl::visitor::KineticBlockVisitor::non_state_var_fflux
std::vector< std::string > non_state_var_fflux
multiplicate constant terms for fluxes from non-state vars as reactants e.g.
Definition: kinetic_block_visitor.hpp:75
nmodl::visitor::KineticBlockVisitor::conserve_statement_count
int conserve_statement_count
counts the number of CONSERVE statements in Kinetic blocks
Definition: kinetic_block_visitor.hpp:112
nmodl::ast::KineticBlock::get_statement_block
std::shared_ptr< StatementBlock > get_statement_block() const noexcept override
Getter for member variable KineticBlock::statement_block.
Definition: kinetic_block.hpp:208
nmodl
encapsulates code generation backend implementations
Definition: ast_common.hpp:26
nmodl::ast::ReactVarName
TODO.
Definition: react_var_name.hpp:38
nmodl::visitor::KineticBlockVisitor::compartment_factors
std::vector< std::string > compartment_factors
multiplicative factors for ODEs from COMPARTMENT statements
Definition: kinetic_block_visitor.hpp:66
nmodl::visitor::KineticBlockVisitor::visit_program
void visit_program(ast::Program &node) override
visit node of type ast::Program
Definition: kinetic_block_visitor.cpp:432
nmodl::visitor::KineticBlockVisitor::state_var_count
int state_var_count
number of state variables
Definition: kinetic_block_visitor.hpp:90
nmodl::visitor::KineticBlockVisitor::visit_compartment
void visit_compartment(ast::Compartment &node) override
visit node of type ast::Compartment
Definition: kinetic_block_visitor.cpp:144
nmodl::ast::ReactVarName::get_name
std::shared_ptr< VarName > get_name() const noexcept
Getter for member variable ReactVarName::name.
Definition: react_var_name.hpp:166
string_utils.hpp
Implement string manipulation functions.
nmodl::visitor::KineticBlockVisitor::fflux
std::vector< std::string > fflux
generated set of fluxes and ODEs
Definition: kinetic_block_visitor.hpp:79
nmodl::visitor::KineticBlockVisitor::conserve_equation_statevar
std::string conserve_equation_statevar
conserve statement: current state variable being processed
Definition: kinetic_block_visitor.hpp:118
nmodl::ast::Conserve::set_expr
void set_expr(std::shared_ptr< Expression > &&expr)
Setter for member variable Conserve::expr (rvalue reference)
Definition: ast.cpp:10246
nmodl::logger
logger_type logger
Definition: logger.cpp:34
nmodl::visitor::KineticBlockVisitor::visit_reaction_operator
void visit_reaction_operator(ast::ReactionOperator &node) override
visit node of type ast::ReactionOperator
Definition: kinetic_block_visitor.cpp:169
nmodl::ast::KineticBlock::visit_children
void visit_children(visitor::Visitor &v) override
visit children i.e.
Definition: ast.cpp:5143
nmodl::ast::Compartment::get_names
const NameVector & get_names() const noexcept
Getter for member variable Compartment::names.
Definition: compartment.hpp:180
nmodl::ast::ReactionStatement::get_reaction1
std::shared_ptr< Expression > get_reaction1() const noexcept
Getter for member variable ReactionStatement::reaction1.
Definition: reaction_statement.hpp:166
nmodl::visitor::KineticBlockVisitor::rate_eqs
struct nmodl::visitor::KineticBlockVisitor::RateEqs rate_eqs
nmodl::ast::ReactionOperator
TODO.
Definition: reaction_operator.hpp:38
nmodl::visitor::KineticBlockVisitor::visit_conserve
void visit_conserve(ast::Conserve &node) override
visit node of type ast::Conserve
Definition: kinetic_block_visitor.cpp:102
kinetic_block_visitor.hpp
Visitor for kinetic block statements
visitor_utils.hpp
Utility functions for visitors implementation.
nmodl::visitor::KineticBlockVisitor::in_reaction_statement_lhs
bool in_reaction_statement_lhs
true if we are visiting the left hand side of reaction statement
Definition: kinetic_block_visitor.hpp:106
nmodl::visitor::KineticBlockVisitor::i_statement
int i_statement
current statement index
Definition: kinetic_block_visitor.hpp:124
nmodl::ast::StatementBlock::erase_statement
StatementVector::const_iterator erase_statement(StatementVector::const_iterator first)
Erase member to statements.
Definition: ast.cpp:3092
nmodl::ast::Conserve::visit_children
void visit_children(visitor::Visitor &v) override
visit children i.e.
Definition: ast.cpp:10157
nmodl::visitor::KineticBlockVisitor::in_conserve_statement
bool in_conserve_statement
true if we are visiting a CONSERVE statement
Definition: kinetic_block_visitor.hpp:109
nmodl::visitor::KineticBlockVisitor::statements_to_remove
std::unordered_set< ast::Statement * > statements_to_remove
statements to remove from block
Definition: kinetic_block_visitor.hpp:130
nmodl::symtab::syminfo::to_string
std::string to_string(const T &obj)
Definition: symbol_properties.hpp:279
nmodl::ast::WrappedExpression::set_expression
void set_expression(std::shared_ptr< Expression > &&expression)
Setter for member variable WrappedExpression::expression (rvalue reference)
Definition: ast.cpp:13674
nmodl::visitor::KineticBlockVisitor::modfile_fflux
std::string modfile_fflux
current expressions for the fflux, bflux variables that can be used in the mod file and that are dete...
Definition: kinetic_block_visitor.hpp:86
nmodl::visitor::KineticBlockVisitor::visit_reaction_statement
void visit_reaction_statement(ast::ReactionStatement &node) override
visit node of type ast::ReactionStatement
Definition: kinetic_block_visitor.cpp:201
nmodl::ast::ReactionStatement::get_op
const ReactionOperator & get_op() const noexcept
Getter for member variable ReactionStatement::op.
Definition: reaction_statement.hpp:175
nmodl::visitor::KineticBlockVisitor::state_var
std::vector< std::string > state_var
state variables vector
Definition: kinetic_block_visitor.hpp:93
nmodl::visitor::KineticBlockVisitor::conserve_equation_str
std::string conserve_equation_str
conserve statement equation as string
Definition: kinetic_block_visitor.hpp:115
nmodl::ast::KineticBlock
TODO.
Definition: kinetic_block.hpp:39
nmodl::visitor::KineticBlockVisitor::bflux
std::vector< std::string > bflux
Definition: kinetic_block_visitor.hpp:80
nmodl::visitor::create_statement
std::shared_ptr< Statement > create_statement(const std::string &code_statement)
Convert given code statement (in string format) to corresponding ast node.
Definition: visitor_utils.cpp:126
nmodl::collect_nodes
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
Definition: visitor_utils.cpp:205
nmodl::ast::Compartment
Represent COMPARTMENT statement in NMODL.
Definition: compartment.hpp:39
nmodl::visitor::create_expr
std::shared_ptr< ast::Expression > create_expr(const std::string &str_expr)
Definition: kinetic_block_visitor.cpp:96
nmodl::visitor::KineticBlockVisitor::visit_react_var_name
void visit_react_var_name(ast::ReactVarName &node) override
visit node of type ast::ReactVarName
Definition: kinetic_block_visitor.cpp:179
nmodl::ast::ReactionStatement::visit_children
void visit_children(visitor::Visitor &v) override
visit children i.e.
Definition: ast.cpp:10606
nmodl::stringutils::split_string
static std::vector< std::string > split_string(const std::string &text, char delimiter)
Split a text in a list of words, using a given delimiter character.
Definition: string_utils.hpp:116
nmodl::ast::StatementBlock
Represents block encapsulating list of statements.
Definition: statement_block.hpp:53
nmodl::ast::Conserve::set_react
void set_react(std::shared_ptr< Expression > &&react)
Setter for member variable Conserve::react (rvalue reference)
Definition: ast.cpp:10229
nmodl::symtab::syminfo::NmodlType
NmodlType
NMODL variable properties.
Definition: symbol_properties.hpp:116
nmodl::ast::LTMINUSGT
@ LTMINUSGT
Definition: ast_common.hpp:92
nmodl::ast::Program::get_blocks
const NodeVector & get_blocks() const noexcept
Getter for member variable Program::blocks.
Definition: program.hpp:216
nmodl::visitor::KineticBlockVisitor::modfile_bflux
std::string modfile_bflux
Definition: kinetic_block_visitor.hpp:87
nmodl::visitor::KineticBlockVisitor::RateEqs::k_b
std::vector< std::string > k_b
Definition: kinetic_block_visitor.hpp:62
nmodl::ast::ReactionStatement
TODO.
Definition: reaction_statement.hpp:39
nmodl::visitor::KineticBlockVisitor::additive_terms
std::vector< std::string > additive_terms
additive constant terms for ODEs from reaction statements like ~ x << (a)
Definition: kinetic_block_visitor.hpp:69
nmodl::visitor::KineticBlockVisitor::visit_kinetic_block
void visit_kinetic_block(ast::KineticBlock &node) override
visit node of type ast::KineticBlock
Definition: kinetic_block_visitor.cpp:354
nmodl::visitor::KineticBlockVisitor::state_var_index
std::unordered_map< std::string, int > state_var_index
unordered_map from state variable to corresponding index
Definition: kinetic_block_visitor.hpp:96
logger.hpp
Implement logger based on spdlog library.
nmodl::visitor::KineticBlockVisitor::kinetic_blocks
std::vector< ast::KineticBlock * > kinetic_blocks
vector of kinetic block nodes
Definition: kinetic_block_visitor.hpp:127
nmodl::visitor::KineticBlockVisitor::current_statement_block
ast::StatementBlock * current_statement_block
current statement block being visited
Definition: kinetic_block_visitor.hpp:133
nmodl::ast::Program::get_symbol_table
symtab::SymbolTable * get_symbol_table() const override
Return associated symbol table for the current ast node.
Definition: program.hpp:153
nmodl::visitor::KineticBlockVisitor::RateEqs::k_f
std::vector< std::string > k_f
Definition: kinetic_block_visitor.hpp:61
nmodl::visitor::KineticBlockVisitor::odes
std::vector< std::string > odes
Definition: kinetic_block_visitor.hpp:81
nmodl::visitor::KineticBlockVisitor::process_reac_var
void process_reac_var(const std::string &varname, int count=1)
update stoichiometric matrices with reaction var term
Definition: kinetic_block_visitor.cpp:22
nmodl::ast::Program
Represents top level AST node for whole NMODL input.
Definition: program.hpp:39
nmodl::ast::WrappedExpression::visit_children
void visit_children(visitor::Visitor &v) override
visit children i.e.
Definition: ast.cpp:13616
nmodl::visitor::KineticBlockVisitor::in_reaction_statement
bool in_reaction_statement
true if we are visiting a reaction statement
Definition: kinetic_block_visitor.hpp:103
nmodl::ast::Program::set_blocks
void set_blocks(NodeVector &&blocks)
Setter for member variable Program::blocks (rvalue reference)
Definition: ast.cpp:12962
nmodl::visitor::KineticBlockVisitor::RateEqs::nu_R
std::vector< std::vector< int > > nu_R
Definition: kinetic_block_visitor.hpp:60
nmodl::ast::ReactVarName::get_value
std::shared_ptr< Integer > get_value() const noexcept
Getter for member variable ReactVarName::value.
Definition: react_var_name.hpp:145
nmodl::ast::LTLT
@ LTLT
Definition: ast_common.hpp:92
nmodl::ModToken
Represent token returned by scanner.
Definition: modtoken.hpp:50
nmodl::visitor::KineticBlockVisitor::RateEqs::nu_L
std::vector< std::vector< int > > nu_L
Definition: kinetic_block_visitor.hpp:59
all.hpp
Auto generated AST classes declaration.
nmodl::ast::WrappedExpression
Wrap any other expression type.
Definition: wrapped_expression.hpp:38
nmodl::visitor::KineticBlockVisitor::non_state_var_bflux
std::vector< std::string > non_state_var_bflux
Definition: kinetic_block_visitor.hpp:76
nmodl::visitor::KineticBlockVisitor::conserve_equation_factor
std::string conserve_equation_factor
conserve statement: current state var multiplicative factor being processed
Definition: kinetic_block_visitor.hpp:121