Skip to content

Commit 1f8b49a

Browse files
author
Goran Jelic-Cizmek
committed
Generalize InitialBlockVisitor
- use a template - add same visitor for BREAKPOINT block - add tests
1 parent 28d3612 commit 1f8b49a

8 files changed

Lines changed: 281 additions & 212 deletions

File tree

src/nmodl/main.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
#include "visitors/cvode_visitor.hpp"
2929
#include "visitors/function_callpath_visitor.hpp"
3030
#include "visitors/global_var_visitor.hpp"
31-
#include "visitors/initial_block_visitor.hpp"
3231
#include "visitors/implicit_argument_visitor.hpp"
3332
#include "visitors/indexedname_visitor.hpp"
3433
#include "visitors/inline_visitor.hpp"
@@ -39,6 +38,7 @@
3938
#include "visitors/localize_visitor.hpp"
4039
#include "visitors/longitudinal_diffusion_visitor.hpp"
4140
#include "visitors/loop_unroll_visitor.hpp"
41+
#include "visitors/merge_top_level_blocks_visitor.hpp"
4242
#include "visitors/neuron_solve_visitor.hpp"
4343
#include "visitors/nmodl_visitor.hpp"
4444
#include "visitors/perf_visitor.hpp"
@@ -347,10 +347,19 @@ int run_nmodl(int argc, const char* argv[]) {
347347
/// merge all INITIAL blocks into one (this needs to run before SymtabVisitor)
348348
{
349349
logger->info("Running INITIAL block merge visitor");
350-
MergeInitialBlocksVisitor().visit_program(*ast);
350+
MergeTopLevelBlocksVisitor<ast::InitialBlock, ast::AstNodeType::INITIAL_BLOCK>()
351+
.visit_program(*ast);
351352
ast_to_nmodl(*ast, filepath("merge_initial_block"));
352353
}
353354

355+
/// merge all BREAKPOINT blocks into one (this needs to run before SymtabVisitor)
356+
{
357+
logger->info("Running BREAKPOINT block merge visitor");
358+
MergeTopLevelBlocksVisitor<ast::BreakpointBlock, ast::AstNodeType::BREAKPOINT_BLOCK>()
359+
.visit_program(*ast);
360+
ast_to_nmodl(*ast, filepath("merge_breakpoint_block"));
361+
}
362+
354363
/// construct symbol table
355364
{
356365
logger->info("Running symtab visitor");

src/nmodl/visitors/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ add_library(
2828
neuron_solve_visitor.cpp
2929
perf_visitor.cpp
3030
rename_visitor.cpp
31-
initial_block_visitor.cpp
3231
rename_function_arguments.cpp
3332
semantic_analysis_visitor.cpp
3433
solve_block_visitor.cpp

src/nmodl/visitors/initial_block_visitor.cpp

Lines changed: 0 additions & 53 deletions
This file was deleted.

src/nmodl/visitors/initial_block_visitor.hpp

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2025 EPFL.
3+
* See the top-level LICENSE file for details.
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#pragma once
9+
10+
/**
11+
* \file
12+
* \brief \copybrief nmodl::visitor::MergeTopLevelBlocksVisitor
13+
*/
14+
15+
#include "visitors/ast_visitor.hpp"
16+
17+
#include "visitors/visitor_utils.hpp"
18+
19+
namespace nmodl {
20+
namespace visitor {
21+
22+
/**
23+
* \addtogroup visitor_classes
24+
* \{
25+
*/
26+
27+
/**
28+
* \class MergeTopLevelBlocksVisitor
29+
* \brief Visitor which merges given top-level blocks into one
30+
*/
31+
template <typename ast_class, ast::AstNodeType ast_type>
32+
class MergeTopLevelBlocksVisitor: public AstVisitor {
33+
public:
34+
MergeTopLevelBlocksVisitor() = default;
35+
void visit_program(ast::Program& node) override {
36+
// check if there is > 1 blocks in total
37+
if (collect_nodes(node, {ast_type}).size() <= 1) {
38+
return;
39+
}
40+
41+
// collect all top-level blocks in the program
42+
const auto& blocks = node.get_blocks();
43+
logger->info("Collecting blocks of type {}", typeid(ast_class).name());
44+
45+
// collect all statements from top-level blocks, and the blocks themselves
46+
ast::StatementVector statements;
47+
std::unordered_set<ast::Node*> blocks_to_delete;
48+
for (auto& block: blocks) {
49+
auto temp_block = std::dynamic_pointer_cast<ast_class>(block);
50+
// check if it's the correct type
51+
if (temp_block) {
52+
auto statement_block = temp_block->get_statement_block();
53+
// if block is not empty, copy statements into vector
54+
if (statement_block) {
55+
for (const auto& statement: statement_block->get_statements()) {
56+
statements.push_back(statement);
57+
}
58+
}
59+
blocks_to_delete.insert(block.get());
60+
}
61+
}
62+
63+
// insert new top-level block which has the above statements
64+
auto new_block = ast::StatementBlock(statements);
65+
auto new_initial_block = ast_class(new_block.clone());
66+
node.emplace_back_node(new_initial_block.clone());
67+
68+
// delete all of the previously-found top-level blocks
69+
node.erase_node(blocks_to_delete);
70+
}
71+
};
72+
73+
/** \} */ // end of visitor_classes
74+
75+
} // namespace visitor
76+
} // namespace nmodl

test/nmodl/transpiler/unit/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ add_executable(
4848
visitor/global_to_range.cpp
4949
visitor/implicit_argument.cpp
5050
visitor/inline.cpp
51-
visitor/initial_block.cpp
5251
visitor/json.cpp
5352
visitor/kinetic_block.cpp
5453
visitor/localize.cpp
@@ -57,6 +56,7 @@ add_executable(
5756
visitor/local_to_assigned.cpp
5857
visitor/lookup.cpp
5958
visitor/loop_unroll.cpp
59+
visitor/merge_top_level_blocks.cpp
6060
visitor/misc.cpp
6161
visitor/neuron_solve.cpp
6262
visitor/nmodl.cpp

test/nmodl/transpiler/unit/visitor/initial_block.cpp

Lines changed: 0 additions & 118 deletions
This file was deleted.

0 commit comments

Comments
 (0)