From 2605cd626bb91cd87dd09e23aa886e6f9e827d89 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Fri, 26 Jul 2019 18:12:51 +0200
Subject: [PATCH] Add ASTNodeDeclarationToAffectationConverter and its unit
 tests

---
 ...TNodeDeclarationToAffectationConverter.cpp |  27 +++++
 ...TNodeDeclarationToAffectationConverter.hpp |  15 +++
 src/language/CMakeLists.txt                   |   1 +
 src/language/PugsParser.cpp                   |  35 +-----
 tests/CMakeLists.txt                          |   1 +
 ...TNodeDeclarationToAffectationConverter.cpp | 111 ++++++++++++++++++
 6 files changed, 158 insertions(+), 32 deletions(-)
 create mode 100644 src/language/ASTNodeDeclarationToAffectationConverter.cpp
 create mode 100644 src/language/ASTNodeDeclarationToAffectationConverter.hpp
 create mode 100644 tests/test_ASTNodeDeclarationToAffectationConverter.cpp

diff --git a/src/language/ASTNodeDeclarationToAffectationConverter.cpp b/src/language/ASTNodeDeclarationToAffectationConverter.cpp
new file mode 100644
index 000000000..bc641a01c
--- /dev/null
+++ b/src/language/ASTNodeDeclarationToAffectationConverter.cpp
@@ -0,0 +1,27 @@
+#include <ASTNodeDeclarationToAffectationConverter.hpp>
+
+#include <PEGGrammar.hpp>
+#include <PugsAssert.hpp>
+
+void
+ASTNodeDeclarationToAffectationConverter::_convertNodeDeclaration(ASTNode& n)
+{
+  if (n.is<language::declaration>()) {
+    if (n.children.size() == 3) {
+      n.children[0] = std::move(n.children[1]);
+      n.children[1] = std::move(n.children[2]);
+      n.children.resize(2);
+      n.id = typeid(language::eq_op);
+    }
+  } else {
+    for (auto& child : n.children) {
+      this->_convertNodeDeclaration(*child);
+    }
+  }
+}
+
+ASTNodeDeclarationToAffectationConverter::ASTNodeDeclarationToAffectationConverter(ASTNode& n)
+{
+  Assert(n.is_root());
+  this->_convertNodeDeclaration(n);
+}
diff --git a/src/language/ASTNodeDeclarationToAffectationConverter.hpp b/src/language/ASTNodeDeclarationToAffectationConverter.hpp
new file mode 100644
index 000000000..8a5dd0cf0
--- /dev/null
+++ b/src/language/ASTNodeDeclarationToAffectationConverter.hpp
@@ -0,0 +1,15 @@
+#ifndef AST_NODE_DECLARATION_TO_AFFECTATION_CONVERTER_HPP
+#define AST_NODE_DECLARATION_TO_AFFECTATION_CONVERTER_HPP
+
+#include <ASTNode.hpp>
+
+class ASTNodeDeclarationToAffectationConverter
+{
+ private:
+  void _convertNodeDeclaration(ASTNode& node);
+
+ public:
+  ASTNodeDeclarationToAffectationConverter(ASTNode& root_node);
+};
+
+#endif   // AST_NODE_DECLARATION_TO_AFFECTATION_CONVERTER_HPP
diff --git a/src/language/CMakeLists.txt b/src/language/CMakeLists.txt
index ae4c49563..496f44e92 100644
--- a/src/language/CMakeLists.txt
+++ b/src/language/CMakeLists.txt
@@ -12,6 +12,7 @@ add_library(
   ASTNodeDataType.cpp
   ASTNodeDataTypeBuilder.cpp
   ASTNodeDataTypeChecker.cpp
+  ASTNodeDeclarationToAffectationConverter.cpp
   ASTNodeExpressionBuilder.cpp
   ASTNodeIncDecExpressionBuilder.cpp
   ASTNodeJumpPlacementChecker.cpp
diff --git a/src/language/PugsParser.cpp b/src/language/PugsParser.cpp
index 518250a29..0972e9117 100644
--- a/src/language/PugsParser.cpp
+++ b/src/language/PugsParser.cpp
@@ -29,42 +29,13 @@
 #include <ASTSymbolInitializationChecker.hpp>
 #include <ASTSymbolTableBuilder.hpp>
 
+#include <ASTNodeDeclarationToAffectationConverter.hpp>
+
 #include <ASTDotPrinter.hpp>
 #include <ASTPrinter.hpp>
 
 #include <ASTNodeValueBuilder.hpp>
 
-namespace language
-{
-namespace internal
-{
-void
-simplify_declarations(ASTNode& n)
-{
-  if (n.is<language::declaration>()) {
-    if (n.children.size() == 3) {
-      n.children[0] = std::move(n.children[1]);
-      n.children[1] = std::move(n.children[2]);
-      n.children.resize(2);
-      n.id = typeid(language::eq_op);
-    }
-  } else {
-    for (auto& child : n.children) {
-      simplify_declarations(*child);
-    }
-  }
-}
-}   // namespace internal
-
-void
-simplify_declarations(ASTNode& n)
-{
-  Assert(n.is_root());
-  internal::simplify_declarations(n);
-}
-
-}   // namespace language
-
 void
 parser(const std::string& filename)
 {
@@ -100,7 +71,7 @@ parser(const std::string& filename)
     ASTNodeJumpPlacementChecker{*root_node};
 
     // optimizations
-    language::simplify_declarations(*root_node);
+    ASTNodeDeclarationToAffectationConverter{*root_node};
 
     language::build_node_type(*root_node);
 
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 246771d48..235e13153 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -10,6 +10,7 @@ add_executable (unit_tests
   test_ASTNodeDataType.cpp
   test_ASTNodeDataTypeBuilder.cpp
   test_ASTNodeDataTypeChecker.cpp
+  test_ASTNodeDeclarationToAffectationConverter.cpp
   test_ASTNodeJumpPlacementChecker.cpp
   test_ASTNodeValueBuilder.cpp
   test_ASTPrinter.cpp
diff --git a/tests/test_ASTNodeDeclarationToAffectationConverter.cpp b/tests/test_ASTNodeDeclarationToAffectationConverter.cpp
new file mode 100644
index 000000000..b7f00390c
--- /dev/null
+++ b/tests/test_ASTNodeDeclarationToAffectationConverter.cpp
@@ -0,0 +1,111 @@
+#include <catch2/catch.hpp>
+
+#include <ASTNodeValueBuilder.hpp>
+
+#include <ASTBuilder.hpp>
+#include <ASTNodeDataTypeBuilder.hpp>
+
+#include <ASTNodeDeclarationToAffectationConverter.hpp>
+
+#include <ASTSymbolTableBuilder.hpp>
+
+#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};                                            \
+                                                                                               \
+    std::stringstream ast_output;                                                              \
+    ast_output << '\n' << ASTPrinter{*ast, ASTPrinter::Format::raw, {ASTPrinter::Info::none}}; \
+                                                                                               \
+    REQUIRE(ast_output.str() == expected_output);                                              \
+  }
+
+TEST_CASE("ASTNodeDeclarationToAffectationConverter", "[language]")
+{
+  SECTION("nothing to convert")
+  {
+    std::string_view data = R"(
+R z;
+)";
+
+    std::string_view result = R"(
+(root)
+ `-(language::declaration)
+     +-(language::R_set)
+     `-(language::name:z)
+)";
+
+    CHECK_AST(data, result);
+  }
+
+  SECTION("simple constructor")
+  {
+    std::string_view data = R"(
+R z = 0;
+)";
+
+    std::string_view result = R"(
+(root)
+ `-(language::eq_op)
+     +-(language::name:z)
+     `-(language::integer:0)
+)";
+
+    CHECK_AST(data, result);
+  }
+
+  SECTION("complex constructors")
+  {
+    std::string_view data = R"(
+N k = 0;
+for(N i=0; i<2; ++i) {
+  N j = 2*i+k;
+  k = 2*j-1;
+}
+)";
+
+    std::string_view result = R"(
+(root)
+ +-(language::eq_op)
+ |   +-(language::name:k)
+ |   `-(language::integer:0)
+ `-(language::for_statement)
+     +-(language::eq_op)
+     |   +-(language::name:i)
+     |   `-(language::integer:0)
+     +-(language::lesser_op)
+     |   +-(language::name:i)
+     |   `-(language::integer:2)
+     +-(language::unary_plusplus)
+     |   `-(language::name:i)
+     `-(language::for_statement_bloc)
+         +-(language::eq_op)
+         |   +-(language::name:j)
+         |   `-(language::plus_op)
+         |       +-(language::multiply_op)
+         |       |   +-(language::integer:2)
+         |       |   `-(language::name:i)
+         |       `-(language::name:k)
+         `-(language::eq_op)
+             +-(language::name:k)
+             `-(language::minus_op)
+                 +-(language::multiply_op)
+                 |   +-(language::integer:2)
+                 |   `-(language::name:j)
+                 `-(language::integer:1)
+)";
+
+    CHECK_AST(data, result);
+  }
+}
-- 
GitLab