User Guide
constant_folder.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"
17 
18 using namespace nmodl;
19 using namespace visitor;
20 using namespace test;
21 using namespace test_utils;
22 
24 
25 //=============================================================================
26 // Constant folding tests
27 //=============================================================================
28 
29 std::string run_constant_folding_visitor(const std::string& text) {
31  const auto& ast = driver.parse_string(text);
32 
33  SymtabVisitor().visit_program(*ast);
34  ConstantFolderVisitor().visit_program(*ast);
35 
36  std::stringstream stream;
37  NmodlPrintVisitor(stream).visit_program(*ast);
38 
39  // check that, after visitor rearrangement, parents are still up-to-date
40  CheckParentVisitor().check_ast(*ast);
41 
42  return stream.str();
43 }
44 
45 SCENARIO("Perform constant folder on NMODL constructs") {
46  GIVEN("Simple integer expression") {
47  std::string nmodl_text = R"(
48  PROCEDURE dummy() {
49  a = 1 + 2
50  }
51  )";
52  std::string expected_text = R"(
53  PROCEDURE dummy() {
54  a = 3
55  }
56  )";
57  THEN("successfully folds") {
58  auto result = run_constant_folding_visitor(nmodl_text);
59  REQUIRE(reindent_text(result) == reindent_text(expected_text));
60  }
61  }
62 
63  GIVEN("Simple double expression") {
64  std::string nmodl_text = R"(
65  PROCEDURE dummy() {
66  a = 1.1 + 2e-10
67  }
68  )";
69  std::string expected_text = R"(
70  PROCEDURE dummy() {
71  a = 1.1000000002
72  }
73  )";
74  THEN("successfully folds") {
75  auto result = run_constant_folding_visitor(nmodl_text);
76  REQUIRE(reindent_text(result) == reindent_text(expected_text));
77  }
78  }
79 
80  GIVEN("Complex expression") {
81  std::string nmodl_text = R"(
82  PROCEDURE dummy() {
83  a = 1 + (2) + (2 / 2) + (((1+((2)))))
84  }
85  )";
86  std::string expected_text = R"(
87  PROCEDURE dummy() {
88  a = 7
89  }
90  )";
91  THEN("successfully folds") {
92  auto result = run_constant_folding_visitor(nmodl_text);
93  REQUIRE(reindent_text(result) == reindent_text(expected_text));
94  }
95  }
96 
97  GIVEN("Integer expression with define statement") {
98  std::string nmodl_text = R"(
99  DEFINE N 10
100 
101  PROCEDURE dummy() {
102  a = N + (2*N) + (N / 2) + (((1+((N)))))
103  FROM i = 0 TO N-2 {
104  }
105  }
106  )";
107  std::string expected_text = R"(
108  DEFINE N 10
109 
110  PROCEDURE dummy() {
111  a = 46
112  FROM i = 0 TO 8 {
113  }
114  }
115  )";
116  THEN("successfully folds") {
117  auto result = run_constant_folding_visitor(nmodl_text);
118  REQUIRE(reindent_text(result) == reindent_text(expected_text));
119  }
120  }
121 
122  GIVEN("Only fold part of the statement") {
123  std::string nmodl_text = R"(
124  DEFINE N 10
125 
126  PROCEDURE dummy() {
127  a = N + 2.0 + b
128  c = a + d
129  d = 2^3
130  e = 2 || 3
131  }
132  )";
133  std::string expected_text = R"(
134  DEFINE N 10
135 
136  PROCEDURE dummy() {
137  a = 12+b
138  c = a+d
139  d = 2^3
140  e = 2 || 3
141  }
142  )";
143  THEN("successfully folds and keep other statements untouched") {
144  auto result = run_constant_folding_visitor(nmodl_text);
145  REQUIRE(reindent_text(result) == reindent_text(expected_text));
146  }
147  }
148 
149  GIVEN("Don't remove parentheses if not simplifying") {
150  std::string nmodl_text = R"(
151  DEFINE N 10
152 
153  PROCEDURE dummy() {
154  a = ((N+1)+5)*(c+1+N)/(b - 2)
155  }
156  )";
157  std::string expected_text = R"(
158  DEFINE N 10
159 
160  PROCEDURE dummy() {
161  a = 16*(c+1+10)/(b-2)
162  }
163  )";
164  THEN("successfully folds and keep other statements untouched") {
165  auto result = run_constant_folding_visitor(nmodl_text);
166  REQUIRE(reindent_text(result) == reindent_text(expected_text));
167  }
168  }
169 }
test_utils.hpp
nmodl::parser::NmodlDriver
Class that binds all pieces together for parsing nmodl file.
Definition: nmodl_driver.hpp:67
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
constant_folder_visitor.hpp
Perform constant folding of integer/float/double expressions.
program.hpp
Auto generated AST classes declaration.
driver
nmodl::parser::UnitDriver driver
Definition: parser.cpp:28
SCENARIO
SCENARIO("Perform constant folder on NMODL constructs")
Definition: constant_folder.cpp:45
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
run_constant_folding_visitor
std::string run_constant_folding_visitor(const std::string &text)
Definition: constant_folder.cpp:29
checkparent_visitor.hpp
Visitor for checking parents of ast nodes
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.