diff --git a/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp b/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp
index f7e0627cb03acddf10e8b5d03dbb0699fdb6bd4a..ec499edb30589824b5578dbc0701db0b3639166b 100644
--- a/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp
@@ -9,6 +9,371 @@
 #include <language/utils/AffectationMangler.hpp>
 #include <language/utils/OperatorRepository.hpp>
 
+template <typename OperatorT, typename TupleContentType>
+void
+ASTNodeListAffectationExpressionBuilder::_buildListAffectationFromTupleProcessor(
+  ListAffectationFromTupleProcessor<OperatorT, TupleContentType>& list_affectation_processor)
+{
+  ASTNode& name_list_node = *m_node.children[0];
+  for (size_t i = 0; i < name_list_node.children.size(); ++i) {
+    ASTNode& value_node = *name_list_node.children[i];
+    if constexpr (std::is_same_v<TupleContentType, bool>) {
+      switch (value_node.m_data_type) {
+      case ASTNodeDataType::bool_t: {
+        list_affectation_processor.template add<bool>(value_node);
+        break;
+      }
+      case ASTNodeDataType::unsigned_int_t: {
+        list_affectation_processor.template add<uint64_t>(value_node);
+        break;
+      }
+      case ASTNodeDataType::int_t: {
+        list_affectation_processor.template add<int64_t>(value_node);
+        break;
+      }
+      case ASTNodeDataType::double_t: {
+        list_affectation_processor.template add<double>(value_node);
+        break;
+      }
+      case ASTNodeDataType::vector_t: {
+        if (value_node.m_data_type.dimension() == 1) {
+          list_affectation_processor.template add<TinyVector<1>>(value_node);
+        } else {
+          // LCOV_EXCL_START
+          throw UnexpectedError("invalid vector dimension");
+          // LCOV_EXCL_STOP
+        }
+        break;
+      }
+      case ASTNodeDataType::matrix_t: {
+        if ((value_node.m_data_type.numberOfRows() == 1) and (value_node.m_data_type.numberOfColumns() == 1)) {
+          list_affectation_processor.template add<TinyMatrix<1>>(value_node);
+        } else {
+          // LCOV_EXCL_START
+          throw UnexpectedError("invalid vector dimension");
+          // LCOV_EXCL_STOP
+        }
+        break;
+      }
+      case ASTNodeDataType::string_t: {
+        list_affectation_processor.template add<std::string>(value_node);
+        break;
+      }
+        // LCOV_EXCL_START
+      default: {
+        throw UnexpectedError("incompatible tuple types in affectation");
+      }
+        // LCOV_EXCL_STOP
+      }
+    } else if constexpr ((std::is_same_v<TupleContentType, uint64_t>) or (std::is_same_v<TupleContentType, int64_t>)) {
+      switch (value_node.m_data_type) {
+      case ASTNodeDataType::unsigned_int_t: {
+        list_affectation_processor.template add<uint64_t>(value_node);
+        break;
+      }
+      case ASTNodeDataType::int_t: {
+        list_affectation_processor.template add<int64_t>(value_node);
+        break;
+      }
+      case ASTNodeDataType::double_t: {
+        list_affectation_processor.template add<double>(value_node);
+        break;
+      }
+      case ASTNodeDataType::vector_t: {
+        if (value_node.m_data_type.dimension() == 1) {
+          list_affectation_processor.template add<TinyVector<1>>(value_node);
+        } else {
+          // LCOV_EXCL_START
+          throw UnexpectedError("invalid vector dimension");
+          // LCOV_EXCL_STOP
+        }
+        break;
+      }
+      case ASTNodeDataType::matrix_t: {
+        if ((value_node.m_data_type.numberOfRows() == 1) and (value_node.m_data_type.numberOfColumns() == 1)) {
+          list_affectation_processor.template add<TinyMatrix<1>>(value_node);
+        } else {
+          // LCOV_EXCL_START
+          throw UnexpectedError("invalid vector dimension");
+          // LCOV_EXCL_STOP
+        }
+        break;
+      }
+      case ASTNodeDataType::string_t: {
+        list_affectation_processor.template add<std::string>(value_node);
+        break;
+      }
+        // LCOV_EXCL_START
+      default: {
+        throw UnexpectedError("incompatible tuple types in affectation");
+      }
+        // LCOV_EXCL_STOP
+      }
+    } else if constexpr (std::is_same_v<TupleContentType, double>) {
+      switch (value_node.m_data_type) {
+      case ASTNodeDataType::double_t: {
+        list_affectation_processor.template add<double>(value_node);
+        break;
+      }
+      case ASTNodeDataType::vector_t: {
+        if (value_node.m_data_type.dimension() == 1) {
+          list_affectation_processor.template add<TinyVector<1>>(value_node);
+        } else {
+          // LCOV_EXCL_START
+          throw UnexpectedError("invalid vector dimension");
+          // LCOV_EXCL_STOP
+        }
+        break;
+      }
+      case ASTNodeDataType::matrix_t: {
+        if ((value_node.m_data_type.numberOfRows() == 1) and (value_node.m_data_type.numberOfColumns() == 1)) {
+          list_affectation_processor.template add<TinyMatrix<1>>(value_node);
+        } else {
+          // LCOV_EXCL_START
+          throw UnexpectedError("invalid vector dimension");
+          // LCOV_EXCL_STOP
+        }
+        break;
+      }
+      case ASTNodeDataType::string_t: {
+        list_affectation_processor.template add<std::string>(value_node);
+        break;
+      }
+        // LCOV_EXCL_START
+      default: {
+        throw UnexpectedError("incompatible tuple types in affectation");
+      }
+        // LCOV_EXCL_STOP
+      }
+    } else if constexpr (is_tiny_vector_v<TupleContentType>) {
+      switch (value_node.m_data_type) {
+      case ASTNodeDataType::vector_t: {
+        if (value_node.m_data_type.dimension() == TupleContentType::Dimension) {
+          list_affectation_processor.template add<TupleContentType>(value_node);
+        } else {
+          // LCOV_EXCL_START
+          throw UnexpectedError("invalid vector dimension");
+          // LCOV_EXCL_STOP
+        }
+        break;
+      }
+      case ASTNodeDataType::string_t: {
+        list_affectation_processor.template add<std::string>(value_node);
+        break;
+      }
+        // LCOV_EXCL_START
+      default: {
+        throw UnexpectedError("incompatible tuple types in affectation");
+      }
+        // LCOV_EXCL_STOP
+      }
+    } else if constexpr (is_tiny_matrix_v<TupleContentType>) {
+      switch (value_node.m_data_type) {
+      case ASTNodeDataType::matrix_t: {
+        if ((value_node.m_data_type.numberOfRows() == TupleContentType::NumberOfRows) and
+            (value_node.m_data_type.numberOfColumns() == TupleContentType::NumberOfColumns)) {
+          list_affectation_processor.template add<TupleContentType>(value_node);
+        } else {
+          // LCOV_EXCL_START
+          throw UnexpectedError("invalid vector dimension");
+          // LCOV_EXCL_STOP
+        }
+        break;
+      }
+      case ASTNodeDataType::string_t: {
+        list_affectation_processor.template add<std::string>(value_node);
+        break;
+      }
+        // LCOV_EXCL_START
+      default: {
+        throw UnexpectedError("incompatible tuple types in affectation");
+      }
+        // LCOV_EXCL_STOP
+      }
+    } else if constexpr (std::is_same_v<std::string, TupleContentType>) {
+      if (value_node.m_data_type == ASTNodeDataType::string_t) {
+        list_affectation_processor.template add<std::string>(value_node);
+      } else {
+        // LCOV_EXCL_START
+        throw UnexpectedError("incompatible tuple types in affectation");
+        // LCOV_EXCL_STOP
+      }
+    } else if constexpr (std::is_same_v<EmbeddedData, TupleContentType>) {
+      if (value_node.m_data_type == ASTNodeDataType::type_id_t) {
+        list_affectation_processor.template add<EmbeddedData>(value_node);
+      } else {
+        // LCOV_EXCL_START
+        throw UnexpectedError("incompatible tuple types in affectation");
+        // LCOV_EXCL_STOP
+      }
+    } else {
+      // LCOV_EXCL_START
+      throw UnexpectedError("incompatible tuple types in affectation");
+      // LCOV_EXCL_STOP
+    }
+  }
+}
+
+template <typename OperatorT>
+void
+ASTNodeListAffectationExpressionBuilder::_buildListAffectationFromTupleProcessor()
+{
+  auto& rhs = *m_node.children[1];
+
+  Assert(rhs.m_data_type == ASTNodeDataType::tuple_t);
+
+  const ASTNodeSubDataType tuple_content_type{rhs.m_data_type.contentType(), rhs};
+
+  for (auto&& child : m_node.children[0]->children) {
+    if (child->m_data_type == ASTNodeDataType::tuple_t) {
+      throw ParseError("cannot affect a tuple to a compound type made of tuples", std::vector{child->begin()});
+    }
+
+    ASTNodeNaturalConversionChecker<AllowRToR1Conversion>(tuple_content_type, child->m_data_type);
+  }
+
+  switch (rhs.m_data_type.contentType()) {
+  case ASTNodeDataType::bool_t: {
+    std::unique_ptr list_affectation_processor =
+      std::make_unique<ListAffectationFromTupleProcessor<OperatorT, bool>>(m_node);
+
+    this->_buildListAffectationFromTupleProcessor(*list_affectation_processor);
+
+    m_node.m_node_processor = std::move(list_affectation_processor);
+    break;
+  }
+  case ASTNodeDataType::unsigned_int_t: {
+    std::unique_ptr list_affectation_processor =
+      std::make_unique<ListAffectationFromTupleProcessor<OperatorT, uint64_t>>(m_node);
+
+    this->_buildListAffectationFromTupleProcessor(*list_affectation_processor);
+
+    m_node.m_node_processor = std::move(list_affectation_processor);
+    break;
+  }
+  case ASTNodeDataType::int_t: {
+    std::unique_ptr list_affectation_processor =
+      std::make_unique<ListAffectationFromTupleProcessor<OperatorT, int64_t>>(m_node);
+
+    this->_buildListAffectationFromTupleProcessor(*list_affectation_processor);
+
+    m_node.m_node_processor = std::move(list_affectation_processor);
+    break;
+  }
+  case ASTNodeDataType::double_t: {
+    std::unique_ptr list_affectation_processor =
+      std::make_unique<ListAffectationFromTupleProcessor<OperatorT, double>>(m_node);
+
+    this->_buildListAffectationFromTupleProcessor(*list_affectation_processor);
+
+    m_node.m_node_processor = std::move(list_affectation_processor);
+    break;
+  }
+  case ASTNodeDataType::vector_t: {
+    switch (rhs.m_data_type.contentType().dimension()) {
+    case 1: {
+      std::unique_ptr list_affectation_processor =
+        std::make_unique<ListAffectationFromTupleProcessor<OperatorT, TinyVector<1>>>(m_node);
+
+      this->_buildListAffectationFromTupleProcessor(*list_affectation_processor);
+
+      m_node.m_node_processor = std::move(list_affectation_processor);
+      break;
+    }
+    case 2: {
+      std::unique_ptr list_affectation_processor =
+        std::make_unique<ListAffectationFromTupleProcessor<OperatorT, TinyVector<2>>>(m_node);
+
+      this->_buildListAffectationFromTupleProcessor(*list_affectation_processor);
+
+      m_node.m_node_processor = std::move(list_affectation_processor);
+      break;
+    }
+    case 3: {
+      std::unique_ptr list_affectation_processor =
+        std::make_unique<ListAffectationFromTupleProcessor<OperatorT, TinyVector<3>>>(m_node);
+
+      this->_buildListAffectationFromTupleProcessor(*list_affectation_processor);
+
+      m_node.m_node_processor = std::move(list_affectation_processor);
+      break;
+    }
+      // LCOV_EXCL_START
+    default: {
+      throw UnexpectedError("invalid vector dimension");
+    }
+      // LCOV_EXCL_STOP
+    }
+    break;
+  }
+  case ASTNodeDataType::matrix_t: {
+    if (rhs.m_data_type.contentType().numberOfColumns() != rhs.m_data_type.contentType().numberOfRows()) {
+      // LCOV_EXCL_START
+      throw UnexpectedError("invalid matrix dimensions");
+      // LCOV_EXCL_STOP
+    }
+    switch (rhs.m_data_type.contentType().numberOfColumns()) {
+    case 1: {
+      std::unique_ptr list_affectation_processor =
+        std::make_unique<ListAffectationFromTupleProcessor<OperatorT, TinyMatrix<1>>>(m_node);
+
+      this->_buildListAffectationFromTupleProcessor(*list_affectation_processor);
+
+      m_node.m_node_processor = std::move(list_affectation_processor);
+      break;
+    }
+    case 2: {
+      std::unique_ptr list_affectation_processor =
+        std::make_unique<ListAffectationFromTupleProcessor<OperatorT, TinyMatrix<2>>>(m_node);
+
+      this->_buildListAffectationFromTupleProcessor(*list_affectation_processor);
+
+      m_node.m_node_processor = std::move(list_affectation_processor);
+      break;
+    }
+    case 3: {
+      std::unique_ptr list_affectation_processor =
+        std::make_unique<ListAffectationFromTupleProcessor<OperatorT, TinyMatrix<3>>>(m_node);
+
+      this->_buildListAffectationFromTupleProcessor(*list_affectation_processor);
+
+      m_node.m_node_processor = std::move(list_affectation_processor);
+      break;
+    }
+      // LCOV_EXCL_START
+    default: {
+      throw UnexpectedError("invalid matrix dimensions");
+    }
+      // LCOV_EXCL_STOP
+    }
+    break;
+  }
+  case ASTNodeDataType::string_t: {
+    std::unique_ptr list_affectation_processor =
+      std::make_unique<ListAffectationFromTupleProcessor<OperatorT, std::string>>(m_node);
+
+    this->_buildListAffectationFromTupleProcessor(*list_affectation_processor);
+
+    m_node.m_node_processor = std::move(list_affectation_processor);
+    break;
+  }
+  case ASTNodeDataType::type_id_t: {
+    std::unique_ptr list_affectation_processor =
+      std::make_unique<ListAffectationFromTupleProcessor<OperatorT, EmbeddedData>>(m_node);
+
+    this->_buildListAffectationFromTupleProcessor(*list_affectation_processor);
+
+    m_node.m_node_processor = std::move(list_affectation_processor);
+    break;
+  }
+    // LCOV_EXCL_START
+  default: {
+    throw UnexpectedError("undefined affectation type");
+  }
+    // LCOV_EXCL_STOP
+  }
+}
+
 template <typename OperatorT>
 void
 ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor(
@@ -905,9 +1270,14 @@ ASTNodeListAffectationExpressionBuilder::_buildListAffectationProcessor()
 ASTNodeListAffectationExpressionBuilder::ASTNodeListAffectationExpressionBuilder(ASTNode& node) : m_node(node)
 {
   if (node.children[1]->is_type<language::expression_list>() or
-      node.children[1]->is_type<language::function_evaluation>()) {
+      node.children[1]->is_type<language::function_evaluation>() or
+      (node.children[1]->m_data_type == ASTNodeDataType::tuple_t)) {
     if (node.is_type<language::eq_op>()) {
-      this->_buildListAffectationProcessor<language::eq_op>();
+      if (node.children[1]->m_data_type == ASTNodeDataType::tuple_t) {
+        this->_buildListAffectationFromTupleProcessor<language::eq_op>();
+      } else {
+        this->_buildListAffectationProcessor<language::eq_op>();
+      }
     } else {
       throw ParseError("undefined affectation operator for lists", std::vector{node.begin()});
     }
diff --git a/src/language/ast/ASTNodeListAffectationExpressionBuilder.hpp b/src/language/ast/ASTNodeListAffectationExpressionBuilder.hpp
index 50aaf94d27d364ecb5f40a3b125e09470c4b9d56..1cda4a94402b9d1803e0731484bf51a4eb8c2a14 100644
--- a/src/language/ast/ASTNodeListAffectationExpressionBuilder.hpp
+++ b/src/language/ast/ASTNodeListAffectationExpressionBuilder.hpp
@@ -4,6 +4,9 @@
 #include <language/ast/ASTNode.hpp>
 #include <language/ast/ASTNodeSubDataType.hpp>
 
+template <typename OperatorT, typename TupleType>
+class ListAffectationFromTupleProcessor;
+
 template <typename OperatorT>
 class ListAffectationProcessor;
 
@@ -12,6 +15,12 @@ class ASTNodeListAffectationExpressionBuilder
  private:
   ASTNode& m_node;
 
+  template <typename OperatorT, typename TupleContentType>
+  void _buildListAffectationFromTupleProcessor(ListAffectationFromTupleProcessor<OperatorT, TupleContentType>&);
+
+  template <typename OperatorT>
+  void _buildListAffectationFromTupleProcessor();
+
   template <typename OperatorT>
   void _buildAffectationProcessor(const ASTNodeSubDataType& rhs_node_sub_data_type,
                                   ASTNode& value_node,
diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp
index 4aaace91aacd89b44eb2be5f6ce4e080c5420413..8fea3a7546b9f96298e97b0603a849c84915f47a 100644
--- a/src/language/node_processor/AffectationProcessor.hpp
+++ b/src/language/node_processor/AffectationProcessor.hpp
@@ -82,7 +82,7 @@ struct AffOp<language::minuseq_op>
 
 struct IAffectationExecutor
 {
-  virtual void affect(ExecutionPolicy& exec_policy, DataVariant&& rhs) = 0;
+  virtual void affect(DataVariant&& rhs) = 0;
 
   IAffectationExecutor(const IAffectationExecutor&) = delete;
   IAffectationExecutor(IAffectationExecutor&&)      = delete;
@@ -101,9 +101,7 @@ class AffectationExecutor final : public IAffectationExecutor
 
   static inline const bool m_is_defined{[] {
     if constexpr (std::is_same_v<std::decay_t<ValueT>, bool>) {
-      if constexpr (not std::is_same_v<OperatorT, language::eq_op>) {
-        return false;
-      }
+      return std::is_same_v<OperatorT, language::eq_op>;
     }
     return true;
   }()};
@@ -119,7 +117,7 @@ class AffectationExecutor final : public IAffectationExecutor
   }
 
   PUGS_INLINE void
-  affect(ExecutionPolicy&, DataVariant&& rhs)
+  affect(DataVariant&& rhs)
   {
     if constexpr (m_is_defined) {
       if constexpr (not std::is_same_v<DataT, ZeroType>) {
@@ -459,7 +457,7 @@ class AffectationProcessor final : public INodeProcessor
   execute(ExecutionPolicy& exec_policy)
   {
     try {
-      m_affectation_executor->affect(exec_policy, m_rhs_node.execute(exec_policy));
+      m_affectation_executor->affect(m_rhs_node.execute(exec_policy));
     }
     catch (std::domain_error& e) {
       throw ParseError(e.what(), m_rhs_node.begin());
@@ -620,15 +618,6 @@ class AffectationToTupleFromListProcessor final : public AffectationToDataVarian
  private:
   ASTNode& m_rhs_node;
 
-  template <typename T>
-  std::string
-  stringify(const T& value)
-  {
-    std::ostringstream os;
-    os << std::boolalpha << value;
-    return os.str();
-  }
-
   void
   _copyAggregateDataVariant(const AggregateDataVariant& children_values)
   {
@@ -727,15 +716,6 @@ class AffectationToTupleFromTupleProcessor final : public AffectationToDataVaria
  private:
   ASTNode& m_rhs_node;
 
-  template <typename T>
-  std::string
-  stringify(const T& value)
-  {
-    std::ostringstream os;
-    os << std::boolalpha << value;
-    return os.str();
-  }
-
   template <typename DataType>
   void
   _copyVector(const std::vector<DataType>& values)
@@ -857,7 +837,7 @@ class ListAffectationProcessor final : public INodeProcessor
     Assert(m_affectation_executor_list.size() == children_values.size());
     for (size_t i = 0; i < m_affectation_executor_list.size(); ++i) {
       try {
-        m_affectation_executor_list[i]->affect(exec_policy, std::move(children_values[i]));
+        m_affectation_executor_list[i]->affect(std::move(children_values[i]));
       }
       catch (std::domain_error& e) {
         throw ParseError(e.what(), m_node.children[1]->children[i]->begin());
@@ -869,4 +849,123 @@ class ListAffectationProcessor final : public INodeProcessor
   ListAffectationProcessor(ASTNode& node) : m_node{node} {}
 };
 
+struct IAffectationFromTupleExecutor
+{
+  virtual void affect(ExecutionPolicy& exec_policy, DataVariant&& rhs) = 0;
+
+  IAffectationFromTupleExecutor(const IAffectationFromTupleExecutor&) = delete;
+  IAffectationFromTupleExecutor(IAffectationFromTupleExecutor&&)      = delete;
+
+  IAffectationFromTupleExecutor() = default;
+
+  virtual ~IAffectationFromTupleExecutor() = default;
+};
+
+template <typename OperatorT, typename ValueT, typename DataT>
+class AffectationFromTupleExecutor final : public IAffectationFromTupleExecutor
+{
+ private:
+  DataVariant& m_lhs;
+  ASTNode& m_node;
+
+  static_assert(std::is_same_v<OperatorT, language::eq_op>);
+
+ public:
+  AffectationFromTupleExecutor(ASTNode& node, DataVariant& lhs) : m_lhs{lhs}, m_node{node} {}
+
+  PUGS_INLINE void
+  affect(ExecutionPolicy&, DataVariant&& rhs) final
+  {
+    if constexpr (std::is_same_v<DataT, ValueT>) {
+      m_lhs = rhs;
+    } else if constexpr (std::is_convertible_v<DataT, ValueT>) {
+      const DataT& v = std::get<DataT>(rhs);
+      if constexpr (std::is_same_v<int64_t, DataT> and std::is_same_v<uint64_t, ValueT>) {
+        if (v < 0) {
+          throw std::domain_error("trying to affect negative value (" + stringify(v) + ")");
+        }
+      }
+      m_lhs = static_cast<ValueT>(v);
+    } else if constexpr ((std::is_same_v<ValueT, TinyVector<1>>)and(std::is_arithmetic_v<DataT>)) {
+      m_lhs = std::move(ValueT(std::get<DataT>(rhs)));
+    } else if constexpr ((std::is_same_v<ValueT, TinyMatrix<1>>)and(std::is_arithmetic_v<DataT>)) {
+      m_lhs = std::move(ValueT(std::get<DataT>(rhs)));
+    } else if constexpr (std::is_same_v<ValueT, std::string>) {
+      m_lhs = std::move(stringify(std::get<DataT>(rhs)));
+    } else {
+      // LCOV_EXCL_START
+      throw UnexpectedError("incompatible types in affectation from tuple");
+      // LCOV_EXCL_STOP
+    }
+  }
+};
+
+template <typename OperatorT, typename TupleContentType>
+class ListAffectationFromTupleProcessor final : public INodeProcessor
+{
+ public:
+  static_assert(not is_std_vector_v<TupleContentType>);
+
+ private:
+  ASTNode& m_node;
+
+  std::vector<std::unique_ptr<IAffectationFromTupleExecutor>> m_affectation_executor_list;
+
+ public:
+  template <typename ValueT>
+  void
+  add(ASTNode& lhs_node)
+  {
+    using DataT = std::decay_t<TupleContentType>;
+
+    using AffectationExecutorT = AffectationFromTupleExecutor<OperatorT, ValueT, DataT>;
+
+    if (lhs_node.is_type<language::name>()) {
+      const std::string& symbol = lhs_node.string();
+      auto [i_symbol, found]    = m_node.m_symbol_table->find(symbol, m_node.children[0]->end());
+      Assert(found);
+      DataVariant& value = i_symbol->attributes().value();
+
+      if (not std::holds_alternative<ValueT>(value)) {
+        value = ValueT{};
+      }
+
+      m_affectation_executor_list.emplace_back(std::make_unique<AffectationExecutorT>(m_node, value));
+    } else {
+      // LCOV_EXCL_START
+      throw UnexpectedError("invalid left hand side");
+      // LCOV_EXCL_STOP
+    }
+  }
+
+  DataVariant
+  execute(ExecutionPolicy& exec_policy)
+  {
+    using TupleType = std::vector<TupleContentType>;
+
+    TupleType tuple_values = std::move(std::get<TupleType>(m_node.children[1]->execute(exec_policy)));
+
+    if (m_affectation_executor_list.size() == tuple_values.size()) {
+      for (size_t i = 0; i < m_affectation_executor_list.size(); ++i) {
+        try {
+          m_affectation_executor_list[i]->affect(exec_policy,
+                                                 DataVariant(static_cast<TupleContentType>(tuple_values[i])));
+        }
+        catch (std::domain_error& e) {
+          throw ParseError(e.what(), m_node.children[1]->begin());
+        }
+      }
+    } else {
+      std::ostringstream error_msg;
+      error_msg << "cannot affect a " << rang::fgB::yellow << dataTypeName(m_node.children[1]->m_data_type)
+                << rang::fg::reset << " of size " << tuple_values.size() << " to a " << rang::fgB::yellow
+                << dataTypeName(m_node.children[0]->m_data_type) << rang::fg::reset;
+      throw ParseError(error_msg.str(), m_node.children[1]->begin());
+    }
+    return {};
+  }
+
+  ListAffectationFromTupleProcessor(ASTNode& node) : m_node{node} {}
+};
+
 #endif   // AFFECTATION_PROCESSOR_HPP
diff --git a/tests/test_ASTNodeAffectationExpressionBuilder.cpp b/tests/test_ASTNodeAffectationExpressionBuilder.cpp
index c20490e5a2d6e872ee4d0e6533a95fd839eccb65..36d82b038c4a8211ebfd28b9033b3aa2994751f9 100644
--- a/tests/test_ASTNodeAffectationExpressionBuilder.cpp
+++ b/tests/test_ASTNodeAffectationExpressionBuilder.cpp
@@ -171,7 +171,9 @@ const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const dou
     OperatorRepository::instance().reset();                                                                     \
   }
 
+#ifdef __clang__
 #pragma clang optimize off
+#endif   // __clang__
 
 // clazy:excludeall=non-pod-global-static
 
@@ -2419,7 +2421,7 @@ let t : (builtin_t), t = a;
 let bt: builtin_t, bt = t;
 )";
 
-        std::string_view result = R"(
+        std::string result = R"(
 (root:ASTNodeListProcessor)
  +-(language::eq_op:AffectationToTupleProcessor<EmbeddedData>)
  |   +-(language::name:t:NameProcessor)
@@ -7486,4 +7488,6 @@ let v :(R^3x3), v = bt;
   }
 }
 
+#ifdef __clang__
 #pragma clang optimize on
+#endif   // __clang__
diff --git a/tests/test_ASTNodeListAffectationExpressionBuilder.cpp b/tests/test_ASTNodeListAffectationExpressionBuilder.cpp
index 9a02c71a3068cd3bc59e91f800d746445a5d777d..3f71228607f80f2ac04ad69fc408258ced89b413 100644
--- a/tests/test_ASTNodeListAffectationExpressionBuilder.cpp
+++ b/tests/test_ASTNodeListAffectationExpressionBuilder.cpp
@@ -61,25 +61,37 @@ const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const dou
     REQUIRE(ast_output.str() == expected_output);                                                               \
   }
 
-#define CHECK_AST_THROWS_WITH(data, error)                                         \
-  {                                                                                \
-    static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>); \
-    static_assert(std::is_same_v<std::decay_t<decltype(error)>, std::string>);     \
-                                                                                   \
-    TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"};                     \
-    auto ast = ASTBuilder::build(input);                                           \
-                                                                                   \
-    ASTModulesImporter{*ast};                                                      \
-    ASTNodeTypeCleaner<language::import_instruction>{*ast};                        \
-                                                                                   \
-    ASTSymbolTableBuilder{*ast};                                                   \
-    ASTNodeDataTypeBuilder{*ast};                                                  \
-                                                                                   \
-    ASTNodeDeclarationToAffectationConverter{*ast};                                \
-    ASTNodeTypeCleaner<language::var_declaration>{*ast};                           \
-    ASTNodeTypeCleaner<language::fct_declaration>{*ast};                           \
-                                                                                   \
-    REQUIRE_THROWS_WITH(ASTNodeExpressionBuilder{*ast}, error);                    \
+#define CHECK_AST_THROWS_WITH(data, error)                                                                      \
+  {                                                                                                             \
+    static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>);                              \
+    static_assert(std::is_same_v<std::decay_t<decltype(error)>, std::string>);                                  \
+                                                                                                                \
+    TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"};                                                  \
+    auto ast = ASTBuilder::build(input);                                                                        \
+                                                                                                                \
+    ASTModulesImporter{*ast};                                                                                   \
+    BasicAffectationRegisterFor<EmbeddedData>{ASTNodeDataType::build<ASTNodeDataType::type_id_t>("builtin_t")}; \
+                                                                                                                \
+    ASTNodeTypeCleaner<language::import_instruction>{*ast};                                                     \
+    SymbolTable& symbol_table = *ast->m_symbol_table;                                                           \
+    auto [i_symbol, success]  = symbol_table.add(builtin_data_type.nameOfTypeId(), ast->begin());               \
+    if (not success) {                                                                                          \
+      throw UnexpectedError("cannot add '" + builtin_data_type.nameOfTypeId() + "' type for testing");          \
+    }                                                                                                           \
+                                                                                                                \
+    i_symbol->attributes().setDataType(ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>());              \
+    i_symbol->attributes().setIsInitialized();                                                                  \
+    i_symbol->attributes().value() = symbol_table.typeEmbedderTable().size();                                   \
+    symbol_table.typeEmbedderTable().add(std::make_shared<TypeDescriptor>(builtin_data_type.nameOfTypeId()));   \
+                                                                                                                \
+    ASTSymbolTableBuilder{*ast};                                                                                \
+    ASTNodeDataTypeBuilder{*ast};                                                                               \
+                                                                                                                \
+    ASTNodeDeclarationToAffectationConverter{*ast};                                                             \
+    ASTNodeTypeCleaner<language::var_declaration>{*ast};                                                        \
+    ASTNodeTypeCleaner<language::fct_declaration>{*ast};                                                        \
+                                                                                                                \
+    REQUIRE_THROWS_WITH(ASTNodeExpressionBuilder{*ast}, error);                                                 \
   }
 
 // clazy:excludeall=non-pod-global-static
@@ -1507,106 +1519,1607 @@ let (b0,b1): builtin_t*builtin_t, (b0,b1) = (b0,b1);
     }
   }
 
-  SECTION("Errors")
+  SECTION("list from tuple")
   {
-    SECTION("invalid affectation rhs")
+    SECTION("(B) -> list")
     {
       std::string_view data = R"(
-let x:R;
-let i:R;
-(x,i) = 3;
+let t : (B), t = (true, false, true, false, false, true, false);
+let (b,n,z,r,x1,x11,s):B*N*Z*R*R^1*R^1x1*string,
+    (b,n,z,r,x1,x11,s) = t;
 )";
 
-      CHECK_AST_THROWS_WITH(data, std::string{"invalid right hand side in list affectation"});
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ +-(language::eq_op:AffectationToTupleFromListProcessor<bool>)
+ |   +-(language::name:t:NameProcessor)
+ |   `-(language::expression_list:ASTNodeExpressionListProcessor)
+ |       +-(language::true_kw:ValueProcessor)
+ |       +-(language::false_kw:ValueProcessor)
+ |       +-(language::true_kw:ValueProcessor)
+ |       +-(language::false_kw:ValueProcessor)
+ |       +-(language::false_kw:ValueProcessor)
+ |       +-(language::true_kw:ValueProcessor)
+ |       `-(language::false_kw:ValueProcessor)
+ `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, bool>)
+     +-(language::name_list:FakeProcessor)
+     |   +-(language::name:b:NameProcessor)
+     |   +-(language::name:n:NameProcessor)
+     |   +-(language::name:z:NameProcessor)
+     |   +-(language::name:r:NameProcessor)
+     |   +-(language::name:x1:NameProcessor)
+     |   +-(language::name:x11:NameProcessor)
+     |   `-(language::name:s:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
     }
 
-    SECTION("incompatible list sizes")
+    SECTION("(N) -> list")
     {
       std::string_view data = R"(
-let (x,y) : R*R, (x,y) = (3, 3, 2);
+let t : (N), t = (1, 3, 6, 2, 7, 1);
+let (n,z,r,x1,x11,s):N*Z*R*R^1*R^1x1*string,
+    (n,z,r,x1,x11,s) = t;
 )";
 
-      CHECK_AST_THROWS_WITH(data, std::string{"incompatible list sizes in affectation"});
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ +-(language::eq_op:AffectationToTupleFromListProcessor<unsigned long>)
+ |   +-(language::name:t:NameProcessor)
+ |   `-(language::expression_list:ASTNodeExpressionListProcessor)
+ |       +-(language::integer:1:ValueProcessor)
+ |       +-(language::integer:3:ValueProcessor)
+ |       +-(language::integer:6:ValueProcessor)
+ |       +-(language::integer:2:ValueProcessor)
+ |       +-(language::integer:7:ValueProcessor)
+ |       `-(language::integer:1:ValueProcessor)
+ `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, unsigned long>)
+     +-(language::name_list:FakeProcessor)
+     |   +-(language::name:n:NameProcessor)
+     |   +-(language::name:z:NameProcessor)
+     |   +-(language::name:r:NameProcessor)
+     |   +-(language::name:x1:NameProcessor)
+     |   +-(language::name:x11:NameProcessor)
+     |   `-(language::name:s:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
     }
 
-    SECTION("incompatible list sizes 2")
+    SECTION("(Z) -> list")
     {
       std::string_view data = R"(
-let (x,y,z):R*R*R, (x,y,z) = (1, 2);
+let t : (Z), t = (1, 3, 6, 2, 7, 1);
+let (n,z,r,x1,x11,s):N*Z*R*R^1*R^1x1*string,
+    (n,z,r,x1,x11,s) = t;
 )";
 
-      CHECK_AST_THROWS_WITH(data, std::string{"incompatible list sizes in affectation"});
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ +-(language::eq_op:AffectationToTupleFromListProcessor<long>)
+ |   +-(language::name:t:NameProcessor)
+ |   `-(language::expression_list:ASTNodeExpressionListProcessor)
+ |       +-(language::integer:1:ValueProcessor)
+ |       +-(language::integer:3:ValueProcessor)
+ |       +-(language::integer:6:ValueProcessor)
+ |       +-(language::integer:2:ValueProcessor)
+ |       +-(language::integer:7:ValueProcessor)
+ |       `-(language::integer:1:ValueProcessor)
+ `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, long>)
+     +-(language::name_list:FakeProcessor)
+     |   +-(language::name:n:NameProcessor)
+     |   +-(language::name:z:NameProcessor)
+     |   +-(language::name:r:NameProcessor)
+     |   +-(language::name:x1:NameProcessor)
+     |   +-(language::name:x11:NameProcessor)
+     |   `-(language::name:s:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
     }
 
-    SECTION("incompatible list sizes from function evaluation")
+    SECTION("(R) -> list")
     {
       std::string_view data = R"(
-let f: R -> R, x -> x*x;
-let(x,y) : R*R, (x,y) = f(3);
+let t : (R), t = (6.2, -2.1, 7.2, 3);
+let (r,x1,x11,s):R*R^1*R^1x1*string,
+    (r,x1,x11,s) = t;
 )";
 
-      CHECK_AST_THROWS_WITH(data, std::string{"incompatible list sizes in affectation"});
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ +-(language::eq_op:AffectationToTupleFromListProcessor<double>)
+ |   +-(language::name:t:NameProcessor)
+ |   `-(language::expression_list:ASTNodeExpressionListProcessor)
+ |       +-(language::real:6.2:ValueProcessor)
+ |       +-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, double, double>)
+ |       |   `-(language::real:2.1:ValueProcessor)
+ |       +-(language::real:7.2:ValueProcessor)
+ |       `-(language::integer:3:ValueProcessor)
+ `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, double>)
+     +-(language::name_list:FakeProcessor)
+     |   +-(language::name:r:NameProcessor)
+     |   +-(language::name:x1:NameProcessor)
+     |   +-(language::name:x11:NameProcessor)
+     |   `-(language::name:s:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
     }
 
-    SECTION("incompatible list sizes from function evaluation")
+    SECTION("(R^1) -> list")
     {
       std::string_view data = R"(
-let(x,y):R*R,(x,y)=(2,3);
-(x,y) += (1,4);
+let t : (R^1), t = (6.2, [-2.1]);
+let (x1,s):R^1*string,
+    (x1,s) = t;
 )";
 
-      CHECK_AST_THROWS_WITH(data, std::string{"undefined affectation operator for lists"});
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ +-(language::eq_op:AffectationToTupleFromListProcessor<TinyVector<1ul, double> >)
+ |   +-(language::name:t:NameProcessor)
+ |   `-(language::expression_list:ASTNodeExpressionListProcessor)
+ |       +-(language::real:6.2:ValueProcessor)
+ |       `-(language::vector_expression:TinyVectorExpressionProcessor<1ul>)
+ |           `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, double, double>)
+ |               `-(language::real:2.1:ValueProcessor)
+ `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, TinyVector<1ul, double> >)
+     +-(language::name_list:FakeProcessor)
+     |   +-(language::name:x1:NameProcessor)
+     |   `-(language::name:s:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
     }
 
-    SECTION("invalid operand type for affectation")
+    SECTION("(R^2) -> list")
     {
       std::string_view data = R"(
-let f: R -> R, x -> x+1;
-let  (x,y) : R*R, (x,y) = (f,2);
+let t : (R^2), t = ([6.2, -2.1], 0);
+let (x2,s):R^2*string,
+    (x2,s) = t;
 )";
 
-      CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: function -> R"});
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ +-(language::eq_op:AffectationToTupleFromListProcessor<TinyVector<2ul, double> >)
+ |   +-(language::name:t:NameProcessor)
+ |   `-(language::expression_list:ASTNodeExpressionListProcessor)
+ |       +-(language::vector_expression:TinyVectorExpressionProcessor<2ul>)
+ |       |   +-(language::real:6.2:ValueProcessor)
+ |       |   `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, double, double>)
+ |       |       `-(language::real:2.1:ValueProcessor)
+ |       `-(language::integer:0:ValueProcessor)
+ `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, TinyVector<2ul, double> >)
+     +-(language::name_list:FakeProcessor)
+     |   +-(language::name:x2:NameProcessor)
+     |   `-(language::name:s:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
     }
 
-    SECTION("invalid operand type for string affectation")
+    SECTION("(R^3) -> list")
     {
       std::string_view data = R"(
-let f: R -> R, x -> x+1;
-let (s,n):string*N, (s,n) = (f,2);
+let t : (R^3), t = ([6.2, -2.1, 0], [1, 2, 3]);
+let (x3,s):R^3*string,
+    (x3,s) = t;
 )";
 
-      CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: function -> string"});
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ +-(language::eq_op:AffectationToTupleFromListProcessor<TinyVector<3ul, double> >)
+ |   +-(language::name:t:NameProcessor)
+ |   `-(language::expression_list:ASTNodeExpressionListProcessor)
+ |       +-(language::vector_expression:TinyVectorExpressionProcessor<3ul>)
+ |       |   +-(language::real:6.2:ValueProcessor)
+ |       |   +-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, double, double>)
+ |       |   |   `-(language::real:2.1:ValueProcessor)
+ |       |   `-(language::integer:0:ValueProcessor)
+ |       `-(language::vector_expression:TinyVectorExpressionProcessor<3ul>)
+ |           +-(language::integer:1:ValueProcessor)
+ |           +-(language::integer:2:ValueProcessor)
+ |           `-(language::integer:3:ValueProcessor)
+ `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, TinyVector<3ul, double> >)
+     +-(language::name_list:FakeProcessor)
+     |   +-(language::name:x3:NameProcessor)
+     |   `-(language::name:s:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
     }
 
