User Guide
defuse_analyze_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 <algorithm>
11 #include <utility>
12 
13 #include "ast/all.hpp"
14 #include "utils/logger.hpp"
15 
16 namespace nmodl {
17 namespace visitor {
18 
19 using printer::JSONPrinter;
21 
22 /// DUState to string conversion for pretty-printing
23 std::string to_string(DUState state) {
24  switch (state) {
25  case DUState::U:
26  return "U";
27  case DUState::D:
28  return "D";
29  case DUState::CD:
30  return "CD";
31  case DUState::LU:
32  return "LU";
33  case DUState::LD:
34  return "LD";
36  return "CONDITIONAL_BLOCK";
37  case DUState::IF:
38  return "IF";
39  case DUState::ELSEIF:
40  return "ELSEIF";
41  case DUState::ELSE:
42  return "ELSE";
43  case DUState::UNKNOWN:
44  return "UNKNOWN";
45  case DUState::NONE:
46  return "NONE";
47  default:
48  throw std::runtime_error("Unhandled DUState?");
49  }
50 }
51 
52 std::ostream& operator<<(std::ostream& os, DUState state) {
53  return os << to_string(state);
54 }
55 
56 /// DUInstance to JSON string
57 void DUInstance::print(JSONPrinter& printer) const {
58  if (children.empty()) {
59  printer.add_node(to_string(state));
60  } else {
61  printer.push_block(to_string(state));
62  for (const auto& inst: children) {
63  inst.print(printer);
64  }
65  printer.pop_block();
66  }
67 }
68 
69 /// DUChain to JSON string
70 std::string DUChain::to_string(bool compact) const {
71  std::ostringstream stream;
72  JSONPrinter printer(stream);
73  printer.compact_json(compact);
74 
75  printer.push_block(name);
76  for (const auto& instance: chain) {
77  instance.print(printer);
78  }
79  printer.pop_block();
80 
81  printer.flush();
82  return stream.str();
83 }
84 
85 /** Evaluate sub-blocks like if, elseif and else
86  * As these are innermost blocks, we have to just check first use
87  * of variable in this block and that's the result of this block.
88  */
90  DUState result = DUState::NONE;
91  for (const auto& chain: children) {
92  const auto& child_state = chain.eval(variable_type);
93  if ((variable_type == DUVariableType::Global &&
94  (child_state == DUState::U || child_state == DUState::D)) ||
95  (variable_type == DUVariableType::Local &&
96  (child_state == DUState::LU || child_state == DUState::LD))) {
97  result = child_state;
98  break;
99  }
100  if (child_state == DUState::CD) {
101  result = DUState::CD;
102  }
103  }
104  return result;
105 }
106 
107 /**
108  * Evaluate conditional block containing sub-blocks like if, elseif and else
109  *
110  * Note that sub-blocks are already evaluated by sub_block_eval() and has only
111  * leaf nodes. In order to find effective defuse, following rules are used:
112  *
113  * - If variable is "used" in any of the sub-block then it's effectively
114  * "U". This is because any branch can be taken at runtime.
115  *
116  * - If variable is "defined" in all sub-blocks doesn't mean that it's
117  * effectively "D". This is because if we can have just "if-elseif"
118  * which could never be taken. Same for empty "if". In order to decide
119  * if it is "D", we make sure there is no empty block and there must
120  * be "else" block with "D". Note that "U" definitions are already
121  * covered in 1) and hence this rule is safe.
122  *
123  * - If there is an "if" with "D" or empty "if" followed by "D" in "else"
124  * block, we can't say it's definition. In this case we return "CD".
125  *
126  * - If there is empty "if" followed by "U" in "else" block, we can say
127  * it's "use". This is because we don't want to "localize" such variables.
128  *
129  * - If we reach else block with either D or CD and if there is no empty
130  * block encountered, this means every block has either "D" or "CD". In
131  * this case we can say that entire block effectively has "D".
132  */
134  DUVariableType variable_type = DUVariableType::Global) const {
135  DUState result = DUState::NONE;
136  bool block_with_none = false;
137 
138  for (const auto& chain: children) {
139  auto child_state = chain.eval(variable_type);
140  if ((variable_type == DUVariableType::Global && child_state == DUState::U) ||
141  (variable_type == DUVariableType::Local && child_state == DUState::LU)) {
142  result = child_state;
143  break;
144  }
145  if (child_state == DUState::NONE) {
146  block_with_none = true;
147  }
148  if ((variable_type == DUVariableType::Global && child_state == DUState::D) ||
149  (variable_type == DUVariableType::Local && child_state == DUState::LD) ||
150  child_state == DUState::CD) {
151  result = DUState::CD;
152  if (chain.state == DUState::ELSE && !block_with_none) {
153  result = child_state;
154  break;
155  }
156  }
157  }
158  return result;
159 }
160 
161 /** Find "effective" usage of variable from def-use chain.
162  * Note that we are interested in "global" variable usage
163  * and hence we consider only [U,D] states and not [LU, LD]
164  */
166  auto result = state;
168  result = sub_block_eval(variable_type);
169  } else if (state == DUState::CONDITIONAL_BLOCK) {
170  result = conditional_block_eval(variable_type);
171  }
172  return result;
173 }
174 
175 /// first usage of a variable in a block decides whether it's definition
176 /// or usage. Note that if-else blocks already evaluated.
178  auto result = DUState::NONE;
179  for (auto& inst: chain) {
180  auto re = inst.eval(variable_type);
181  if ((variable_type == DUVariableType::Global && (re == DUState::U || re == DUState::D)) ||
182  (variable_type == DUVariableType::Local && (re == DUState::LU || re == DUState::LD))) {
183  result = re;
184  break;
185  }
186  if (re == DUState::CD) {
187  result = re;
188  }
189  }
190  return result;
191 }
192 
194  unsupported_node = true;
195  node.visit_children(*this);
196  unsupported_node = false;
197 }
198 
199 /** Nothing to do if called function is not defined or it's external
200  * but if there is a function call for internal function that means
201  * there is no inlining happened. In this case we mark the call as
202  * unsupported.
203  */
205  const auto& function_name = node.get_node_name();
206  const auto& symbol = global_symtab->lookup_in_scope(function_name);
207  if (symbol == nullptr || symbol->is_external_variable()) {
208  node.visit_children(*this);
209  } else {
211  }
212 }
213 
215  const auto& symtab = node.get_symbol_table();
216  if (symtab != nullptr) {
217  current_symtab = symtab;
218  }
219 
221  node.visit_children(*this);
222  symtab_stack.pop();
224 }
225 
226 /** Nmodl grammar doesn't allow assignment operator on rhs (e.g. a = b + (b=c)
227  * and hence not necessary to keep track of assignment operator using stack.
228  */
230  // only the outermost binary expression is important
231  const bool is_outer_binary_expression = !current_binary_expression;
232  if (is_outer_binary_expression) {
233  current_binary_expression = std::static_pointer_cast<const ast::BinaryExpression>(
234  node.get_shared_ptr());
235  }
236 
237  node.get_rhs()->visit_children(*this);
238  if (node.get_op().get_value() == ast::BOP_ASSIGN) {
239  visiting_lhs = true;
240  }
241  node.get_lhs()->visit_children(*this);
242  visiting_lhs = false;
243 
244  if (is_outer_binary_expression) {
245  current_binary_expression = nullptr;
246  }
247 }
248 
250  /// store previous chain
251  auto previous_chain = current_chain;
252 
253  /// starting new if block
255  current_chain = &(previous_chain->back().children);
256 
257  /// visiting if sub-block
258  auto last_chain = current_chain;
260  node.get_condition()->accept(*this);
261  const auto& block = node.get_statement_block();
262  if (block) {
263  block->accept(*this);
264  }
265  current_chain = last_chain;
266 
267  /// visiting else if sub-blocks
268  for (const auto& item: node.get_elseifs()) {
270  }
271 
272  /// visiting else sub-block
273  if (node.get_elses()) {
275  }
276 
277  /// restore to previous chain
278  current_chain = previous_chain;
279 }
280 
281 /** We are not analyzing verbatim blocks yet and hence if there is
282  * a verbatim block we assume there is variable usage.
283  *
284  * \todo One simple way would be to look for p_name in the string
285  * of verbatim block to find the variable usage.
286  */
288  if (!ignore_verbatim) {
290  }
291 }
292 
293 
294 /// unsupported statements : we aren't sure how to handle this "yet" and
295 /// hence variables used in any of the below statements are handled separately
296 
299 }
300 
303 }
304 
307 }
308 
311 }
312 
315 }
316 
318  const std::string& variable = to_nmodl(node);
319  process_variable(variable);
320 }
321 
323  const std::string& variable = to_nmodl(node);
324  process_variable(variable);
325 }
326 
328  const auto& name = node.get_node_name();
329  const auto& length = node.get_length();
330 
331  /// index should be an integer (e.g. after constant folding)
332  /// if this is not the case and then we can't determine exact
333  /// def-use chain
334  if (!length->is_integer()) {
335  /// check if variable name without index part is same
336  auto variable_name_prefix = variable_name.substr(0, variable_name.find('['));
337  if (name == variable_name_prefix) {
338  update_defuse_chain(variable_name_prefix);
339  const std::string& text = to_nmodl(node);
340  nmodl::logger->info("index used to access variable is not known : {} ", text);
341  }
342  return;
343  }
344  auto index = std::dynamic_pointer_cast<ast::Integer>(length);
345  process_variable(name, index->eval());
346 }
347 
348 /// statements / nodes that should not be used for def-use chain analysis
349 
351 
353 
355 
356 
357 /**
358  * Update the Def-Use chain for given variable
359  *
360  * @param name Name of the variable excluding index or dimension
361  *
362  * Update def-use chain if we encounter a variable that we are looking for.
363  * If we encounter non-supported construct then we mark that variable as "use"
364  * because we haven't completely analyzed the usage. Marking that variable "U"
365  * make sures that won't get optimized. Then we distinguish between local and
366  * non-local variables. All variables that appear on lhs are marked as "definitions"
367  * whereas the one on rhs are marked as "usages".
368  */
369 void DefUseAnalyzeVisitor::update_defuse_chain(const std::string& name) {
370  const auto& symbol = current_symtab->lookup_in_scope(name);
371  assert(symbol != nullptr);
372  // variable properties that make variable local
373  const auto properties = NmodlType::local_var | NmodlType::argument;
374  const auto is_local = symbol->has_any_property(properties);
375 
376  if (unsupported_node) {
378  } else if (visiting_lhs) {
379  if (is_local) {
381  } else {
383  }
384  } else {
385  if (is_local) {
387  } else {
389  }
390  }
391 }
392 
393 void DefUseAnalyzeVisitor::process_variable(const std::string& name) {
394  if (name == variable_name) {
395  update_defuse_chain(name);
396  }
397 }
398 
399 void DefUseAnalyzeVisitor::process_variable(const std::string& name, int index) {
400  std::ostringstream fullname;
401  fullname << name << '[' << std::to_string(index) + ']';
402  if (fullname.str() == variable_name) {
403  update_defuse_chain(name);
404  }
405 }
406 
408  const auto last_chain = current_chain;
409  start_new_chain(state);
410  node.visit_children(*this);
411  current_chain = last_chain;
412 }
413 
416  current_chain = &current_chain->back().children;
417 }
418 
419 DUChain DefUseAnalyzeVisitor::analyze(const ast::Ast& node, const std::string& name) {
420  /// re-initialize state
421  variable_name = name;
422  visiting_lhs = false;
424  unsupported_node = false;
425 
426  // variable types that we try to localise: RANGE, GLOBAL and ASSIGNED
427  auto global_symbol_properties = NmodlType::global_var | NmodlType::range_var |
428  NmodlType::assigned_definition;
429  auto global_symbol = global_symtab->lookup_in_scope(variable_name);
430  // If global_symbol exists in the global_symtab then search for a global variable. Otherwise the
431  // variable can only be local if it exists
432  if (global_symbol != nullptr && global_symbol->has_any_property(global_symbol_properties)) {
434  } else {
436  }
437 
438  /// new chain
440  current_chain = &usage.chain;
441 
442  /// analyze given node
444  node.visit_children(*this);
445  symtab_stack.pop();
446 
447  return usage;
448 }
449 
450 } // namespace visitor
451 } // namespace nmodl
nmodl::ast::FunctionCall::get_node_name
std::string get_node_name() const override
Return name of the node.
Definition: ast.cpp:7061
nmodl::ast::IndexedName::get_length
std::shared_ptr< Expression > get_length() const noexcept
Getter for member variable IndexedName::length.
Definition: indexed_name.hpp:176
nmodl::visitor::DefUseAnalyzeVisitor::unsupported_node
bool unsupported_node
indicate that there is unsupported construct encountered
Definition: defuse_analyze_visitor.hpp:236
nmodl::visitor::DefUseAnalyzeVisitor::visit_function_call
void visit_function_call(const ast::FunctionCall &node) override
Nothing to do if called function is not defined or it's external but if there is a function call for ...
Definition: defuse_analyze_visitor.cpp:204
nmodl::ast::Node
Base class for all AST node.
Definition: node.hpp:40
nmodl::ast::Verbatim
Represents a C code block.
Definition: verbatim.hpp:38
nmodl::visitor::DefUseAnalyzeVisitor::variable_name
std::string variable_name
variable for which to construct def-use chain
Definition: defuse_analyze_visitor.hpp:230
nmodl::visitor::DUVariableType
DUVariableType
Variable type processed by DefUseAnalyzeVisitor.
Definition: defuse_analyze_visitor.hpp:59
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::DUInstance::eval
DUState eval(DUVariableType variable_type) const
analyze all children and return "effective" usage
Definition: defuse_analyze_visitor.cpp:165
nmodl::visitor::DUInstance::print
void print(printer::JSONPrinter &printer) const
DUInstance to JSON string.
Definition: defuse_analyze_visitor.cpp:57
nmodl::visitor::DUState
DUState
Represent a state in Def-Use chain.
Definition: defuse_analyze_visitor.hpp:28
nmodl::visitor::DefUseAnalyzeVisitor::visit_indexed_name
void visit_indexed_name(const ast::IndexedName &node) override
visit node of type ast::IndexedName
Definition: defuse_analyze_visitor.cpp:327
nmodl::ast::Ast
Base class for all Abstract Syntax Tree node types.
Definition: ast.hpp:69
nmodl::ast::NonLinEquation
TODO.
Definition: non_lin_equation.hpp:38
nmodl::visitor::DefUseAnalyzeVisitor::variable_type
DUVariableType variable_type
variable type (Local or Global)
Definition: defuse_analyze_visitor.hpp:233
nmodl::ast::BinaryExpression::get_shared_ptr
std::shared_ptr< Ast > get_shared_ptr() override
Get std::shared_ptr from this pointer of the current ast node.
Definition: binary_expression.hpp:132
nmodl::visitor::DefUseAnalyzeVisitor::update_defuse_chain
void update_defuse_chain(const std::string &name)
Update the Def-Use chain for given variable.
Definition: defuse_analyze_visitor.cpp:369
nmodl::visitor::DefUseAnalyzeVisitor::visit_lin_equation
void visit_lin_equation(const ast::LinEquation &node) override
visit node of type ast::LinEquation
Definition: defuse_analyze_visitor.cpp:305
nmodl::visitor::DefUseAnalyzeVisitor::visit_conductance_hint
void visit_conductance_hint(const ast::ConductanceHint &node) override
statements / nodes that should not be used for def-use chain analysis
Definition: defuse_analyze_visitor.cpp:350
nmodl::ast::IndexedName::get_node_name
std::string get_node_name() const override
Return name of the node.
Definition: ast.cpp:1000
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::ConductanceHint
Represents CONDUCTANCE statement in NMODL.
Definition: conductance_hint.hpp:46
nmodl
encapsulates code generation backend implementations
Definition: ast_common.hpp:26
nmodl::visitor::DefUseAnalyzeVisitor::start_new_chain
void start_new_chain(DUState state)
Definition: defuse_analyze_visitor.cpp:414
nmodl::visitor::DefUseAnalyzeVisitor::visit_unsupported_node
void visit_unsupported_node(const ast::Node &node)
Definition: defuse_analyze_visitor.cpp:193
nmodl::visitor::DUState::LD
@ LD
local variable is defined
nmodl::visitor::DUVariableType::Local
@ Local
nmodl::visitor::DUChain::eval
DUState eval() const
return "effective" usage of a variable
Definition: defuse_analyze_visitor.cpp:177
nmodl::visitor::DefUseAnalyzeVisitor::visit_from_statement
void visit_from_statement(const ast::FromStatement &node) override
visit node of type ast::FromStatement
Definition: defuse_analyze_visitor.cpp:309
nmodl::ast::VarName
Represents a variable.
Definition: var_name.hpp:43
nmodl::ast::BOP_ASSIGN
@ BOP_ASSIGN
=
Definition: ast_common.hpp:59
nmodl::visitor::DUChain::variable_type
DUVariableType variable_type
type of variable
Definition: defuse_analyze_visitor.hpp:137
nmodl::logger
logger_type logger
Definition: logger.cpp:34
nmodl::visitor::DefUseAnalyzeVisitor::ignore_verbatim
bool ignore_verbatim
ignore verbatim blocks
Definition: defuse_analyze_visitor.hpp:239
nmodl::ast::BinaryExpression::get_rhs
std::shared_ptr< Expression > get_rhs() const noexcept
Getter for member variable BinaryExpression::rhs.
Definition: binary_expression.hpp:179
nmodl::visitor::DUState::D
@ D
global variable is defined
nmodl::visitor::DefUseAnalyzeVisitor::global_symtab
symtab::SymbolTable * global_symtab
symbol table containing global variables
Definition: defuse_analyze_visitor.hpp:217
nmodl::visitor::DefUseAnalyzeVisitor::analyze
DUChain analyze(const ast::Ast &node, const std::string &name)
compute def-use chain for a variable within the node
Definition: defuse_analyze_visitor.cpp:419
nmodl::visitor::DUState::U
@ U
global variable is used
nmodl::visitor::DUState::ELSEIF
@ ELSEIF
elseif sub-block
nmodl::visitor::DUInstance::conditional_block_eval
DUState conditional_block_eval(DUVariableType variable_type) const
evaluate global usage i.e. with [D,U] states of children
Definition: defuse_analyze_visitor.cpp:133
nmodl::ast::IfStatement::get_elseifs
const ElseIfStatementVector & get_elseifs() const noexcept
Getter for member variable IfStatement::elseifs.
Definition: if_statement.hpp:182
nmodl::printer::JSONPrinter::add_node
void add_node(std::string value, const std::string &key="name")
Add node to json (typically basic type)
Definition: json_printer.cpp:33
nmodl::ast::IfStatement::get_condition
std::shared_ptr< Expression > get_condition() const noexcept
Getter for member variable IfStatement::condition.
Definition: if_statement.hpp:164
nmodl::ast::LocalListStatement
TODO.
Definition: local_list_statement.hpp:39
nmodl::printer::JSONPrinter
Helper class for printing AST in JSON form.
Definition: json_printer.hpp:46
nmodl::visitor::DefUseAnalyzeVisitor::visit_with_new_chain
void visit_with_new_chain(const ast::Node &node, DUState state)
Definition: defuse_analyze_visitor.cpp:407
nmodl::ast::Ast::get_node_type_name
virtual std::string get_node_type_name() const =0
Return type (ast::AstNodeType) of ast node as std::string.
nmodl::visitor::DUInstance::sub_block_eval
DUState sub_block_eval(DUVariableType variable_type) const
if, elseif and else evaluation
Definition: defuse_analyze_visitor.cpp:89
nmodl::visitor::DefUseAnalyzeVisitor::visit_conserve
void visit_conserve(const ast::Conserve &node) override
visit node of type ast::Conserve
Definition: defuse_analyze_visitor.cpp:313
nmodl::printer::JSONPrinter::compact_json
void compact_json(bool flag)
print json in compact mode
Definition: json_printer.hpp:92
nmodl::ast::IndexedName
Represents specific element of an array variable.
Definition: indexed_name.hpp:48
nmodl::visitor::DefUseAnalyzeVisitor::visit_statement_block
void visit_statement_block(const ast::StatementBlock &node) override
visit node of type ast::StatementBlock
Definition: defuse_analyze_visitor.cpp:214
nmodl::visitor::operator<<
std::ostream & operator<<(std::ostream &os, DUState state)
Definition: defuse_analyze_visitor.cpp:52
nmodl::printer::JSONPrinter::push_block
void push_block(const std::string &value, const std::string &key="name")
Add new json object (typically start of new block) name here is type of new block encountered.
Definition: json_printer.cpp:54
nmodl::ast::FunctionCall
TODO.
Definition: function_call.hpp:38
nmodl::ast::Node::visit_children
virtual void visit_children(visitor::Visitor &v) override
visit children i.e.
Definition: ast.cpp:322
nmodl::printer::JSONPrinter::pop_block
void pop_block()
We finished processing a block, add processed block to it's parent block.
Definition: json_printer.cpp:70
nmodl::ast::StatementBlock::get_symbol_table
symtab::SymbolTable * get_symbol_table() const override
Return associated symbol table for the current ast node.
Definition: statement_block.hpp:164
nmodl::visitor::DefUseAnalyzeVisitor::process_variable
void process_variable(const std::string &name)
Definition: defuse_analyze_visitor.cpp:393
nmodl::visitor::DefUseAnalyzeVisitor::current_chain
std::vector< DUInstance > * current_chain
def-use chain currently being constructed
Definition: defuse_analyze_visitor.hpp:220
nmodl::visitor::DUState::NONE
@ NONE
variable is not used
nmodl::visitor::DefUseAnalyzeVisitor::visit_verbatim
void visit_verbatim(const ast::Verbatim &node) override
We are not analyzing verbatim blocks yet and hence if there is a verbatim block we assume there is va...
Definition: defuse_analyze_visitor.cpp:287
nmodl::visitor::DefUseAnalyzeVisitor::current_binary_expression
std::shared_ptr< const ast::BinaryExpression > current_binary_expression
Definition: defuse_analyze_visitor.hpp:244
nmodl::ast::BinaryExpression::get_op
const BinaryOperator & get_op() const noexcept
Getter for member variable BinaryExpression::op.
Definition: binary_expression.hpp:170
nmodl::visitor::DUChain::to_string
std::string to_string(bool compact=true) const
return json representation
Definition: defuse_analyze_visitor.cpp:70
nmodl::ast::IfStatement
TODO.
Definition: if_statement.hpp:39
nmodl::visitor::DefUseAnalyzeVisitor::symtab_stack
std::stack< symtab::SymbolTable * > symtab_stack
symbol tables in call hierarchy
Definition: defuse_analyze_visitor.hpp:227
nmodl::visitor::to_string
std::string to_string(DUState state)
DUState to string conversion for pretty-printing.
Definition: defuse_analyze_visitor.cpp:23
nmodl::visitor::DUState::CONDITIONAL_BLOCK
@ CONDITIONAL_BLOCK
conditional block
nmodl::printer::JSONPrinter::flush
void flush()
Dump json object to stream (typically at the end) nspaces is number of spaces used for indentation.
Definition: json_printer.cpp:81
nmodl::visitor::DefUseAnalyzeVisitor::visit_argument
void visit_argument(const ast::Argument &node) override
visit node of type ast::Argument
Definition: defuse_analyze_visitor.cpp:354
nmodl::visitor::DefUseAnalyzeVisitor::visit_non_lin_equation
void visit_non_lin_equation(const ast::NonLinEquation &node) override
visit node of type ast::NonLinEquation
Definition: defuse_analyze_visitor.cpp:301
nmodl::visitor::DUInstance::children
std::vector< DUInstance > children
usage of variable in case of if like statements
Definition: defuse_analyze_visitor.hpp:91
defuse_analyze_visitor.hpp
Visitor to return Def-Use chain for a given variable in the block/node
nmodl::visitor::DUState::ELSE
@ ELSE
else sub-block
nmodl::visitor::DefUseAnalyzeVisitor::visiting_lhs
bool visiting_lhs
starting visiting lhs of assignment statement
Definition: defuse_analyze_visitor.hpp:242
nmodl::ast::IfStatement::get_statement_block
std::shared_ptr< StatementBlock > get_statement_block() const noexcept override
Getter for member variable IfStatement::statement_block.
Definition: if_statement.hpp:173
nmodl::ast::StatementBlock
Represents block encapsulating list of statements.
Definition: statement_block.hpp:53
nmodl::visitor::DUInstance::state
DUState state
state of the usage
Definition: defuse_analyze_visitor.hpp:88
nmodl::symtab::syminfo::NmodlType
NmodlType
NMODL variable properties.
Definition: symbol_properties.hpp:116
nmodl::ast::Argument
Represents an argument to functions and procedures.
Definition: argument.hpp:48
nmodl::visitor::DefUseAnalyzeVisitor::visit_if_statement
void visit_if_statement(const ast::IfStatement &node) override
visit node of type ast::IfStatement
Definition: defuse_analyze_visitor.cpp:249
nmodl::visitor::DUState::IF
@ IF
if sub-block
nmodl::visitor::DefUseAnalyzeVisitor::visit_local_list_statement
void visit_local_list_statement(const ast::LocalListStatement &node) override
visit node of type ast::LocalListStatement
Definition: defuse_analyze_visitor.cpp:352
nmodl::visitor::DUState::LU
@ LU
local variable is used
nmodl::ast::ReactionStatement
TODO.
Definition: reaction_statement.hpp:39
nmodl::ast::FunctionCall::visit_children
void visit_children(visitor::Visitor &v) override
visit children i.e.
Definition: ast.cpp:7068
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::ast::LinEquation
TODO.
Definition: lin_equation.hpp:38
nmodl::visitor::DUVariableType::Global
@ Global
nmodl::visitor::DUChain::chain
std::vector< DUInstance > chain
def-use chain for a variable
Definition: defuse_analyze_visitor.hpp:140
nmodl::visitor::DefUseAnalyzeVisitor::visit_name
void visit_name(const ast::Name &node) override
visit node of type ast::Name
Definition: defuse_analyze_visitor.cpp:322
nmodl::visitor::DefUseAnalyzeVisitor::current_symtab
symtab::SymbolTable * current_symtab
symbol table for current statement block (or of parent block if doesn't have) should be initialized b...
Definition: defuse_analyze_visitor.hpp:224
nmodl::ast::IfStatement::get_elses
std::shared_ptr< ElseStatement > get_elses() const noexcept
Getter for member variable IfStatement::elses.
Definition: if_statement.hpp:191
nmodl::visitor::DefUseAnalyzeVisitor::visit_var_name
void visit_var_name(const ast::VarName &node) override
visit node of type ast::VarName
Definition: defuse_analyze_visitor.cpp:317
nmodl::visitor::DUChain::name
std::string name
name of the node
Definition: defuse_analyze_visitor.hpp:134
nmodl::visitor::DUState::CD
@ CD
global or local variable is conditionally defined
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::DefUseAnalyzeVisitor::visit_reaction_statement
void visit_reaction_statement(const ast::ReactionStatement &node) override
unsupported statements : we aren't sure how to handle this "yet" and hence variables used in any of t...
Definition: defuse_analyze_visitor.cpp:297
nmodl::ast::Name
Represents a name.
Definition: name.hpp:44
nmodl::ast::Ast::visit_children
virtual void visit_children(visitor::Visitor &v)=0
Visit children i.e.
nmodl::ast::BinaryExpression
Represents binary expression in the NMODL.
Definition: binary_expression.hpp:52
nmodl::visitor::DUState::UNKNOWN
@ UNKNOWN
state not known
nmodl::visitor::DUChain
Def-Use chain for an AST node.
Definition: defuse_analyze_visitor.hpp:131
nmodl::visitor::DefUseAnalyzeVisitor::visit_binary_expression
void visit_binary_expression(const ast::BinaryExpression &node) override
Nmodl grammar doesn't allow assignment operator on rhs (e.g.
Definition: defuse_analyze_visitor.cpp:229
nmodl::visitor::DUInstance
Represent use of a variable in the statement.
Definition: defuse_analyze_visitor.hpp:85
all.hpp
Auto generated AST classes declaration.
nmodl::ast::FromStatement
TODO.
Definition: from_statement.hpp:38
nmodl::symtab::SymbolTable::lookup_in_scope
std::shared_ptr< Symbol > lookup_in_scope(const std::string &name) const
check if symbol with given name exist in the current table (including all parents)
Definition: symbol_table.cpp:164