From 7e91888bed25ecea6b6b3671521808b6ece4e967 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 9 Nov 2023 10:00:29 +0100 Subject: [PATCH 1/3] SemanticAnalysisVisitor: detect if several solve blocks are given --- src/visitors/semantic_analysis_visitor.cpp | 20 ++++++++++++++++++++ src/visitors/semantic_analysis_visitor.hpp | 8 ++++++++ 2 files changed, 28 insertions(+) diff --git a/src/visitors/semantic_analysis_visitor.cpp b/src/visitors/semantic_analysis_visitor.cpp index 40d6b1667..558dbf7e3 100644 --- a/src/visitors/semantic_analysis_visitor.cpp +++ b/src/visitors/semantic_analysis_visitor.cpp @@ -6,6 +6,7 @@ */ #include "visitors/semantic_analysis_visitor.hpp" +#include "ast/breakpoint_block.hpp" #include "ast/function_block.hpp" #include "ast/function_table_block.hpp" #include "ast/independent_block.hpp" @@ -170,5 +171,24 @@ void SemanticAnalysisVisitor::visit_mutex_unlock(const ast::MutexUnlock& /* node /// --> } +void SemanticAnalysisVisitor::visit_breakpoint_block(const ast::BreakpointBlock& node) { + /// <-- This code is for check 8 + solve_block_found_in_this_breakpoint_block = false; + node.visit_children(*this); + solve_block_found_in_this_breakpoint_block = false; + /// --> +} + +void SemanticAnalysisVisitor::visit_solve_block(const ast::SolveBlock& /* node */) { + /// <-- This code is for check 8 + if (solve_block_found_in_this_breakpoint_block) { + logger->critical("It is not allowed to have several solve blocks in the same breakpoint block"); + check_fail = true; + } else { + solve_block_found_in_this_breakpoint_block = true; + } + /// --> +} + } // namespace visitor } // namespace nmodl diff --git a/src/visitors/semantic_analysis_visitor.hpp b/src/visitors/semantic_analysis_visitor.hpp index 1deffcb15..f51b10dfe 100644 --- a/src/visitors/semantic_analysis_visitor.hpp +++ b/src/visitors/semantic_analysis_visitor.hpp @@ -31,6 +31,7 @@ * 5. Check if an independent variable is not 't'. * 6. Check that mutex are not badly use * 7. Check than function table got at least one argument. + * 8. Check that at most one solve block is present per breakpoint block. */ #include "ast/ast.hpp" #include "visitors/ast_visitor.hpp" @@ -54,6 +55,8 @@ class SemanticAnalysisVisitor: public ConstAstVisitor { bool is_point_process = false; /// true if we are inside a mutex locked part bool in_mutex = false; + /// true if we already found a solve block + bool solve_block_found_in_this_breakpoint_block = false; /// Store if we are in a procedure and if the arity of this is 1 void visit_procedure_block(const ast::ProcedureBlock& node) override; @@ -82,6 +85,11 @@ class SemanticAnalysisVisitor: public ConstAstVisitor { /// Look if MUTEXUNLOCK is outside a locked block void visit_mutex_unlock(const ast::MutexUnlock& node) override; + void visit_breakpoint_block(const ast::BreakpointBlock& node) override; + + /// Check how many solve block we got + void visit_solve_block(const ast::SolveBlock& node) override; + public: SemanticAnalysisVisitor(bool accel_backend = false) : accel_backend(accel_backend) {} From f491ac3735eae798e9ceae0fcf5997bcb0b2efd9 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 9 Nov 2023 10:55:37 +0100 Subject: [PATCH 2/3] Format --- src/visitors/semantic_analysis_visitor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/visitors/semantic_analysis_visitor.cpp b/src/visitors/semantic_analysis_visitor.cpp index 558dbf7e3..365fac7ad 100644 --- a/src/visitors/semantic_analysis_visitor.cpp +++ b/src/visitors/semantic_analysis_visitor.cpp @@ -182,7 +182,8 @@ void SemanticAnalysisVisitor::visit_breakpoint_block(const ast::BreakpointBlock& void SemanticAnalysisVisitor::visit_solve_block(const ast::SolveBlock& /* node */) { /// <-- This code is for check 8 if (solve_block_found_in_this_breakpoint_block) { - logger->critical("It is not allowed to have several solve blocks in the same breakpoint block"); + logger->critical( + "It is not allowed to have several solve blocks in the same breakpoint block"); check_fail = true; } else { solve_block_found_in_this_breakpoint_block = true; From 175f89de3fa5aed5440dda45a3e6c1d90e991c23 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 9 Nov 2023 11:49:14 +0100 Subject: [PATCH 3/3] Add tests --- test/unit/visitor/semantic_analysis.cpp | 38 +++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/unit/visitor/semantic_analysis.cpp b/test/unit/visitor/semantic_analysis.cpp index 23c58d266..0d51aeb75 100644 --- a/test/unit/visitor/semantic_analysis.cpp +++ b/test/unit/visitor/semantic_analysis.cpp @@ -165,3 +165,41 @@ SCENARIO("FUNCTION_TABLE block", "[visitor][semantic_analysis]") { } } } + + +SCENARIO("At most one solve block per breakpoint block", "[visitor][semantic_analysis]") { + GIVEN("A breakpoint block with only one solve block") { + std::string nmodl_text = R"( + BREAKPOINT { + SOLVE dX METHOD cnexp + } + )"; + THEN("Semantic analysis should success") { + REQUIRE_FALSE(run_semantic_analysis_visitor(nmodl_text)); + } + } + GIVEN("2 breakpoints block with one solve block each") { + std::string nmodl_text = R"( + PROCEDURE foo() { + SOLVE dX METHOD cnexp + } + BREAKPOINT { + SOLVE dY METHOD cnexp + } + )"; + THEN("Semantic analysis should success") { + REQUIRE_FALSE(run_semantic_analysis_visitor(nmodl_text)); + } + } + GIVEN("A breakpoint block with two solve blocks") { + std::string nmodl_text = R"( + BREAKPOINT { + SOLVE dX METHOD cnexp + SOLVE dY METHOD cnexp + } + )"; + THEN("Semantic analysis should fail") { + REQUIRE(run_semantic_analysis_visitor(nmodl_text)); + } + } +}