-    SECTION("invalid value type for affectation")
+    SECTION("(R^1x1) -> list")
     {
       std::string_view data = R"(
-let f: R -> R, x -> x+1;
-let x:R;
+let t : (R^1x1), t = (6.2, [[-2.1]]);
+let (x11,s):R^1x1*string,
+    (x11,s) = t;
+)";
 
-(f,x) = (3,2);
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ +-(language::eq_op:AffectationToTupleFromListProcessor<TinyMatrix<1ul, 1ul, double> >)
+ |   +-(language::name:t:NameProcessor)
+ |   `-(language::expression_list:ASTNodeExpressionListProcessor)
+ |       +-(language::real:6.2:ValueProcessor)
+ |       `-(language::matrix_expression:TinyMatrixExpressionProcessor<1ul, 1ul>)
+ |           `-(language::row_expression:FakeProcessor)
+ |               `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, double, double>)
+ |                   `-(language::real:2.1:ValueProcessor)
+ `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, TinyMatrix<1ul, 1ul, double> >)
+     +-(language::name_list:FakeProcessor)
+     |   +-(language::name:x11:NameProcessor)
+     |   `-(language::name:s:NameProcessor)
+     `-(language::name:t:NameProcessor)
 )";
 
-      CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> function"});
+      CHECK_AST(data, result);
     }
 
