diff --git a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp
index 7e79b35d55abf14d3540b76b3587c1db9035f8d5..43bd40932c82310d039f851c9ddc810744c6f72b 100644
--- a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp
@@ -194,7 +194,7 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode
           // LCOV_EXCL_STOP
         }
       } else {
-        throw parse_error("invalid operator for string affectation", std::vector{n.begin()});
+        throw parse_error("invalid affectation operator for string", std::vector{n.begin()});
       }
     };
 
@@ -215,7 +215,7 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode
           // LCOV_EXCL_STOP
         }
       } else {
-        throw parse_error("invalid operator for '" + data_type.nameOfTypeId() + "' affectation",
+        throw parse_error("invalid affectation operator for '" + dataTypeName(n.children[0]->m_data_type) + "'",
                           std::vector{n.begin()});
       }
     };
@@ -224,8 +224,7 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode
                                                         const ASTNodeDataType& data_type) {
       using OperatorT = std::decay_t<decltype(operator_v)>;
       if constexpr (std::is_same_v<OperatorT, language::eq_op>) {
-        switch (data_type) {
-        case ASTNodeDataType::list_t: {
+        if ((data_type == ASTNodeDataType::list_t) or (data_type == ASTNodeDataType::tuple_t)) {
           switch (content_data_type) {
           case ASTNodeDataType::type_id_t: {
             n.m_node_processor = std::make_unique<AffectationToTupleFromListProcessor<OperatorT, EmbeddedData>>(n);
@@ -274,68 +273,71 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode
             }
             break;
           }
+            // LCOV_EXCL_START
           default: {
-            throw NotImplementedError(dataTypeName(content_data_type) + " argument to tuple ");
+            throw UnexpectedError("invalid tuple content " + dataTypeName(content_data_type));
           }
+            // LCOV_EXCL_STOP
           }
-          break;
-        }
-        case ASTNodeDataType::type_id_t: {
-          n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, EmbeddedData>>(n);
-          break;
-        }
-        case ASTNodeDataType::bool_t: {
-          n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, bool>>(n);
-          break;
-        }
-        case ASTNodeDataType::unsigned_int_t: {
-          n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, uint64_t>>(n);
-          break;
-        }
-        case ASTNodeDataType::int_t: {
-          n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, int64_t>>(n);
-          break;
-        }
-        case ASTNodeDataType::double_t: {
-          n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, double>>(n);
-          break;
-        }
-        case ASTNodeDataType::string_t: {
-          n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, std::string>>(n);
-          break;
-        }
-        case ASTNodeDataType::vector_t: {
-          switch (content_data_type.dimension()) {
-          case 1: {
-            n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, TinyVector<1>>>(n);
+        } else {
+          switch (content_data_type) {
+          case ASTNodeDataType::type_id_t: {
+            n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, EmbeddedData>>(n);
             break;
           }
-          case 2: {
-            n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, TinyVector<2>>>(n);
+          case ASTNodeDataType::bool_t: {
+            n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, bool>>(n);
             break;
           }
-          case 3: {
-            n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, TinyVector<3>>>(n);
+          case ASTNodeDataType::unsigned_int_t: {
+            n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, uint64_t>>(n);
             break;
           }
-            // LCOV_EXCL_START
+          case ASTNodeDataType::int_t: {
+            n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, int64_t>>(n);
+            break;
+          }
+          case ASTNodeDataType::double_t: {
+            n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, double>>(n);
+            break;
+          }
+          case ASTNodeDataType::string_t: {
+            n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, std::string>>(n);
+            break;
+          }
+          case ASTNodeDataType::vector_t: {
+            switch (content_data_type.dimension()) {
+            case 1: {
+              n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, TinyVector<1>>>(n);
+              break;
+            }
+            case 2: {
+              n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, TinyVector<2>>>(n);
+              break;
+            }
+            case 3: {
+              n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, TinyVector<3>>>(n);
+              break;
+            }
+              // LCOV_EXCL_START
+            default: {
+              throw parse_error("unexpected error: invalid vector dimension for tuple affectation",
+                                std::vector{n.children[1]->begin()});
+            }
+              // LCOV_EXCL_STOP
+            }
+            break;
+          }
+          // LCOV_EXCL_START
           default: {
-            throw parse_error("unexpected error: invalid vector dimension for tuple affectation",
+            throw parse_error("unexpected error: undefined operand type for tuple affectation",
                               std::vector{n.children[1]->begin()});
           }
             // LCOV_EXCL_STOP
           }
-          break;
-        }
-        // LCOV_EXCL_START
-        default: {
-          throw parse_error("unexpected error: undefined operand type for tuple affectation",
-                            std::vector{n.children[1]->begin()});
-        }
-          // LCOV_EXCL_STOP
         }
       } else {
-        throw parse_error("invalid operator for '" + data_type.nameOfTypeId() + "' affectation",
+        throw parse_error("invalid affectation operator for '" + dataTypeName(n.children[0]->m_data_type) + "'",
                           std::vector{n.begin()});
       }
     };
diff --git a/src/language/ast/ASTNodeNaturalConversionChecker.cpp b/src/language/ast/ASTNodeNaturalConversionChecker.cpp
index 553ab60a1282e0b9b720e298d13fe8aad4df176c..b01ff1fc346856797b37f58a20b72039e8b49f59 100644
--- a/src/language/ast/ASTNodeNaturalConversionChecker.cpp
+++ b/src/language/ast/ASTNodeNaturalConversionChecker.cpp
@@ -59,12 +59,30 @@ ASTNodeNaturalConversionChecker::_checkIsNaturalExpressionConversion(const ASTNo
     }
   } else if (target_data_type == ASTNodeDataType::tuple_t) {
     const ASTNodeDataType& target_content_type = target_data_type.contentType();
-    if (node.m_data_type == ASTNodeDataType::list_t) {
-      for (const auto& child : node.children) {
-        this->_checkIsNaturalExpressionConversion(*child, child->m_data_type, target_content_type);
+    if (node.m_data_type == ASTNodeDataType::tuple_t) {
+      this->_checkIsNaturalExpressionConversion(node, data_type.contentType(), target_content_type);
+    } else if (node.m_data_type == ASTNodeDataType::list_t) {
+      if ((target_data_type.contentType() == ASTNodeDataType::vector_t) and
+          (target_data_type.contentType().dimension() == 1)) {
+        for (const auto& child : node.children) {
+          if (not isNaturalConversion(child->m_data_type, target_data_type)) {
+            this->_checkIsNaturalExpressionConversion(*child, child->m_data_type, ASTNodeDataType::double_t);
+          }
+        }
+      } else {
+        for (const auto& child : node.children) {
+          this->_checkIsNaturalExpressionConversion(*child, child->m_data_type, target_content_type);
+        }
       }
     } else {
-      this->_checkIsNaturalTypeConversion(node, data_type, target_data_type);
+      if ((target_data_type.contentType() == ASTNodeDataType::vector_t) and
+          (target_data_type.contentType().dimension() == 1)) {
+        if (not isNaturalConversion(data_type, target_data_type)) {
+          this->_checkIsNaturalExpressionConversion(node, data_type, ASTNodeDataType::double_t);
+        }
+      } else {
+        this->_checkIsNaturalExpressionConversion(node, data_type, target_content_type);
+      }
     }
   } else {
     this->_checkIsNaturalTypeConversion(node, data_type, target_data_type);
diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp
index ae06f5153a7e0c70b78fe1f99ff06c972e9cba57..31e1f070f5fadc1366ad4470b49a8052977bfce2 100644
--- a/src/language/node_processor/AffectationProcessor.hpp
+++ b/src/language/node_processor/AffectationProcessor.hpp
@@ -417,7 +417,8 @@ class AffectationToTupleProcessor final : public INodeProcessor
             os << v << std::ends;
             *m_lhs = std::vector{os.str()};
           }
-
+        } else if constexpr (std::is_same_v<ValueT, TinyVector<1>> and std::is_arithmetic_v<T>) {
+          *m_lhs = std::vector{TinyVector<1>{static_cast<double>(v)}};
         } else {
           // LCOV_EXCL_START
           throw parse_error("unexpected error: unexpected right hand side type in affectation", m_node.begin());
@@ -447,14 +448,9 @@ class AffectationToTupleFromListProcessor final : public INodeProcessor
 
   DataVariant* m_lhs;
 
- public:
-  DataVariant
-  execute(ExecutionPolicy& exec_policy)
+  void
+  _copyAggregateDataVariant(const AggregateDataVariant& children_values)
   {
-    AggregateDataVariant children_values = std::get<AggregateDataVariant>(m_node.children[1]->execute(exec_policy));
-
-    static_assert(std::is_same_v<OperatorT, language::eq_op>, "forbidden affection operator for list to tuple");
-
     std::vector<ValueT> tuple_value(children_values.size());
     for (size_t i = 0; i < children_values.size(); ++i) {
       std::visit(
@@ -510,8 +506,66 @@ class AffectationToTupleFromListProcessor final : public INodeProcessor
         },
         children_values[i]);
     }
-
     *m_lhs = std::move(tuple_value);
+  }
+
+  template <typename DataType>
+  void
+  _copyVector(const std::vector<DataType>& values)
+  {
+    std::vector<ValueT> v(values.size());
+    if constexpr (std::is_same_v<ValueT, DataType>) {
+      for (size_t i = 0; i < values.size(); ++i) {
+        v[i] = values[i];
+      }
+    } else if constexpr (std::is_arithmetic_v<ValueT> and std::is_convertible_v<DataType, ValueT>) {
+      for (size_t i = 0; i < values.size(); ++i) {
+        v[i] = static_cast<DataType>(values[i]);
+      }
+    } else if constexpr (std::is_same_v<ValueT, std::string>) {
+      if constexpr (std::is_arithmetic_v<DataType>) {
+        for (size_t i = 0; i < values.size(); ++i) {
+          v[i] = std::to_string(values[i]);
+        }
+      } else {
+        for (size_t i = 0; i < values.size(); ++i) {
+          std::ostringstream sout;
+          sout << values[i] << std::ends;
+          v[i] = sout.str();
+        }
+      }
+    } else {
+      // LCOV_EXCL_START
+      throw parse_error("unexpected error: unexpected right hand side type in tuple affectation",
+                        m_node.children[1]->begin());
+      // LCOV_EXCL_STOP
+    }
+
+    *m_lhs = std::move(v);
+  }
+
+ public:
+  DataVariant
+  execute(ExecutionPolicy& exec_policy)
+  {
+    static_assert(std::is_same_v<OperatorT, language::eq_op>, "forbidden affection operator for list to tuple");
+
+    std::visit(
+      [&](auto&& value_list) {
+        using ValueListT = std::decay_t<decltype(value_list)>;
+        if constexpr (std::is_same_v<AggregateDataVariant, ValueListT>) {
+          this->_copyAggregateDataVariant(value_list);
+        } else if constexpr (is_std_vector_v<ValueListT>) {
+          this->_copyVector(value_list);
+        } else {
+          // LCOV_EXCL_START
+          throw parse_error("unexpected error: invalid lhs (expecting list or tuple)",
+                            std::vector{m_node.children[1]->begin()});
+          // LCOV_EXCL_STOP
+        }
+      },
+      m_node.children[1]->execute(exec_policy));
+
     return {};
   }
 
diff --git a/src/language/node_processor/FunctionArgumentConverter.hpp b/src/language/node_processor/FunctionArgumentConverter.hpp
index c93516a86be9a75485819eb19e63132b35522182..afd4373ce8dedb5cf460e77c6d4b9ba7e30035fc 100644
--- a/src/language/node_processor/FunctionArgumentConverter.hpp
+++ b/src/language/node_processor/FunctionArgumentConverter.hpp
@@ -107,7 +107,7 @@ class FunctionTupleArgumentConverter final : public IFunctionArgumentConverter
           using ValueT = std::decay_t<decltype(v)>;
           if constexpr (std::is_same_v<ValueT, ContentType>) {
             exec_policy.currentContext()[m_argument_id] = std::move(TupleType{std::move(v)});
-          } else if constexpr (is_vector_v<ValueT>) {
+          } else if constexpr (is_std_vector_v<ValueT>) {
             using ContentT = typename ValueT::value_type;
             if constexpr (std::is_same_v<ContentT, ContentType>) {
               TupleType list_value;
@@ -168,7 +168,7 @@ class FunctionListArgumentConverter final : public IFunctionArgumentConverter
             exec_policy.currentContext()[m_argument_id] = std::move(list_value);
           } else if constexpr (std::is_same_v<ValueT, ContentType>) {
             exec_policy.currentContext()[m_argument_id] = std::move(v);
-          } else if constexpr (is_vector_v<ValueT>) {
+          } else if constexpr (is_std_vector_v<ValueT>) {
             using ContentT = typename ValueT::value_type;
             if constexpr (std::is_same_v<ContentT, ContentType>) {
               TupleType list_value;
diff --git a/src/language/utils/BuiltinFunctionEmbedder.hpp b/src/language/utils/BuiltinFunctionEmbedder.hpp
index 8073a47ef7b634a17d4498522d9ecf663cbcd716..3974398e1803856585f91f09565b29da3d877533 100644
--- a/src/language/utils/BuiltinFunctionEmbedder.hpp
+++ b/src/language/utils/BuiltinFunctionEmbedder.hpp
@@ -80,7 +80,7 @@ class BuiltinFunctionEmbedder<FX(Args...)> : public IBuiltinFunctionEmbedder
             throw UnexpectedError("unexpected argument types while casting: expecting EmbeddedData");
           }
         } else if constexpr (std::is_same_v<Vi_Type, std::vector<EmbeddedData>>) {
-          if constexpr (is_vector_v<Ti_Type>) {
+          if constexpr (is_std_vector_v<Ti_Type>) {
             using Ti_value_type = typename Ti_Type::value_type;
             if constexpr (is_shared_ptr_v<Ti_value_type>) {
               static_assert(is_shared_ptr_v<Ti_value_type>, "expecting shared_ptr");
diff --git a/src/language/utils/DataVariant.cpp b/src/language/utils/DataVariant.cpp
index 8796833250019d10a7ab7e28b0d895c232726244..fc82eec7b805cd49daa2a097490b36fa33e0c561 100644
--- a/src/language/utils/DataVariant.cpp
+++ b/src/language/utils/DataVariant.cpp
@@ -11,7 +11,7 @@ operator<<(std::ostream& os, const DataVariant& v)
       using ValueT = std::decay_t<decltype(v)>;
       if constexpr (std::is_same_v<ValueT, std::monostate>) {
         os << "--";
-      } else if constexpr (is_vector_v<ValueT>) {
+      } else if constexpr (is_std_vector_v<ValueT>) {
         os << '(';
         if (v.size() > 0) {
           os << v[0];
diff --git a/src/utils/PugsTraits.hpp b/src/utils/PugsTraits.hpp
index 52acae2bb0c80aecab29fb125604b7b869fc5f3c..e34e0433bb69316af695fec1c8d571ef23e03155 100644
--- a/src/utils/PugsTraits.hpp
+++ b/src/utils/PugsTraits.hpp
@@ -68,13 +68,13 @@ inline constexpr bool is_std_ptr_v<std::unique_ptr<T>> = true;
 template <typename T>
 inline constexpr bool is_std_ptr_v<std::weak_ptr<T>> = true;
 
-// Traits is_vector
+// Traits is_std_vector
 
 template <typename T>
-inline constexpr bool is_vector_v = false;
+inline constexpr bool is_std_vector_v = false;
 
 template <typename T>
-inline constexpr bool is_vector_v<std::vector<T>> = true;
+inline constexpr bool is_std_vector_v<std::vector<T>> = true;
 
 // Traits is_tiny_vector
 
diff --git a/tests/test_ASTNodeAffectationExpressionBuilder.cpp b/tests/test_ASTNodeAffectationExpressionBuilder.cpp
index f439786a088c0eb293019bf8e048fc56e8eda1e8..895fa860eafe2f6216066d422597e539c1a1cd65 100644
--- a/tests/test_ASTNodeAffectationExpressionBuilder.cpp
+++ b/tests/test_ASTNodeAffectationExpressionBuilder.cpp
@@ -8,8 +8,11 @@
 #include <language/ast/ASTNodeTypeCleaner.hpp>
 #include <language/ast/ASTSymbolInitializationChecker.hpp>
 #include <language/ast/ASTSymbolTableBuilder.hpp>
+#include <language/utils/ASTNodeDataTypeTraits.hpp>
 #include <language/utils/ASTPrinter.hpp>
+#include <language/utils/TypeDescriptor.hpp>
 #include <utils/Demangle.hpp>
+#include <utils/Exceptions.hpp>
 
 #include <pegtl/string_input.hpp>
 
@@ -36,6 +39,58 @@
     REQUIRE(ast_output.str() == expected_output);                                                   \
   }
 
+template <>
+inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> = {ASTNodeDataType::type_id_t,
+                                                                                 "builtin_t"};
+const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const double>>;
+
+#define CHECK_AST_WITH_BUILTIN(data, expected_output)                                                         \
+  {                                                                                                           \
+    static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>);                            \
+    static_assert(std::is_same_v<std::decay_t<decltype(expected_output)>, std::string_view> or                \
+                  std::is_same_v<std::decay_t<decltype(expected_output)>, std::string>);                      \
+                                                                                                              \
+    string_input input{data, "test.pgs"};                                                                     \
+    auto ast = ASTBuilder::build(input);                                                                      \
+                                                                                                              \
+    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::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())); \
+                                                                                                              \
+    auto [i_symbol_a, success_a] = symbol_table.add("a", ast->begin());                                       \
+    if (not success_a) {                                                                                      \
+      throw UnexpectedError("cannot add 'a' of type builtin_t for testing");                                  \
+    }                                                                                                         \
+    i_symbol_a->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>);             \
+    i_symbol_a->attributes().setIsInitialized();                                                              \
+    auto [i_symbol_b, success_b] = symbol_table.add("b", ast->begin());                                       \
+    if (not success_b) {                                                                                      \
+      throw UnexpectedError("cannot add 'b' of type builtin_t for testing");                                  \
+    }                                                                                                         \
+    i_symbol_b->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>);             \
+    i_symbol_b->attributes().setIsInitialized();                                                              \
+                                                                                                              \
+    ASTSymbolTableBuilder{*ast};                                                                              \
+    ASTNodeDataTypeBuilder{*ast};                                                                             \
+                                                                                                              \
+    ASTNodeDeclarationToAffectationConverter{*ast};                                                           \
+    ASTNodeTypeCleaner<language::var_declaration>{*ast};                                                      \
+                                                                                                              \
+    ASTNodeExpressionBuilder{*ast};                                                                           \
+                                                                                                              \
+    std::stringstream ast_output;                                                                             \
+    ast_output << '\n' << ASTPrinter{*ast, ASTPrinter::Format::raw, {ASTPrinter::Info::exec_type}};           \
+                                                                                                              \
+    REQUIRE(ast_output.str() == expected_output);                                                             \
+  }
+
 #define CHECK_AST_THROWS_WITH(data, expected_error)                                           \
   {                                                                                           \
     static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>);            \
@@ -54,6 +109,48 @@
     REQUIRE_THROWS_WITH(ASTNodeExpressionBuilder{*ast}, expected_error);                      \
   }
 
+#define CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, expected_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(expected_error)>, std::string_view> or                 \
+                  std::is_same_v<std::decay_t<decltype(expected_error)>, std::string>);                       \
+                                                                                                              \
+    string_input input{data, "test.pgs"};                                                                     \
+    auto ast = ASTBuilder::build(input);                                                                      \
+                                                                                                              \
+    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::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())); \
+                                                                                                              \
+    auto [i_symbol_a, success_a] = symbol_table.add("a", ast->begin());                                       \
+    if (not success_a) {                                                                                      \
+      throw UnexpectedError("cannot add 'a' of type builtin_t for testing");                                  \
+    }                                                                                                         \
+    i_symbol_a->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>);             \
+    i_symbol_a->attributes().setIsInitialized();                                                              \
+    auto [i_symbol_b, success_b] = symbol_table.add("b", ast->begin());                                       \
+    if (not success_b) {                                                                                      \
+      throw UnexpectedError("cannot add 'b' of type builtin_t for testing");                                  \
+    }                                                                                                         \
+    i_symbol_b->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>);             \
+    i_symbol_b->attributes().setIsInitialized();                                                              \
+                                                                                                              \
+    ASTSymbolTableBuilder{*ast};                                                                              \
+    ASTNodeDataTypeBuilder{*ast};                                                                             \
+                                                                                                              \
+    ASTNodeDeclarationToAffectationConverter{*ast};                                                           \
+    ASTNodeTypeCleaner<language::var_declaration>{*ast};                                                      \
+                                                                                                              \
+    REQUIRE_THROWS_WITH(ASTNodeExpressionBuilder{*ast}, expected_error);                                      \
+  }
+
 // clazy:excludeall=non-pod-global-static
 
 TEST_CASE("ASTNodeAffectationExpressionBuilder", "[language]")
