![Logo](logo.png) |
User Guide
|
Go to the documentation of this file.
25 bool to_inline =
true;
27 for (
const auto& statement: statements) {
29 if (statement->is_table_statement() || statement->is_lag_statement()) {
35 if (statement->is_verbatim()) {
36 const auto node =
dynamic_cast<const Verbatim*
>(statement.get());
38 auto text = node->get_statement()->eval();
41 if (
driver.has_token(
"return")) {
52 auto rhs =
new Integer(0,
nullptr);
54 auto statement = std::make_shared<ExpressionStatement>(expression);
67 if (!statement->is_expression_statement()) {
71 bool to_replace =
false;
74 auto e = es->get_expression();
75 if (e->is_wrapped_expression()) {
77 assert(wrapped_expression);
78 if (wrapped_expression->get_expression()->is_function_call()) {
80 const auto& function_call = std::static_pointer_cast<FunctionCall>(
81 wrapped_expression->get_expression());
82 const auto& function_name = function_call->get_node_name();
83 const auto& symbol = program_symtab->lookup_in_scope(function_name);
84 to_replace = !symbol->is_external_variable();
94 if (caller_expressions.empty()) {
101 for (
const auto& argument: callee_parameters) {
102 auto name = argument->get_name()->clone();
103 auto old_name = name->get_node_name();
104 auto new_name =
get_new_name(old_name,
"in", inlined_variables);
105 name->set_name(new_name);
114 auto lhs =
new VarName(name->clone(),
nullptr,
nullptr);
115 auto rhs = caller_expressions.at(counter)->clone();
119 auto statement = std::make_shared<ExpressionStatement>(expression);
121 static_cast<std::ptrdiff_t
>(counter + 1ul),
135 logger->debug(
"Can not inline function call to {}", function_name);
146 std::string new_varname =
get_new_name(function_name,
"in", inlined_variables);
149 bool to_replace = can_replace_statement(caller_statement);
157 name->set_token(tok);
161 if (local_list_statement ==
nullptr) {
162 throw std::logic_error(
"got local statement as nullptr");
164 local_list_statement->emplace_back_local_var(std::make_shared<ast::LocalVar>(name));
168 auto inlined_block = std::unique_ptr<ast::StatementBlock>(
174 inlined_block->visit_children(visitor);
176 inlined_block->set_symbol_table(
nullptr);
179 inline_arguments(*inlined_block, callee.
get_parameters(), caller_arguments);
183 add_return_variable(*inlined_block, new_varname);
189 replaced_statements[caller_statement] = statement;
191 inlined_statements[caller_statement].push_back(
192 std::shared_ptr<ast::ExpressionStatement>(statement));
196 replaced_fun_calls[&node] = new_varname;
205 const auto& function_name = node.
get_name()->get_node_name();
206 auto symbol = program_symtab->lookup_in_scope(function_name);
209 if (symbol ==
nullptr || symbol->is_external_variable()) {
213 auto nodes = symbol->get_nodes_by_type(
214 {AstNodeType::FUNCTION_BLOCK, AstNodeType::PROCEDURE_BLOCK});
216 throw std::runtime_error(
"symbol table doesn't have ast node for " + function_name);
218 auto f_block = nodes.front();
221 f_block->visit_children(*
this);
223 bool inlined =
false;
225 auto block =
dynamic_cast<ast::Block*
>(f_block);
227 inlined = inline_function_call(*block, node, *caller_block);
230 symbol->mark_inlined();
240 caller_block = &node;
241 statementblock_stack.push(&node);
253 for (
const auto& statement: statements) {
254 caller_statement = statement;
255 statement_stack.push(statement);
256 caller_statement->visit_children(*
this);
257 statement_stack.pop();
262 if (local_list_statement->get_variables().empty()) {
268 for (
auto it = statements.begin(); it < statements.end(); ++it) {
269 const auto& statement = *it;
270 if (replaced_statements.find(statement) != replaced_statements.end()) {
276 for (
auto& element: inlined_statements) {
277 auto it = std::find(statements.begin(), statements.end(), element.first);
278 if (it != statements.end()) {
279 node.
insert_statement(it, element.second, element.second.begin(), element.second.end());
280 element.second.clear();
291 statementblock_stack.pop();
293 if (!statement_stack.empty()) {
294 caller_statement = statement_stack.top();
296 if (!statementblock_stack.empty()) {
297 caller_block = statementblock_stack.top();
308 if (e->is_function_call()) {
312 if (replaced_fun_calls.find(expression) != replaced_fun_calls.end()) {
313 auto var = replaced_fun_calls[expression];
315 replaced_fun_calls.erase(expression);
322 if (program_symtab ==
nullptr) {
323 throw std::runtime_error(
"Program node doesn't have symbol table");
Represents a C code block.
std::shared_ptr< Expression > get_expression() const noexcept
Getter for member variable WrappedExpression::expression.
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
void visit_children(visitor::Visitor &v) override
visit children i.e.
std::shared_ptr< Name > get_name() const noexcept
Getter for member variable FunctionCall::name.
THIS FILE IS GENERATED AT BUILD TIME AND SHALL NOT BE EDITED.
std::shared_ptr< ast::LocalListStatement > get_local_list_statement(const StatementBlock &node)
Return pointer to local statement in the given block, otherwise nullptr.
encapsulates code generation backend implementations
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/procedur...
StatementVector::const_iterator insert_statement(StatementVector::const_iterator position, const std::shared_ptr< Statement > &n)
Insert member to statements.
virtual bool is_procedure_block() const noexcept
Check if the ast node is an instance of ast::ProcedureBlock.
Represents an integer variable.
virtual bool is_function_block() const noexcept
Check if the ast node is an instance of ast::FunctionBlock.
bool inline_function_call(ast::Block &callee, ast::FunctionCall &node, ast::StatementBlock &caller)
inline function/procedure into caller block
Class that binds all pieces together for parsing C verbatim blocks.
static bool can_inline_block(const ast::StatementBlock &block)
true if given statement block can be inlined
const StatementVector & get_statements() const noexcept
Getter for member variable StatementBlock::statements.
Base class for all block scoped nodes.
void visit_function_call(ast::FunctionCall &node) override
visit node of type ast::FunctionCall
Utility functions for visitors implementation.
std::vector< std::shared_ptr< Argument > > ArgumentVector
nmodl::parser::UnitDriver driver
StatementVector::const_iterator erase_statement(StatementVector::const_iterator first)
Erase member to statements.
void visit_children(visitor::Visitor &v) override
visit children i.e.
void visit_program(ast::Program &node) override
visit node of type ast::Program
const ExpressionVector & get_arguments() const noexcept
Getter for member variable FunctionCall::arguments.
Visitor to rename local variables conflicting with global scope
void set_expression(std::shared_ptr< Expression > &&expression)
Setter for member variable WrappedExpression::expression (rvalue reference)
void emplace_back_statement(Statement *n)
Add member to statements by raw pointer.
Blindly rename given variable to new name
void add_local_statement(StatementBlock &node)
Add empty local statement to given block if already doesn't exist.
std::string get_new_name(const std::string &name, const std::string &suffix, std::map< std::string, int > &variables)
Return new name variable by appending _suffix_COUNT where COUNT is number of times the given variable...
Represents block encapsulating list of statements.
std::vector< std::shared_ptr< Expression > > ExpressionVector
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)
void reset_statement(StatementVector::const_iterator position, Statement *n)
Reset member to statements.
void visit_wrapped_expression(ast::WrappedExpression &node) override
Visit all wrapped expressions which can contain function calls.
Operator used in ast::BinaryExpression.
void visit_children(visitor::Visitor &v) override
visit children i.e.
Implement logger based on spdlog library.
LocalVar * add_local_variable(StatementBlock &node, Identifier *varname)
symtab::SymbolTable * get_symbol_table() const override
Return associated symbol table for the current ast node.
Visitor to inline local procedure and function calls
virtual std::shared_ptr< StatementBlock > get_statement_block() const
Return associated statement block for the AST node.
Represents top level AST node for whole NMODL input.
Blindly rename given variable to new name
void visit_children(visitor::Visitor &v) override
visit children i.e.
void visit_statement_block(ast::StatementBlock &node) override
rename name conflicting variables in the statement block and it's all children
virtual const ArgumentVector & get_parameters() const
Represents binary expression in the NMODL.
Visitor to rename local variables conflicting with global scope
Represent token returned by scanner.
virtual std::string get_node_name() const
Return name of of the node.
Auto generated AST classes declaration.
Wrap any other expression type.
void visit_statement_block(ast::StatementBlock &node) override
visit node of type ast::StatementBlock