-    SECTION("invalid R^n -> R^m conversion")
+    SECTION("(R^2x2) -> list")
     {
       std::string_view data = R"(
-let x:R^2, x = [1,2];
-let y:R^3, y = x;
+let t : (R^2x2), t = ([[6.2, -2.1],[1, 2]], 0);
+let (x22,s):R^2x2*string,
+    (x22,s) = t;
 )";
 
-      CHECK_AST_THROWS_WITH(data, std::string{"undefined affectation type: R^3 = R^2"});
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ +-(language::eq_op:AffectationToTupleFromListProcessor<TinyMatrix<2ul, 2ul, double> >)
+ |   +-(language::name:t:NameProcessor)
+ |   `-(language::expression_list:ASTNodeExpressionListProcessor)
+ |       +-(language::matrix_expression:TinyMatrixExpressionProcessor<2ul, 2ul>)
+ |       |   +-(language::row_expression:FakeProcessor)
+ |       |   |   +-(language::real:6.2:ValueProcessor)
+ |       |   |   `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, double, double>)
+ |       |   |       `-(language::real:2.1:ValueProcessor)
+ |       |   `-(language::row_expression:FakeProcessor)
+ |       |       +-(language::integer:1:ValueProcessor)
+ |       |       `-(language::integer:2:ValueProcessor)
+ |       `-(language::integer:0:ValueProcessor)
+ `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, TinyMatrix<2ul, 2ul, double> >)
+     +-(language::name_list:FakeProcessor)
+     |   +-(language::name:x22:NameProcessor)
+     |   `-(language::name:s:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
     }
 
