From ca8c171a1a8c4675a6cdf65ebc67104de0f96b2b Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Thu, 21 Nov 2019 16:38:00 +0100
Subject: [PATCH] Rewrite string affectations

works also for strings being embedded into tuples
---
 .../ASTNodeAffectationExpressionBuilder.cpp   | 11 ++-
 ...STNodeListAffectationExpressionBuilder.cpp | 84 +++++++++----------
 .../node_processor/AffectationProcessor.hpp   | 28 +++++--
 .../AffectationToStringProcessor.hpp          | 45 ----------
 ...st_ASTNodeAffectationExpressionBuilder.cpp | 46 +++++-----
 5 files changed, 90 insertions(+), 124 deletions(-)
 delete mode 100644 src/language/node_processor/AffectationToStringProcessor.hpp

diff --git a/src/language/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ASTNodeAffectationExpressionBuilder.cpp
index c515da24d..3475e2c00 100644
--- a/src/language/ASTNodeAffectationExpressionBuilder.cpp
+++ b/src/language/ASTNodeAffectationExpressionBuilder.cpp
@@ -2,7 +2,6 @@
 #include <PEGGrammar.hpp>
 
 #include <node_processor/AffectationProcessor.hpp>
-#include <node_processor/AffectationToStringProcessor.hpp>
 
 ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode& n)
 {
@@ -40,23 +39,23 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode
       if constexpr (std::is_same_v<OperatorT, language::eq_op> or std::is_same_v<OperatorT, language::pluseq_op>) {
         switch (data_type) {
         case ASTNodeDataType::bool_t: {
-          n.m_node_processor = std::make_unique<AffectationToStringProcessor<OperatorT, bool>>(n);
+          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, bool>>(n);
           break;
         }
         case ASTNodeDataType::unsigned_int_t: {
-          n.m_node_processor = std::make_unique<AffectationToStringProcessor<OperatorT, uint64_t>>(n);
+          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, uint64_t>>(n);
           break;
         }
         case ASTNodeDataType::int_t: {
-          n.m_node_processor = std::make_unique<AffectationToStringProcessor<OperatorT, int64_t>>(n);
+          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, int64_t>>(n);
           break;
         }
         case ASTNodeDataType::double_t: {
-          n.m_node_processor = std::make_unique<AffectationToStringProcessor<OperatorT, double>>(n);
+          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, double>>(n);
           break;
         }
         case ASTNodeDataType::string_t: {
-          n.m_node_processor = std::make_unique<AffectationToStringProcessor<OperatorT, std::string>>(n);
+          n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, std::string>>(n);
           break;
         }
         default: {
diff --git a/src/language/ASTNodeListAffectationExpressionBuilder.cpp b/src/language/ASTNodeListAffectationExpressionBuilder.cpp
index 9850ca24a..da3473367 100644
--- a/src/language/ASTNodeListAffectationExpressionBuilder.cpp
+++ b/src/language/ASTNodeListAffectationExpressionBuilder.cpp
@@ -2,7 +2,6 @@
 #include <PEGGrammar.hpp>
 
 #include <node_processor/AffectationProcessor.hpp>
-#include <node_processor/AffectationToStringProcessor.hpp>
 
 template <typename OperatorT>
 void
@@ -10,8 +9,8 @@ ASTNodeListAffectationExpressionBuilder::_buildListAffectationProcessor(ASTNode&
 {
   using ListAffectationProcessorT = ListAffectationProcessor<OperatorT>;
 
-  auto add_affectation_processor = [](ASTNode& value_node, ASTNode& data_node,
-                                      std::unique_ptr<ListAffectationProcessorT>& list_affectation_processor) {
+  auto add_affectation_processor = [&](ASTNode& value_node, ASTNode& data_node,
+                                       std::unique_ptr<ListAffectationProcessorT>& list_affectation_processor) {
     auto add_affectation_processor_for_data = [&](const auto& value, const ASTNodeDataType& data_type) {
       using ValueT = std::decay_t<decltype(value)>;
       switch (data_type) {
@@ -37,38 +36,39 @@ ASTNodeListAffectationExpressionBuilder::_buildListAffectationProcessor(ASTNode&
       }
     };
 
-    // auto add_affectation_processor_for_string_data = [&](const ASTNodeDataType& data_type) {
-    //   if constexpr (std::is_same_v<OperatorT, language::eq_op> or std::is_same_v<OperatorT, language::pluseq_op>) {
-    //     switch (data_type) {
-    //     case ASTNodeDataType::bool_t: {
-    //       node.m_node_processor = std::make_unique<AffectationToStringProcessor<OperatorT, bool>>(node);
-    //       break;
-    //     }
-    //     case ASTNodeDataType::unsigned_int_t: {
-    //       node.m_node_processor = std::make_unique<AffectationToStringProcessor<OperatorT, uint64_t>>(node);
-    //       break;
-    //     }
-    //     case ASTNodeDataType::int_t: {
-    //       node.m_node_processor = std::make_unique<AffectationToStringProcessor<OperatorT, int64_t>>(node);
-    //       break;
-    //     }
-    //     case ASTNodeDataType::double_t: {
-    //       node.m_node_processor = std::make_unique<AffectationToStringProcessor<OperatorT, double>>(node);
-    //       break;
-    //     }
-    //     case ASTNodeDataType::string_t: {
-    //       node.m_node_processor = std::make_unique<AffectationToStringProcessor<OperatorT, std::string>>(node);
-    //       break;
-    //     }
-    //     default: {
-    //       throw parse_error("unexpected error: undefined operand type for string affectation",
-    //                         std::vector{node.children[1]->begin()});
-    //     }
-    //     }
-    //   } else {
-    //     throw parse_error("unexpected error: undefined operator type", std::vector{node.children[0]->begin()});
-    //   }
-    // };
+    auto add_affectation_processor_for_string_data = [&](const ASTNodeDataType& data_type) {
+      if constexpr (std::is_same_v<OperatorT, language::eq_op> or std::is_same_v<OperatorT, language::pluseq_op>) {
+        switch (data_type) {
+        case ASTNodeDataType::bool_t: {
+          list_affectation_processor->template add<std::string, bool>(value_node, data_node);
+          break;
+        }
+        case ASTNodeDataType::unsigned_int_t: {
+          list_affectation_processor->template add<std::string, uint64_t>(value_node, data_node);
+          break;
+        }
+        case ASTNodeDataType::int_t: {
+          list_affectation_processor->template add<std::string, int64_t>(value_node, data_node);
+          break;
+        }
+        case ASTNodeDataType::double_t: {
+          list_affectation_processor->template add<std::string, double>(value_node, data_node);
+          break;
+        }
+        case ASTNodeDataType::string_t: {
+          list_affectation_processor->template add<std::string, std::string>(value_node, data_node);
+          break;
+        }
+        default: {
+          throw parse_error("unexpected error: undefined operand type for string affectation",
+                            std::vector{data_node.begin()});
+        }
+        }
+      } else {
+        throw parse_error("unexpected error: undefined operator type for string affectation",
+                          std::vector{node.begin()});
+      }
+    };
 
     auto add_affectation_processor_for_value = [&](const ASTNodeDataType& value_type,
                                                    const ASTNodeDataType& data_type) {
@@ -90,12 +90,12 @@ ASTNodeListAffectationExpressionBuilder::_buildListAffectationProcessor(ASTNode&
         break;
       }
       case ASTNodeDataType::string_t: {
-        // add_affectation_processor_for_string_data(data_type);
-        throw parse_error("unexpected error: string in list NIY", std::vector{value_node.begin()});
+        add_affectation_processor_for_string_data(data_type);
         break;
       }
       default: {
-        throw parse_error("unexpected error: undefined value type for affectation", std::vector{value_node.begin()});
+        throw parse_error("unexpected error: undefined value type for tuple affectation",
+                          std::vector{value_node.begin()});
       }
       }
     };
@@ -127,20 +127,16 @@ ASTNodeListAffectationExpressionBuilder::ASTNodeListAffectationExpressionBuilder
   if (n.children[1]->is_type<language::expression_list>()) {
     if (n.is_type<language::eq_op>()) {
       this->_buildListAffectationProcessor<language::eq_op>(n);
-    } else if (n.is_type<language::multiplyeq_op>()) {
-      this->_buildListAffectationProcessor<language::multiplyeq_op>(n);
-    } else if (n.is_type<language::divideeq_op>()) {
-      this->_buildListAffectationProcessor<language::divideeq_op>(n);
     } else if (n.is_type<language::pluseq_op>()) {
       this->_buildListAffectationProcessor<language::pluseq_op>(n);
     } else if (n.is_type<language::minuseq_op>()) {
       this->_buildListAffectationProcessor<language::minuseq_op>(n);
 
     } else {
-      throw parse_error("unexpected error: undefined affectation operator", std::vector{n.begin()});
+      throw parse_error("undefined affectation operator for tuples", std::vector{n.begin()});
     }
   } else {
-    throw parse_error("unexpected error: invalid right hand side in list affectation",
+    throw parse_error("unexpected error: invalid right hand side in tuple affectation",
                       std::vector{n.children[1]->begin()});
   }
 }
diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp
index b22af5df3..a538c351a 100644
--- a/src/language/node_processor/AffectationProcessor.hpp
+++ b/src/language/node_processor/AffectationProcessor.hpp
@@ -86,14 +86,31 @@ class AffectationExecutor final : public IAffectationExecutor
   execute()
   {
     if constexpr (_is_defined) {
-      if constexpr (std::is_same_v<OperatorT, language::eq_op>) {
-        if constexpr (std::is_same_v<ValueT, DataT>) {
-          *m_lhs = *m_rhs;
+      if constexpr (std::is_same_v<ValueT, std::string>) {
+        if constexpr (std::is_same_v<OperatorT, language::eq_op>) {
+          if constexpr (std::is_same_v<std::string, DataT>) {
+            *m_lhs = *m_rhs;
+          } else {
+            *m_lhs = std::to_string(std::get<DataT>(*m_rhs));
+          }
         } else {
-          *m_lhs = static_cast<ValueT>(std::get<DataT>(*m_rhs));
+          static_assert(std::is_same_v<OperatorT, language::pluseq_op>, "unexpected operator type");
+          if constexpr (std::is_same_v<std::string, DataT>) {
+            std::get<std::string>(*m_lhs) += std::get<std::string>(*m_rhs);
+          } else {
+            std::get<std::string>(*m_lhs) += std::to_string(std::get<DataT>(*m_rhs));
+          }
         }
       } else {
-        AffOp<OperatorT>().eval(std::get<ValueT>(*m_lhs), std::get<DataT>(*m_rhs));
+        if constexpr (std::is_same_v<OperatorT, language::eq_op>) {
+          if constexpr (std::is_same_v<ValueT, DataT>) {
+            *m_lhs = *m_rhs;
+          } else {
+            *m_lhs = static_cast<ValueT>(std::get<DataT>(*m_rhs));
+          }
+        } else {
+          AffOp<OperatorT>().eval(std::get<ValueT>(*m_lhs), std::get<DataT>(*m_rhs));
+        }
       }
     }
   }
@@ -106,7 +123,6 @@ class AffectationProcessor final : public INodeProcessor
   ASTNode& m_node;
 
   using AffectationExecutorT = AffectationExecutor<OperatorT, ValueT, DataT>;
-
   std::unique_ptr<AffectationExecutorT> m_affectation_executor;
 
  public:
diff --git a/src/language/node_processor/AffectationToStringProcessor.hpp b/src/language/node_processor/AffectationToStringProcessor.hpp
deleted file mode 100644
index 7c22c095d..000000000
--- a/src/language/node_processor/AffectationToStringProcessor.hpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef AFFECTATION_TO_STRING_PROCESSOR_HPP
-#define AFFECTATION_TO_STRING_PROCESSOR_HPP
-
-#include <node_processor/INodeProcessor.hpp>
-
-#include <SymbolTable.hpp>
-
-template <typename OperatorT, typename DataT>
-class AffectationToStringProcessor final : public INodeProcessor
-{
- private:
-  ASTNode& m_node;
-  ASTNodeDataVariant* p_value{nullptr};
-
- public:
-  void
-  execute(ExecUntilBreakOrContinue& exec_policy)
-  {
-    m_node.children[1]->execute(exec_policy);
-
-    if constexpr (std::is_same_v<OperatorT, language::eq_op>) {
-      if constexpr (std::is_same_v<std::string, DataT>) {
-        *p_value = m_node.children[1]->m_value;
-      } else {
-        *p_value = std::to_string(std::get<DataT>(m_node.children[1]->m_value));
-      }
-    } else if constexpr (std::is_same_v<OperatorT, language::pluseq_op>) {
-      if constexpr (std::is_same_v<std::string, DataT>) {
-        std::get<std::string>(*p_value) += std::get<std::string>(m_node.children[1]->m_value);
-      } else {
-        std::get<std::string>(*p_value) += std::to_string(std::get<DataT>(m_node.children[1]->m_value));
-      }
-    }
-  }
-
-  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->attributes().value();
-  }
-};
-
-#endif   // AFFECTATION_TO_STRING_PROCESSOR_HPP
diff --git a/tests/test_ASTNodeAffectationExpressionBuilder.cpp b/tests/test_ASTNodeAffectationExpressionBuilder.cpp
index 9758fbbb1..cdceab453 100644
--- a/tests/test_ASTNodeAffectationExpressionBuilder.cpp
+++ b/tests/test_ASTNodeAffectationExpressionBuilder.cpp
@@ -46,6 +46,8 @@
 
 TEST_CASE("ASTNodeAffectationExpressionBuilder", "[language]")
 {
+  const std::string demangled_stdstring = demangle(typeid(std::string{}).name());
+
   SECTION("Affectations")
   {
     SECTION("boolean affectation")
@@ -381,9 +383,10 @@ R r="foo";
 string s=true;
 )";
 
-        std::string_view result = R"(
+        std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eq_op:AffectationToStringProcessor<language::eq_op, bool>)
+ `-(language::eq_op:AffectationProcessor<language::eq_op, )" +
+                             demangled_stdstring + R"(, bool>)
      +-(language::name:s:NameProcessor)
      `-(language::true_kw:FakeProcessor)
 )";
@@ -397,9 +400,10 @@ string s=true;
 N n; string s=n;
 )";
 
-        std::string_view result = R"(
+        std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eq_op:AffectationToStringProcessor<language::eq_op, unsigned long>)
+ `-(language::eq_op:AffectationProcessor<language::eq_op, )" +
+                             demangled_stdstring + R"(, unsigned long>)
      +-(language::name:s:NameProcessor)
      `-(language::name:n:NameProcessor)
 )";
@@ -413,9 +417,11 @@ N n; string s=n;
 Z z; string s=z;
 )";
 
-        std::string_view result = R"(
+        std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eq_op:AffectationToStringProcessor<language::eq_op, long>)
+ `-(language::eq_op:AffectationProcessor<language::eq_op, )" +
+                             demangled_stdstring +
+                             R"(, long>)
      +-(language::name:s:NameProcessor)
      `-(language::name:z:NameProcessor)
 )";
@@ -429,9 +435,11 @@ Z z; string s=z;
 R r; string s=r;
 )";
 
-        std::string_view result = R"(
+        std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eq_op:AffectationToStringProcessor<language::eq_op, double>)
+ `-(language::eq_op:AffectationProcessor<language::eq_op, )" +
+                             demangled_stdstring +
+                             R"(, double>)
      +-(language::name:s:NameProcessor)
      `-(language::name:r:NameProcessor)
 )";
