Skip to content

Commit

Permalink
Implement CONSTRUCTOR/DESTRUCTOR. (#1424)
Browse files Browse the repository at this point in the history
  • Loading branch information
1uc authored Sep 11, 2024
1 parent f697c12 commit 2c376ea
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 4 deletions.
58 changes: 54 additions & 4 deletions src/codegen/codegen_neuron_cpp_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1120,10 +1120,16 @@ void CodegenNeuronCppVisitor::print_mechanism_register() {
"_pointtype = point_register_mech({}, _hoc_create_pnt, _hoc_destroy_pnt, "
"_member_func);",
register_mech_args);

if (info.destructor_node) {
printer->fmt_line("register_destructor({});",
method_name(naming::NRN_DESTRUCTOR_METHOD));
}
} else {
printer->fmt_line("register_mech({});", register_mech_args);
}


if (info.thread_callback_register) {
printer->fmt_line("_extcall_thread.resize({});", info.thread_data_index + 1);
printer->fmt_line("thread_mem_init(_extcall_thread.data());");
Expand Down Expand Up @@ -1560,21 +1566,55 @@ void CodegenNeuronCppVisitor::print_nrn_jacob() {
}


/// TODO: Edit for NEURON
void CodegenNeuronCppVisitor::print_callable_preamble_from_prop() {
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;");

printer->fmt_line("auto inst = make_instance_{}(_lmc);", info.mod_suffix);
if (!info.artificial_cell) {
printer->fmt_line("auto node_data = make_node_data_{}(prop);", info.mod_suffix);
}

if (!codegen_thread_variables.empty()) {
printer->fmt_line("auto _thread_vars = {}({}_global.thread_data);",
thread_variables_struct(),
info.mod_suffix);
}

printer->add_newline();
}


void CodegenNeuronCppVisitor::print_nrn_constructor() {
return;
if (info.constructor_node) {
printer->fmt_push_block("void {}(Prop* prop)", method_name(naming::NRN_CONSTRUCTOR_METHOD));

print_callable_preamble_from_prop();

auto block = info.constructor_node->get_statement_block();
print_statement_block(*block, false, false);

printer->pop_block();
}
}


void CodegenNeuronCppVisitor::print_nrn_destructor() {
printer->fmt_push_block("void {}(Prop* _prop)", method_name(naming::NRN_DESTRUCTOR_METHOD));
printer->add_line("Datum* _ppvar = _nrn_mechanism_access_dparam(_prop);");
printer->fmt_push_block("void {}(Prop* prop)", method_name(naming::NRN_DESTRUCTOR_METHOD));
print_callable_preamble_from_prop();

for (const auto& rv: info.random_variables) {
printer->fmt_line("nrnran123_deletestream((nrnran123_State*) {});",
get_variable_name(get_name(rv), false));
}


if (info.destructor_node) {
auto block = info.destructor_node->get_statement_block();
print_statement_block(*block, false, false);
}

printer->pop_block();
}

Expand Down Expand Up @@ -1699,6 +1739,15 @@ void CodegenNeuronCppVisitor::print_nrn_alloc() {
method_name(naming::NRN_DESTRUCTOR_METHOD));
}

if (info.point_process || info.artificial_cell) {
printer->fmt_push_block("if(!nrn_point_prop_)");

if (info.constructor_node) {
printer->fmt_line("{}(_prop);", method_name(naming::NRN_CONSTRUCTOR_METHOD));
}
printer->pop_block();
}

printer->pop_block();
}

Expand Down Expand Up @@ -2089,6 +2138,7 @@ void CodegenNeuronCppVisitor::print_codegen_routines() {
print_prcellstate_macros();
print_mechanism_info();
print_data_structures(true);
print_nrn_constructor();
print_nrn_destructor();
print_nrn_alloc();
print_function_prototypes();
Expand Down
4 changes: 4 additions & 0 deletions src/codegen/codegen_neuron_cpp_visitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,10 @@ class CodegenNeuronCppVisitor: public CodegenCppVisitor {
*/
void print_nrn_constructor() override;

/**
* Print the set of common variables from a `Prop` only.
*/
void print_callable_preamble_from_prop();

/**
* Print nrn_destructor function definition
Expand Down
1 change: 1 addition & 0 deletions test/usecases/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ set(NMODL_USECASE_DIRS
solve
constant
electrode_current
constructor
function
procedure
global
Expand Down
17 changes: 17 additions & 0 deletions test/usecases/constructor/art_ctor.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
NEURON {
ARTIFICIAL_CELL art_ctor
GLOBAL ctor_calls, dtor_calls
}

ASSIGNED {
ctor_calls
dtor_calls
}

CONSTRUCTOR {
ctor_calls = ctor_calls + 1
}

DESTRUCTOR {
dtor_calls = dtor_calls + 1
}
17 changes: 17 additions & 0 deletions test/usecases/constructor/ctor.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
NEURON {
POINT_PROCESS ctor
GLOBAL ctor_calls, dtor_calls
}

ASSIGNED {
ctor_calls
dtor_calls
}

CONSTRUCTOR {
ctor_calls = ctor_calls + 1
}

DESTRUCTOR {
dtor_calls = dtor_calls + 1
}
36 changes: 36 additions & 0 deletions test/usecases/constructor/test_ctor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import gc

from neuron import h, gui


def allocate_props(n_instances, mech_name):
s = h.Section()
s.nseg = 1

for _ in range(n_instances):
getattr(h, mech_name)(s(0.5))


def assert_equal(actual, expected):
assert actual == expected, f"{actual} != {expected}"


def check_ctor(n_instances, mech_name):
allocate_props(n_instances, mech_name)
gc.collect()

assert_equal(getattr(h, f"ctor_calls_{mech_name}"), n_instances)
assert_equal(getattr(h, f"dtor_calls_{mech_name}"), n_instances)


def test_ctor():
check_ctor(12, "ctor")


def test_art_ctor():
check_ctor(32, "art_ctor")


if __name__ == "__main__":
test_ctor()
test_art_ctor()

0 comments on commit 2c376ea

Please sign in to comment.