-    SECTION("invalid Z -> R^d conversion (non-zero)")
+    SECTION("(R^3x3) -> list")
     {
       std::string_view data = R"(
-let x:R^2, x = 1;
+let t : (R^3x3), t = ([[6.2, -2.1, 0], [1, 2, 3], [0, -2, 1]], 0);
+let (x33,s):R^3x3*string,
+    (x33,s) = t;
 )";
 
-      CHECK_AST_THROWS_WITH(data, std::string{"invalid integral value (0 is the solely valid value)"});
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ +-(language::eq_op:AffectationToTupleFromListProcessor<TinyMatrix<3ul, 3ul, double> >)
+ |   +-(language::name:t:NameProcessor)
+ |   `-(language::expression_list:ASTNodeExpressionListProcessor)
+ |       +-(language::matrix_expression:TinyMatrixExpressionProcessor<3ul, 3ul>)
+ |       |   +-(language::row_expression:FakeProcessor)
+ |       |   |   +-(language::real:6.2:ValueProcessor)
+ |       |   |   +-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, double, double>)
+ |       |   |   |   `-(language::real:2.1:ValueProcessor)
+ |       |   |   `-(language::integer:0:ValueProcessor)
+ |       |   +-(language::row_expression:FakeProcessor)
+ |       |   |   +-(language::integer:1:ValueProcessor)
+ |       |   |   +-(language::integer:2:ValueProcessor)
+ |       |   |   `-(language::integer:3:ValueProcessor)
+ |       |   `-(language::row_expression:FakeProcessor)
+ |       |       +-(language::integer:0:ValueProcessor)
+ |       |       +-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>)
+ |       |       |   `-(language::integer:2:ValueProcessor)
+ |       |       `-(language::integer:1:ValueProcessor)
+ |       `-(language::integer:0:ValueProcessor)
+ `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, TinyMatrix<3ul, 3ul, double> >)
+     +-(language::name_list:FakeProcessor)
+     |   +-(language::name:x33:NameProcessor)
+     |   `-(language::name:s:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("(string) -> list")
+    {
+      std::string_view data = R"(
+let t : (string), t = ("foo", "bar", "foobar");
+let (s1,s2,s3):string*string*string,
+    (s1,s2,s3) = t;
+)";
+
+      std::string result = R"(
+(root:ASTNodeListProcessor)
+ +-(language::eq_op:AffectationToTupleFromListProcessor<)" +
+                           demangled_stdstring + R"( >)
+ |   +-(language::name:t:NameProcessor)
+ |   `-(language::expression_list:ASTNodeExpressionListProcessor)
+ |       +-(language::literal:"foo":ValueProcessor)
+ |       +-(language::literal:"bar":ValueProcessor)
+ |       `-(language::literal:"foobar":ValueProcessor)
+ `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, )" +
+                           demangled_stdstring + R"( >)
+     +-(language::name_list:FakeProcessor)
+     |   +-(language::name:s1:NameProcessor)
+     |   +-(language::name:s2:NameProcessor)
+     |   `-(language::name:s3:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("(builtin_t) -> list")
+    {
+      std::string_view data = R"(
+let b: builtin_t, b = b;
+let t: (builtin_t), t = (b,b,b);
+let (b1,b2,b3): builtin_t*builtin_t*builtin_t, (b1,b2,b3) = t;
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ +-(language::eq_op:AffectationProcessor<language::eq_op, EmbeddedData, EmbeddedData>)
+ |   +-(language::name:b:NameProcessor)
+ |   `-(language::name:b:NameProcessor)
+ +-(language::eq_op:AffectationToTupleFromListProcessor<EmbeddedData>)
+ |   +-(language::name:t:NameProcessor)
+ |   `-(language::expression_list:ASTNodeExpressionListProcessor)
+ |       +-(language::name:b:NameProcessor)
+ |       +-(language::name:b:NameProcessor)
+ |       `-(language::name:b:NameProcessor)
+ `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, EmbeddedData>)
+     +-(language::name_list:FakeProcessor)
+     |   +-(language::name:b1:NameProcessor)
+     |   +-(language::name:b2:NameProcessor)
+     |   `-(language::name:b3:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+  }
+
+  SECTION("Errors")
+  {
+    SECTION("invalid affectation rhs")
+    {
+      std::string_view data = R"(
+let x:R;
+let i:R;
+(x,i) = 3;
+)";
+
+      CHECK_AST_THROWS_WITH(data, std::string{"invalid right hand side in list affectation"});
+    }
+
+    SECTION("incompatible list sizes")
+    {
+      std::string_view data = R"(
+let (x,y) : R*R, (x,y) = (3, 3, 2);
+)";
+
+      CHECK_AST_THROWS_WITH(data, std::string{"incompatible list sizes in affectation"});
+    }
+
+    SECTION("incompatible list sizes 2")
+    {
+      std::string_view data = R"(
+let (x,y,z):R*R*R, (x,y,z) = (1, 2);
+)";
+
+      CHECK_AST_THROWS_WITH(data, std::string{"incompatible list sizes in affectation"});
+    }
+
+    SECTION("incompatible list sizes from function evaluation")
+    {
+      std::string_view data = R"(
+let f: R -> R, x -> x*x;
+let(x,y) : R*R, (x,y) = f(3);
+)";
+
+      CHECK_AST_THROWS_WITH(data, std::string{"incompatible list sizes in affectation"});
+    }
+
+    SECTION("incompatible list sizes from function evaluation")
+    {
+      std::string_view data = R"(
+let(x,y):R*R,(x,y)=(2,3);
+(x,y) += (1,4);
+)";
+
+      CHECK_AST_THROWS_WITH(data, std::string{"undefined affectation operator for lists"});
+    }
+
+    SECTION("invalid operand type for affectation")
+    {
+      std::string_view data = R"(
+let f: R -> R, x -> x+1;
+let  (x,y) : R*R, (x,y) = (f,2);
+)";
+
+      CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: function -> R"});
+    }
+
+    SECTION("invalid operand type for string affectation")
+    {
+      std::string_view data = R"(
+let f: R -> R, x -> x+1;
+let (s,n):string*N, (s,n) = (f,2);
+)";
+
+      CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: function -> string"});
+    }
+
+    SECTION("invalid value type for affectation")
+    {
+      std::string_view data = R"(
+let f: R -> R, x -> x+1;
+let x:R;
+
+(f,x) = (3,2);
+)";
+
+      CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> function"});
+    }
+
+    SECTION("invalid R^n -> R^m conversion")
+    {
+      std::string_view data = R"(
+let x:R^2, x = [1,2];
+let y:R^3, y = x;
+)";
+
+      CHECK_AST_THROWS_WITH(data, std::string{"undefined affectation type: R^3 = R^2"});
+    }
+
+    SECTION("invalid Z -> R^d conversion (non-zero)")
+    {
+      std::string_view data = R"(
+let x:R^2, x = 1;
+)";
+
+      CHECK_AST_THROWS_WITH(data, std::string{"invalid integral value (0 is the solely valid value)"});
+    }
+
+    SECTION("tuples -> list")
+    {
+      SECTION("bad cast")
+      {
+        SECTION("from (string)")
+        {
+          SECTION("string -> B")
+          {
+            std::string_view data = R"(
+let t:(string), t = ("foo", "bar");
+let (s,b) : string*B, (s,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> B"});
+          }
+
+          SECTION("string -> N")
+          {
+            std::string_view data = R"(
+let t:(string), t = ("foo", "bar");
+let (s,n) : string*N, (s,n) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> N"});
+          }
+
+          SECTION("string -> Z")
+          {
+            std::string_view data = R"(
+let t:(string), t = ("foo", "bar");
+let (z,n) : Z*N, (z,n) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> Z"});
+          }
+
+          SECTION("string -> R")
+          {
+            std::string_view data = R"(
+let t:(string), t = ("foo", "bar");
+let (s,r) : string*R, (s,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R"});
+          }
+
+          SECTION("string -> R^1")
+          {
+            std::string_view data = R"(
+let t:(string), t = ("foo", "bar");
+let (s,r) : string*R^1, (s,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R^1"});
+          }
+
+          SECTION("string -> R^2")
+          {
+            std::string_view data = R"(
+let t:(string), t = ("foo", "bar");
+let (s,r) : string*R^2, (s,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R^2"});
+          }
+
+          SECTION("string -> R^3")
+          {
+            std::string_view data = R"(
+let t:(string), t = ("foo", "bar");
+let (s,r) : string*R^3, (s,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R^3"});
+          }
+
+          SECTION("string -> R^1x1")
+          {
+            std::string_view data = R"(
+let t:(string), t = ("foo", "bar");
+let (s,r) : string*R^1x1, (s,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R^1x1"});
+          }
+
+          SECTION("string -> R^2x2")
+          {
+            std::string_view data = R"(
+let t:(string), t = ("foo", "bar");
+let (s,r) : string*R^2x2, (s,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R^2x2"});
+          }
+
+          SECTION("string -> R^3x3")
+          {
+            std::string_view data = R"(
+let t:(string), t = ("foo", "bar");
+let (s,r) : string*R^3x3, (s,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R^3x3"});
+          }
+
+          SECTION("string -> builtin_t")
+          {
+            std::string_view data = R"(
+let t:(string), t = ("foo", "bar");
+let (s,r) : string*builtin_t, (s,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> builtin_t"});
+          }
+        }
+
+        SECTION("from (builtin_t)")
+        {
+          SECTION("builtin_t -> B")
+          {
+            std::string_view data = R"(
+let bt:builtin_t, bt = bt;
+let t:(builtin_t), t = (bt, bt);
+let (s,b) : builtin_t*B, (s,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> B"});
+          }
+
+          SECTION("builtin_t -> N")
+          {
+            std::string_view data = R"(
+let bt:builtin_t, bt = bt;
+let t:(builtin_t), t = (bt, bt);
+let (s,n) : builtin_t*N, (s,n) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> N"});
+          }
+
+          SECTION("builtin_t -> Z")
+          {
+            std::string_view data = R"(
+let bt:builtin_t, bt = bt;
+let t:(builtin_t), t = (bt, bt);
+let (z,n) : Z*N, (z,n) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> Z"});
+          }
+
+          SECTION("builtin_t -> R")
+          {
+            std::string_view data = R"(
+let bt:builtin_t, bt = bt;
+let t:(builtin_t), t = (bt, bt);
+let (s,r) : builtin_t*R, (s,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> R"});
+          }
+
+          SECTION("builtin_t -> R^1")
+          {
+            std::string_view data = R"(
+let bt:builtin_t, bt = bt;
+let t:(builtin_t), t = (bt, bt);
+let (s,r) : builtin_t*R^1, (s,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> R^1"});
+          }
+
+          SECTION("builtin_t -> R^2")
+          {
+            std::string_view data = R"(
+let bt:builtin_t, bt = bt;
+let t:(builtin_t), t = (bt, bt);
+let (s,r) : builtin_t*R^2, (s,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> R^2"});
+          }
+
+          SECTION("builtin_t -> R^3")
+          {
+            std::string_view data = R"(
+let bt:builtin_t, bt = bt;
+let t:(builtin_t), t = (bt, bt);
+let (s,r) : builtin_t*R^3, (s,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> R^3"});
+          }
+
+          SECTION("builtin_t -> R^1x1")
+          {
+            std::string_view data = R"(
+let bt:builtin_t, bt = bt;
+let t:(builtin_t), t = (bt, bt);
+let (s,r) : builtin_t*R^1x1, (s,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> R^1x1"});
+          }
+
+          SECTION("builtin_t -> R^2x2")
+          {
+            std::string_view data = R"(
+let bt:builtin_t, bt = bt;
+let t:(builtin_t), t = (bt, bt);
+let (s,r) : builtin_t*R^2x2, (s,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> R^2x2"});
+          }
+
+          SECTION("builtin_t -> R^3x3")
+          {
+            std::string_view data = R"(
+let bt:builtin_t, bt = bt;
+let t:(builtin_t), t = (bt, bt);
+let (s,r) : builtin_t*R^3x3, (s,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> R^3x3"});
+          }
+        }
+
+        SECTION("from (B)")
+        {
+          SECTION("B -> R^2")
+          {
+            std::string_view data = R"(
+let t:(B), t = (true, false);
+let (r,b) : R^2*B, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^2"});
+          }
+
+          SECTION("B -> R^3")
+          {
+            std::string_view data = R"(
+let t:(B), t = (true, false);
+let (r,b) : R^3*B, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^3"});
+          }
+
+          SECTION("B -> R^2x2")
+          {
+            std::string_view data = R"(
+let t:(B), t = (true, false);
+let (r,b) : R^2x2*B, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^2x2"});
+          }
+
+          SECTION("B -> R^3x3")
+          {
+            std::string_view data = R"(
+let t:(B), t = (true, false);
+let (r,b) : R^3x3*B, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^3x3"});
+          }
+
+          SECTION("B -> builtin_t")
+          {
+            std::string_view data = R"(
+let t:(B), t = (true, false);
+let (s,b) : string*builtin_t, (s,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> builtin_t"});
+          }
+        }
+
+        SECTION("from (N)")
+        {
+          SECTION("N -> B")
+          {
+            std::string_view data = R"(
+let t:(N), t = (1, 3);
+let (r,b) : B*N, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> B"});
+          }
+
+          SECTION("N -> R^2")
+          {
+            std::string_view data = R"(
+let t:(N), t = (1, 3);
+let (r,b) : R^2*N, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^2"});
+          }
+
+          SECTION("N -> R^3")
+          {
+            std::string_view data = R"(
+let t:(N), t = (1, 3);
+let (r,b) : R^3*N, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^3"});
+          }
+
+          SECTION("N -> R^2x2")
+          {
+            std::string_view data = R"(
+let t:(N), t = (1, 3);
+let (r,b) : R^2x2*N, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^2x2"});
+          }
+
+          SECTION("N -> R^3x3")
+          {
+            std::string_view data = R"(
+let t:(N), t = (1, 3);
+let (r,b) : R^3x3*N, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^3x3"});
+          }
+
+          SECTION("N -> builtin_t")
+          {
+            std::string_view data = R"(
+let t:(N), t = (1, 3);
+let (s,b) : string*builtin_t, (s,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> builtin_t"});
+          }
+        }
+
+        SECTION("from (Z)")
+        {
+          SECTION("Z -> B")
+          {
+            std::string_view data = R"(
+let t:(Z), t = (1, 3);
+let (r,b) : B*Z, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> B"});
+          }
+
+          SECTION("Z -> R^2")
+          {
+            std::string_view data = R"(
+let t:(Z), t = (1, 3);
+let (r,b) : R^2*Z, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^2"});
+          }
+
+          SECTION("Z -> R^3")
+          {
+            std::string_view data = R"(
+let t:(Z), t = (1, 3);
+let (r,b) : R^3*Z, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^3"});
+          }
+
+          SECTION("Z -> R^2x2")
+          {
+            std::string_view data = R"(
+let t:(Z), t = (1, 3);
+let (r,b) : R^2x2*Z, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^2x2"});
+          }
+
+          SECTION("Z -> R^3x3")
+          {
+            std::string_view data = R"(
+let t:(Z), t = (1, 3);
+let (r,b) : R^3x3*Z, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^3x3"});
+          }
+
+          SECTION("Z -> builtin_t")
+          {
+            std::string_view data = R"(
+let t:(Z), t = (1, 3);
+let (s,b) : string*builtin_t, (s,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> builtin_t"});
+          }
+        }
+
+        SECTION("from (R)")
+        {
+          SECTION("R -> B")
+          {
+            std::string_view data = R"(
+let t:(R), t = (1.2, 3.2);
+let (r,b) : R*B, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> B"});
+          }
+
+          SECTION("R -> N")
+          {
+            std::string_view data = R"(
+let t:(R), t = (1.2, 3.2);
+let (r,n) : R*N, (r,n) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> N"});
+          }
+
+          SECTION("R -> Z")
+          {
+            std::string_view data = R"(
+let t:(R), t = (1.2, 3.2);
+let (r,z) : R*Z, (r,z) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> Z"});
+          }
+
+          SECTION("R -> R^2")
+          {
+            std::string_view data = R"(
+let t:(R), t = (1.2, 3.2);
+let (x,r) : R^2*R, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^2"});
+          }
+
+          SECTION("R -> R^3")
+          {
+            std::string_view data = R"(
+let t:(R), t = (1.2, 3.2);
+let (x,r) : R^3*R, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^3"});
+          }
+
+          SECTION("R -> R^2x2")
+          {
+            std::string_view data = R"(
+let t:(R), t = (1.2, 3.2);
+let (x,r) : R^2x2*R, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^2x2"});
+          }
+
+          SECTION("R -> R^3x3")
+          {
+            std::string_view data = R"(
+let t:(R), t = (1.2, 3.2);
+let (x,r) : R^3x3*R, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^3x3"});
+          }
+
+          SECTION("R -> builtin_t")
+          {
+            std::string_view data = R"(
+let t:(R), t = (1.2, 3.2);
+let (s,b) : string*builtin_t, (s,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> builtin_t"});
+          }
+        }
+
+        SECTION("from (R^1)")
+        {
+          SECTION("R^1 -> B")
+          {
+            std::string_view data = R"(
+let t:(R^1), t = (1.2, 3.2);
+let (r,b) : R^1*B, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> B"});
+          }
+
+          SECTION("R^1 -> N")
+          {
+            std::string_view data = R"(
+let t:(R^1), t = (1.2, 3.2);
+let (r,n) : R^1*N, (r,n) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> N"});
+          }
+
+          SECTION("R^1 -> Z")
+          {
+            std::string_view data = R"(
+let t:(R^1), t = (1.2, 3.2);
+let (r,z) : R^1*Z, (r,z) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> Z"});
+          }
+
+          SECTION("R^1 -> R")
+          {
+            std::string_view data = R"(
+let t:(R^1), t = (1.2, 3.2);
+let (r,x) : R^1*R, (r,x) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R"});
+          }
+
+          SECTION("R^1 -> R^2")
+          {
+            std::string_view data = R"(
+let t:(R^1), t = (1.2, 3.2);
+let (x,r) : R^2*R^1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R^2"});
+          }
+
+          SECTION("R^1 -> R^3")
+          {
+            std::string_view data = R"(
+let t:(R^1), t = (1.2, 3.2);
+let (x,r) : R^3*R^1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R^3"});
+          }
+
+          SECTION("R^1 -> R^1x1")
+          {
+            std::string_view data = R"(
+let t:(R^1), t = (1.2, 3.2);
+let (x,r) : R^1x1*R^1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R^1x1"});
+          }
+
+          SECTION("R^1 -> R^2x2")
+          {
+            std::string_view data = R"(
+let t:(R^1), t = (1.2, 3.2);
+let (x,r) : R^2x2*R^1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R^2x2"});
+          }
+
+          SECTION("R^1 -> R^3x3")
+          {
+            std::string_view data = R"(
+let t:(R^1), t = (1.2, 3.2);
+let (x,r) : R^3x3*R^1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R^3x3"});
+          }
+
+          SECTION("R^1 -> builtin_t")
+          {
+            std::string_view data = R"(
+let t:(R^1), t = (1.2, 3.2);
+let (s,b) : string*builtin_t, (s,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> builtin_t"});
+          }
+        }
+
+        SECTION("from (R^2)")
+        {
+          SECTION("R^2 -> B")
+          {
+            std::string_view data = R"(
+let t:(R^2), t = ([1.2, 3.2], 0);
+let (r,b) : R^2*B, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> B"});
+          }
+
+          SECTION("R^2 -> N")
+          {
+            std::string_view data = R"(
+let t:(R^2), t = ([1.2, 3.2], 0);
+let (r,n) : R^2*N, (r,n) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> N"});
+          }
+
+          SECTION("R^2 -> Z")
+          {
+            std::string_view data = R"(
+let t:(R^2), t = ([1.2, 3.2], 0);
+let (r,z) : R^2*Z, (r,z) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> Z"});
+          }
+
+          SECTION("R^2 -> R")
+          {
+            std::string_view data = R"(
+let t:(R^2), t = ([1.2, 3.2], 0);
+let (r,x) : R^2*R, (r,x) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R"});
+          }
+
+          SECTION("R^2 -> R^1")
+          {
+            std::string_view data = R"(
+let t:(R^2), t = ([1.2, 3.2], 0);
+let (x,r) : R^2*R^1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R^1"});
+          }
+
+          SECTION("R^2 -> R^3")
+          {
+            std::string_view data = R"(
+let t:(R^2), t = ([1.2, 3.2], 0);
+let (x,r) : R^3*R^2, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R^3"});
+          }
+
+          SECTION("R^2 -> R^1x1")
+          {
+            std::string_view data = R"(
+let t:(R^2), t = ([1.2, 3.2], 0);
+let (x,r) : R^1x1*R^1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R^1x1"});
+          }
+
+          SECTION("R^2 -> R^2x2")
+          {
+            std::string_view data = R"(
+let t:(R^2), t = ([1.2, 3.2], 0);
+let (x,r) : R^2x2*R^2, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R^2x2"});
+          }
+
+          SECTION("R^2 -> R^3x3")
+          {
+            std::string_view data = R"(
+let t:(R^2), t = ([1.2, 3.2], 0);
+let (x,r) : R^3x3*R^2, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R^3x3"});
+          }
+
+          SECTION("R^2 -> builtin_t")
+          {
+            std::string_view data = R"(
+let t:(R^2), t = ([1.2, 3.2], 0);
+let (s,b) : string*builtin_t, (s,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> builtin_t"});
+          }
+        }
+
+        SECTION("from (R^3)")
+        {
+          SECTION("R^3 -> B")
+          {
+            std::string_view data = R"(
+let t:(R^3), t = ([1.2, 3.2, 1], 0);
+let (r,b) : R^3*B, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> B"});
+          }
+
+          SECTION("R^3 -> N")
+          {
+            std::string_view data = R"(
+let t:(R^3), t = ([1.2, 3.2, 1], 0);
+let (r,n) : R^3*N, (r,n) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> N"});
+          }
+
+          SECTION("R^3 -> Z")
+          {
+            std::string_view data = R"(
+let t:(R^3), t = ([1.2, 3.2, 1], 0);
+let (r,z) : R^3*Z, (r,z) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> Z"});
+          }
+
+          SECTION("R^3 -> R")
+          {
+            std::string_view data = R"(
+let t:(R^3), t = ([1.2, 3.2, 1], 0);
+let (r,x) : R^3*R, (r,x) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> R"});
+          }
+
+          SECTION("R^3 -> R^1")
+          {
+            std::string_view data = R"(
+let t:(R^3), t = ([1.2, 3.2, 1], 0);
+let (x,r) : R^3*R^1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> R^1"});
+          }
+
+          SECTION("R^3 -> R^2")
+          {
+            std::string_view data = R"(
+let t:(R^3), t = ([1.2, 3.2, 1], 0);
+let (x,r) : R^3*R^2, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> R^2"});
+          }
+
+          SECTION("R^3 -> R^1x1")
+          {
+            std::string_view data = R"(
+let t:(R^3), t = ([1.2, 3.2, 1], 0);
+let (x,r) : R^1x1*R^3, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> R^1x1"});
+          }
+
+          SECTION("R^3 -> R^2x2")
+          {
+            std::string_view data = R"(
+let t:(R^3), t = ([1.2, 3.2, 1], 0);
+let (x,r) : R^2x2*R^3, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> R^2x2"});
+          }
+
+          SECTION("R^3 -> R^3x3")
+          {
+            std::string_view data = R"(
+let t:(R^3), t = ([1.2, 3.2, 1], 0);
+let (x,r) : R^3x3*R^2, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> R^3x3"});
+          }
+
+          SECTION("R^3 -> builtin_t")
+          {
+            std::string_view data = R"(
+let t:(R^3), t = ([1.2, 3.2, 1], 0);
+let (s,b) : string*builtin_t, (s,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> builtin_t"});
+          }
+        }
+
+        SECTION("from (R^1x1)")
+        {
+          SECTION("R^1x1 -> B")
+          {
+            std::string_view data = R"(
+let t:(R^1x1), t = (1.2, 3.2);
+let (r,b) : R^1x1*B, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> B"});
+          }
+
+          SECTION("R^1x1 -> N")
+          {
+            std::string_view data = R"(
+let t:(R^1x1), t = (1.2, 3.2);
+let (r,n) : R^1x1*N, (r,n) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> N"});
+          }
+
+          SECTION("R^1x1 -> Z")
+          {
+            std::string_view data = R"(
+let t:(R^1x1), t = (1.2, 3.2);
+let (r,z) : R^1x1*Z, (r,z) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> Z"});
+          }
+
+          SECTION("R^1x1 -> R")
+          {
+            std::string_view data = R"(
+let t:(R^1x1), t = (1.2, 3.2);
+let (r,x) : R^1x1*R, (r,x) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> R"});
+          }
+
+          SECTION("R^1x1 -> R^2")
+          {
+            std::string_view data = R"(
+let t:(R^1x1), t = (1.2, 3.2);
+let (x,r) : R^2*R^1x1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> R^2"});
+          }
+
+          SECTION("R^1x1 -> R^3")
+          {
+            std::string_view data = R"(
+let t:(R^1x1), t = (1.2, 3.2);
+let (x,r) : R^3*R^1x1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> R^3"});
+          }
+
+          SECTION("R^1x1 -> R^1")
+          {
+            std::string_view data = R"(
+let t:(R^1x1), t = (1.2, 3.2);
+let (x,r) : R^1x1*R^1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> R^1"});
+          }
+
+          SECTION("R^1x1 -> R^2x2")
+          {
+            std::string_view data = R"(
+let t:(R^1x1), t = (1.2, 3.2);
+let (x,r) : R^2x2*R^1x1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> R^2x2"});
+          }
+
+          SECTION("R^1x1 -> R^3x3")
+          {
+            std::string_view data = R"(
+let t:(R^1x1), t = (1.2, 3.2);
+let (x,r) : R^3x3*R^1x1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> R^3x3"});
+          }
+
+          SECTION("R^1x1 -> builtin_t")
+          {
+            std::string_view data = R"(
+let t:(R^1x1), t = (1.2, 3.2);
+let (s,b) : string*builtin_t, (s,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> builtin_t"});
+          }
+        }
+
+        SECTION("from (R^2x2)")
+        {
+          SECTION("R^2x2 -> B")
+          {
+            std::string_view data = R"(
+let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0);
+let (r,b) : R^2x2*B, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> B"});
+          }
+
+          SECTION("R^2x2 -> N")
+          {
+            std::string_view data = R"(
+let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0);
+let (r,n) : R^2x2*N, (r,n) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> N"});
+          }
+
+          SECTION("R^2x2 -> Z")
+          {
+            std::string_view data = R"(
+let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0);
+let (r,z) : R^2x2*Z, (r,z) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> Z"});
+          }
+
+          SECTION("R^2x2 -> R")
+          {
+            std::string_view data = R"(
+let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0);
+let (r,x) : R^2x2*R, (r,x) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> R"});
+          }
+
+          SECTION("R^2x2 -> R^2")
+          {
+            std::string_view data = R"(
+let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0);
+let (x,r) : R^2*R^2x2, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> R^2"});
+          }
+
+          SECTION("R^2x2 -> R^3")
+          {
+            std::string_view data = R"(
+let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0);
+let (x,r) : R^3*R^2x2, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> R^3"});
+          }
+
+          SECTION("R^2x2 -> R^1")
+          {
+            std::string_view data = R"(
+let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0);
+let (x,r) : R^2x2*R^1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> R^1"});
+          }
+
+          SECTION("R^2x2 -> R^1x1")
+          {
+            std::string_view data = R"(
+let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0);
+let (x,r) : R^2x2*R^1x1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> R^1x1"});
+          }
+
+          SECTION("R^2x2 -> R^3x3")
+          {
+            std::string_view data = R"(
+let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0);
+let (x,r) : R^3x3*R^2x2, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> R^3x3"});
+          }
+
+          SECTION("R^2x2 -> builtin_t")
+          {
+            std::string_view data = R"(
+let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0);
+let (s,b) : string*builtin_t, (s,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> builtin_t"});
+          }
+        }
+
+        SECTION("from (R^3x3)")
+        {
+          SECTION("R^3x3 -> B")
+          {
+            std::string_view data = R"(
+let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0);
+let (r,b) : R^3x3*B, (r,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> B"});
+          }
+
+          SECTION("R^3x3 -> N")
+          {
+            std::string_view data = R"(
+let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0);
+let (r,n) : R^3x3*N, (r,n) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> N"});
+          }
+
+          SECTION("R^3x3 -> Z")
+          {
+            std::string_view data = R"(
+let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0);
+let (r,z) : R^3x3*Z, (r,z) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> Z"});
+          }
+
+          SECTION("R^3x3 -> R")
+          {
+            std::string_view data = R"(
+let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0);
+let (r,x) : R^3x3*R, (r,x) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> R"});
+          }
+
+          SECTION("R^3x3 -> R^2")
+          {
+            std::string_view data = R"(
+let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0);
+let (x,r) : R^2*R^3x3, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> R^2"});
+          }
+
+          SECTION("R^3x3 -> R^3")
+          {
+            std::string_view data = R"(
+let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0);
+let (x,r) : R^3*R^3x3, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> R^3"});
+          }
+
+          SECTION("R^3x3 -> R^1")
+          {
+            std::string_view data = R"(
+let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0);
+let (x,r) : R^3x3*R^1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> R^1"});
+          }
+
+          SECTION("R^3x3 -> R^1x1")
+          {
+            std::string_view data = R"(
+let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0);
+let (x,r) : R^3x3*R^1x1, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> R^1x1"});
+          }
+
+          SECTION("R^3x3 -> R^2x2")
+          {
+            std::string_view data = R"(
+let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0);
+let (x,r) : R^3x3*R^2x2, (x,r) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> R^2x2"});
+          }
+
+          SECTION("R^3x3 -> builtin_t")
+          {
+            std::string_view data = R"(
+let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0);
+let (s,b) : string*builtin_t, (s,b) = t;
+)";
+
+            CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> builtin_t"});
+          }
+        }
+      }
+
+      SECTION("tuple -> list with tuple")
+      {
+        std::string_view data = R"(
+let t:(N), t = (1, 2, 3, 4);
+let (a,b,c,d) : R*N*(R)*Z, (a,b,c,d) = t;
+)";
+
+        CHECK_AST_THROWS_WITH(data, std::string{"cannot affect a tuple to a compound type made of tuples"});
+      }
     }
   }
 }
diff --git a/tests/test_DiscreteFunctionP0.cpp b/tests/test_DiscreteFunctionP0.cpp
index 3253cd6fe4f3e419f81d1f051010ec787424e9f0..39b91c4de355c1a96feaa1f1b5e2a59bf9c494d8 100644
--- a/tests/test_DiscreteFunctionP0.cpp
+++ b/tests/test_DiscreteFunctionP0.cpp
@@ -4,7 +4,9 @@
 #include <MeshDataBaseForTests.hpp>
 #include <scheme/DiscreteFunctionP0.hpp>
 
+#ifdef __clang__
 #pragma clang optimize off
+#endif   // __clang__
 
 // clazy:excludeall=non-pod-global-static
 
@@ -3437,7 +3439,7 @@ TEST_CASE("DiscreteFunctionP0", "[scheme]")
               mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) {
                 const double x = xj[cell_id][0];
                 Ah[cell_id]    = TinyMatrix<2>{x + 1, 2 * x - 3,   //
-                                               -0.2 * x - 1, 2 + x};
+                                            -0.2 * x - 1, 2 + x};
               });
 
             {
@@ -3459,7 +3461,7 @@ TEST_CASE("DiscreteFunctionP0", "[scheme]")
               mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) {
                 const double x = xj[cell_id][0];
                 Ah[cell_id]    = TinyMatrix<2>{x + 1, 2 * x - 3,   //
-                                               -0.2 * x - 1, 2 + x};
+                                            -0.2 * x - 1, 2 + x};
               });
 
             {
@@ -3481,7 +3483,7 @@ TEST_CASE("DiscreteFunctionP0", "[scheme]")
               mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) {
                 const double x = xj[cell_id][0];
                 Ah[cell_id]    = TinyMatrix<2>{x + 1, 2 * x - 3,   //
-                                               -0.2 * x - 1, 2 + x};
+                                            -0.2 * x - 1, 2 + x};
               });
 
             {
@@ -3503,7 +3505,7 @@ TEST_CASE("DiscreteFunctionP0", "[scheme]")
               mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) {
                 const double x = xj[cell_id][0];
                 Ah[cell_id]    = TinyMatrix<2>{x + 1, 2 * x - 3,   //
-                                               -0.2 * x - 1, 2 + x};
+                                            -0.2 * x - 1, 2 + x};
               });
 
             {
@@ -3700,4 +3702,6 @@ TEST_CASE("DiscreteFunctionP0", "[scheme]")
 #endif   // NDEBUG
 }
 
+#ifdef __clang__
 #pragma clang optimize on
+#endif   // __clang__
diff --git a/tests/test_ListAffectationProcessor.cpp b/tests/test_ListAffectationProcessor.cpp
index 219b9a2f16907f3d6010d3144b7d2b903455d6fa..2c28e6e0b0e6a8c8ae8c61d4b5778c8e3617af58 100644
--- a/tests/test_ListAffectationProcessor.cpp
+++ b/tests/test_ListAffectationProcessor.cpp
@@ -45,6 +45,25 @@
     REQUIRE(value == expected_value);                                         \
   }
 
+#define CHECK_AFFECTATION_THROW_WITH(data, error_message)          \
+  {                                                                \
+    TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"};     \
+    auto ast = ASTBuilder::build(input);                           \
+                                                                   \
+    ASTModulesImporter{*ast};                                      \
+    ASTNodeTypeCleaner<language::import_instruction>{*ast};        \
+                                                                   \
+    ASTSymbolTableBuilder{*ast};                                   \
+    ASTNodeDataTypeBuilder{*ast};                                  \
+                                                                   \
+    ASTNodeDeclarationToAffectationConverter{*ast};                \
+    ASTNodeTypeCleaner<language::var_declaration>{*ast};           \
+                                                                   \
+    ASTNodeExpressionBuilder{*ast};                                \
+    ExecutionPolicy exec_policy;                                   \
+    REQUIRE_THROWS_WITH(ast->execute(exec_policy), error_message); \
+  }
+
 // clazy:excludeall=non-pod-global-static
 
 TEST_CASE("ListAffectationProcessor", "[language]")
@@ -738,4 +757,176 @@ let (s1,b2) : (string)*B, (s1,b2) = (s, false);
       }
     }
   }
+
+  SECTION("list from tuple affectation")
+  {
+    SECTION("from (B)")
+    {
+      std::string_view data = R"(
+let t:(B), t = (true, false, true, false, true, false, true);
+let (b,n,z,r,r1,r11,s):B*N*Z*R*R^1*R^1x1*string, (b,n,z,r,r1,r11,s)=t;
+)";
+
+      CHECK_AFFECTATION_RESULT(data, "b", (true));
+      CHECK_AFFECTATION_RESULT(data, "n", (0ul));
+      CHECK_AFFECTATION_RESULT(data, "z", (1l));
+      CHECK_AFFECTATION_RESULT(data, "r", (double{0}));
+      CHECK_AFFECTATION_RESULT(data, "r1", (TinyVector<1>{1}));
+      CHECK_AFFECTATION_RESULT(data, "r11", (TinyMatrix<1>{0}));
+      CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(true)}));
+    }
+
+    SECTION("from (N)")
+    {
+      std::string_view data = R"(
+let t:(N), t = (1, 2, 3, 4, 5, 6);
+let (n,z,r,r1,r11,s):N*Z*R*R^1*R^1x1*string, (n,z,r,r1,r11,s)=t;
+)";
+
+      CHECK_AFFECTATION_RESULT(data, "n", (1ul));
+      CHECK_AFFECTATION_RESULT(data, "z", (2l));
+      CHECK_AFFECTATION_RESULT(data, "r", (double{3}));
+      CHECK_AFFECTATION_RESULT(data, "r1", (TinyVector<1>{4}));
+      CHECK_AFFECTATION_RESULT(data, "r11", (TinyMatrix<1>{5}));
+      CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(6ul)}));
+    }
+
+    SECTION("from (Z)")
+    {
+      std::string_view data = R"(
+let t:(Z), t = (1, -2, 3, -4, 5, 6);
+let (n,z,r,r1,r11,s):N*Z*R*R^1*R^1x1*string, (n,z,r,r1,r11,s)=t;
+)";
+
+      CHECK_AFFECTATION_RESULT(data, "n", (1ul));
+      CHECK_AFFECTATION_RESULT(data, "z", (-2l));
+      CHECK_AFFECTATION_RESULT(data, "r", (double{3}));
+      CHECK_AFFECTATION_RESULT(data, "r1", (TinyVector<1>{-4}));
+      CHECK_AFFECTATION_RESULT(data, "r11", (TinyMatrix<1>{5}));
+      CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(6l)}));
+    }
+
+    SECTION("from (R)")
+    {
+      std::string_view data = R"(
+let t:(R), t = (1.2, -2.3, 7.3, -4.2);
+let (r,r1,r11,s):R*R^1*R^1x1*string, (r,r1,r11,s)=t;
+)";
+
+      CHECK_AFFECTATION_RESULT(data, "r", (double{1.2}));
+      CHECK_AFFECTATION_RESULT(data, "r1", (TinyVector<1>{-2.3}));
+      CHECK_AFFECTATION_RESULT(data, "r11", (TinyMatrix<1>{7.3}));
+      CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(-4.2)}));
+    }
+
+    SECTION("from (R^1)")
+    {
+      std::string_view data = R"(
+let t:(R^1), t = (1.2, -[2.3]);
+let (r1,s):R^1*string, (r1,s)=t;
+)";
+
+      CHECK_AFFECTATION_RESULT(data, "r1", (TinyVector<1>{1.2}));
+      CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(TinyVector<1>{-2.3})}));
+    }
+
+    SECTION("from (R^2)")
+    {
+      std::string_view data = R"(
+let t:(R^2), t = ([1.2, 2], [2.3, 0]);
+let (r2,s):R^2*string, (r2,s)=t;
+)";
+
+      CHECK_AFFECTATION_RESULT(data, "r2", (TinyVector<2>{1.2, 2}));
+      CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(TinyVector<2>{2.3, 0})}));
+    }
+
+    SECTION("from (R^3)")
+    {
+      std::string_view data = R"(
+let t:(R^3), t = ([1.2, 2, -1], [2.3, 0, 2]);
+let (r3,s):R^3*string, (r3,s)=t;
+)";
+
+      CHECK_AFFECTATION_RESULT(data, "r3", (TinyVector<3>{1.2, 2, -1}));
+      CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(TinyVector<3>{2.3, 0, 2})}));
+    }
+
+    SECTION("from (R^1x1)")
+    {
+      std::string_view data = R"(
+let t:(R^1x1), t = (1.2, -[[2.3]]);
+let (r11,s):R^1x1*string, (r11,s)=t;
+)";
+
+      CHECK_AFFECTATION_RESULT(data, "r11", (TinyMatrix<1>{1.2}));
+      CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(TinyMatrix<1>{-2.3})}));
+    }
+
+    SECTION("from (R^2x2)")
+    {
+      std::string_view data = R"(
+let t:(R^2x2), t = ([[1.2, 2], [2.3, 0]], [[1.1, 2.2], [-1.3, 2]]);
+let (r22,s):R^2x2*string, (r22,s)=t;
+)";
+
+      CHECK_AFFECTATION_RESULT(data, "r22", (TinyMatrix<2>{1.2, 2, 2.3, 0}));
+      CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(TinyMatrix<2>{1.1, 2.2, -1.3, 2})}));
+    }
+
+    SECTION("from (R^3x3)")
+    {
+      std::string_view data = R"(
+let t:(R^3x3), t = ([[1.2, 2, -1], [2.3, 0, 2], [1, 4, 5]], 0);
+let (r33,s):R^3x3*string, (r33,s)=t;
+)";
+
+      CHECK_AFFECTATION_RESULT(data, "r33", (TinyMatrix<3>{1.2, 2, -1, 2.3, 0, 2, 1, 4, 5}));
+      CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(TinyMatrix<3>{zero})}));
+    }
+
+    SECTION("from (string)")
+    {
+      std::string_view data = R"(
+let t:(string), t = ("foo", "bar");
+let (s1,s2):string*string, (s1,s2)=t;
+)";
+
+      CHECK_AFFECTATION_RESULT(data, "s1", (std::string{"foo"}));
+      CHECK_AFFECTATION_RESULT(data, "s2", (std::string{"bar"}));
+    }
+
+    SECTION("errors")
+    {
+      SECTION("negative (Z) -> N")
+      {
+        std::string_view data = R"(
+let t:(Z), t = (2, 3, -4, 5);
+let (a,b,c,d):Z*N*N*R , (a,b,c,d)=t;
+)";
+
+        CHECK_AFFECTATION_THROW_WITH(data, "trying to affect negative value (-4)");
+      }
+
+      SECTION("tuple too small")
+      {
+        std::string_view data = R"(
+let t:(Z), t = (2, 3, 4);
+let (a,b,c,d):Z*N*N*R , (a,b,c,d)=t;
+)";
+
+        CHECK_AFFECTATION_THROW_WITH(data, "cannot affect a (Z) of size 3 to a Z*N*N*R");
+      }
+
+      SECTION("tuple too large")
+      {
+        std::string_view data = R"(
+let t:(Z), t = (1, 2, 3, 4, 5);
+let (a,b,c,d):Z*N*N*R , (a,b,c,d)=t;
+)";
+
+        CHECK_AFFECTATION_THROW_WITH(data, "cannot affect a (Z) of size 5 to a Z*N*N*R");
+      }
+    }
+  }
 }