24 #include <string_view>
31 #include "utils/logger.hpp"
129 const std::shared_ptr<symtab::Symbol>
symbol;
176 inline std::string
get_name(
const std::shared_ptr<symtab::Symbol>& sym) {
177 return sym->get_name();
181 return var.symbol->get_name();
186 auto it = std::find_if(variables.cbegin(), variables.cend(), [&
name](
const auto&
var) {
187 return get_name(var) == name;
190 if (it == variables.cend()) {
191 throw std::runtime_error(fmt::format(
"Unknown variable: {}",
name));
194 return static_cast<int>(it - variables.cbegin());
197 inline int get_length(
const std::shared_ptr<symtab::Symbol>& sym) {
198 return sym->get_length();
202 return var.symbol->get_length();
208 for (
const auto&
var: variables) {
214 throw std::logic_error(
name +
" variable not found");
260 std::ostream& stream,
263 std::unique_ptr<nmodl::utils::Blame> blame =
nullptr)
270 std::ostream& stream,
274 std::unique_ptr<nmodl::utils::Blame> blame =
nullptr)
297 using ParamVector = std::vector<std::tuple<std::string, std::string, std::string, std::string>>;
515 return std::string(
"mechanism_info");
562 template <
typename T>
834 bool open_brace =
true,
835 bool close_brace =
true);
887 const std::string&
name,
888 const std::unordered_set<CppObjectSpecifier>& specifiers) = 0;
971 template <
typename T>
973 const std::string& separator,
974 const std::string&
prefix =
"");
1049 return "\"" +
text +
"\"";
1076 return std::make_shared<symtab::Symbol>(
name,
ModToken());
1088 const std::string& concentration) = 0;
1155 const std::string&
name,
1156 bool use_instance)
const = 0;
1167 bool use_instance =
true)
const = 0;
1179 bool use_instance =
true)
const = 0;
1290 const std::string& function_name =
"") = 0;
1535 template <
typename T>
1537 const std::string&
name,
1538 const std::unordered_set<CppObjectSpecifier>& =
1544 template <
typename T>
1546 const std::string& separator,
1547 const std::string&
prefix) {
1548 for (
auto iter = elements.begin(); iter != elements.end(); iter++) {
1550 (*iter)->accept(*
this);
1564 template <
typename T>
1567 const std::string&
name,
1568 const std::unordered_set<CppObjectSpecifier>& specifiers) {
1574 const auto& params =
node.get_parameters();
1575 for (
const auto&
param: params) {
1576 internal_params.emplace_back(
"",
type,
"",
param.get()->get_node_name());
1580 const char* return_type =
"int";
1581 if (
node.is_function_block()) {
1586 printer->fmt_text(
"{} {} {}({})",
Concrete visitor for all AST classes.
Represent token returned by scanner.
Represents binary expression in the NMODL.
Operator used in ast::BinaryExpression.
Base class for all block scoped nodes.
Represents a boolean variable.
Represents a BREAKPOINT block in NMODL.
Represents a double variable.
Represent linear solver solution block based on Eigen.
Represent newton solver solution block based on Eigen.
Represents a float variable.
Represents specific element of an array variable.
Represents an integer variable.
Represent MUTEXLOCK statement in NMODL.
Represent MUTEXUNLOCK statement in NMODL.
Represents a prime variable (for ODE)
Represents top level AST node for whole NMODL input.
Represent solution of a block in the AST.
Represents block encapsulating list of statements.
Represents TABLE statement in NMODL.
Statement to indicate a change in timestep in a given block.
Visitor for printing C++ code compatible with legacy api of CoreNEURON
virtual const std::string external_method_arguments() noexcept=0
Arguments for external functions called from generated code.
virtual void print_mechanism_register()=0
Print the mechanism registration function.
std::vector< SymbolType > get_float_variables() const
Determine all float variables required during code generation.
bool nrn_cur_required() const noexcept
Check if nrn_cur function is required.
void visit_prime_name(const ast::PrimeName &node) override
visit node of type ast::PrimeName
std::string get_channel_info_var_name() const noexcept
Name of channel info variable.
virtual std::string namespace_name()=0
Name of "our" namespace.
virtual void print_nrn_pointing(const ast::FunctionCall &node)
Print nrn_pointing.
void print_functors_definitions()
Print all Newton functor structs.
virtual void print_headers_include()=0
Print all includes.
const char * default_int_data_type() const noexcept
Default data type for integer (offset) elements.
std::string thread_variables_struct() const
bool range_variable_setup_required() const noexcept
Check if setup_range_variable function is required.
void visit_from_statement(const ast::FromStatement &node) override
visit node of type ast::FromStatement
void print_top_verbatim_blocks()
Print top level (global scope) verbatim blocks.
virtual void print_codegen_routines()=0
Print entry point to code generation.
void visit_unit(const ast::Unit &node) override
visit node of type ast::Unit
void visit_binary_operator(const ast::BinaryOperator &node) override
visit node of type ast::BinaryOperator
virtual void print_nrn_state()=0
Print nrn_state / state update function definition.
virtual void add_variable_point_process(std::vector< IndexVariableInfo > &variables)=0
Add the variable point_process during get_int_variables.
std::vector< std::string > ion_read_statements_optimized(BlockType type) const
For a given output block type, return minimal statements for all read ion variables.
bool is_net_event(const std::string &name) const noexcept
Checks if given function name is net_event.
bool net_receive_buffering_required() const noexcept
Check if net receive/send buffering kernels required.
std::vector< SymbolType > codegen_global_variables
All global variables for the model.
bool is_function_table_call(const std::string &name) const
std::string format_float_string(const std::string &value)
Convert a given float value to its string representation.
void print_namespace_start()
Prints the start of the simulator namespace.
const char * operator_for_d() const noexcept
Operator for diagonal vector update (matrix update)
std::vector< ShadowUseStatement > ion_write_statements(BlockType type)
For a given output block type, return statements for writing back ion variables.
bool is_net_send(const std::string &name) const noexcept
Checks if given function name is net_send.
bool defined_method(const std::string &name) const
Check if given method is defined in this model.
virtual std::string backend_name() const =0
Name of the code generation backend.
bool printing_top_verbatim_blocks
true if currently printing top level verbatim blocks
virtual ParamVector internal_method_parameters()=0
Parameters for internally defined functions.
void visit_integer(const ast::Integer &node) override
visit node of type ast::Integer
virtual void print_fast_imem_calculation()=0
Print fast membrane current calculation code.
virtual void print_sdlists_init(bool print_initializers)=0
virtual void add_variable_tqitem(std::vector< IndexVariableInfo > &variables)=0
Add the variable tqitem during get_int_variables.
virtual void print_net_move_call(const ast::FunctionCall &node)=0
Print call to net_move.
bool nrn_state_required() const noexcept
Check if nrn_state function is required.
symtab::SymbolTable * program_symtab
Symbol table for the program.
virtual void print_parallel_iteration_hint(BlockType type, const ast::Block *block)
Print pragma annotations for channel iterations.
bool net_receive_exist() const noexcept
Check if net_receive node exist.
void visit_function_call(const ast::FunctionCall &node) override
visit node of type ast::FunctionCall
void visit_eigen_linear_solver_block(const ast::EigenLinearSolverBlock &node) override
visit node of type ast::EigenLinearSolverBlock
void visit_if_statement(const ast::IfStatement &node) override
visit node of type ast::IfStatement
static std::pair< std::string, std::string > read_ion_variable_name(const std::string &name)
Return ion variable name and corresponding ion read variable name.
virtual int position_of_float_var(const std::string &name) const =0
Determine the position in the data array for a given float variable.
virtual void print_compute_functions()=0
Print all compute functions for every backend.
void visit_solution_expression(const ast::SolutionExpression &node) override
visit node of type ast::SolutionExpression
virtual void print_g_unused() const =0
Set g_unused (conductance) for NRN_PRCELLSTATE feature.
void visit_else_statement(const ast::ElseStatement &node) override
visit node of type ast::ElseStatement
std::unordered_map< CppObjectSpecifier, std::string > object_specifier_map
std::string get_object_specifiers(const std::unordered_set< CppObjectSpecifier > &)
virtual void print_nrn_destructor()=0
Print nrn_destructor function definition.
std::tuple< bool, int > check_if_var_is_array(const std::string &name)
Check if the given name exist in the symbol.
void visit_program(const ast::Program &program) override
Main and only member function to call after creating an instance of this class.
virtual void print_global_var_struct_assertions() const
Print static assertions about the global variable struct.
void print_namespace_stop()
Prints the end of the simulator namespace.
virtual void print_nrn_current(const ast::BreakpointBlock &node)=0
Print the nrn_current kernel.
void visit_var_name(const ast::VarName &node) override
void visit_string(const ast::String &node) override
visit node of type ast::String
static std::string get_parameter_str(const ParamVector ¶ms)
Generate the string representing the procedure parameter declaration.
virtual void print_function_prototypes()=0
Print function and procedures prototype declaration.
void print_prcellstate_macros() const
Print declaration of macro NRN_PRCELLSTATE for debugging.
bool enable_variable_name_lookup
Variable name should be converted to instance name (but not for function arguments)
std::string mod_filename
Name of mod file (without .mod suffix)
void visit_float(const ast::Float &node) override
visit node of type ast::Float
bool breakpoint_exist() const noexcept
Check if breakpoint node exist.
virtual void print_function_table_call(const ast::FunctionCall &node)=0
Print special code when calling FUNCTION_TABLEs.
bool net_receive_required() const noexcept
Check if net_receive function is required.
CodegenCppVisitor(std::string mod_filename, std::ostream &stream, std::string float_type, const bool optimize_ionvar_copies, const bool enable_cvode, std::unique_ptr< nmodl::utils::Blame > blame=nullptr)
virtual void print_v_unused() const =0
Set v_unused (voltage) for NRN_PRCELLSTATE feature.
void print_procedure(const ast::ProcedureBlock &node)
Print NMODL procedure in target backend code.
virtual void print_standard_includes()=0
Print standard C/C++ includes.
virtual void print_nrn_constructor()=0
Print nrn_constructor function definition.
void print_using_namespace()
Prints f"using namespace {namespace_name()}".
bool printing_net_init
true if currently initial block of net_receive being printed
virtual void print_global_struct_function_table_ptrs()
Print the entries of for FUNCTION_TABLEs in the global struct.
virtual std::string float_variable_name(const SymbolType &symbol, bool use_instance) const =0
Determine the name of a float variable given its symbol.
static std::string get_arg_str(const ParamVector ¶ms)
Generate the string representing the parameters in a function call.
std::vector< IndexVariableInfo > codegen_int_variables
All int variables for the model.
std::string global_struct() const
Name of structure that wraps global variables.
virtual bool needs_v_unused() const =0
void visit_update_dt(const ast::UpdateDt &node) override
visit node of type ast::UpdateDt
std::string nmodl_version() const noexcept
Return Nmodl language version.
const char * operator_for_rhs() const noexcept
Operator for rhs vector update (matrix update)
virtual void print_global_function_common_code(BlockType type, const std::string &function_name="")=0
Print common code for global functions like nrn_init, nrn_cur and nrn_state.
std::vector< std::string > ion_read_statements(BlockType type) const
For a given output block type, return statements for all read ion variables.
bool ion_variable_struct_required() const
Check if a structure for ion variables is required.
void visit_unary_operator(const ast::UnaryOperator &node) override
visit node of type ast::UnaryOperator
const ast::TableStatement * get_table_statement(const ast::Block &)
std::vector< std::tuple< std::string, std::string, std::string, std::string > > ParamVector
A vector of parameters represented by a 4-tuple of strings:
void print_eigen_linear_solver(const std::string &float_type, int N)
Print linear solver using Eigen.
bool is_net_move(const std::string &name) const noexcept
Checks if given function name is net_move.
virtual void append_conc_write_statements(std::vector< ShadowUseStatement > &statements, const Ion &ion, const std::string &concentration)=0
Generate Function call statement for nrn_wrote_conc.
virtual void print_net_send_call(const ast::FunctionCall &node)=0
Print call to net_send.
static bool statement_to_skip(const ast::Statement &node)
Check if given statement should be skipped during code generation.
virtual void print_nrn_alloc()=0
Print nrn_alloc function definition.
virtual std::string int_variable_name(const IndexVariableInfo &symbol, const std::string &name, bool use_instance) const =0
Determine the name of an int variable given its symbol.
std::string method_name(const std::string &name) const
Constructs the name of a function or procedure.
virtual void print_nrn_cur_kernel(const ast::BreakpointBlock &node)=0
Print main body of nrn_cur function.
virtual bool optimize_ion_variable_copies() const =0
Check if ion variable copies should be avoided.
void visit_else_if_statement(const ast::ElseIfStatement &node) override
visit node of type ast::ElseIfStatement
void visit_name(const ast::Name &node) override
visit node of type ast::Name
std::shared_ptr< symtab::Symbol > SymbolType
virtual std::string simulator_name()=0
Name of the simulator the code was generated for.
void print_statement_block(const ast::StatementBlock &node, bool open_brace=true, bool close_brace=true)
Print any statement block in nmodl with option to (not) print braces.
static std::pair< std::string, std::string > write_ion_variable_name(const std::string &name)
Return ion variable name and corresponding ion write variable name.
void print_nmodl_constants()
Print the nmodl constants used in backend code.
void visit_statement_block(const ast::StatementBlock &node) override
void visit_mutex_lock(const ast::MutexLock &node) override
visit node of type ast::MutexLock
int float_variables_size() const
Number of float variables in the model.
virtual void print_nrn_cur_conductance_kernel(const ast::BreakpointBlock &node)=0
Print the nrn_cur kernel with NMODL conductance keyword provisions.
std::string table_update_function_name(const std::string &block_name) const
The name of the function that updates the table value if the parameters changed.
virtual void print_nrn_cur()=0
Print nrn_cur / current update function definition.
void visit_boolean(const ast::Boolean &node) override
visit node of type ast::Boolean
void visit_paren_expression(const ast::ParenExpression &node) override
visit node of type ast::ParenExpression
virtual void print_mechanism_global_var_structure(bool print_initializers)=0
Print the structure that wraps all global variables used in the NMODL.
codegen::CodegenInfo info
All ast information for code generation.
void visit_double(const ast::Double &node) override
visit node of type ast::Double
void print_table_replacement_function(const ast::Block &)
Print replacement function for function or procedure using table.
std::string node_data_struct() const
Name of structure that wraps node variables.
virtual void print_function_or_procedure(const ast::Block &node, const std::string &name, const std::unordered_set< CppObjectSpecifier > &specifiers)=0
Print nmodl function or procedure (common code)
std::vector< IndexVariableInfo > get_int_variables()
Determine all int variables required during code generation.
virtual void print_function_procedure_helper(const ast::Block &node)=0
Common helper function to help printing function or procedure blocks.
void print_table_check_function(const ast::Block &)
Print check_function() for functions or procedure using table.
std::unique_ptr< CodePrinter > printer
Code printer object for target (C++)
std::string format_double_string(const std::string &value)
Convert a given double value to its string representation.
std::string process_shadow_update_statement(const ShadowUseStatement &statement, BlockType type)
Process shadow update statement.
virtual int position_of_int_var(const std::string &name) const =0
Determine the position in the data array for a given int variable.
int int_variables_size() const
Number of integer variables in the model.
std::string breakpoint_current(std::string current) const
Determine the variable name for the "current" used in breakpoint block taking into account intermedia...
virtual void print_global_var_struct_decl()
Instantiate global var instance.
virtual void print_nrn_cur_non_conductance_kernel()=0
Print the nrn_cur kernel without NMODL conductance keyword provisions.
bool is_nrn_pointing(const std::string &name) const noexcept
CodegenCppVisitor(std::string mod_filename, std::ostream &stream, std::string float_type, const bool optimize_ionvar_copies, std::unique_ptr< nmodl::utils::Blame > blame=nullptr)
Constructs the C++ code generator visitor.
bool is_functor_const(const ast::StatementBlock &variable_block, const ast::StatementBlock &functor_block)
Checks whether the functor_block generated by sympy solver modifies any variable outside its scope.
virtual std::pair< ParamVector, ParamVector > function_table_parameters(const ast::FunctionTableBlock &node)=0
Parameters of the function itself "{}" and "table_{}".
virtual const ParamVector external_method_parameters(bool table=false) noexcept=0
Parameters for functions in generated code that are called back from external code.
std::string update_if_ion_variable_name(const std::string &name) const
Determine the updated name if the ion variable has been optimized.
SymbolType make_symbol(const std::string &name) const
Creates a temporary symbol.
virtual std::string nrn_thread_internal_arguments()=0
Arguments for "_threadargs_" macro in neuron implementation.
virtual std::string global_variable_name(const SymbolType &symbol, bool use_instance=true) const =0
Determine the variable name for a global variable given its symbol.
const char * local_var_type() const noexcept
Data type for the local variables.
void visit_indexed_name(const ast::IndexedName &node) override
visit node of type ast::IndexedName
bool optimize_ionvar_copies
Flag to indicate if visitor should avoid ion variable copies.
void visit_mutex_unlock(const ast::MutexUnlock &node) override
visit node of type ast::MutexUnlock
int current_watch_statement
Index of watch statement being printed.
virtual std::string get_variable_name(const std::string &name, bool use_instance=true) const =0
Determine variable name in the structure of mechanism properties.
const std::string & float_data_type() const noexcept
Data type for floating point elements specified on command line.
virtual void print_data_structures(bool print_initializers)=0
Print all classes.
virtual void print_global_variables_for_hoc()=0
Print byte arrays that register scalar and vector variables for hoc interface.
std::string float_type
Data type of floating point variables.
bool has_parameter_of_name(const T &node, const std::string &name)
Check if function or procedure node has parameter with given name.
std::string global_struct_instance() const
Name of the (host-only) global instance of global_struct
void visit_local_list_statement(const ast::LocalListStatement &node) override
visit node of type ast::LocalListStatement
void visit_while_statement(const ast::WhileStatement &node) override
visit node of type ast::WhileStatement
bool net_send_buffer_required() const noexcept
Check if net_send_buffer is required.
void print_rename_state_vars() const
virtual void print_function_call(const ast::FunctionCall &node)
Print call to internal or external function.
void visit_eigen_newton_solver_block(const ast::EigenNewtonSolverBlock &node) override
visit node of type ast::EigenNewtonSolverBlock
virtual void print_ion_variable()=0
void visit_binary_expression(const ast::BinaryExpression &node) override
visit node of type ast::BinaryExpression
std::string compute_method_name(BlockType type) const
int get_int_variable_index(const std::string &var_name)
void update_index_semantics()
populate all index semantics needed for registration with coreneuron
void print_mechanism_info()
Print backend code for byte array that has mechanism information (to be registered with NEURON/CoreNE...
bool internal_method_call_encountered
true if internal method call was encountered while processing verbatim block
virtual void setup(const ast::Program &node)
virtual void print_net_event_call(const ast::FunctionCall &node)=0
Print call to net_event.
std::string instance_struct() const
Name of structure that wraps range variables.
std::vector< SymbolType > codegen_float_variables
All float variables for the model.
virtual std::string internal_method_arguments()=0
Arguments for functions that are defined and used internally.
virtual std::string register_mechanism_arguments() const =0
Arguments for register_mech or point_register_mech function.
void print_function(const ast::FunctionBlock &node)
Print NMODL function in target backend code.
void print_function_tables(const ast::FunctionTableBlock &node)
Print the internal function for FUNCTION_TABLES.
virtual void print_mechanism_range_var_structure(bool print_initializers)=0
Print the structure that wraps all range and int variables required for the NMODL.
std::string add_escape_quote(const std::string &text) const
Add quotes to string to be output.
void print_functor_definition(const ast::EigenNewtonSolverBlock &node)
Based on the EigenNewtonSolverBlock passed print the definition needed for its functor.
virtual ParamVector functor_params()=0
The parameters of the Newton solver "functor".
bool printing_net_receive
true if currently net_receive block being printed
const char * default_float_data_type() const noexcept
Default data type for floating point elements.
void print_backend_info()
Print top file header printed in generated code.
static bool need_semicolon(const ast::Statement &node)
Check if a semicolon is required at the end of given statement.
virtual std::string nrn_thread_arguments() const =0
Arguments for "_threadargs_" macro in neuron implementation.
Helper class for printing C/C++ code.
Represent symbol table for a NMODL block.
Concrete constant visitor for all AST classes.
Helper class for printing C/C++ code.
Various types to store code generation specific information.
virtual std::string get_node_name() const
Return name of of the node.
void print_vector_elements(const std::vector< T > &elements, const std::string &separator, const std::string &prefix="")
Print the items in a vector as a list.
void print_function_declaration(const T &node, const std::string &name, const std::unordered_set< CppObjectSpecifier > &={CppObjectSpecifier::Static, CppObjectSpecifier::Inline})
Print prototype declarations of functions or procedures.
int get_length(const std::shared_ptr< symtab::Symbol > &sym)
int get_index_from_name(const std::vector< T > &variables, const std::string &name)
BlockType
Helper to represent various block types.
std::string get_name(ast::Ast const *sym)
CppObjectSpecifier
various specifiers (mostly for function codegen)
int get_prefixsum_from_name(const std::vector< T > &variables, const std::string &name)
MemberType
Helper to represent various variables types.
@ NetReceive
net_receive block
@ Destructor
destructor block
@ Constructor
constructor block
@ BeforeAfter
before / after block
@ Equation
breakpoint block
@ BlockTypeEnd
fake ending block type for loops on the enums. Keep it at the end
@ range
range / double variables
@ index
index / int variables
bool is_last(Iter iter, const Cont &cont)
Check if the iterator is pointing to last element in the container.
double var(InputIterator begin, InputIterator end)
void move(Item *q1, Item *q2, Item *q3)
static constexpr char NET_EVENT_METHOD[]
net_event function call in nmodl
static constexpr char NRN_POINTING_METHOD[]
nrn_pointing function in nmodl
static constexpr char DEFAULT_FLOAT_TYPE[]
default float variable type
static constexpr char NMODL_VERSION[]
nmodl language version
static constexpr char NET_MOVE_METHOD[]
net_move function call in nmodl
static constexpr char DEFAULT_LOCAL_VAR_TYPE[]
default local variable type
static constexpr char NET_SEND_METHOD[]
net_send function call in nmodl
static constexpr char DEFAULT_INTEGER_TYPE[]
default integer variable type
encapsulates code generation backend implementations
static Node * node(Object *)
static double param[NPARAM]
Base class for all Abstract Syntax Tree node types.
Represent information collected from AST for code generation.
bool electrode_current
if electrode current specified
std::string mod_suffix
name of the suffix
Helper to represent information about index/int variables.
bool is_integer
if this is an integer (e.g.
bool is_index
if this is pure index (e.g.
IndexVariableInfo(std::shared_ptr< symtab::Symbol > symbol, bool is_vdata=false, bool is_index=false, bool is_integer=false)
bool is_constant
if the variable is qualified as constant (this is property of IndexVariable)
const std::shared_ptr< symtab::Symbol > symbol
symbol for the variable
bool is_vdata
if variable resides in vdata field of NrnThread typically true for bbcore pointer
Represent ions used in mod file.
Represents ion write statement during code generation.
Implement classes for representing symbol table at block and file scope.