@@ -445,12 +453,10 @@ R r; string s=r;
 string s="foo";
 )";
 
-        std::string string_name = demangle(typeid(std::string{}).name());
-
         std::string result = R"(
 (root:ASTNodeListProcessor)
- `-(language::eq_op:AffectationToStringProcessor<language::eq_op, )" +
-                             string_name + R"( >)
+ `-(language::eq_op:AffectationProcessor<language::eq_op, )" +
+                             demangled_stdstring + ", " + demangled_stdstring + R"( >)
      +-(language::name:s:NameProcessor)
      `-(language::literal:"foo":FakeProcessor)
 )";
@@ -506,15 +512,15 @@ R x=1; x+=2;
 string s="foo"; s+=2;
 )";
 
-      std::string string_name = demangle(typeid(std::string{}).name());
-
       std::string result = R"(
 (root:ASTNodeListProcessor)
- +-(language::eq_op:AffectationToStringProcessor<language::eq_op, )" +
-                           string_name + R"( >)
+ +-(language::eq_op:AffectationProcessor<language::eq_op, )" +
+                           demangled_stdstring + ", " + demangled_stdstring + R"( >)
  |   +-(language::name:s:NameProcessor)
  |   `-(language::literal:"foo":FakeProcessor)
- `-(language::pluseq_op:AffectationToStringProcessor<language::pluseq_op, long>)
+ `-(language::pluseq_op:AffectationProcessor<language::pluseq_op, )" +
+                           demangled_stdstring +
+                           R"(, long>)
      +-(language::name:s:NameProcessor)
      `-(language::integer:2:FakeProcessor)
 )";
@@ -569,8 +575,6 @@ R x=1; x-=2.3;
 string s="foo"; s-="bar";
 )";
 
-      std::string string_name = demangle(typeid(std::string{}).name());
-
       string_input input{data, "test.pgs"};
       auto ast = ASTBuilder::build(input);
 
@@ -631,8 +635,6 @@ R x=1; x*=2.3;
 string s="foo"; s*=2;
 )";
 
-      std::string string_name = demangle(typeid(std::string{}).name());
-
       string_input input{data, "test.pgs"};
       auto ast = ASTBuilder::build(input);
 
@@ -693,8 +695,6 @@ R x=1; x/=2.3;
 string s="foo"; s/="bar";
 )";
 
-      std::string string_name = demangle(typeid(std::string{}).name());
-
       string_input input{data, "test.pgs"};
       auto ast = ASTBuilder::build(input);
 
-- 
GitLab