From 380207ba339ca0b9f6d868d578ce8b723eedf94f Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Tue, 22 Oct 2024 10:46:45 +0200 Subject: [PATCH] Refactor HOC/Python wrapper printing. (#1522) * Split HOC/Py wrapper code printing. * Move printing return variable. * Rename HOC/Py wrapper function name. * Extract HOC/Py signature. --- src/codegen/codegen_neuron_cpp_visitor.cpp | 86 ++++++++++++++-------- src/codegen/codegen_neuron_cpp_visitor.hpp | 32 +++++++- 2 files changed, 85 insertions(+), 33 deletions(-) diff --git a/src/codegen/codegen_neuron_cpp_visitor.cpp b/src/codegen/codegen_neuron_cpp_visitor.cpp index ebd5b5d79..e92190259 100644 --- a/src/codegen/codegen_neuron_cpp_visitor.cpp +++ b/src/codegen/codegen_neuron_cpp_visitor.cpp @@ -284,21 +284,43 @@ void CodegenNeuronCppVisitor::print_function_procedure_helper(const ast::Block& } } - -void CodegenNeuronCppVisitor::print_hoc_py_wrapper_function_body( +void CodegenNeuronCppVisitor::print_hoc_py_wrapper_call_impl( const ast::Block* function_or_procedure_block, InterpreterWrapper wrapper_type) { - if (info.point_process && wrapper_type == InterpreterWrapper::Python) { - return; - } const auto block_name = function_or_procedure_block->get_node_name(); - if (wrapper_type == InterpreterWrapper::HOC) { - printer->fmt_push_block("{}", hoc_function_signature(block_name)); + + const auto get_func_call_str = [&]() { + const auto& params = function_or_procedure_block->get_parameters(); + const auto func_proc_name = block_name + "_" + info.mod_suffix; + auto func_call = fmt::format("{}({}", func_proc_name, internal_method_arguments()); + for (int i = 0; i < params.size(); ++i) { + func_call.append(fmt::format(", *getarg({})", i + 1)); + } + func_call.append(")"); + return func_call; + }; + + printer->add_line("double _r = 0.0;"); + if (function_or_procedure_block->is_function_block()) { + printer->add_indent(); + printer->fmt_text("_r = {};", get_func_call_str()); + printer->add_newline(); } else { - printer->fmt_push_block("{}", py_function_signature(block_name)); + printer->add_line("_r = 1.;"); + printer->fmt_line("{};", get_func_call_str()); } + if (info.point_process || wrapper_type != InterpreterWrapper::HOC) { + printer->add_line("return(_r);"); + } else if (wrapper_type == InterpreterWrapper::HOC) { + printer->add_line("hoc_retpushx(_r);"); + } +} + +void CodegenNeuronCppVisitor::print_hoc_py_wrapper_setup( + const ast::Block* function_or_procedure_block, + InterpreterWrapper wrapper_type) { + const auto block_name = function_or_procedure_block->get_node_name(); printer->add_multi_line(R"CODE( - double _r{}; Datum* _ppvar; Datum* _thread; NrnThread* nt; @@ -369,29 +391,31 @@ void CodegenNeuronCppVisitor::print_hoc_py_wrapper_function_body( table_update_function_name(block_name), internal_method_arguments()); } - const auto get_func_call_str = [&]() { - const auto& params = function_or_procedure_block->get_parameters(); - const auto func_proc_name = block_name + "_" + info.mod_suffix; - auto func_call = fmt::format("{}({}", func_proc_name, internal_method_arguments()); - for (int i = 0; i < params.size(); ++i) { - func_call.append(fmt::format(", *getarg({})", i + 1)); - } - func_call.append(")"); - return func_call; - }; - if (function_or_procedure_block->is_function_block()) { - printer->add_indent(); - printer->fmt_text("_r = {};", get_func_call_str()); - printer->add_newline(); +} + + +std::string CodegenNeuronCppVisitor::hoc_py_wrapper_signature( + const ast::Block* function_or_procedure_block, + InterpreterWrapper wrapper_type) { + const auto block_name = function_or_procedure_block->get_node_name(); + if (wrapper_type == InterpreterWrapper::HOC) { + return hoc_function_signature(block_name); } else { - printer->add_line("_r = 1.;"); - printer->fmt_line("{};", get_func_call_str()); + return py_function_signature(block_name); } - if (info.point_process || wrapper_type != InterpreterWrapper::HOC) { - printer->add_line("return(_r);"); - } else if (wrapper_type == InterpreterWrapper::HOC) { - printer->add_line("hoc_retpushx(_r);"); +} + +void CodegenNeuronCppVisitor::print_hoc_py_wrapper(const ast::Block* function_or_procedure_block, + InterpreterWrapper wrapper_type) { + if (info.point_process && wrapper_type == InterpreterWrapper::Python) { + return; } + + printer->push_block(hoc_py_wrapper_signature(function_or_procedure_block, wrapper_type)); + + print_hoc_py_wrapper_setup(function_or_procedure_block, wrapper_type); + print_hoc_py_wrapper_call_impl(function_or_procedure_block, wrapper_type); + printer->pop_block(); } @@ -399,8 +423,8 @@ void CodegenNeuronCppVisitor::print_hoc_py_wrapper_function_body( void CodegenNeuronCppVisitor::print_hoc_py_wrapper_function_definitions() { auto print_wrappers = [this](const auto& callables) { for (const auto& callable: callables) { - print_hoc_py_wrapper_function_body(callable, InterpreterWrapper::HOC); - print_hoc_py_wrapper_function_body(callable, InterpreterWrapper::Python); + print_hoc_py_wrapper(callable, InterpreterWrapper::HOC); + print_hoc_py_wrapper(callable, InterpreterWrapper::Python); } }; diff --git a/src/codegen/codegen_neuron_cpp_visitor.hpp b/src/codegen/codegen_neuron_cpp_visitor.hpp index 6aecf60fc..3168dda6e 100644 --- a/src/codegen/codegen_neuron_cpp_visitor.hpp +++ b/src/codegen/codegen_neuron_cpp_visitor.hpp @@ -252,9 +252,37 @@ class CodegenNeuronCppVisitor: public CodegenCppVisitor { void print_function_procedure_helper(const ast::Block& node) override; - void print_hoc_py_wrapper_function_body(const ast::Block* function_or_procedure_block, - InterpreterWrapper wrapper_type); + /** Print the wrapper for calling FUNCION/PROCEDURES from HOC/Py. + * + * Usually the function is made up of the following parts: + * * Print setup code `inst`, etc. + * * Print code to call the function and return. + */ + void print_hoc_py_wrapper(const ast::Block* function_or_procedure_block, + InterpreterWrapper wrapper_type); + + /** Print the setup code for HOC/Py wrapper. + */ + void print_hoc_py_wrapper_setup(const ast::Block* function_or_procedure_block, + InterpreterWrapper wrapper_type); + + /** Print the code that calls the impl from the HOC/Py wrapper. + */ + void print_hoc_py_wrapper_call_impl(const ast::Block* function_or_procedure_block, + InterpreterWrapper wrapper_type); + + /** Return the wrapper signature. + * + * Everything without the `{` or `;`. Roughly, as an example: + * (, ) + * + * were ` is the list of arguments required by the + * codegen to be passed along, while are the arguments of + * of the function as they appear in the MOD file. + */ + std::string hoc_py_wrapper_signature(const ast::Block* function_or_procedure_block, + InterpreterWrapper wrapper_type); void print_hoc_py_wrapper_function_definitions();