User Guide
nmodl::visitor::InlineVisitor Class Reference

Visitor to inline local procedure and function calls More...

Detailed Description

Visitor to inline local procedure and function calls

Motivation: Mod files often have function and procedure calls. Procedure typically has use of range variables like:

NEURON {
RANGE tau, alpha, beta
}
DERIVATIVE states() {
...
rates()
alpha = tau + beta
}
PROCEDURE rates() {
tau = xx * 0.12 * some_var
beta = yy * 0.11
}

One can reduce the memory bandwidth pressure by inlining rates() and then replacing tau and beta with local variables. Many mod files from BlueBrain and other open source projects could be hugely benefited by inlining pass. The goal of this pass is to implement procedure and function inlining in the nmodl programs. After inlining we should be able to translate AST back to "transformed" nmodl program which can be compiled and run by NEURON or CoreNEURON simulator.

Implementation Notes:

  • We start with iterating statements in the statement block
  • Function or procedure calls are treated in same way
  • We visit the childrens of a statement and "trap" function calls
  • New ast node WrappedExpression has been added to YAML specification to facilitate easily "capturing" function calls. For example, function call can appear in argument, condition, binary expression, unary expression etc. When inlining happens, we have to replace FunctionCall node with new variable name. As visitor receives the pointer to function call, we can't replace the node. Hence WrappedExpression node has added. With this we can just override visit function of a single node and then can easily replace the expression to whatever the result will be
  • In case of lag and table statement inlining is disabled (haven't carefully looked into side effects)
  • Inlining pass needs to be run after symbol table pass
  • Inlining is done in recursive way i.e. if A() calls B() then first B() is checked for function calls/inlining and so on. This is dony by looking ast node of B() in symbol table and visiting it recursively
  • Procedure calls are typically standalone statements i.e. expression statements. But note that the nmodl grammar allows procedures to appear as part of expression. Procedures always return 0
  • Standalone procedure or function calls are replaced with the procedure/function body

Examples:

PROCEDURE rates_1() {
LOCAL x
rates_2(23.1)
}
PROCEDURE rates_2(y) {
LOCAL x
x = 21.1*v+y
}

The result of inlining :

PROCEDURE rates_1() {
LOCAL x, rates_2_in_0
{
LOCAL x, y_in_0
y_in_0 = 23.1
x = 21.1*v+y_in_0
rates_2_in_0 = 0
}
}
PROCEDURE rates_2(y) {
LOCAL x
x = 21.1*v+y
}
  • Arguments for function call are copied into local variables
  • Local statement gets added to callee block (if doesn't exist)
  • Procedure body gets appended with extra assignment statement with variable used for returning value.
Todo:
  • Recursive function calls are not supported and need to add checks to avoid stack explosion
  • Currently we rename variables more than necessary, this could be improved [low priority]
  • Function calls as part of an argument of function call itself are not completely inlined [low priority]
  • Symbol table pass needs to be re-run in order to update the definitions/usage
  • Location of symbol/nodes after inlining still points to old nodes

Definition at line 130 of file inline_visitor.hpp.

#include <inline_visitor.hpp>

Inheritance diagram for nmodl::visitor::InlineVisitor:
nmodl::visitor::AstVisitor nmodl::visitor::Visitor

Public Member Functions

 InlineVisitor ()=default
 
void visit_function_call (ast::FunctionCall &node) override
 visit node of type ast::FunctionCall More...
 
void visit_statement_block (ast::StatementBlock &node) override
 visit node of type ast::StatementBlock More...
 
void visit_wrapped_expression (ast::WrappedExpression &node) override
 Visit all wrapped expressions which can contain function calls. More...
 
void visit_program (ast::Program &node) override
 visit node of type ast::Program More...
 
- Public Member Functions inherited from nmodl::visitor::AstVisitor
void visit_node (ast::Node &node) override
 visit node of type ast::Node More...
 
void visit_statement (ast::Statement &node) override
 visit node of type ast::Statement More...
 
void visit_expression (ast::Expression &node) override
 visit node of type ast::Expression More...
 
void visit_block (ast::Block &node) override
 visit node of type ast::Block More...
 
void visit_identifier (ast::Identifier &node) override
 visit node of type ast::Identifier More...
 
void visit_number (ast::Number &node) override
 visit node of type ast::Number More...
 
void visit_string (ast::String &node) override
 visit node of type ast::String More...
 
void visit_integer (ast::Integer &node) override
 visit node of type ast::Integer More...
 
void visit_float (ast::Float &node) override
 visit node of type ast::Float More...
 
void visit_double (ast::Double &node) override
 visit node of type ast::Double More...
 
void visit_boolean (ast::Boolean &node) override
 visit node of type ast::Boolean More...
 
void visit_name (ast::Name &node) override
 visit node of type ast::Name More...
 
void visit_prime_name (ast::PrimeName &node) override
 visit node of type ast::PrimeName More...
 
void visit_indexed_name (ast::IndexedName &node) override
 visit node of type ast::IndexedName More...
 
void visit_var_name (ast::VarName &node) override
 visit node of type ast::VarName More...
 
void visit_argument (ast::Argument &node) override
 visit node of type ast::Argument More...
 
void visit_react_var_name (ast::ReactVarName &node) override
 visit node of type ast::ReactVarName More...
 
void visit_read_ion_var (ast::ReadIonVar &node) override
 visit node of type ast::ReadIonVar More...
 
void visit_write_ion_var (ast::WriteIonVar &node) override
 visit node of type ast::WriteIonVar More...
 
void visit_nonspecific_cur_var (ast::NonspecificCurVar &node) override
 visit node of type ast::NonspecificCurVar More...
 
void visit_electrode_cur_var (ast::ElectrodeCurVar &node) override
 visit node of type ast::ElectrodeCurVar More...
 
void visit_range_var (ast::RangeVar &node) override
 visit node of type ast::RangeVar More...
 
void visit_global_var (ast::GlobalVar &node) override
 visit node of type ast::GlobalVar More...
 
void visit_pointer_var (ast::PointerVar &node) override
 visit node of type ast::PointerVar More...
 
void visit_random_var (ast::RandomVar &node) override
 visit node of type ast::RandomVar More...
 
void visit_bbcore_pointer_var (ast::BbcorePointerVar &node) override
 visit node of type ast::BbcorePointerVar More...
 
void visit_extern_var (ast::ExternVar &node) override
 visit node of type ast::ExternVar More...
 
void visit_param_block (ast::ParamBlock &node) override
 visit node of type ast::ParamBlock More...
 
void visit_independent_block (ast::IndependentBlock &node) override
 visit node of type ast::IndependentBlock More...
 
void visit_assigned_block (ast::AssignedBlock &node) override
 visit node of type ast::AssignedBlock More...
 
void visit_state_block (ast::StateBlock &node) override
 visit node of type ast::StateBlock More...
 
void visit_initial_block (ast::InitialBlock &node) override
 visit node of type ast::InitialBlock More...
 
void visit_constructor_block (ast::ConstructorBlock &node) override
 visit node of type ast::ConstructorBlock More...
 
void visit_destructor_block (ast::DestructorBlock &node) override
 visit node of type ast::DestructorBlock More...
 
void visit_statement_block (ast::StatementBlock &node) override
 visit node of type ast::StatementBlock More...
 
void visit_derivative_block (ast::DerivativeBlock &node) override
 visit node of type ast::DerivativeBlock More...
 
void visit_linear_block (ast::LinearBlock &node) override
 visit node of type ast::LinearBlock More...
 
void visit_non_linear_block (ast::NonLinearBlock &node) override
 visit node of type ast::NonLinearBlock More...
 
void visit_discrete_block (ast::DiscreteBlock &node) override
 visit node of type ast::DiscreteBlock More...
 
void visit_function_table_block (ast::FunctionTableBlock &node) override
 visit node of type ast::FunctionTableBlock More...
 
void visit_function_block (ast::FunctionBlock &node) override
 visit node of type ast::FunctionBlock More...
 
void visit_procedure_block (ast::ProcedureBlock &node) override
 visit node of type ast::ProcedureBlock More...
 
void visit_net_receive_block (ast::NetReceiveBlock &node) override
 visit node of type ast::NetReceiveBlock More...
 
void visit_solve_block (ast::SolveBlock &node) override
 visit node of type ast::SolveBlock More...
 
void visit_breakpoint_block (ast::BreakpointBlock &node) override
 visit node of type ast::BreakpointBlock More...
 
void visit_before_block (ast::BeforeBlock &node) override
 visit node of type ast::BeforeBlock More...
 
void visit_after_block (ast::AfterBlock &node) override
 visit node of type ast::AfterBlock More...
 
void visit_ba_block (ast::BABlock &node) override
 visit node of type ast::BABlock More...
 
void visit_for_netcon (ast::ForNetcon &node) override
 visit node of type ast::ForNetcon More...
 
void visit_kinetic_block (ast::KineticBlock &node) override
 visit node of type ast::KineticBlock More...
 
void visit_unit_block (ast::UnitBlock &node) override
 visit node of type ast::UnitBlock More...
 
void visit_constant_block (ast::ConstantBlock &node) override
 visit node of type ast::ConstantBlock More...
 
void visit_neuron_block (ast::NeuronBlock &node) override
 visit node of type ast::NeuronBlock More...
 
void visit_unit (ast::Unit &node) override
 visit node of type ast::Unit More...
 
void visit_double_unit (ast::DoubleUnit &node) override
 visit node of type ast::DoubleUnit More...
 
void visit_local_var (ast::LocalVar &node) override
 visit node of type ast::LocalVar More...
 
void visit_limits (ast::Limits &node) override
 visit node of type ast::Limits More...
 
void visit_number_range (ast::NumberRange &node) override
 visit node of type ast::NumberRange More...
 
void visit_constant_var (ast::ConstantVar &node) override
 visit node of type ast::ConstantVar More...
 
void visit_binary_operator (ast::BinaryOperator &node) override
 visit node of type ast::BinaryOperator More...
 
void visit_unary_operator (ast::UnaryOperator &node) override
 visit node of type ast::UnaryOperator More...
 
void visit_reaction_operator (ast::ReactionOperator &node) override
 visit node of type ast::ReactionOperator More...
 
void visit_paren_expression (ast::ParenExpression &node) override
 visit node of type ast::ParenExpression More...
 
void visit_binary_expression (ast::BinaryExpression &node) override
 visit node of type ast::BinaryExpression More...
 
void visit_diff_eq_expression (ast::DiffEqExpression &node) override
 visit node of type ast::DiffEqExpression More...
 
void visit_unary_expression (ast::UnaryExpression &node) override
 visit node of type ast::UnaryExpression More...
 
void visit_non_lin_equation (ast::NonLinEquation &node) override
 visit node of type ast::NonLinEquation More...
 
void visit_lin_equation (ast::LinEquation &node) override
 visit node of type ast::LinEquation More...
 
void visit_function_call (ast::FunctionCall &node) override
 visit node of type ast::FunctionCall More...
 
void visit_watch (ast::Watch &node) override
 visit node of type ast::Watch More...
 
void visit_ba_block_type (ast::BABlockType &node) override
 visit node of type ast::BABlockType More...
 
void visit_unit_def (ast::UnitDef &node) override
 visit node of type ast::UnitDef More...
 
void visit_factor_def (ast::FactorDef &node) override
 visit node of type ast::FactorDef More...
 
void visit_valence (ast::Valence &node) override
 visit node of type ast::Valence More...
 
void visit_unit_state (ast::UnitState &node) override
 visit node of type ast::UnitState More...
 
void visit_local_list_statement (ast::LocalListStatement &node) override
 visit node of type ast::LocalListStatement More...
 
void visit_model (ast::Model &node) override
 visit node of type ast::Model More...
 
void visit_define (ast::Define &node) override
 visit node of type ast::Define More...
 
void visit_include (ast::Include &node) override
 visit node of type ast::Include More...
 
void visit_param_assign (ast::ParamAssign &node) override
 visit node of type ast::ParamAssign More...
 
void visit_assigned_definition (ast::AssignedDefinition &node) override
 visit node of type ast::AssignedDefinition More...
 
void visit_conductance_hint (ast::ConductanceHint &node) override
 visit node of type ast::ConductanceHint More...
 
void visit_expression_statement (ast::ExpressionStatement &node) override
 visit node of type ast::ExpressionStatement More...
 
void visit_protect_statement (ast::ProtectStatement &node) override
 visit node of type ast::ProtectStatement More...
 
void visit_from_statement (ast::FromStatement &node) override
 visit node of type ast::FromStatement More...
 
void visit_while_statement (ast::WhileStatement &node) override
 visit node of type ast::WhileStatement More...
 
void visit_if_statement (ast::IfStatement &node) override
 visit node of type ast::IfStatement More...
 
void visit_else_if_statement (ast::ElseIfStatement &node) override
 visit node of type ast::ElseIfStatement More...
 
void visit_else_statement (ast::ElseStatement &node) override
 visit node of type ast::ElseStatement More...
 
void visit_watch_statement (ast::WatchStatement &node) override
 visit node of type ast::WatchStatement More...
 
void visit_mutex_lock (ast::MutexLock &node) override
 visit node of type ast::MutexLock More...
 
void visit_mutex_unlock (ast::MutexUnlock &node) override
 visit node of type ast::MutexUnlock More...
 
void visit_conserve (ast::Conserve &node) override
 visit node of type ast::Conserve More...
 
void visit_compartment (ast::Compartment &node) override
 visit node of type ast::Compartment More...
 
void visit_lon_difuse (ast::LonDifuse &node) override
 visit node of type ast::LonDifuse More...
 
void visit_reaction_statement (ast::ReactionStatement &node) override
 visit node of type ast::ReactionStatement More...
 
void visit_lag_statement (ast::LagStatement &node) override
 visit node of type ast::LagStatement More...
 
void visit_constant_statement (ast::ConstantStatement &node) override
 visit node of type ast::ConstantStatement More...
 
void visit_table_statement (ast::TableStatement &node) override
 visit node of type ast::TableStatement More...
 
void visit_suffix (ast::Suffix &node) override
 visit node of type ast::Suffix More...
 
void visit_useion (ast::Useion &node) override
 visit node of type ast::Useion More...
 
void visit_nonspecific (ast::Nonspecific &node) override
 visit node of type ast::Nonspecific More...
 
void visit_electrode_current (ast::ElectrodeCurrent &node) override
 visit node of type ast::ElectrodeCurrent More...
 
void visit_range (ast::Range &node) override
 visit node of type ast::Range More...
 
void visit_global (ast::Global &node) override
 visit node of type ast::Global More...
 
void visit_random_var_list (ast::RandomVarList &node) override
 visit node of type ast::RandomVarList More...
 
void visit_pointer (ast::Pointer &node) override
 visit node of type ast::Pointer More...
 
void visit_bbcore_pointer (ast::BbcorePointer &node) override
 visit node of type ast::BbcorePointer More...
 
void visit_external (ast::External &node) override
 visit node of type ast::External More...
 
void visit_thread_safe (ast::ThreadSafe &node) override
 visit node of type ast::ThreadSafe More...
 
void visit_verbatim (ast::Verbatim &node) override
 visit node of type ast::Verbatim More...
 
void visit_line_comment (ast::LineComment &node) override
 visit node of type ast::LineComment More...
 
void visit_block_comment (ast::BlockComment &node) override
 visit node of type ast::BlockComment More...
 
void visit_ontology_statement (ast::OntologyStatement &node) override
 visit node of type ast::OntologyStatement More...
 
void visit_program (ast::Program &node) override
 visit node of type ast::Program More...
 
void visit_nrn_state_block (ast::NrnStateBlock &node) override
 visit node of type ast::NrnStateBlock More...
 
void visit_eigen_newton_solver_block (ast::EigenNewtonSolverBlock &node) override
 visit node of type ast::EigenNewtonSolverBlock More...
 
void visit_eigen_linear_solver_block (ast::EigenLinearSolverBlock &node) override
 visit node of type ast::EigenLinearSolverBlock More...
 
void visit_wrapped_expression (ast::WrappedExpression &node) override
 visit node of type ast::WrappedExpression More...
 
void visit_derivimplicit_callback (ast::DerivimplicitCallback &node) override
 visit node of type ast::DerivimplicitCallback More...
 
void visit_solution_expression (ast::SolutionExpression &node) override
 visit node of type ast::SolutionExpression More...
 
void visit_update_dt (ast::UpdateDt &node) override
 visit node of type ast::UpdateDt More...
 
- Public Member Functions inherited from nmodl::visitor::Visitor
virtual ~Visitor ()=default
 

Private Member Functions

bool can_replace_statement (const std::shared_ptr< ast::Statement > &statement)
 true if statement can be replaced with inlined body this is possible for standalone function/procedure call as statement More...
 
bool inline_function_call (ast::Block &callee, ast::FunctionCall &node, ast::StatementBlock &caller)
 inline function/procedure into caller block More...
 
void inline_arguments (ast::StatementBlock &inlined_block, const ast::ArgumentVector &callee_parameters, const ast::ExpressionVector &caller_expressions)
 add assignment statements into given statement block to inline arguments More...
 

Static Private Member Functions

static bool can_inline_block (const ast::StatementBlock &block)
 true if given statement block can be inlined More...
 
static void add_return_variable (ast::StatementBlock &block, std::string &varname)
 add assignment statement at end of block (to use as a return statement in case of procedure blocks) More...
 

Private Attributes

ast::StatementBlockcaller_block = nullptr
 statement block containing current function call More...
 
std::shared_ptr< ast::Statementcaller_statement
 statement containing current function call More...
 
symtab::SymbolTable const * program_symtab = nullptr
 symbol table for program node More...
 
std::stack< ast::StatementBlock * > statementblock_stack
 statement blocks in call hierarchy More...
 
std::stack< std::shared_ptr< ast::Statement > > statement_stack
 statements being executed in call hierarchy More...
 
std::map< std::shared_ptr< ast::Statement >, ast::ExpressionStatement * > replaced_statements
 map to track the statements being replaces (typically for procedure calls) More...
 
std::map< std::shared_ptr< ast::Statement >, std::vector< std::shared_ptr< ast::ExpressionStatement > > > inlined_statements
 map to track statements being prepended before function call (typically for function calls) More...
 
std::map< ast::FunctionCall *, std::string > replaced_fun_calls
 map to track replaced function calls (typically for function calls) More...
 
std::map< std::string, int > inlined_variables
 variables currently being renamed and their count (for renaming) More...
 

Constructor & Destructor Documentation

◆ InlineVisitor()

nmodl::visitor::InlineVisitor::InlineVisitor ( )
default

Member Function Documentation

◆ add_return_variable()

void nmodl::visitor::InlineVisitor::add_return_variable ( ast::StatementBlock block,
std::string &  varname 
)
staticprivate

add assignment statement at end of block (to use as a return statement in case of procedure blocks)

Definition at line 50 of file inline_visitor.cpp.

◆ can_inline_block()

bool nmodl::visitor::InlineVisitor::can_inline_block ( const ast::StatementBlock block)
staticprivate

true if given statement block can be inlined

inlining is disabled if function/procedure contains table or lag statement

Definition at line 24 of file inline_visitor.cpp.

◆ can_replace_statement()

bool nmodl::visitor::InlineVisitor::can_replace_statement ( const std::shared_ptr< ast::Statement > &  statement)
private

true if statement can be replaced with inlined body this is possible for standalone function/procedure call as statement

We can replace statement if the entire statement itself is a function call.

In this case we check if:

  • given statement is expression statement
  • if expression is wrapped expression
  • if wrapped expression is a function call
Todo:
Add method to ast itself to simplify this implementation

Definition at line 66 of file inline_visitor.cpp.

◆ inline_arguments()

void nmodl::visitor::InlineVisitor::inline_arguments ( ast::StatementBlock inlined_block,
const ast::ArgumentVector callee_parameters,
const ast::ExpressionVector caller_expressions 
)
private

add assignment statements into given statement block to inline arguments

nothing to inline if no arguments for function call

for argument add new variable to local statement

variables in cloned block needs to be renamed

create assignment statement and insert after the local variables

Definition at line 90 of file inline_visitor.cpp.

◆ inline_function_call()

bool nmodl::visitor::InlineVisitor::inline_function_call ( ast::Block callee,
ast::FunctionCall node,
ast::StatementBlock caller 
)
private

inline function/procedure into caller block

Parameters
callee: ast node representing function/procedure definition being called
node: function/procedure call node
caller: statement block containing function call

do nothing if we can't inline given procedure/function

make sure to rename conflicting local variable in caller block because in case of procedure inlining they can conflict with global variables used in procedure being inlined

check if caller statement could be replaced

need to add local variable for function calls or for procedure call if it is part of expression (standalone procedure calls don't need return statement)

create new variable which will be used for returning value from inlined block

each block should already have local statement

get a copy of function/procedure body

function definition has function name as return value. we have to rename it with new variable name

each argument is added as new assignment statement

to return value from procedure we have to add new variable

variable name which will replace the function call that we just inlined

Definition at line 128 of file inline_visitor.cpp.

◆ visit_function_call()

void nmodl::visitor::InlineVisitor::visit_function_call ( ast::FunctionCall node)
overridevirtual

visit node of type ast::FunctionCall

argument can be function call itself

nothing to do if called function is not defined or it's external

first inline called function

Implements nmodl::visitor::Visitor.

Definition at line 201 of file inline_visitor.cpp.

◆ visit_program()

void nmodl::visitor::InlineVisitor::visit_program ( ast::Program node)
overridevirtual

visit node of type ast::Program

Implements nmodl::visitor::Visitor.

Definition at line 320 of file inline_visitor.cpp.

◆ visit_statement_block()

void nmodl::visitor::InlineVisitor::visit_statement_block ( ast::StatementBlock node)
overridevirtual

visit node of type ast::StatementBlock

While inlining we have to add new statements before call site. In order to return result we also have to add new local variable to the caller block. Hence we have to keep track of caller block, caller block's symbol table and caller statement.

Add empty local statement at the begining of block if already doesn't exist. Why? When we iterate over statements and inline function call, we have to add local variable to return the result. As we can't modify vector while iterating, we pre-add local statement without any local variables. If inlining pass doesn't add any variable then this statement will be removed.

each block should already have local statement

check if any statement is candidate for replacement due to inlining this is typicall case of procedure calls

all statements from inlining needs to be added before the caller statement

Restore the caller context : consider call chain A() -> B() -> none. When we finishes processing B's statements, even we pop the stack, caller_* variables still point to B's context. Hence first we have to pop elements and then use top() to get context of A(). We have to check for non-empty() stack because if there is only A() -> none then stack is already empty.

Implements nmodl::visitor::Visitor.

Definition at line 234 of file inline_visitor.cpp.

◆ visit_wrapped_expression()

void nmodl::visitor::InlineVisitor::visit_wrapped_expression ( ast::WrappedExpression node)
overridevirtual

Visit all wrapped expressions which can contain function calls.

If a function call is replaced then the wrapped expression is also replaced with new variable node from the inlining result.

Implements nmodl::visitor::Visitor.

Definition at line 305 of file inline_visitor.cpp.

Member Data Documentation

◆ caller_block

ast::StatementBlock* nmodl::visitor::InlineVisitor::caller_block = nullptr
private

statement block containing current function call

Definition at line 133 of file inline_visitor.hpp.

◆ caller_statement

std::shared_ptr<ast::Statement> nmodl::visitor::InlineVisitor::caller_statement
private

statement containing current function call

Definition at line 136 of file inline_visitor.hpp.

◆ inlined_statements

std::map<std::shared_ptr<ast::Statement>, std::vector<std::shared_ptr<ast::ExpressionStatement> > > nmodl::visitor::InlineVisitor::inlined_statements
private

map to track statements being prepended before function call (typically for function calls)

Definition at line 153 of file inline_visitor.hpp.

◆ inlined_variables

std::map<std::string, int> nmodl::visitor::InlineVisitor::inlined_variables
private

variables currently being renamed and their count (for renaming)

Definition at line 159 of file inline_visitor.hpp.

◆ program_symtab

symtab::SymbolTable const* nmodl::visitor::InlineVisitor::program_symtab = nullptr
private

symbol table for program node

Definition at line 139 of file inline_visitor.hpp.

◆ replaced_fun_calls

std::map<ast::FunctionCall*, std::string> nmodl::visitor::InlineVisitor::replaced_fun_calls
private

map to track replaced function calls (typically for function calls)

Definition at line 156 of file inline_visitor.hpp.

◆ replaced_statements

std::map<std::shared_ptr<ast::Statement>, ast::ExpressionStatement*> nmodl::visitor::InlineVisitor::replaced_statements
private

map to track the statements being replaces (typically for procedure calls)

Definition at line 148 of file inline_visitor.hpp.

◆ statement_stack

std::stack<std::shared_ptr<ast::Statement> > nmodl::visitor::InlineVisitor::statement_stack
private

statements being executed in call hierarchy

Definition at line 145 of file inline_visitor.hpp.

◆ statementblock_stack

std::stack<ast::StatementBlock*> nmodl::visitor::InlineVisitor::statementblock_stack
private

statement blocks in call hierarchy

Definition at line 142 of file inline_visitor.hpp.


The documentation for this class was generated from the following files: