From 82ec52799469d0814e5e277e72869996b3e66d19 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Wed, 12 Feb 2020 19:31:15 +0100
Subject: [PATCH] Add R^d -> string in compound affectations and corresponding
 tests

---
 ...STNodeListAffectationExpressionBuilder.cpp |  25 +++-
 tests/CMakeLists.txt                          |   1 +
 tests/test_ListAffectationProcessor.cpp       | 111 ++++++++++++++++++
 3 files changed, 136 insertions(+), 1 deletion(-)
 create mode 100644 tests/test_ListAffectationProcessor.cpp

diff --git a/src/language/ASTNodeListAffectationExpressionBuilder.cpp b/src/language/ASTNodeListAffectationExpressionBuilder.cpp
index 2218ae864..624bddbcb 100644
--- a/src/language/ASTNodeListAffectationExpressionBuilder.cpp
+++ b/src/language/ASTNodeListAffectationExpressionBuilder.cpp
@@ -96,10 +96,33 @@ ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor(
       case ASTNodeDataType::string_t: {
         list_affectation_processor->template add<std::string, std::string>(value_node);
         break;
+      }
+      case ASTNodeDataType::vector_t: {
+        switch (node_sub_data_type.m_data_type.dimension()) {
+        case 1: {
+          list_affectation_processor->template add<std::string, TinyVector<1>>(value_node);
+          break;
+        }
+        case 2: {
+          list_affectation_processor->template add<std::string, TinyVector<2>>(value_node);
+          break;
+        }
+        case 3: {
+          list_affectation_processor->template add<std::string, TinyVector<3>>(value_node);
+          break;
+        }
+          // LCOV_EXCL_START
+        default: {
+          throw parse_error("unexpected error: invalid vector dimension",
+                            std::vector{node_sub_data_type.m_parent_node.begin()});
+        }
+          // LCOV_EXCL_STOP
+        }
+        break;
       }
         // LCOV_EXCL_START
       default: {
-        throw parse_error("invalid operand type for string affectation",
+        throw parse_error("unexpected error:invalid operand type for string affectation",
                           std::vector{node_sub_data_type.m_parent_node.begin()});
       }
         // LCOV_EXCL_STOP
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index f72040858..01762e9d1 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -59,6 +59,7 @@ add_executable (unit_tests
   test_IncDecExpressionProcessor.cpp
   test_INodeProcessor.cpp
   test_ItemType.cpp
+  test_ListAffectationProcessor.cpp
   test_NameProcessor.cpp
   test_OStreamProcessor.cpp
   test_PCG.cpp
diff --git a/tests/test_ListAffectationProcessor.cpp b/tests/test_ListAffectationProcessor.cpp
new file mode 100644
index 000000000..eb86bdb66
--- /dev/null
+++ b/tests/test_ListAffectationProcessor.cpp
@@ -0,0 +1,111 @@
+#include <catch2/catch.hpp>
+
+#include <ASTBuilder.hpp>
+#include <ASTNodeDataTypeBuilder.hpp>
+
+#include <ASTNodeDeclarationToAffectationConverter.hpp>
+#include <ASTNodeTypeCleaner.hpp>
+
+#include <ASTNodeExpressionBuilder.hpp>
+
+#include <ASTNodeAffectationExpressionBuilder.hpp>
+
+#include <ASTSymbolTableBuilder.hpp>
+
+#include <ASTPrinter.hpp>
+
+#include <Demangle.hpp>
+
+#include <PEGGrammar.hpp>
+
+#include <sstream>
+
+#define CHECK_AFFECTATION_RESULT(data, variable_name, expected_value)         \
+  {                                                                           \
+    string_input input{data, "test.pgs"};                                     \
+    auto ast = ASTBuilder::build(input);                                      \
+                                                                              \
+    ASTSymbolTableBuilder{*ast};                                              \
+    ASTNodeDataTypeBuilder{*ast};                                             \
+                                                                              \
+    ASTNodeDeclarationToAffectationConverter{*ast};                           \
+    ASTNodeTypeCleaner<language::declaration>{*ast};                          \
+                                                                              \
+    ASTNodeExpressionBuilder{*ast};                                           \
+    ExecutionPolicy exec_policy;                                              \
+    ast->execute(exec_policy);                                                \
+                                                                              \
+    auto symbol_table = ast->m_symbol_table;                                  \
+                                                                              \
+    using namespace TAO_PEGTL_NAMESPACE;                                      \
+    position use_position{internal::iterator{"fixture"}, "fixture"};          \
+    use_position.byte    = 10000;                                             \
+    auto [symbol, found] = symbol_table->find(variable_name, use_position);   \
+                                                                              \
+    auto attributes = symbol->attributes();                                   \
+    auto value      = std::get<decltype(expected_value)>(attributes.value()); \
+                                                                              \
+    REQUIRE(value == expected_value);                                         \
+  }
+
+#define CHECK_AFFECTATION_THROWS(data)                                                       \
+  {                                                                                          \
+    string_input input{data, "test.pgs"};                                                    \
+    auto ast = ASTBuilder::build(input);                                                     \
+                                                                                             \
+    ASTSymbolTableBuilder{*ast};                                                             \
+    ASTNodeDataTypeBuilder{*ast};                                                            \
+                                                                                             \
+    ASTNodeDeclarationToAffectationConverter{*ast};                                          \
+    ASTNodeTypeCleaner<language::declaration>{*ast};                                         \
+                                                                                             \
+    REQUIRE_THROWS(ASTNodeExpressionBuilder{*ast},                                           \
+                   Catch::Matchers::Contains("invalid operands to affectation expression")); \
+  }
+
+#define CHECK_AFFECTATION_THROWS_WITH(data, error_message)              \
+  {                                                                     \
+    string_input input{data, "test.pgs"};                               \
+    auto ast = ASTBuilder::build(input);                                \
+                                                                        \
+    ASTSymbolTableBuilder{*ast};                                        \
+    ASTNodeDataTypeBuilder{*ast};                                       \
+                                                                        \
+    ASTNodeDeclarationToAffectationConverter{*ast};                     \
+    ASTNodeTypeCleaner<language::declaration>{*ast};                    \
+                                                                        \
+    REQUIRE_THROWS_WITH(ASTNodeExpressionBuilder{*ast}, error_message); \
+  }
+
+TEST_CASE("ListAffectationProcessor", "[language]")
+{
+  SECTION("ListAffectations")
+  {
+    SECTION("R*R^2*string")
+    {
+      CHECK_AFFECTATION_RESULT(R"(R*R^2*string (x,u,s) = (1.2, (2,3), "foo");)", "x", double{1.2});
+      CHECK_AFFECTATION_RESULT(R"(R*R^2*string (x,u,s) = (1.2, (2,3), "foo");)", "u", (TinyVector<2>{2, 3}));
+      CHECK_AFFECTATION_RESULT(R"(R*R^2*string (x,u,s) = (1.2, (2,3), "foo");)", "s", std::string{"foo"});
+    }
+
+    SECTION("compound with string conversion")
+    {
+      CHECK_AFFECTATION_RESULT(R"(R z = 3; R*R^2*string (x,u,s) = (1.2, (2,3), z);)", "s", std::to_string(double{3}));
+      {
+        std::ostringstream os;
+        os << TinyVector<1>{7} << std::ends;
+        CHECK_AFFECTATION_RESULT(R"(R^1 v = 7; R*R^2*string (x,u,s) = (1.2, (2,3), v);)", "s", os.str());
+      }
+      {
+        std::ostringstream os;
+        os << TinyVector<2>{6, 3} << std::ends;
+        CHECK_AFFECTATION_RESULT(R"(R^2 v = (6,3); R*R^2*string (x,u,s) = (1.2, (2,3), v);)", "s", os.str());
+      }
+      {
+        std::ostringstream os;
+        os << TinyVector<3>{1, 2, 3} << std::ends;
+        CHECK_AFFECTATION_RESULT(R"(R^3 v = (1,2,3); R*R^2*string (x,u,s) = (1.2, (2,3), v);)", "s", os.str());
+      }
+    }
+  }
+}
-- 
GitLab