From fe5963c7fc79cfe4c4f4de5a171ea27d67095505 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Wed, 5 Feb 2020 19:26:19 +0100
Subject: [PATCH] Finish list affectation containing R^d by 0

Now it is possible to write
``
R^3 x=(1,2,3);
R^2 y=(1,3);

R z = 2;
(x, z, y) = (0, 3, 0);
``
This will lead to the final values: `x==(0,0,0)`, `y==(0,0)` and `z==3`
Remember that the only valid **N** value in such instruction is `0`.
---
 ...STNodeListAffectationExpressionBuilder.cpp | 43 ++++++++++++++++++-
 .../node_processor/AffectationProcessor.hpp   | 42 ++++++++++--------
 2 files changed, 64 insertions(+), 21 deletions(-)

diff --git a/src/language/ASTNodeListAffectationExpressionBuilder.cpp b/src/language/ASTNodeListAffectationExpressionBuilder.cpp
index a39f53c6a..3f88ad804 100644
--- a/src/language/ASTNodeListAffectationExpressionBuilder.cpp
+++ b/src/language/ASTNodeListAffectationExpressionBuilder.cpp
@@ -46,6 +46,12 @@ ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor(
     using ValueT = std::decay_t<decltype(value)>;
     if (node_sub_data_type.m_data_type.dimension() == value.dimension()) {
       list_affectation_processor->template add<ValueT, ValueT>(value_node);
+    } else if (node_sub_data_type.m_parent_node.is_type<language::integer>()) {
+      if (std::stoi(node_sub_data_type.m_parent_node.string()) == 0) {
+        list_affectation_processor->template add<ValueT, ZeroType>(value_node);
+      } else {
+        throw parse_error("invalid operand value", std::vector{node_sub_data_type.m_parent_node.begin()});
+      }
     } else {
       throw parse_error("invalid dimension", std::vector{node_sub_data_type.m_parent_node.begin()});
     }
@@ -89,8 +95,6 @@ ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor(
 
   auto add_affectation_processor_for_value = [&](const ASTNodeDataType& value_type,
                                                  const ASTNodeSubDataType& node_sub_data_type) {
-    ASTNodeNaturalConversionChecker{node_sub_data_type.m_parent_node, node_sub_data_type.m_data_type, value_type};
-
     switch (value_type) {
     case ASTNodeDataType::bool_t: {
       add_affectation_processor_for_data(bool{}, node_sub_data_type);
@@ -141,6 +145,41 @@ ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor(
     }
   };
 
+  if (value_node.m_data_type == ASTNodeDataType::vector_t) {
+    // Only real data are considered
+    const ASTNode& data_node = rhs_node_sub_data_type.m_parent_node;
+    switch (data_node.m_data_type) {
+    case ASTNodeDataType::list_t: {
+      if (data_node.children.size() != value_node.m_data_type.dimension()) {
+        throw parse_error("incompatible dimensions in affectation", std::vector{value_node.begin()});
+      }
+      for (const auto& child : data_node.children) {
+        ASTNodeNaturalConversionChecker{rhs_node_sub_data_type.m_parent_node, child->m_data_type,
+                                        ASTNodeDataType::double_t};
+      }
+
+      break;
+    }
+    case ASTNodeDataType::vector_t: {
+      if (data_node.m_data_type.dimension() != value_node.m_data_type.dimension()) {
+        throw parse_error("incompatible dimensions in affectation", std::vector{value_node.begin()});
+      }
+      break;
+    }
+    case ASTNodeDataType::int_t: {
+      // Nothing to check by now since the special value 0 is allowed
+      break;
+    }
+    default: {
+      ASTNodeNaturalConversionChecker{rhs_node_sub_data_type.m_parent_node, rhs_node_sub_data_type.m_data_type,
+                                      value_node.m_data_type};
+    }
+    }
+  } else {
+    ASTNodeNaturalConversionChecker{rhs_node_sub_data_type.m_parent_node, rhs_node_sub_data_type.m_data_type,
+                                    value_node.m_data_type};
+  }
+
   add_affectation_processor_for_value(value_node.m_data_type, rhs_node_sub_data_type);
 }
 
diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp
index dec7f5b54..c9e91663f 100644
--- a/src/language/node_processor/AffectationProcessor.hpp
+++ b/src/language/node_processor/AffectationProcessor.hpp
@@ -88,31 +88,35 @@ class AffectationExecutor final : public IAffectationExecutor
   affect(ExecutionPolicy&, DataVariant&& rhs)
   {
     if constexpr (_is_defined) {
-      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 = std::get<DataT>(rhs);
+      if constexpr (not std::is_same_v<DataT, ZeroType>) {
+        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 = std::get<DataT>(rhs);
+            } else {
+              m_lhs = std::to_string(std::get<DataT>(rhs));
+            }
           } else {
-            m_lhs = std::to_string(std::get<DataT>(rhs));
+            static_assert(std::is_same_v<OperatorT, language::pluseq_op>, "unexpected operator type");
+            if constexpr (std::is_same_v<std::string, DataT>) {
+              m_lhs += std::get<std::string>(rhs);
+            } else {
+              m_lhs += std::to_string(std::get<DataT>(rhs));
+            }
           }
         } else {
-          static_assert(std::is_same_v<OperatorT, language::pluseq_op>, "unexpected operator type");
-          if constexpr (std::is_same_v<std::string, DataT>) {
-            m_lhs += std::get<std::string>(rhs);
-          } else {
-            m_lhs += std::to_string(std::get<DataT>(rhs));
-          }
-        }
-      } else {
-        if constexpr (std::is_same_v<OperatorT, language::eq_op>) {
-          if constexpr (std::is_same_v<ValueT, DataT>) {
-            m_lhs = std::get<DataT>(rhs);
+          if constexpr (std::is_same_v<OperatorT, language::eq_op>) {
+            if constexpr (std::is_same_v<ValueT, DataT>) {
+              m_lhs = std::get<DataT>(rhs);
+            } else {
+              m_lhs = static_cast<ValueT>(std::get<DataT>(rhs));
+            }
           } else {
-            m_lhs = static_cast<ValueT>(std::get<DataT>(rhs));
+            AffOp<OperatorT>().eval(m_lhs, std::get<DataT>(rhs));
           }
-        } else {
-          AffOp<OperatorT>().eval(m_lhs, std::get<DataT>(rhs));
         }
+      } else if (std::is_same_v<OperatorT, language::eq_op>) {
+        m_lhs = ValueT{zero};
       }
     }
   }
-- 
GitLab