From edaa090288c3180d7d79e9728d763a0ff28dd5d6 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Tue, 22 Oct 2024 13:20:02 +0200 Subject: [PATCH] Support `SUFFIX nothing`. (#1525) --- src/codegen/codegen_cpp_visitor.cpp | 8 ++- src/codegen/codegen_neuron_cpp_visitor.cpp | 71 ++++++++++++++++--- src/codegen/codegen_neuron_cpp_visitor.hpp | 13 +++- test/usecases/suffix/suffix_nothing.mod | 11 +++ test/usecases/suffix/suffix_nothing_again.mod | 7 ++ test/usecases/suffix/test_suffix_nothing.py | 12 ++++ 6 files changed, 109 insertions(+), 13 deletions(-) create mode 100644 test/usecases/suffix/suffix_nothing.mod create mode 100644 test/usecases/suffix/suffix_nothing_again.mod create mode 100644 test/usecases/suffix/test_suffix_nothing.py diff --git a/src/codegen/codegen_cpp_visitor.cpp b/src/codegen/codegen_cpp_visitor.cpp index f1d815872..312ea2a89 100644 --- a/src/codegen/codegen_cpp_visitor.cpp +++ b/src/codegen/codegen_cpp_visitor.cpp @@ -513,8 +513,9 @@ void CodegenCppVisitor::print_function_call(const FunctionCall& node) { printer->add_text(function_name, '('); if (defined_method(name)) { - printer->add_text(internal_method_arguments()); - if (!arguments.empty()) { + auto internal_args = internal_method_arguments(); + printer->add_text(internal_args); + if (!arguments.empty() && !internal_args.empty()) { printer->add_text(", "); } } @@ -1436,6 +1437,9 @@ void CodegenCppVisitor::setup(const Program& node) { info.mod_suffix = std::filesystem::path(mod_filename).stem().string(); } info.rsuffix = info.point_process ? "" : "_" + info.mod_suffix; + if (info.mod_suffix == "nothing") { + info.rsuffix = ""; + } if (!info.vectorize) { logger->warn( diff --git a/src/codegen/codegen_neuron_cpp_visitor.cpp b/src/codegen/codegen_neuron_cpp_visitor.cpp index e92190259..97004d601 100644 --- a/src/codegen/codegen_neuron_cpp_visitor.cpp +++ b/src/codegen/codegen_neuron_cpp_visitor.cpp @@ -258,7 +258,7 @@ void CodegenNeuronCppVisitor::print_function_or_procedure( printer->fmt_line("int ret_{} = 0;", name); } - if (!info.artificial_cell) { + if (info.mod_suffix != "nothing" && !info.artificial_cell) { printer->add_line( "double v = node_data.node_voltages ? " "node_data.node_voltages[node_data.nodeindices[id]] : 0.0;"); @@ -292,12 +292,17 @@ void CodegenNeuronCppVisitor::print_hoc_py_wrapper_call_impl( 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()); + std::vector args; + args.reserve(params.size()); for (int i = 0; i < params.size(); ++i) { - func_call.append(fmt::format(", *getarg({})", i + 1)); + args.push_back(fmt::format("*getarg({})", i + 1)); } - func_call.append(")"); - return func_call; + + auto internal_args = internal_method_arguments(); + return fmt::format("{}({})", + func_proc_name, + stringutils::join_arguments(internal_args, + fmt::format("{}", fmt::join(args, ", ")))); }; printer->add_line("double _r = 0.0;"); @@ -319,6 +324,10 @@ void CodegenNeuronCppVisitor::print_hoc_py_wrapper_call_impl( void CodegenNeuronCppVisitor::print_hoc_py_wrapper_setup( const ast::Block* function_or_procedure_block, InterpreterWrapper wrapper_type) { + if (info.mod_suffix == "nothing") { + return; + } + const auto block_name = function_or_procedure_block->get_node_name(); printer->add_multi_line(R"CODE( Datum* _ppvar; @@ -563,6 +572,10 @@ std::string CodegenNeuronCppVisitor::internal_method_arguments() { CodegenCppVisitor::ParamVector CodegenNeuronCppVisitor::internal_method_parameters() { + if (info.mod_suffix == "nothing") { + return {}; + } + ParamVector params; params.emplace_back("", "_nrn_mechanism_cache_range&", "", "_lmc"); params.emplace_back("", fmt::format("{}&", instance_struct()), "", "inst"); @@ -1228,7 +1241,9 @@ void CodegenNeuronCppVisitor::print_global_variables_for_hoc() { {"has_loc", _hoc_has_loc}, {"get_loc", _hoc_get_loc_pnt},)CODE"); } else { - printer->fmt_line("{{\"setdata_{}\", _hoc_setdata}},", info.mod_suffix); + if (info.mod_suffix != "nothing") { + printer->fmt_line("{{\"setdata_{}\", _hoc_setdata}},", info.mod_suffix); + } } auto print_callable_reg = [this](const auto& callables, auto get_name) { @@ -1276,8 +1291,16 @@ void CodegenNeuronCppVisitor::print_global_variables_for_hoc() { void CodegenNeuronCppVisitor::print_mechanism_register() { printer->add_newline(2); - printer->add_line("/** register channel with the simulator */"); printer->fmt_push_block("extern \"C\" void _{}_reg()", info.mod_file); + if (info.mod_suffix == "nothing") { + print_mechanism_register_nothing(); + } else { + print_mechanism_register_regular(); + } + printer->pop_block(); +} + +void CodegenNeuronCppVisitor::print_mechanism_register_regular() { printer->add_line("_initlists();"); printer->add_newline(); @@ -1468,8 +1491,10 @@ void CodegenNeuronCppVisitor::print_mechanism_register() { printer->fmt_line("{}._morphology_sym = hoc_lookup(\"morphology\");", global_struct_instance()); } +} - printer->pop_block(); +void CodegenNeuronCppVisitor::print_mechanism_register_nothing() { + printer->add_line("hoc_register_var(hoc_scalar_double, hoc_vector_double, hoc_intfunc);"); } @@ -1720,6 +1745,10 @@ void CodegenNeuronCppVisitor::print_initial_block(const InitialBlock* node) { } void CodegenNeuronCppVisitor::print_entrypoint_setup_code_from_memb_list() { + if (info.mod_suffix == "nothing") { + return; + } + printer->add_line( "_nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()};"); printer->fmt_line("auto inst = make_instance_{}(&_lmc);", info.mod_suffix); @@ -1736,6 +1765,10 @@ void CodegenNeuronCppVisitor::print_entrypoint_setup_code_from_memb_list() { void CodegenNeuronCppVisitor::print_entrypoint_setup_code_from_prop() { + if (info.mod_suffix == "nothing") { + return; + } + printer->add_line("Datum* _ppvar = _nrn_mechanism_access_dparam(prop);"); printer->add_line("_nrn_mechanism_cache_instance _lmc{prop};"); printer->add_line("const size_t id = 0;"); @@ -2394,8 +2427,7 @@ void CodegenNeuronCppVisitor::print_compute_functions() { print_net_init(); } - -void CodegenNeuronCppVisitor::print_codegen_routines() { +void CodegenNeuronCppVisitor::print_codegen_routines_regular() { print_backend_info(); print_headers_include(); print_macro_definitions(); @@ -2425,6 +2457,25 @@ void CodegenNeuronCppVisitor::print_codegen_routines() { print_namespace_stop(); } +void CodegenNeuronCppVisitor::print_codegen_routines_nothing() { + print_backend_info(); + print_headers_include(); + print_namespace_start(); + print_function_prototypes(); + print_global_variables_for_hoc(); + print_function_definitions(); + print_mechanism_register(); + print_namespace_stop(); +} + +void CodegenNeuronCppVisitor::print_codegen_routines() { + if (info.mod_suffix == "nothing") { + print_codegen_routines_nothing(); + } else { + print_codegen_routines_regular(); + } +} + void CodegenNeuronCppVisitor::print_ion_variable() { throw std::runtime_error("Not implemented."); } diff --git a/src/codegen/codegen_neuron_cpp_visitor.hpp b/src/codegen/codegen_neuron_cpp_visitor.hpp index 3168dda6e..de56f061c 100644 --- a/src/codegen/codegen_neuron_cpp_visitor.hpp +++ b/src/codegen/codegen_neuron_cpp_visitor.hpp @@ -530,12 +530,17 @@ class CodegenNeuronCppVisitor: public CodegenCppVisitor { */ void print_mechanism_register() override; + /** Function body for anything not SUFFIX nothing. */ + void print_mechanism_register_regular(); + + /** Function body for SUFFIX nothing. */ + void print_mechanism_register_nothing(); + /** * Print thread variable (de-)initialization functions. */ void print_thread_memory_callbacks(); - /** * Print common code for global functions like nrn_init, nrn_cur and nrn_state * \param type The target backend code block type @@ -748,6 +753,12 @@ class CodegenNeuronCppVisitor: public CodegenCppVisitor { */ void print_codegen_routines() override; + /** Anything not SUFFIX nothing. */ + void print_codegen_routines_regular(); + + /** SUFFIX nothing is special. */ + void print_codegen_routines_nothing(); + void print_ion_variable() override; diff --git a/test/usecases/suffix/suffix_nothing.mod b/test/usecases/suffix/suffix_nothing.mod new file mode 100644 index 000000000..b4bd9cf7f --- /dev/null +++ b/test/usecases/suffix/suffix_nothing.mod @@ -0,0 +1,11 @@ +NEURON { + SUFFIX nothing +} + +FUNCTION forty_two_plus_x(x) { + forty_two_plus_x = 42.0 + x +} + +FUNCTION twice_forty_two_plus_x(x) { + twice_forty_two_plus_x = 2.0 * forty_two_plus_x(x) +} diff --git a/test/usecases/suffix/suffix_nothing_again.mod b/test/usecases/suffix/suffix_nothing_again.mod new file mode 100644 index 000000000..7054e5dac --- /dev/null +++ b/test/usecases/suffix/suffix_nothing_again.mod @@ -0,0 +1,7 @@ +NEURON { + SUFFIX nothing +} + +FUNCTION forty_three() { + forty_three = 43.0 +} diff --git a/test/usecases/suffix/test_suffix_nothing.py b/test/usecases/suffix/test_suffix_nothing.py new file mode 100644 index 000000000..9cbc6d846 --- /dev/null +++ b/test/usecases/suffix/test_suffix_nothing.py @@ -0,0 +1,12 @@ +from neuron import h, gui + + +def test_nothing(): + x = 15.0 + assert h.forty_two_plus_x(x) == 42.0 + x + assert h.twice_forty_two_plus_x(x) == 2.0 * (42.0 + x) + assert h.forty_three() == 43.0 + + +if __name__ == "__main__": + test_nothing()