8 #include <catch2/catch_test_macros.hpp>
20 using namespace nmodl;
21 using namespace visitor;
35 CodegenHelperVisitor
v;
38 const auto&
info =
v.analyze(*ast);
41 std::string variables;
44 for (
const auto&
var:
info.range_parameter_vars) {
45 variables +=
var->get_name() +
";";
47 for (
const auto&
var:
info.range_assigned_vars) {
48 variables +=
var->get_name() +
";";
50 for (
const auto&
var:
info.range_state_vars) {
51 variables +=
var->get_name() +
";";
53 for (
const auto&
var:
info.assigned_vars) {
54 variables +=
var->get_name() +
";";
72 bool enable_cvode =
true;
73 CodegenHelperVisitor
v(enable_cvode);
74 const auto info =
v.analyze(*ast);
79 SCENARIO(
"unusual / failing mod files",
"[codegen][var_order]") {
80 GIVEN(
"cal_mig.mod : USEION variables declared as RANGE") {
83 gcalbar=.003 (mho/cm2)
92 USEION ca READ cai,cao WRITE ica
93 RANGE gcalbar, cai, ica, gcal, ggk
113 THEN("ionic current variable declared as RANGE appears first") {
114 std::string expected =
"gcalbar;ica;gcal;minf;tau;ggk;m;cai;cao;";
116 REQUIRE(
result == expected);
120 GIVEN(
"CaDynamics_E2.mod : USEION variables declared as STATE variable") {
124 USEION ca READ ica WRITE cai
125 RANGE decay, gamma, minCai, depth
129 gamma = 0.05 : percent of free calcium (not buffered)
130 decay = 80 (ms) : rate of removal of calcium
131 depth = 0.1 (um) : depth of shell
135 ASSIGNED {ica (mA/cm2)}
142 cai' = -(10000)*(ica*gamma/(2*FARADAY*depth)) - (cai - minCai)/decay
146 THEN("ion state variable is ordered after parameter and assigned ionic current") {
147 std::string expected =
"gamma;decay;depth;minCai;ica;cai;";
149 REQUIRE(
result == expected);
153 GIVEN(
"cadyn.mod : same USEION variables used for read as well as write") {
157 USEION ca READ cai,ica WRITE cai
159 GLOBAL depth,cainf,taur
164 taur = 200 (ms) : rate of calcium removal
165 cainf = 50e-6(mM) :changed oct2
171 drive_channel (mM/ms)
179 SOLVE state METHOD euler
183 ca' = drive_channel/18 + (cainf -ca)/taur*11
188 THEN("ion variables are ordered correctly") {
189 std::string expected =
"ca;cai;ica;drive_channel;";
191 REQUIRE(
result == expected);
196 SCENARIO(
"Check global variable setup",
"[codegen][global_variables]") {
197 GIVEN(
"SH_na8st.mod: modfile from reduced_dentate model") {
204 SOLVE kin METHOD derivimplicit
207 SOLVE kin STEADYSTATE derivimplicit
226 CodegenHelperVisitor
v;
227 const auto info =
v.analyze(*ast);
229 THEN(
"Checking that primes_size and prime_variables_by_order have the expected size") {
230 REQUIRE(
info.primes_size == 2);
231 REQUIRE(
info.prime_variables_by_order.size() == 2);
241 CodegenHelperVisitor
v;
243 return v.analyze(*ast);
246 TEST_CASE(
"Check ion write/read checks") {
247 std::string input_nmodl = R
"(
250 USEION ca READ cai WRITE cai, eca
251 USEION na WRITE nao, ena
279 for (
const auto& ion:
info.ions) {
280 if (ion.name ==
"ca") {
281 REQUIRE(ion.is_conc_read());
282 REQUIRE(ion.is_interior_conc_read());
283 REQUIRE(!ion.is_exterior_conc_read());
284 REQUIRE(!ion.is_rev_read());
286 REQUIRE(ion.is_conc_written());
287 REQUIRE(ion.is_interior_conc_written());
288 REQUIRE(!ion.is_exterior_conc_written());
289 REQUIRE(ion.is_rev_written());
291 if (ion.name ==
"na") {
292 REQUIRE(!ion.is_conc_read());
293 REQUIRE(!ion.is_interior_conc_read());
294 REQUIRE(!ion.is_exterior_conc_read());
295 REQUIRE(!ion.is_rev_read());
297 REQUIRE(ion.is_conc_written());
298 REQUIRE(!ion.is_interior_conc_written());
299 REQUIRE(ion.is_exterior_conc_written());
300 REQUIRE(ion.is_rev_written());
302 if (ion.name ==
"K") {
303 REQUIRE(ion.is_conc_read());
304 REQUIRE(ion.is_interior_conc_read());
305 REQUIRE(!ion.is_exterior_conc_read());
306 REQUIRE(ion.is_rev_read());
308 REQUIRE(!ion.is_conc_written());
309 REQUIRE(!ion.is_interior_conc_written());
310 REQUIRE(!ion.is_exterior_conc_written());
311 REQUIRE(!ion.is_rev_written());
317 GIVEN(
"a mod file with a single KINETIC block") {
318 std::string input_nmodl = R
"(
326 SOLVE states METHOD cnexp
331 REQUIRE(
info.emit_cvode);
334 GIVEN(
"a mod file with a single DERIVATIVE block") {
335 std::string input_nmodl = R
"(
340 SOLVE state METHOD derivimplicit
349 REQUIRE(
info.emit_cvode);
352 GIVEN(
"a mod file with a single PROCEDURE block solved with method `after_cvode`") {
353 std::string input_nmodl = R
"(
355 SOLVE state METHOD after_cvode
363 REQUIRE(
info.emit_cvode);
366 GIVEN(
"a mod file with a single PROCEDURE block NOT solved with method `after_cvode`") {
367 std::string input_nmodl = R
"(
369 SOLVE state METHOD cnexp
376 THEN(
"Do not emit CVODE") {
377 REQUIRE(!
info.emit_cvode);
380 GIVEN(
"a mod file with a DERIVATIVE and a KINETIC block") {
381 std::string input_nmodl = R
"(
387 SOLVE der METHOD derivimplicit
388 SOLVE kin METHOD cnexp
400 THEN(
"Do not emit CVODE") {
401 REQUIRE(!
info.emit_cvode);
404 GIVEN(
"a mod file with a PROCEDURE and a DERIVATIVE block") {
405 std::string input_nmodl = R
"(
410 SOLVE der METHOD derivimplicit
411 SOLVE func METHOD cnexp
422 THEN(
"Do not emit CVODE") {
423 REQUIRE(!
info.emit_cvode);
Class that binds all pieces together for parsing nmodl file.
std::shared_ptr< ast::Program > parse_string(const std::string &input)
parser nmodl provided as string (used for testing)
Visitor for kinetic block statements
void visit_program(ast::Program &node) override
visit node of type ast::Program
Visitor that solves ODEs using old solvers of NEURON
void visit_program(ast::Program &node) override
visit node of type ast::Program
Replace solve block statements with actual solution node in the AST.
void visit_program(ast::Program &node) override
visit node of type ast::Program
Visitor for STEADYSTATE solve statements
void visit_program(ast::Program &node) override
visit node of type ast::Program
Concrete visitor for constructing symbol table from AST.
void visit_program(ast::Program &node) override
visit node of type ast::Program
CodegenInfo make_codegen_info(const std::string &text)
TEST_CASE("Check ion write/read checks")
SCENARIO("unusual / failing mod files", "[codegen][var_order]")
CodegenInfo run_codegen_helper_get_info(const std::string &text)
std::string run_codegen_helper_visitor(const std::string &text)
Helper visitor to gather AST information to help code generation.
Various types to store code generation specific information.
bool parse_string(const std::string &input)
parser Units provided as string (used for testing)
double var(InputIterator begin, InputIterator end)
Visitor for kinetic block statements
encapsulates code generation backend implementations
Visitor that solves ODEs using old solvers of NEURON
Auto generated AST classes declaration.
Replace solve block statements with actual solution node in the AST.
Visitor for STEADYSTATE solve statements
THIS FILE IS GENERATED AT BUILD TIME AND SHALL NOT BE EDITED.
nmodl::parser::UnitDriver driver