User Guide
localize.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 
10 #include "ast/program.hpp"
11 #include "parser/nmodl_driver.hpp"
18 
19 using namespace nmodl;
20 using namespace visitor;
21 using namespace test;
22 using namespace test_utils;
23 
25 
26 //=============================================================================
27 // Localizer visitor tests
28 //=============================================================================
29 
30 std::string run_localize_visitor(const std::string& text) {
32  const auto& ast = driver.parse_string(text);
33  SymtabVisitor().visit_program(*ast);
34  InlineVisitor().visit_program(*ast);
35  LocalizeVisitor().visit_program(*ast);
36 
37  std::stringstream stream;
38  NmodlPrintVisitor(stream).visit_program(*ast);
39 
40  // check that, after visitor rearrangement, parents are still up-to-date
41  CheckParentVisitor().check_ast(*ast);
42 
43  return stream.str();
44 }
45 
46 
47 SCENARIO("Localizer test with single global block", "[visitor][localizer]") {
48  GIVEN("Single derivative block with variable definition") {
49  static const std::string nmodl_text = R"(
50  NEURON {
51  RANGE tau
52  }
53 
54  DERIVATIVE states {
55  tau = 11.1
56  exp(tau)
57  }
58  )";
59 
60  static const std::string output_nmodl = R"(
61  NEURON {
62  RANGE tau
63  }
64 
65  DERIVATIVE states {
66  LOCAL tau
67  tau = 11.1
68  exp(tau)
69  }
70  )";
71 
72  THEN("tau variable gets localized") {
73  const std::string input = reindent_text(nmodl_text);
74  auto expected_result = reindent_text(output_nmodl);
75  auto result = run_localize_visitor(input);
76  REQUIRE(result == expected_result);
77  }
78  }
79 }
80 
81 SCENARIO("Localizer test with use of verbatim block", "[visitor][localizer]") {
82  GIVEN("Verbatim block usage in one of the global block") {
83  static const std::string nmodl_text = R"(
84  NEURON {
85  RANGE tau
86  }
87 
88  DERIVATIVE states {
89  tau = 11.1
90  exp(tau)
91  }
92 
93  BREAKPOINT {
94  VERBATIM ENDVERBATIM
95  }
96  )";
97 
98  static const std::string output_nmodl = R"(
99  NEURON {
100  RANGE tau
101  }
102 
103  DERIVATIVE states {
104  tau = 11.1
105  exp(tau)
106  }
107 
108  BREAKPOINT {
109  VERBATIM ENDVERBATIM
110  }
111  )";
112 
113  THEN("Localization is disabled") {
114  static const std::string input = reindent_text(nmodl_text);
115  auto expected_result = reindent_text(output_nmodl);
116  auto result = run_localize_visitor(input);
117  REQUIRE(result == expected_result);
118  }
119  }
120 }
121 
122 
123 SCENARIO("Localizer test with multiple global blocks", "[visitor][localizer]") {
124  GIVEN("Multiple global blocks with definition of variable") {
125  static const std::string nmodl_text = R"(
126  NEURON {
127  RANGE tau, beta
128  }
129 
130  INITIAL {
131  LOCAL tau
132  tau = beta
133  }
134 
135  DERIVATIVE states {
136  tau = 11.1
137  exp(tau)
138  }
139 
140  BREAKPOINT {
141  IF (1) {
142  tau = beta
143  } ELSE {
144  tau = 11
145  }
146 
147  }
148  )";
149 
150  static const std::string output_nmodl = R"(
151  NEURON {
152  RANGE tau, beta
153  }
154 
155  INITIAL {
156  LOCAL tau
157  tau = beta
158  }
159 
160  DERIVATIVE states {
161  LOCAL tau
162  tau = 11.1
163  exp(tau)
164  }
165 
166  BREAKPOINT {
167  LOCAL tau
168  IF (1) {
169  tau = beta
170  } ELSE {
171  tau = 11
172  }
173  }
174  )";
175 
176  THEN("Localization across multiple blocks is done") {
177  const std::string input = reindent_text(nmodl_text);
178  auto expected_result = reindent_text(output_nmodl);
179  auto result = run_localize_visitor(input);
180  REQUIRE(result == expected_result);
181  }
182  }
183 
184 
185  GIVEN("Two global blocks with definition and use of the variable") {
186  static const std::string nmodl_text = R"(
187  NEURON {
188  RANGE tau
189  }
190 
191  DERIVATIVE states {
192  tau = 11.1
193  }
194 
195  BREAKPOINT {
196  IF (1) {
197  tau = 22
198  } ELSE {
199  tau = exp(tau) + 11
200  }
201 
202  }
203  )";
204 
205  static const std::string output_nmodl = R"(
206  NEURON {
207  RANGE tau
208  }
209 
210  DERIVATIVE states {
211  tau = 11.1
212  }
213 
214  BREAKPOINT {
215  IF (1) {
216  tau = 22
217  } ELSE {
218  tau = exp(tau)+11
219  }
220  }
221  )";
222 
223  THEN("Localization is not done due to use of variable") {
224  const std::string input = reindent_text(nmodl_text);
225  auto expected_result = reindent_text(output_nmodl);
226  auto result = run_localize_visitor(input);
227  REQUIRE(result == expected_result);
228  }
229  }
230 }
test_utils.hpp
nmodl::parser::NmodlDriver
Class that binds all pieces together for parsing nmodl file.
Definition: nmodl_driver.hpp:67
localize_visitor.hpp
Visitor to transform global variable usage to local
nmodl::test_utils::reindent_text
std::string reindent_text(const std::string &text, int indent_level)
Reindent nmodl text for text-to-text comparison.
Definition: test_utils.cpp:53
nmodl
encapsulates code generation backend implementations
Definition: ast_common.hpp:26
program.hpp
Auto generated AST classes declaration.
driver
nmodl::parser::UnitDriver driver
Definition: parser.cpp:28
nmodl::parser::UnitDriver::parse_string
bool parse_string(const std::string &input)
parser Units provided as string (used for testing)
Definition: unit_driver.cpp:40
SCENARIO
SCENARIO("Localizer test with single global block", "[visitor][localizer]")
Definition: localize.cpp:47
run_localize_visitor
std::string run_localize_visitor(const std::string &text)
Definition: localize.cpp:30
checkparent_visitor.hpp
Visitor for checking parents of ast nodes
inline_visitor.hpp
Visitor to inline local procedure and function calls
nmodl_driver.hpp
symtab_visitor.hpp
THIS FILE IS GENERATED AT BUILD TIME AND SHALL NOT BE EDITED.
nmodl_visitor.hpp
THIS FILE IS GENERATED AT BUILD TIME AND SHALL NOT BE EDITED.