User Guide
codegen_compatibility_visitor.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2023 Blue Brain Project, EPFL.
3  * See the top-level LICENSE file for details.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <catch2/catch_test_macros.hpp>
9 #include <catch2/matchers/catch_matchers_string.hpp>
10 
11 #include "ast/program.hpp"
13 #include "parser/nmodl_driver.hpp"
17 
18 using Catch::Matchers::ContainsSubstring;
19 
20 using namespace nmodl;
21 using namespace visitor;
22 using namespace codegen;
23 
25 
26 /// Return true if it failed and false otherwise
27 bool runCompatibilityVisitor(const std::string& nmodl_text,
28  const std::string& simulator = "coreneuron") {
29  const auto& ast = NmodlDriver().parse_string(nmodl_text);
30  SymtabVisitor().visit_program(*ast);
31  PerfVisitor().visit_program(*ast);
32  return CodegenCompatibilityVisitor(simulator).find_unhandled_ast_nodes(*ast);
33 }
34 
35 SCENARIO("Uncompatible constructs should failed", "[codegen][compatibility_visitor]") {
36  GIVEN("A mod file containing an EXTERNAL construct") {
37  std::string const nmodl_text = R"(
38  NEURON {
39  EXTERNAL apc_metap
40  }
41  )";
42 
43  THEN("should fail for CoreNEURON") {
44  bool failed = runCompatibilityVisitor(nmodl_text, "coreneuron");
45  REQUIRE(failed);
46  }
47 
48  THEN("but succeed for NEURON") {
49  bool failed = runCompatibilityVisitor(nmodl_text, "neuron");
50  REQUIRE(!failed);
51  }
52  }
53  GIVEN("A mod file containing a written GLOBAL var") {
54  std::string const nmodl_text = R"(
55  NEURON {
56  GLOBAL foo
57  }
58 
59  PROCEDURE bar() {
60  foo = 1
61  }
62  )";
63 
64  THEN("should failed") {
65  bool failed = runCompatibilityVisitor(nmodl_text);
66  REQUIRE(failed);
67  }
68  }
69  GIVEN("A mod file containing a written un-writtable var") {
70  std::string const nmodl_text = R"(
71  PARAMETER {
72  foo = 1
73  }
74 
75  PROCEDURE bar() {
76  foo = 1
77  }
78  )";
79 
80  THEN("should failed") {
81  bool failed = runCompatibilityVisitor(nmodl_text);
82  REQUIRE(failed);
83  }
84  }
85  GIVEN("A mod file with BBCOREPOINTER without bbcore_read / bbcore_write") {
86  std::string const nmodl_text = R"(
87  NEURON {
88  BBCOREPOINTER rng
89  }
90  )";
91 
92  THEN("should failed") {
93  bool failed = runCompatibilityVisitor(nmodl_text);
94  REQUIRE(failed);
95  }
96  }
97  GIVEN("A mod file with BBCOREPOINTER without bbcore_write") {
98  std::string const nmodl_text = R"(
99  NEURON {
100  BBCOREPOINTER rng
101  }
102 
103  VERBATIM
104  static void bbcore_read(double* x, int* d, int* xx, int* offset, _threadargsproto_) {
105  }
106  ENDVERBATIM
107  )";
108 
109  THEN("should failed") {
110  bool failed = runCompatibilityVisitor(nmodl_text);
111  REQUIRE(failed);
112  }
113  }
114  GIVEN("A mod file with BBCOREPOINTER without bbcore_read") {
115  std::string const nmodl_text = R"(
116  NEURON {
117  BBCOREPOINTER rng
118  }
119 
120  VERBATIM
121  static void bbcore_write(double* x, int* d, int* xx, int* offset, _threadargsproto_) {
122  }
123  ENDVERBATIM
124  )";
125 
126  THEN("should failed") {
127  bool failed = runCompatibilityVisitor(nmodl_text);
128  REQUIRE(failed);
129  }
130  }
131  GIVEN("A mod file with BBCOREPOINTER with bbcore_read / bbcore_write") {
132  std::string const nmodl_text = R"(
133  NEURON {
134  BBCOREPOINTER rng
135  }
136 
137  VERBATIM
138  static void bbcore_read(double* x, int* d, int* xx, int* offset, _threadargsproto_) {
139  }
140  static void bbcore_write(double* x, int* d, int* xx, int* offset, _threadargsproto_) {
141  }
142  ENDVERBATIM
143  )";
144 
145  THEN("should succeed") {
146  bool failed = runCompatibilityVisitor(nmodl_text);
147  REQUIRE(!failed);
148  }
149  }
150  GIVEN("A mod file with a no SOLVE method") {
151  std::string const nmodl_text = R"(
152  BREAKPOINT {
153  SOLVE state
154  }
155  )";
156 
157  THEN("should succeed") {
158  bool failed = runCompatibilityVisitor(nmodl_text);
159  REQUIRE(!failed);
160  }
161  }
162  GIVEN("A mod file with a invalid SOLVE method") {
163  std::string const nmodl_text = R"(
164  BREAKPOINT {
165  SOLVE state METHOD runge
166  }
167  )";
168 
169  THEN("should failed") {
170  bool failed = runCompatibilityVisitor(nmodl_text);
171  REQUIRE(failed);
172  }
173  }
174 }
test_utils.hpp
nmodl::parser::NmodlDriver
Class that binds all pieces together for parsing nmodl file.
Definition: nmodl_driver.hpp:67
SCENARIO
SCENARIO("Uncompatible constructs should failed", "[codegen][compatibility_visitor]")
Definition: codegen_compatibility_visitor.cpp:35
perf_visitor.hpp
Visitor for measuring performance related information
nmodl
encapsulates code generation backend implementations
Definition: ast_common.hpp:26
runCompatibilityVisitor
bool runCompatibilityVisitor(const std::string &nmodl_text, const std::string &simulator="coreneuron")
Return true if it failed and false otherwise.
Definition: codegen_compatibility_visitor.cpp:27
program.hpp
Auto generated AST classes declaration.
codegen_compatibility_visitor.hpp
Visitor for printing compatibility issues of the mod file
nmodl::parser::NmodlDriver::parse_string
std::shared_ptr< ast::Program > parse_string(const std::string &input)
parser nmodl provided as string (used for testing)
Definition: nmodl_driver.cpp:89
nmodl_driver.hpp
symtab_visitor.hpp
THIS FILE IS GENERATED AT BUILD TIME AND SHALL NOT BE EDITED.