From 67b4fac378aa035b24a41ebd8d0ed1d9629cf1e8 Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Mon, 29 Jul 2019 19:20:02 +0200 Subject: [PATCH] Begin ASTNodeExpressionBuilder tests --- src/language/ASTNode.hpp | 8 +- .../ASTNodeAffectationExpressionBuilder.cpp | 42 ++++--- ...ASTNodeBinaryOperatorExpressionBuilder.cpp | 32 +++-- src/language/ASTNodeExpressionBuilder.cpp | 92 +++++++++++--- .../ASTNodeIncDecExpressionBuilder.cpp | 23 ++-- .../ASTNodeUnaryOperatorExpressionBuilder.cpp | 15 ++- src/language/ASTPrinter.cpp | 13 +- src/language/ASTPrinter.hpp | 1 + src/language/CMakeLists.txt | 3 +- tests/CMakeLists.txt | 2 +- tests/test_ASTNodeExpressionBuilder.cpp | 113 ++++++++++++++---- 11 files changed, 268 insertions(+), 76 deletions(-) diff --git a/src/language/ASTNode.hpp b/src/language/ASTNode.hpp index 54e47efc3..53d20e687 100644 --- a/src/language/ASTNode.hpp +++ b/src/language/ASTNode.hpp @@ -56,11 +56,13 @@ class INodeProcessor public: virtual void execute(ExecUntilBreakOrContinue& exec_policy) = 0; - INodeProcessor(const INodeProcessor& node) = delete; + virtual std::string describe() const = 0; - INodeProcessor() {} + INodeProcessor(const INodeProcessor&) = delete; - virtual ~INodeProcessor() {} + INodeProcessor() = default; + + virtual ~INodeProcessor() = default; }; class SymbolTable; diff --git a/src/language/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ASTNodeAffectationExpressionBuilder.cpp index 89a86a295..5eaa3f785 100644 --- a/src/language/ASTNodeAffectationExpressionBuilder.cpp +++ b/src/language/ASTNodeAffectationExpressionBuilder.cpp @@ -2,6 +2,8 @@ #include <PEGGrammar.hpp> #include <SymbolTable.hpp> +#include <Demangle.hpp> + template <typename Op> struct AffOp; @@ -77,16 +79,10 @@ class AffectationProcessor final : public INodeProcessor }()}; public: - AffectationProcessor(ASTNode& node) : m_node{node} + std::string + describe() const { - if constexpr (_is_defined) { - const std::string& symbol = m_node.children[0]->string(); - auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin()); - Assert(found); - p_value = &i_symbol->second.value(); - } else { - throw parse_error("invalid operands to binary expression", std::vector{m_node.begin()}); - } + return demangle<decltype(*this)>(); } void @@ -106,6 +102,18 @@ class AffectationProcessor final : public INodeProcessor } } } + + AffectationProcessor(ASTNode& node) : m_node{node} + { + if constexpr (_is_defined) { + const std::string& symbol = m_node.children[0]->string(); + auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin()); + Assert(found); + p_value = &i_symbol->second.value(); + } else { + throw parse_error("invalid operands to binary expression", std::vector{m_node.begin()}); + } + } }; template <typename OperatorT, typename DataT> @@ -116,12 +124,10 @@ class AffectationToStringProcessor final : public INodeProcessor ASTNodeDataVariant* p_value{nullptr}; public: - AffectationToStringProcessor(ASTNode& node) : m_node{node} + std::string + describe() const { - const std::string& symbol = m_node.children[0]->string(); - auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin()); - Assert(found); - p_value = &i_symbol->second.value(); + return demangle<decltype(*this)>(); } void @@ -143,6 +149,14 @@ class AffectationToStringProcessor final : public INodeProcessor } } } + + AffectationToStringProcessor(ASTNode& node) : m_node{node} + { + const std::string& symbol = m_node.children[0]->string(); + auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin()); + Assert(found); + p_value = &i_symbol->second.value(); + } }; ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode& n) diff --git a/src/language/ASTNodeBinaryOperatorExpressionBuilder.cpp b/src/language/ASTNodeBinaryOperatorExpressionBuilder.cpp index 8309bf1b4..496668c57 100644 --- a/src/language/ASTNodeBinaryOperatorExpressionBuilder.cpp +++ b/src/language/ASTNodeBinaryOperatorExpressionBuilder.cpp @@ -2,6 +2,8 @@ #include <PEGGrammar.hpp> #include <SymbolTable.hpp> +#include <Demangle.hpp> + #include <type_traits> template <typename Op> @@ -156,7 +158,7 @@ class BinaryExpressionProcessor final : public INodeProcessor ASTNode& m_node; PUGS_INLINE auto - eval(const ASTNodeDataVariant& a, const ASTNodeDataVariant& b, ASTNodeDataVariant& value) + _eval(const ASTNodeDataVariant& a, const ASTNodeDataVariant& b, ASTNodeDataVariant& value) { // Add 'signed' when necessary to avoid signed/unsigned comparison warnings if constexpr ((not(std::is_same_v<A_DataT, bool> or std::is_same_v<B_DataT, bool>)) and @@ -194,11 +196,10 @@ class BinaryExpressionProcessor final : public INodeProcessor }()}; public: - BinaryExpressionProcessor(ASTNode& node) : m_node{node} + std::string + describe() const { - if constexpr (not _is_defined) { - throw parse_error("invalid operands to binary expression", std::vector{m_node.begin()}); - } + return demangle<decltype(*this)>(); } void @@ -208,7 +209,14 @@ class BinaryExpressionProcessor final : public INodeProcessor m_node.children[0]->execute(exec_policy); m_node.children[1]->execute(exec_policy); - this->eval(m_node.children[0]->m_value, m_node.children[1]->m_value, m_node.m_value); + this->_eval(m_node.children[0]->m_value, m_node.children[1]->m_value, m_node.m_value); + } + } + + BinaryExpressionProcessor(ASTNode& node) : m_node{node} + { + if constexpr (not _is_defined) { + throw parse_error("invalid operands to binary expression", std::vector{m_node.begin()}); } } }; @@ -219,7 +227,7 @@ class ConcatExpressionProcessor final : public INodeProcessor ASTNode& m_node; PUGS_INLINE auto - eval(const std::string& a, const ASTNodeDataVariant& b, ASTNodeDataVariant& value) + _eval(const std::string& a, const ASTNodeDataVariant& b, ASTNodeDataVariant& value) { if constexpr (std::is_same_v<B_DataT, std::string>) { value = a + std::get<B_DataT>(b); @@ -229,7 +237,11 @@ class ConcatExpressionProcessor final : public INodeProcessor } public: - ConcatExpressionProcessor(ASTNode& node) : m_node{node} {} + std::string + describe() const + { + return demangle<decltype(*this)>(); + } void execute(ExecUntilBreakOrContinue& exec_policy) @@ -237,8 +249,10 @@ class ConcatExpressionProcessor final : public INodeProcessor m_node.children[0]->execute(exec_policy); m_node.children[1]->execute(exec_policy); - this->eval(std::get<std::string>(m_node.children[0]->m_value), m_node.children[1]->m_value, m_node.m_value); + this->_eval(std::get<std::string>(m_node.children[0]->m_value), m_node.children[1]->m_value, m_node.m_value); } + + ConcatExpressionProcessor(ASTNode& node) : m_node{node} {} }; ASTNodeBinaryOperatorExpressionBuilder::ASTNodeBinaryOperatorExpressionBuilder(ASTNode& n) diff --git a/src/language/ASTNodeExpressionBuilder.cpp b/src/language/ASTNodeExpressionBuilder.cpp index 93068490c..5c07d1d5e 100644 --- a/src/language/ASTNodeExpressionBuilder.cpp +++ b/src/language/ASTNodeExpressionBuilder.cpp @@ -8,12 +8,18 @@ #include <PEGGrammar.hpp> #include <SymbolTable.hpp> +#include <Demangle.hpp> + class ASTNodeList final : public INodeProcessor { ASTNode& m_node; public: - ASTNodeList(ASTNode& node) : m_node{node} {} + std::string + describe() const + { + return demangle<decltype(*this)>(); + } void execute(ExecUntilBreakOrContinue& exec_policy) @@ -22,12 +28,18 @@ class ASTNodeList final : public INodeProcessor child->execute(exec_policy); } } + + ASTNodeList(ASTNode& node) : m_node{node} {} }; class NoProcess final : public INodeProcessor { public: - NoProcess() {} + std::string + describe() const + { + return demangle<decltype(*this)>(); + } PUGS_INLINE void @@ -35,6 +47,8 @@ class NoProcess final : public INodeProcessor { ; } + + NoProcess() = default; }; class IfStatement final : public INodeProcessor @@ -42,7 +56,11 @@ class IfStatement final : public INodeProcessor ASTNode& m_node; public: - IfStatement(ASTNode& node) : m_node{node} {} + std::string + describe() const + { + return demangle<decltype(*this)>(); + } void execute(ExecUntilBreakOrContinue& exec_policy) @@ -69,6 +87,8 @@ class IfStatement final : public INodeProcessor } } } + + IfStatement(ASTNode& node) : m_node{node} {} }; class DoWhileStatement final : public INodeProcessor @@ -76,7 +96,11 @@ class DoWhileStatement final : public INodeProcessor ASTNode& m_node; public: - DoWhileStatement(ASTNode& node) : m_node{node} {} + std::string + describe() const + { + return demangle<decltype(*this)>(); + } void execute(ExecUntilBreakOrContinue& exec_policy) @@ -105,6 +129,8 @@ class DoWhileStatement final : public INodeProcessor m_node.children[1]->m_value)); } while (continuation_test); } + + DoWhileStatement(ASTNode& node) : m_node{node} {} }; class WhileStatement final : public INodeProcessor @@ -112,7 +138,11 @@ class WhileStatement final : public INodeProcessor ASTNode& m_node; public: - WhileStatement(ASTNode& node) : m_node{node} {} + std::string + describe() const + { + return demangle<decltype(*this)>(); + } void execute(ExecUntilBreakOrContinue& exec_policy) @@ -141,6 +171,8 @@ class WhileStatement final : public INodeProcessor } } } + + WhileStatement(ASTNode& node) : m_node{node} {} }; class ForStatement final : public INodeProcessor @@ -148,7 +180,11 @@ class ForStatement final : public INodeProcessor ASTNode& m_node; public: - ForStatement(ASTNode& node) : m_node{node} {} + std::string + describe() const + { + return demangle<decltype(*this)>(); + } void execute(ExecUntilBreakOrContinue& exec_policy) @@ -180,6 +216,8 @@ class ForStatement final : public INodeProcessor m_node.children[2]->execute(exec_policy); } } + + ForStatement(ASTNode& node) : m_node{node} {} }; class NameExpression final : public INodeProcessor @@ -188,12 +226,10 @@ class NameExpression final : public INodeProcessor ASTNodeDataVariant* p_value{nullptr}; public: - NameExpression(ASTNode& node) : m_node{node} + std::string + describe() const { - const std::string& symbol = m_node.string(); - auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.begin()); - Assert(found); - p_value = &(i_symbol->second.value()); + return demangle<decltype(*this)>(); } void @@ -201,30 +237,50 @@ class NameExpression final : public INodeProcessor { m_node.m_value = *p_value; } + + NameExpression(ASTNode& node) : m_node{node} + { + const std::string& symbol = m_node.string(); + auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.begin()); + Assert(found); + p_value = &(i_symbol->second.value()); + } }; class BreakExpression final : public INodeProcessor { public: - BreakExpression() {} + std::string + describe() const + { + return demangle<decltype(*this)>(); + } void execute(ExecUntilBreakOrContinue& exec_policy) { exec_policy = ExecUntilBreakOrContinue(ExecUntilBreakOrContinue::JumpType::break_jump); } + + BreakExpression() = default; }; class ContinueExpression final : public INodeProcessor { public: - ContinueExpression() {} + std::string + describe() const + { + return demangle<decltype(*this)>(); + } void execute(ExecUntilBreakOrContinue& exec_policy) { exec_policy = ExecUntilBreakOrContinue(ExecUntilBreakOrContinue::JumpType::continue_jump); } + + ContinueExpression() = default; }; class OStreamObject final : public INodeProcessor @@ -233,9 +289,10 @@ class OStreamObject final : public INodeProcessor std::ostream& m_os; public: - OStreamObject(ASTNode& node, std::ostream& os) : m_node{node}, m_os(os) + std::string + describe() const { - ; + return demangle<decltype(*this)>(); } void @@ -257,6 +314,11 @@ class OStreamObject final : public INodeProcessor m_node.children[i]->m_value); } } + + OStreamObject(ASTNode& node, std::ostream& os) : m_node{node}, m_os(os) + { + ; + } }; void diff --git a/src/language/ASTNodeIncDecExpressionBuilder.cpp b/src/language/ASTNodeIncDecExpressionBuilder.cpp index cae715aef..485c5d653 100644 --- a/src/language/ASTNodeIncDecExpressionBuilder.cpp +++ b/src/language/ASTNodeIncDecExpressionBuilder.cpp @@ -2,6 +2,8 @@ #include <PEGGrammar.hpp> #include <SymbolTable.hpp> +#include <Demangle.hpp> + template <typename Op> struct IncDecOp; @@ -66,6 +68,20 @@ class IncDecExpressionProcessor final : public INodeProcessor }()}; public: + std::string + describe() const + { + return demangle<decltype(*this)>(); + } + + void + execute(ExecUntilBreakOrContinue&) + { + if constexpr (_is_defined) { + m_node.m_value = IncDecOp<IncDecOpT>().eval(std::get<DataT>(*p_value)); + } + } + IncDecExpressionProcessor(ASTNode& node) : m_node{node} { if constexpr (_is_defined) { @@ -79,13 +95,6 @@ class IncDecExpressionProcessor final : public INodeProcessor throw parse_error("invalid operand to unary operator", std::vector{m_node.begin()}); } } - void - execute(ExecUntilBreakOrContinue&) - { - if constexpr (_is_defined) { - m_node.m_value = IncDecOp<IncDecOpT>().eval(std::get<DataT>(*p_value)); - } - } }; ASTNodeIncDecExpressionBuilder::ASTNodeIncDecExpressionBuilder(ASTNode& n) diff --git a/src/language/ASTNodeUnaryOperatorExpressionBuilder.cpp b/src/language/ASTNodeUnaryOperatorExpressionBuilder.cpp index 9112ad553..8d70f9f65 100644 --- a/src/language/ASTNodeUnaryOperatorExpressionBuilder.cpp +++ b/src/language/ASTNodeUnaryOperatorExpressionBuilder.cpp @@ -2,6 +2,8 @@ #include <PEGGrammar.hpp> #include <SymbolTable.hpp> +#include <Demangle.hpp> + template <typename Op> struct UnaryOp; @@ -32,22 +34,27 @@ class UnaryExpressionProcessor final : public INodeProcessor { ASTNode& m_node; - public: PUGS_INLINE ValueT - eval(const ASTNodeDataVariant& a) + _eval(const ASTNodeDataVariant& a) { return UnaryOp<UnaryOpT>().eval(std::get<DataT>(a)); } public: - UnaryExpressionProcessor(ASTNode& node) : m_node{node} {} + std::string + describe() const + { + return demangle<decltype(*this)>(); + } void execute(ExecUntilBreakOrContinue& exec_policy) { m_node.children[0]->execute(exec_policy); - m_node.m_value = eval(m_node.children[0]->m_value); + m_node.m_value = this->_eval(m_node.children[0]->m_value); } + + UnaryExpressionProcessor(ASTNode& node) : m_node{node} {} }; ASTNodeUnaryOperatorExpressionBuilder::ASTNodeUnaryOperatorExpressionBuilder(ASTNode& n) diff --git a/src/language/ASTPrinter.cpp b/src/language/ASTPrinter.cpp index 3f5b7344a..84e03e38f 100644 --- a/src/language/ASTPrinter.cpp +++ b/src/language/ASTPrinter.cpp @@ -39,8 +39,19 @@ ASTPrinter::_print(std::ostream& os, const ASTNode& node) const } }, node.m_value); + os << rang::fg::reset; } - os << rang::fg::reset << ")\n"; + + if (m_info & static_cast<InfoBaseType>(Info::exec_type)) { + if (node.m_node_processor) { + os << ':'; + os << rang::fgB::magenta; + os << node.m_node_processor->describe(); + os << rang::fg::reset; + } + } + + os << ")\n"; if (not node.children.empty()) { _print(os, node.children); diff --git a/src/language/ASTPrinter.hpp b/src/language/ASTPrinter.hpp index 464a67435..d8eb0802a 100644 --- a/src/language/ASTPrinter.hpp +++ b/src/language/ASTPrinter.hpp @@ -19,6 +19,7 @@ class ASTPrinter none = 0, data_type = 1 << 0, data_value = 1 << 1, + exec_type = 1 << 2, all = std::numeric_limits<InfoBaseType>::max() }; diff --git a/src/language/CMakeLists.txt b/src/language/CMakeLists.txt index 3333d9b76..7b440e23e 100644 --- a/src/language/CMakeLists.txt +++ b/src/language/CMakeLists.txt @@ -27,4 +27,5 @@ add_library( #include_directories(${PUGS_SOURCE_DIR}/utils) # Additional dependencies -#add_dependencies(PugsMesh) +add_dependencies(PugsLanguage + PugsUtils) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 29d77d5d0..569578559 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -32,8 +32,8 @@ add_executable (mpi_unit_tests ) target_link_libraries (unit_tests - PugsUtils PugsLanguage + PugsUtils kokkos Catch2 ) diff --git a/tests/test_ASTNodeExpressionBuilder.cpp b/tests/test_ASTNodeExpressionBuilder.cpp index 2ce02e86e..b7a6c82a1 100644 --- a/tests/test_ASTNodeExpressionBuilder.cpp +++ b/tests/test_ASTNodeExpressionBuilder.cpp @@ -14,26 +14,29 @@ #include <ASTPrinter.hpp> -#define CHECK_AST(data, expected_output) \ - { \ - static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>); \ - static_assert(std::is_same_v<std::decay_t<decltype(expected_output)>, std::string_view>); \ - \ - string_input input{data, "test.pgs"}; \ - auto ast = ASTBuilder::build(input); \ - \ - ASTSymbolTableBuilder{*ast}; \ - ASTNodeDataTypeBuilder{*ast}; \ - ASTNodeValueBuilder{*ast}; \ - \ - ASTNodeDeclarationToAffectationConverter{*ast}; \ - ASTNodeDeclarationCleaner{*ast}; \ - \ - ASTNodeExpressionBuilder{*ast}; \ - std::stringstream ast_output; \ - ast_output << '\n' << ASTPrinter{*ast, ASTPrinter::Format::raw, {ASTPrinter::Info::none}}; \ - \ - REQUIRE(ast_output.str() == expected_output); \ +#include <Demangle.hpp> + +#define CHECK_AST(data, expected_output) \ + { \ + static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>); \ + static_assert((std::is_same_v<std::decay_t<decltype(expected_output)>, std::string_view>) or \ + (std::is_same_v<std::decay_t<decltype(expected_output)>, std::string>)); \ + \ + string_input input{data, "test.pgs"}; \ + auto ast = ASTBuilder::build(input); \ + \ + ASTSymbolTableBuilder{*ast}; \ + ASTNodeDataTypeBuilder{*ast}; \ + ASTNodeValueBuilder{*ast}; \ + \ + ASTNodeDeclarationToAffectationConverter{*ast}; \ + ASTNodeDeclarationCleaner{*ast}; \ + \ + ASTNodeExpressionBuilder{*ast}; \ + std::stringstream ast_output; \ + ast_output << '\n' << ASTPrinter{*ast, ASTPrinter::Format::raw, {ASTPrinter::Info::exec_type}}; \ + \ + REQUIRE(ast_output.str() == expected_output); \ } TEST_CASE("ASTNodeExpressionBuilder", "[language]") @@ -44,9 +47,77 @@ TEST_CASE("ASTNodeExpressionBuilder", "[language]") )"; std::string_view result = R"( -(root) +(root:ASTNodeList) )"; CHECK_AST(data, result); } + + SECTION("string affectation") + { + SECTION("from bool") + { + std::string_view data = R"( +string s = true; +)"; + + std::string result = R"( +(root:ASTNodeList) + `-(language::eq_op:AffectationToStringProcessor<language::eq_op, bool>) + +-(language::name:s:NameExpression) + `-(language::true_kw:NoProcess) +)"; + + CHECK_AST(data, result); + } + + SECTION("from int") + { + std::string_view data = R"( +string s = 0; +)"; + + std::string result = R"( +(root:ASTNodeList) + `-(language::eq_op:AffectationToStringProcessor<language::eq_op, long>) + +-(language::name:s:NameExpression) + `-(language::integer:0:NoProcess) +)"; + CHECK_AST(data, result); + } + + SECTION("from unsigned") + { + std::string_view data = R"( +N n = 0; +string s = n; +)"; + + std::string result = R"( +(root:ASTNodeList) + +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>) + | +-(language::name:n:NameExpression) + | `-(language::integer:0:NoProcess) + `-(language::eq_op:AffectationToStringProcessor<language::eq_op, unsigned long>) + +-(language::name:s:NameExpression) + `-(language::name:n:NameExpression) +)"; + CHECK_AST(data, result); + } + + SECTION("from real") + { + std::string_view data = R"( +string s = 0.; +)"; + + std::string result = R"( +(root:ASTNodeList) + `-(language::eq_op:AffectationToStringProcessor<language::eq_op, double>) + +-(language::name:s:NameExpression) + `-(language::real:0.:NoProcess) +)"; + CHECK_AST(data, result); + } + } } -- GitLab