@@ -545,6 +642,320 @@ let s : string, s="foo";
         CHECK_AST(data, result);
       }
     }
+
+    SECTION("type_id affectation")
+    {
+      SECTION("type_id <- type_id")
+      {
+        std::string_view data = R"(
+let t : builtin_t, t=a;
+)";
+
+        std::string result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::eq_op:AffectationProcessor<language::eq_op, EmbeddedData, EmbeddedData>)
+     +-(language::name:t:NameProcessor)
+     `-(language::name:a:NameProcessor)
+)";
+
+        CHECK_AST_WITH_BUILTIN(data, result);
+      }
+    }
+
+    SECTION("tuples")
+    {
+      SECTION("B tuples")
+      {
+        std::string_view data = R"(
+let t : (B), t = (true, false);
+)";
+
+        std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, bool>)
+     +-(language::name:t:NameProcessor)
+     `-(language::expression_list:ASTNodeExpressionListProcessor)
+         +-(language::true_kw:ValueProcessor)
+         `-(language::false_kw:ValueProcessor)
+)";
+
+        CHECK_AST(data, result);
+      }
+
+      SECTION("N tuples")
+      {
+        std::string_view data = R"(
+let t : (N), t = (1, 2, 3, 5);
+)";
+
+        std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, unsigned long>)
+     +-(language::name:t:NameProcessor)
+     `-(language::expression_list:ASTNodeExpressionListProcessor)
+         +-(language::integer:1:ValueProcessor)
+         +-(language::integer:2:ValueProcessor)
+         +-(language::integer:3:ValueProcessor)
+         `-(language::integer:5:ValueProcessor)
+)";
+
+        CHECK_AST(data, result);
+      }
+
+      SECTION("Z tuples")
+      {
+        std::string_view data = R"(
+let n : N, n = 3;
+let t : (Z), t = (2, n, true);
+)";
+
+        std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>)
+ |   +-(language::name:n:NameProcessor)
+ |   `-(language::integer:3:ValueProcessor)
+ `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, long>)
+     +-(language::name:t:NameProcessor)
+     `-(language::expression_list:ASTNodeExpressionListProcessor)
+         +-(language::integer:2:ValueProcessor)
+         +-(language::name:n:NameProcessor)
+         `-(language::true_kw:ValueProcessor)
+)";
+
+        CHECK_AST(data, result);
+      }
+
+      SECTION("R tuples")
+      {
+        std::string_view data = R"(
+let t : (R), t = (2, 3.1, 5);
+)";
+
+        std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, double>)
+     +-(language::name:t:NameProcessor)
+     `-(language::expression_list:ASTNodeExpressionListProcessor)
+         +-(language::integer:2:ValueProcessor)
+         +-(language::real:3.1:ValueProcessor)
+         `-(language::integer:5:ValueProcessor)
+)";
+
+        CHECK_AST(data, result);
+      }
+
+      SECTION("R^d tuples")
+      {
+        std::string_view data = R"(
+let a : R^2, a = (2,3.1);
+let t1 : (R^2), t1 = (a, (1,2), 0);
+let t2 : (R^3), t2 = (0, 0);
+let t3 : (R^1), t3 = (1, 2.3, 0);
+)";
+
+        std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ +-(language::eq_op:AffectationToTinyVectorFromListProcessor<language::eq_op, TinyVector<2ul, double> >)
+ |   +-(language::name:a:NameProcessor)
+ |   `-(language::expression_list:ASTNodeExpressionListProcessor)
+ |       +-(language::integer:2:ValueProcessor)
+ |       `-(language::real:3.1:ValueProcessor)
+ +-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, TinyVector<2ul, double> >)
+ |   +-(language::name:t1:NameProcessor)
+ |   `-(language::expression_list:ASTNodeExpressionListProcessor)
+ |       +-(language::name:a:NameProcessor)
+ |       +-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>)
+ |       |   +-(language::integer:1:ValueProcessor)
+ |       |   `-(language::integer:2:ValueProcessor)
+ |       `-(language::integer:0:ValueProcessor)
+ +-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, TinyVector<3ul, double> >)
+ |   +-(language::name:t2:NameProcessor)
+ |   `-(language::expression_list:ASTNodeExpressionListProcessor)
+ |       +-(language::integer:0:ValueProcessor)
+ |       `-(language::integer:0:ValueProcessor)
+ `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, TinyVector<1ul, double> >)
+     +-(language::name:t3:NameProcessor)
+     `-(language::expression_list:ASTNodeExpressionListProcessor)
+         +-(language::integer:1:ValueProcessor)
+         +-(language::real:2.3:ValueProcessor)
+         `-(language::integer:0:ValueProcessor)
+)";
+
+        CHECK_AST(data, result);
+      }
+
+      SECTION("string tuples")
+      {
+        std::string_view data = R"(
+let t : (string), t = ("foo", "bar");
+)";
+
+        std::string result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, )" +
+                             demangled_stdstring + R"( >)
+     +-(language::name:t:NameProcessor)
+     `-(language::expression_list:ASTNodeExpressionListProcessor)
+         +-(language::literal:"foo":ValueProcessor)
+         `-(language::literal:"bar":ValueProcessor)
+)";
+
+        CHECK_AST(data, result);
+      }
+
+      SECTION("type_id tuples")
+      {
+        std::string_view data = R"(
+let t : (builtin_t), t= (a,b,a);
+)";
+
+        std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, EmbeddedData>)
+     +-(language::name:t:NameProcessor)
+     `-(language::expression_list:ASTNodeExpressionListProcessor)
+         +-(language::name:a:NameProcessor)
+         +-(language::name:b:NameProcessor)
+         `-(language::name:a:NameProcessor)
+)";
+
+        CHECK_AST_WITH_BUILTIN(data, result);
+      }
+    }
+
+    SECTION("tuples from singleton")
+    {
+      SECTION("B tuples")
+      {
+        std::string_view data = R"(
+let t : (B), t = true;
+)";
+
+        std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, bool>)
+     +-(language::name:t:NameProcessor)
+     `-(language::true_kw:ValueProcessor)
+)";
+
+        CHECK_AST(data, result);
+      }
+
+      SECTION("N tuples")
+      {
+        std::string_view data = R"(
+let t : (N), t = 1;
+)";
+
+        std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, unsigned long>)
+     +-(language::name:t:NameProcessor)
+     `-(language::integer:1:ValueProcessor)
+)";
+
+        CHECK_AST(data, result);
+      }
+
+      SECTION("Z tuples")
+      {
+        std::string_view data = R"(
+let n : N, n = 3;
+let t : (Z), t = n;
+)";
+
+        std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>)
+ |   +-(language::name:n:NameProcessor)
+ |   `-(language::integer:3:ValueProcessor)
+ `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, long>)
+     +-(language::name:t:NameProcessor)
+     `-(language::name:n:NameProcessor)
+)";
+
+        CHECK_AST(data, result);
+      }
+
+      SECTION("R tuples")
+      {
+        std::string_view data = R"(
+let t : (R), t = 3.1;
+)";
+
+        std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, double>)
+     +-(language::name:t:NameProcessor)
+     `-(language::real:3.1:ValueProcessor)
+)";
+
+        CHECK_AST(data, result);
+      }
+
+      SECTION("R^d tuples")
+      {
+        std::string_view data = R"(
+let a : R^2, a = (2,3.1);
+let t1 : (R^2), t1 = a;
+let t2 : (R^3), t2 = 0;
+let t3 : (R^1), t3 = 2.3;
+)";
+
+        std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ +-(language::eq_op:AffectationToTinyVectorFromListProcessor<language::eq_op, TinyVector<2ul, double> >)
+ |   +-(language::name:a:NameProcessor)
+ |   `-(language::expression_list:ASTNodeExpressionListProcessor)
+ |       +-(language::integer:2:ValueProcessor)
+ |       `-(language::real:3.1:ValueProcessor)
+ +-(language::eq_op:AffectationToTupleProcessor<language::eq_op, TinyVector<2ul, double> >)
+ |   +-(language::name:t1:NameProcessor)
+ |   `-(language::name:a:NameProcessor)
+ +-(language::eq_op:AffectationToTupleProcessor<language::eq_op, TinyVector<3ul, double> >)
+ |   +-(language::name:t2:NameProcessor)
+ |   `-(language::integer:0:ValueProcessor)
+ `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, TinyVector<1ul, double> >)
+     +-(language::name:t3:NameProcessor)
+     `-(language::real:2.3:ValueProcessor)
+)";
+
+        CHECK_AST(data, result);
+      }
+
+      SECTION("string tuples")
+      {
+        std::string_view data = R"(
+let t : (string), t = "foo";
+)";
+
+        std::string result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, )" +
+                             demangled_stdstring + R"( >)
+     +-(language::name:t:NameProcessor)
+     `-(language::literal:"foo":ValueProcessor)
+)";
+
+        CHECK_AST(data, result);
+      }
+
+      SECTION("type_id tuples")
+      {
+        std::string_view data = R"(
+let t : (builtin_t), t = a;
+)";
+
+        std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, EmbeddedData>)
+     +-(language::name:t:NameProcessor)
+     `-(language::name:a:NameProcessor)
+)";
+
+        CHECK_AST_WITH_BUILTIN(data, result);
+      }
+    }
   }
 
   SECTION("+=")
@@ -1147,7 +1558,7 @@ let x : R, x=1; x/=2.3;
 let s : string, s="foo"; s-="bar";
 )";
 
-        std::string error_message = "invalid operator for string affectation";
+        std::string error_message = "invalid affectation operator for string";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
@@ -1158,7 +1569,7 @@ let s : string, s="foo"; s-="bar";
 let s : string, s="foo"; s*=2;
 )";
 
-        std::string error_message = "invalid operator for string affectation";
+        std::string error_message = "invalid affectation operator for string";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
@@ -1166,15 +1577,48 @@ let s : string, s="foo"; s*=2;
       SECTION("string /= string")
       {
         std::string_view data = R"(
-let s : string, s="foo"; s/="bar";
+ let s : string, s="foo"; s/="bar";
 )";
 
-        std::string error_message = "invalid operator for string affectation";
+        std::string error_message = "invalid affectation operator for string";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
     }
 
+    SECTION("type_id operator")
+    {
+      std::string_view data = R"(
+ let s :builtin_t, s = a; s *= b;
+)";
+
+      std::string error_message = "invalid affectation operator for 'builtin_t'";
+
+      CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message);
+    }
+
+    SECTION("Invalid tuple operator")
+    {
+      std::string_view data = R"(
+ let s :(R), s=(1,2,3); s *= 4;
+)";
+
+      std::string error_message = "invalid affectation operator for 'tuple(R)'";
+
+      CHECK_AST_THROWS_WITH(data, error_message);
+    }
+
+    SECTION("Invalid tuple operator 2")
+    {
+      std::string_view data = R"(
+ let s : (builtin_t), s =(a,b); s *= b;
+)";
+
+      std::string error_message = "invalid affectation operator for 'tuple(builtin_t)'";
+
+      CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message);
+    }
+
     SECTION("Invalid R^n -> R^m affectation")
     {
       SECTION("R^3 <- R^1")
diff --git a/tests/test_ASTNodeNaturalConversionChecker.cpp b/tests/test_ASTNodeNaturalConversionChecker.cpp
index 1470dfc7f183c1bc802cffdc202b9e2d6f75fd95..fe29cf9d0148d7a4d0a31bd71b97d84820e63299 100644
--- a/tests/test_ASTNodeNaturalConversionChecker.cpp
+++ b/tests/test_ASTNodeNaturalConversionChecker.cpp
@@ -344,7 +344,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
 
       SECTION("R^3 -> tuple(R^3)")
       {
-        auto R3                = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
+        auto R3                = ASTNodeDataType{ASTNodeDataType::vector_t, 3};
         data_node->m_data_type = R3;
         REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, R3}});
       }
@@ -352,14 +352,17 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
       SECTION("string -> tuple(string)")
       {
         data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::string_t};
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::string_t}});
+        REQUIRE_NOTHROW(
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
+                                                                      ASTNodeDataType{ASTNodeDataType::string_t}}});
       }
 
       SECTION("type_id_t -> tuple(type_id_t)")
       {
         auto type_id           = ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"};
         data_node->m_data_type = type_id;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, type_id});
+        REQUIRE_NOTHROW(
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, type_id}});
       }
 
       SECTION("(B, B, B) -> tuple(B)")
@@ -514,7 +517,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
         REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
       }
 
-      SECTION("(type_id_t, type_id_t)-> tuple(type_id_t)")
+      SECTION("(type_id_t, type_id_t) -> tuple(type_id_t)")
       {
         auto type_id           = ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"};
         data_node->m_data_type = ASTNodeDataType::list_t;
@@ -530,6 +533,167 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
         auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, type_id};
         REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
       }
+
+      SECTION("tuple(B) -> tuple(B)")
+      {
+        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}};
+        auto tuple_t           = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}};
+
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
+      }
+
+      SECTION("tuple(B) -> tuple(N)")
+      {
+        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}};
+        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}};
+
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
+      }
+
+      SECTION("tuple(Z) -> tuple(N)")
+      {
+        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}};
+        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}};
+
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
+      }
+
+      SECTION("tuple(N) -> tuple(N)")
+      {
+        data_node->m_data_type =
+          ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}};
+        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}};
+
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
+      }
+
+      SECTION("tuple(B) -> tuple(Z)")
+      {
+        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}};
+        auto tuple_t           = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}};
+
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
+      }
+
+      SECTION("tuple(N) -> tuple(Z)")
+      {
+        data_node->m_data_type =
+          ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}};
+        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}};
+
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
+      }
+
+      SECTION("tuple(Z) -> tuple(Z)")
+      {
+        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}};
+        auto tuple_t           = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}};
+
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
+      }
+
+      SECTION("tuple(B) -> tuple(R)")
+      {
+        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}};
+        auto tuple_t           = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}};
+
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
+      }
+
+      SECTION("tuple(Z) -> tuple(R)")
+      {
+        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}};
+        auto tuple_t           = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}};
+
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
+      }
+
+      SECTION("tuple(N) -> tuple(R)")
+      {
+        data_node->m_data_type =
+          ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}};
+        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}};
+
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
+      }
+
+      SECTION("tuple(R) -> tuple(R)")
+      {
+        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}};
+        auto tuple_t           = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}};
+
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
+      }
+
+      SECTION("tuple(B) -> tuple(string)")
+      {
+        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}};
+        auto tuple_t           = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::string_t}};
+
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
+      }
+
+      SECTION("tuple(Z) -> tuple(string)")
+      {
+        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}};
+        auto tuple_t           = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::string_t}};
+
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
+      }
+
+      SECTION("tuple(N) -> tuple(string)")
+      {
+        data_node->m_data_type =
+          ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}};
+        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::string_t}};
+
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
+      }
+
+      SECTION("tuple(R) -> tuple(string)")
+      {
+        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}};
+        auto tuple_t           = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::string_t}};
+
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
+      }
+
+      SECTION("tuple(string) -> tuple(string)")
+      {
+        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::string_t}};
+        auto tuple_t           = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::string_t}};
+
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
+      }
+
+      SECTION("tuple(R^1) -> tuple(R^1)")
+      {
+        auto R1                = ASTNodeDataType{ASTNodeDataType::vector_t, 1};
+        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, R1};
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, R1}});
+      }
+
+      SECTION("tuple(R^2) -> tuple(R^2)")
+      {
+        auto R2                = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
+        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, R2};
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, R2}});
+      }
+
+      SECTION("tuple(R^3) -> tuple(R^3)")
+      {
+        auto R3                = ASTNodeDataType{ASTNodeDataType::vector_t, 3};
+        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, R3};
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, R3}});
+      }
+
+      SECTION("tuple(type_id_t) -> tuple(type_id_t)")
+      {
+        auto type_id           = ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"};
+        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, type_id};
+        REQUIRE_NOTHROW(
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, type_id}});
+      }
     }
   }
 
@@ -724,6 +888,83 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
                                                                ASTNodeDataType{ASTNodeDataType::vector_t, 3}}),
                               "invalid implicit conversion: tuple(R) -> R^3");
         }
+
+        SECTION("tuple(R^1) -> tuple(R^3)")
+        {
+          auto tuple_R1 = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::vector_t, 1}};
+          auto tuple_R3 = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::vector_t, 3}};
+          data_node->m_data_type = tuple_R1;
+          REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R3}),
+                              "invalid implicit conversion: R^1 -> R^3");
+        }
+
+        SECTION("tuple(R^2) -> tuple(R^3)")
+        {
+          auto tuple_R2 = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::vector_t, 2}};
+          auto tuple_R3 = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::vector_t, 3}};
+          data_node->m_data_type = tuple_R2;
+          REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R3}),
+                              "invalid implicit conversion: R^2 -> R^3");
+        }
+
+        SECTION("tuple(R^2) -> tuple(R^1)")
+        {
+          auto tuple_R1 = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::vector_t, 1}};
+          auto tuple_R2 = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::vector_t, 2}};
+          data_node->m_data_type = tuple_R2;
+          REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R1}),
+                              "invalid implicit conversion: R^2 -> R^1");
+        }
+
+        SECTION("tuple(R) -> tuple(Z)")
+        {
+          auto tuple_R = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}};
+          auto tuple_Z = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}};
+          data_node->m_data_type = tuple_R;
+          REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_Z}),
+                              "invalid implicit conversion: R -> Z");
+        }
+
+        SECTION("tuple(R) -> tuple(R^1)")
+        {
+          auto tuple_R  = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}};
+          auto tuple_R1 = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::vector_t, 1}};
+          data_node->m_data_type = tuple_R;
+          REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R1}),
+                              "invalid implicit conversion: R -> R^1");
+        }
+
+        SECTION("tuple(string) -> tuple(R)")
+        {
+          auto tuple_string = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::string_t}};
+          auto tuple_R      = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}};
+          data_node->m_data_type = tuple_string;
+          REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R}),
+                              "invalid implicit conversion: string -> R");
+        }
+
+        SECTION("tuple(type_id) -> tuple(R)")
+        {
+          auto type_id = ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"};
+
+          auto tuple_type_id = ASTNodeDataType{ASTNodeDataType::tuple_t, type_id};
+          auto tuple_R       = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}};
+          data_node->m_data_type = tuple_type_id;
+          REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R}),
+                              "invalid implicit conversion: foo -> R");
+        }
+
+        SECTION("tuple(type_id) -> tuple(R)")
+        {
+          auto type_id0 = ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"};
+          auto type_id1 = ASTNodeDataType{ASTNodeDataType::type_id_t, "bar"};
+
+          auto tuple_type_id0    = ASTNodeDataType{ASTNodeDataType::tuple_t, type_id0};
+          auto tuple_type_id1    = ASTNodeDataType{ASTNodeDataType::tuple_t, type_id1};
+          data_node->m_data_type = tuple_type_id0;
+          REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_type_id1}),
+                              "invalid implicit conversion: foo -> bar");
+        }
       }
 
       SECTION("R -> R^d")
@@ -1088,7 +1329,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
                                                                                          ASTNodeDataType{
                                                                                            ASTNodeDataType::bool_t}}}),
-                            "invalid implicit conversion: N -> tuple(B)");
+                            "invalid implicit conversion: N -> B");
       }
 
       SECTION("Z -> tuple(B)")
@@ -1097,7 +1338,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
                                                                                          ASTNodeDataType{
                                                                                            ASTNodeDataType::bool_t}}}),
-                            "invalid implicit conversion: Z -> tuple(B)");
+                            "invalid implicit conversion: Z -> B");
       }
 
       SECTION("R -> tuple(B)")
@@ -1106,7 +1347,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
                                                                                          ASTNodeDataType{
                                                                                            ASTNodeDataType::bool_t}}}),
-                            "invalid implicit conversion: R -> tuple(B)");
+                            "invalid implicit conversion: R -> B");
       }
 
       SECTION("string -> tuple(B)")
@@ -1115,7 +1356,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
                                                                                          ASTNodeDataType{
                                                                                            ASTNodeDataType::bool_t}}}),
-                            "invalid implicit conversion: string -> tuple(B)");
+                            "invalid implicit conversion: string -> B");
       }
 
       SECTION("R^1 -> tuple(B)")
@@ -1124,7 +1365,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
                                                                                          ASTNodeDataType{
                                                                                            ASTNodeDataType::bool_t}}}),
-                            "invalid implicit conversion: R^1 -> tuple(B)");
+                            "invalid implicit conversion: R^1 -> B");
       }
 
       SECTION("R^2 -> tuple(B)")
@@ -1133,7 +1374,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
                                                                                          ASTNodeDataType{
                                                                                            ASTNodeDataType::bool_t}}}),
-                            "invalid implicit conversion: R^2 -> tuple(B)");
+                            "invalid implicit conversion: R^2 -> B");
       }
 
       SECTION("R^3 -> tuple(B)")
@@ -1142,7 +1383,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
                                                                                          ASTNodeDataType{
                                                                                            ASTNodeDataType::bool_t}}}),
-                            "invalid implicit conversion: R^3 -> tuple(B)");
+                            "invalid implicit conversion: R^3 -> B");
       }
 
       SECTION("R -> tuple(N)")
@@ -1152,7 +1393,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
                                                              ASTNodeDataType{ASTNodeDataType::tuple_t,
                                                                              ASTNodeDataType{
                                                                                ASTNodeDataType::unsigned_int_t}}}),
-                            "invalid implicit conversion: R -> tuple(N)");
+                            "invalid implicit conversion: R -> N");
       }
 
       SECTION("R^1 -> tuple(R^2)")
@@ -1162,7 +1403,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
         data_node->m_data_type = R1;
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                              ASTNodeDataType{ASTNodeDataType::tuple_t, R2}}),
-                            "invalid implicit conversion: R^1 -> tuple(R^2)");
+                            "incompatible dimensions in affectation");
       }
 
       SECTION("R^2 -> tuple(R^3)")
@@ -1172,7 +1413,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
         data_node->m_data_type = R2;
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                              ASTNodeDataType{ASTNodeDataType::tuple_t, R3}}),
-                            "invalid implicit conversion: R^2 -> tuple(R^3)");
+                            "incompatible dimensions in affectation");
       }
 
       SECTION("R^3 -> tuple(R^2)")
@@ -1182,7 +1423,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
         data_node->m_data_type = R3;
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                              ASTNodeDataType{ASTNodeDataType::tuple_t, R2}}),
-                            "invalid implicit conversion: R^3 -> tuple(R^2)");
+                            "incompatible dimensions in affectation");
       }
 
       SECTION("(B, R, Z) -> tuple(N)")