From 4354aab28be9f860396d0e83bc72141a49587571 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Mon, 21 Sep 2020 19:10:37 +0200
Subject: [PATCH] Improve functions and declarations type deduction for AST
 nodes

---
 ...STNodeBuiltinFunctionExpressionBuilder.cpp |  8 +-
 src/language/ast/ASTNodeDataType.cpp          | 11 ++-
 src/language/ast/ASTNodeDataType.hpp          | 72 ++++++++------
 src/language/ast/ASTNodeDataTypeBuilder.cpp   | 95 +++++++++++++++----
 tests/test_ASTNodeDataType.cpp                |  9 +-
 tests/test_ASTNodeDataTypeBuilder.cpp         | 38 ++++----
 .../test_ASTNodeNaturalConversionChecker.cpp  |  7 +-
 7 files changed, 167 insertions(+), 73 deletions(-)

diff --git a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp
index e3d00a407..6b1fe91ec 100644
--- a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp
@@ -281,10 +281,16 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData
         return get_function_argument_to_tuple_converter(double{});
       }
       case ASTNodeDataType::vector_t: {
-        switch (parameter_type.dimension()) {
+        switch (parameter_type.contentType().dimension()) {
         case 1: {
           return get_function_argument_to_tuple_converter(TinyVector<1>{});
         }
+        case 2: {
+          return get_function_argument_to_tuple_converter(TinyVector<2>{});
+        }
+        case 3: {
+          return get_function_argument_to_tuple_converter(TinyVector<3>{});
+        }
         // LCOV_EXCL_START
         default: {
           throw ParseError("unexpected error: unexpected tuple content for function: '" + dataTypeName(parameter_type) +
diff --git a/src/language/ast/ASTNodeDataType.cpp b/src/language/ast/ASTNodeDataType.cpp
index a4a94d762..10ec58b45 100644
--- a/src/language/ast/ASTNodeDataType.cpp
+++ b/src/language/ast/ASTNodeDataType.cpp
@@ -45,9 +45,16 @@ dataTypeName(const ASTNodeDataType& data_type)
   case ASTNodeDataType::tuple_t:
     name = "tuple(" + dataTypeName(data_type.contentType()) + ')';
     break;
-  case ASTNodeDataType::list_t:
-    name = "list";
+  case ASTNodeDataType::list_t: {
+    std::ostringstream data_type_name_list;
+    const auto& data_type_list = data_type.contentTypeList();
+    data_type_name_list << dataTypeName(*data_type_list[0]);
+    for (size_t i = 1; i < data_type_list.size(); ++i) {
+      data_type_name_list << '*' << dataTypeName(*data_type_list[i]);
+    }
+    name = "list(" + data_type_name_list.str() + ")";
     break;
+  }
   case ASTNodeDataType::string_t:
     name = "string";
     break;
diff --git a/src/language/ast/ASTNodeDataType.hpp b/src/language/ast/ASTNodeDataType.hpp
index 39e8e1bfa..46b76406b 100644
--- a/src/language/ast/ASTNodeDataType.hpp
+++ b/src/language/ast/ASTNodeDataType.hpp
@@ -6,6 +6,8 @@
 #include <limits>
 #include <memory>
 #include <string>
+#include <variant>
+#include <vector>
 
 class ASTNode;
 class ASTNodeDataType;
@@ -42,31 +44,46 @@ class ASTNodeDataType
 
  private:
   DataType m_data_type;
-  std::shared_ptr<ASTNodeDataType> m_content_type;
-  size_t m_dimension;
-  std::string m_name_of_type_id;
+
+  using DataTypeDetails = std::variant<std::monostate,
+                                       size_t,
+                                       std::string,
+                                       std::shared_ptr<const ASTNodeDataType>,
+                                       std::vector<std::shared_ptr<const ASTNodeDataType>>>;
+
+  DataTypeDetails m_details;
 
  public:
   PUGS_INLINE
   size_t
   dimension() const
   {
-    return m_dimension;
+    Assert(std::holds_alternative<size_t>(m_details));
+    return std::get<size_t>(m_details);
+  }
+
+  PUGS_INLINE
+  const std::string&
+  nameOfTypeId() const
+  {
+    Assert(std::holds_alternative<std::string>(m_details));
+    return std::get<std::string>(m_details);
   }
 
   PUGS_INLINE
   const ASTNodeDataType&
   contentType() const
   {
-    Assert(m_content_type);
-    return *m_content_type;
+    Assert(std::holds_alternative<std::shared_ptr<const ASTNodeDataType>>(m_details));
+    return *std::get<std::shared_ptr<const ASTNodeDataType>>(m_details);
   }
 
   PUGS_INLINE
-  const std::string&
-  nameOfTypeId() const
+  const std::vector<std::shared_ptr<const ASTNodeDataType>>&
+  contentTypeList() const
   {
-    return m_name_of_type_id;
+    Assert(std::holds_alternative<std::vector<std::shared_ptr<const ASTNodeDataType>>>(m_details));
+    return std::get<std::vector<std::shared_ptr<const ASTNodeDataType>>>(m_details);
   }
 
   PUGS_INLINE
@@ -86,6 +103,7 @@ class ASTNodeDataType
     static_assert(data_type != typename_t, "typename_t requires sub_type");
     static_assert(data_type != vector_t, "vector_t requires dimension");
     static_assert(data_type != type_id_t, "type_id_t requires name");
+    static_assert(data_type != list_t, "list_t requires list of types");
 
     return ASTNodeDataType{data_type};
   }
@@ -102,7 +120,7 @@ class ASTNodeDataType
 
   template <DataType data_type>
   static ASTNodeDataType
-  build(size_t dimension)
+  build(const size_t dimension)
   {
     static_assert((data_type == vector_t), "incorrect data_type construction: cannot have dimension");
     return ASTNodeDataType{data_type, dimension};
@@ -113,14 +131,18 @@ class ASTNodeDataType
   build(const std::string& type_name)
   {
     static_assert((data_type == type_id_t), "incorrect data_type construction: cannot provide name of type");
-    Assert(type_name != "__undefined_name_type");
-
     return ASTNodeDataType{data_type, type_name};
   }
 
-  ASTNodeDataType()
-    : m_data_type{undefined_t}, m_content_type{nullptr}, m_dimension{1}, m_name_of_type_id{"__undefined_name_type"}
-  {}
+  template <DataType data_type>
+  static ASTNodeDataType
+  build(const std::vector<std::shared_ptr<const ASTNodeDataType>>& list_of_types)
+  {
+    static_assert((data_type == list_t), "incorrect data_type construction: cannot provide a list of data types");
+    return ASTNodeDataType{data_type, list_of_types};
+  }
+
+  ASTNodeDataType() : m_data_type{undefined_t} {}
 
   ASTNodeDataType(const ASTNodeDataType&) = default;
 
@@ -129,26 +151,20 @@ class ASTNodeDataType
   ~ASTNodeDataType() = default;
 
  private:
-  explicit ASTNodeDataType(DataType data_type)
-    : m_data_type{data_type}, m_content_type{nullptr}, m_dimension{1}, m_name_of_type_id{"__undefined_name_type"}
-  {}
+  explicit ASTNodeDataType(DataType data_type) : m_data_type{data_type} {}
 
   explicit ASTNodeDataType(DataType data_type, const ASTNodeDataType& content_type)
-    : m_data_type{data_type},
-      m_content_type{std::make_shared<ASTNodeDataType>(content_type)},
-      m_dimension{1},
-      m_name_of_type_id{"__undefined_name_type"}
+    : m_data_type{data_type}, m_details{std::make_shared<const ASTNodeDataType>(content_type)}
   {}
 
-  explicit ASTNodeDataType(DataType data_type, size_t dimension)
-    : m_data_type{data_type},
-      m_content_type{nullptr},
-      m_dimension{dimension},
-      m_name_of_type_id{"__undefined_name_type"}
+  explicit ASTNodeDataType(DataType data_type, const std::vector<std::shared_ptr<const ASTNodeDataType>>& list_of_types)
+    : m_data_type{data_type}, m_details{list_of_types}
   {}
 
+  explicit ASTNodeDataType(DataType data_type, const size_t dimension) : m_data_type{data_type}, m_details{dimension} {}
+
   explicit ASTNodeDataType(DataType data_type, const std::string& type_name)
-    : m_data_type{data_type}, m_content_type{nullptr}, m_dimension{1}, m_name_of_type_id{type_name}
+    : m_data_type{data_type}, m_details{type_name}
   {}
 };
 
diff --git a/src/language/ast/ASTNodeDataTypeBuilder.cpp b/src/language/ast/ASTNodeDataTypeBuilder.cpp
index 9409b4bdb..105556b83 100644
--- a/src/language/ast/ASTNodeDataTypeBuilder.cpp
+++ b/src/language/ast/ASTNodeDataTypeBuilder.cpp
@@ -21,12 +21,15 @@ ASTNodeDataTypeBuilder::_buildDeclarationNodeDataTypes(ASTNode& type_node, ASTNo
       throw ParseError(message.str(), name_node.begin());
     }
 
+    std::vector<std::shared_ptr<const ASTNodeDataType>> sub_data_type_list;
+    sub_data_type_list.reserve(type_node.children.size());
     for (size_t i = 0; i < type_node.children.size(); ++i) {
       auto& sub_type_node = *type_node.children[i];
       auto& sub_name_node = *name_node.children[i];
       _buildDeclarationNodeDataTypes(sub_type_node, sub_name_node);
+      sub_data_type_list.push_back(std::make_shared<const ASTNodeDataType>(sub_type_node.m_data_type));
     }
-    data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>();
+    data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>(sub_data_type_list);
   } else {
     if (type_node.is_type<language::B_set>()) {
       data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
@@ -149,9 +152,6 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
       } else if (n.is_type<language::vector_type>()) {
         n.m_data_type = getVectorDataType(n);
 
-      } else if (n.is_type<language::tuple_expression>()) {
-        n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>();
-
       } else if (n.is_type<language::literal>()) {
         n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
       } else if (n.is_type<language::cout_kw>() or n.is_type<language::cerr_kw>() or n.is_type<language::clog_kw>()) {
@@ -174,6 +174,8 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
         uint64_t function_id                    = std::get<uint64_t>(i_symbol->attributes().value());
         FunctionDescriptor& function_descriptor = function_table[function_id];
 
+        this->_buildNodeDataTypes(function_descriptor.domainMappingNode());
+
         ASTNode& parameters_domain_node = *function_descriptor.domainMappingNode().children[0];
         ASTNode& parameters_name_node   = *function_descriptor.definitionNode().children[0];
 
@@ -237,28 +239,22 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
         if (nb_parameter_domains == 1) {
           simple_type_allocator(parameters_domain_node, parameters_name_node);
         } else {
+          std::vector<std::shared_ptr<const ASTNodeDataType>> sub_data_type_list;
+          sub_data_type_list.reserve(nb_parameter_domains);
+
           for (size_t i = 0; i < nb_parameter_domains; ++i) {
             simple_type_allocator(*parameters_domain_node.children[i], *parameters_name_node.children[i]);
+            sub_data_type_list.push_back(
+              std::make_shared<const ASTNodeDataType>(parameters_name_node.children[i]->m_data_type));
           }
-          parameters_name_node.m_data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>();
+          parameters_name_node.m_data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>(sub_data_type_list);
         }
 
-        // build types for compound types
-        for (auto& child : parameters_domain_node.children) {
-          this->_buildNodeDataTypes(*child);
-        }
-        for (auto& child : parameters_name_node.children) {
-          this->_buildNodeDataTypes(*child);
-        }
+        this->_buildNodeDataTypes(function_descriptor.definitionNode());
 
         ASTNode& image_domain_node     = *function_descriptor.domainMappingNode().children[1];
         ASTNode& image_expression_node = *function_descriptor.definitionNode().children[1];
 
-        this->_buildNodeDataTypes(image_domain_node);
-        for (auto& child : image_domain_node.children) {
-          this->_buildNodeDataTypes(*child);
-        }
-
         const size_t nb_image_domains =
           (image_domain_node.is_type<language::type_expression>()) ? image_domain_node.children.size() : 1;
         const size_t nb_image_expressions =
@@ -308,11 +304,16 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
         };
 
         if (image_domain_node.is_type<language::type_expression>()) {
+          std::vector<std::shared_ptr<const ASTNodeDataType>> sub_data_type_list;
+          sub_data_type_list.reserve(image_domain_node.children.size());
+
           for (size_t i = 0; i < image_domain_node.children.size(); ++i) {
             check_image_type(*image_domain_node.children[i]);
+            sub_data_type_list.push_back(
+              std::make_shared<const ASTNodeDataType>(image_domain_node.children[i]->m_data_type));
           }
-          image_domain_node.m_data_type =
-            ASTNodeDataType::build<ASTNodeDataType::typename_t>(ASTNodeDataType::build<ASTNodeDataType::list_t>());
+          image_domain_node.m_data_type = ASTNodeDataType::build<ASTNodeDataType::typename_t>(
+            ASTNodeDataType::build<ASTNodeDataType::list_t>(sub_data_type_list));
         } else {
           check_image_type(image_domain_node);
         }
@@ -337,8 +338,55 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
                n.is_type<language::divideeq_op>() or n.is_type<language::pluseq_op>() or
                n.is_type<language::minuseq_op>()) {
       n.m_data_type = n.children[0]->m_data_type;
+
+    } else if (n.is_type<language::tuple_expression>()) {
+      std::vector<std::shared_ptr<const ASTNodeDataType>> sub_data_type_list;
+      sub_data_type_list.reserve(n.children.size());
+
+      for (size_t i = 0; i < n.children.size(); ++i) {
+        sub_data_type_list.push_back(std::make_shared<const ASTNodeDataType>(n.children[i]->m_data_type));
+      }
+      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>(sub_data_type_list);
+
     } else if (n.is_type<language::type_mapping>() or n.is_type<language::function_definition>()) {
+      for (auto& child : n.children) {
+        this->_buildNodeDataTypes(*child);
+      }
       n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
+    } else if (n.is_type<language::type_expression>()) {
+      std::vector<std::shared_ptr<const ASTNodeDataType>> sub_data_type_list;
+      sub_data_type_list.reserve(n.children.size());
+
+      auto check_sub_type = [&](const ASTNode& image_node) {
+        ASTNodeDataType value_type;
+        if (image_node.is_type<language::B_set>()) {
+          value_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
+        } else if (image_node.is_type<language::Z_set>()) {
+          value_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+        } else if (image_node.is_type<language::N_set>()) {
+          value_type = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
+        } else if (image_node.is_type<language::R_set>()) {
+          value_type = ASTNodeDataType::build<ASTNodeDataType::double_t>();
+        } else if (image_node.is_type<language::vector_type>()) {
+          value_type = getVectorDataType(image_node);
+        } else if (image_node.is_type<language::string_type>()) {
+          value_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+        }
+
+        // LCOV_EXCL_START
+        if (value_type == ASTNodeDataType::undefined_t) {
+          throw ParseError("invalid value type", image_node.begin());
+        }
+        // LCOV_EXCL_STOP
+      };
+
+      for (size_t i = 0; i < n.children.size(); ++i) {
+        check_sub_type(*n.children[i]);
+        sub_data_type_list.push_back(std::make_shared<const ASTNodeDataType>(n.children[i]->m_data_type));
+      }
+      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::typename_t>(
+        ASTNodeDataType::build<ASTNodeDataType::list_t>(sub_data_type_list));
+
     } else if (n.is_type<language::for_post>() or n.is_type<language::for_init>() or
                n.is_type<language::for_statement_block>()) {
       n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
@@ -471,7 +519,14 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
       n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::typename_t>(getVectorDataType(n));
     } else if (n.is_type<language::name_list>() or n.is_type<language::lvalue_list>() or
                n.is_type<language::function_argument_list>() or n.is_type<language::expression_list>()) {
-      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>();
+      std::vector<std::shared_ptr<const ASTNodeDataType>> sub_data_type_list;
+      sub_data_type_list.reserve(n.children.size());
+
+      for (size_t i = 0; i < n.children.size(); ++i) {
+        sub_data_type_list.push_back(std::make_shared<const ASTNodeDataType>(n.children[i]->m_data_type));
+      }
+
+      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>(sub_data_type_list);
     }
   }
 }
diff --git a/tests/test_ASTNodeDataType.cpp b/tests/test_ASTNodeDataType.cpp
index 94c2b3545..9d1f55234 100644
--- a/tests/test_ASTNodeDataType.cpp
+++ b/tests/test_ASTNodeDataType.cpp
@@ -24,7 +24,12 @@ TEST_CASE("ASTNodeDataType", "[language]")
   const ASTNodeDataType void_dt             = ASTNodeDataType::build<ASTNodeDataType::void_t>();
   const ASTNodeDataType function_dt         = ASTNodeDataType::build<ASTNodeDataType::function_t>();
   const ASTNodeDataType builtin_function_dt = ASTNodeDataType::build<ASTNodeDataType::builtin_function_t>();
-  const ASTNodeDataType list_dt             = ASTNodeDataType::build<ASTNodeDataType::list_t>();
+
+  std::vector<std::shared_ptr<const ASTNodeDataType>> type_list;
+  type_list.push_back(std::make_shared<const ASTNodeDataType>(double_dt));
+  type_list.push_back(std::make_shared<const ASTNodeDataType>(int_dt));
+
+  const ASTNodeDataType list_dt = ASTNodeDataType::build<ASTNodeDataType::list_t>(type_list);
 
   SECTION("dataTypeName")
   {
@@ -38,7 +43,7 @@ TEST_CASE("ASTNodeDataType", "[language]")
     REQUIRE(dataTypeName(void_dt) == "void");
     REQUIRE(dataTypeName(function_dt) == "function");
     REQUIRE(dataTypeName(builtin_function_dt) == "builtin_function");
-    REQUIRE(dataTypeName(list_dt) == "list");
+    REQUIRE(dataTypeName(list_dt) == "list(R*Z)");
     REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt)) == "tuple(B)");
     REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt)) == "tuple(N)");
     REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt)) == "tuple(Z)");
diff --git a/tests/test_ASTNodeDataTypeBuilder.cpp b/tests/test_ASTNodeDataTypeBuilder.cpp
index 1fbe1a2a0..dd206297d 100644
--- a/tests/test_ASTNodeDataTypeBuilder.cpp
+++ b/tests/test_ASTNodeDataTypeBuilder.cpp
@@ -278,12 +278,12 @@ let (x,b,n,s) : R*B*N*string;
       std::string_view result = R"(
 (root:void)
  `-(language::var_declaration:void)
-     +-(language::name_list:list)
+     +-(language::name_list:list(R*B*N*string))
      |   +-(language::name:x:R)
      |   +-(language::name:b:B)
      |   +-(language::name:n:N)
      |   `-(language::name:s:string)
-     `-(language::type_expression:typename(list))
+     `-(language::type_expression:typename(list(typename(R)*typename(B)*typename(N)*typename(string))))
          +-(language::R_set:typename(R))
          +-(language::B_set:typename(B))
          +-(language::N_set:typename(N))
@@ -382,7 +382,7 @@ let t : (B), t = (true, false);
      +-(language::tuple_type_specifier:typename(tuple(B)))
      |   `-(language::B_set:typename(B))
      +-(language::name:t:tuple(B))
-     `-(language::expression_list:list)
+     `-(language::expression_list:list(B*B))
          +-(language::true_kw:B)
          `-(language::false_kw:B)
 )";
@@ -403,7 +403,7 @@ let t : (N), t = (1, 2, 3, 5);
      +-(language::tuple_type_specifier:typename(tuple(N)))
      |   `-(language::N_set:typename(N))
      +-(language::name:t:tuple(N))
-     `-(language::expression_list:list)
+     `-(language::expression_list:list(Z*Z*Z*Z))
          +-(language::integer:1:Z)
          +-(language::integer:2:Z)
          +-(language::integer:3:Z)
@@ -432,7 +432,7 @@ let t : (Z), t = (2, n, true);
      +-(language::tuple_type_specifier:typename(tuple(Z)))
      |   `-(language::Z_set:typename(Z))
      +-(language::name:t:tuple(Z))
-     `-(language::expression_list:list)
+     `-(language::expression_list:list(Z*N*B))
          +-(language::integer:2:Z)
          +-(language::name:n:N)
          `-(language::true_kw:B)
@@ -454,7 +454,7 @@ let t : (R), t = (2, 3.1, 5);
      +-(language::tuple_type_specifier:typename(tuple(R)))
      |   `-(language::R_set:typename(R))
      +-(language::name:t:tuple(R))
-     `-(language::expression_list:list)
+     `-(language::expression_list:list(Z*R*Z))
          +-(language::integer:2:Z)
          +-(language::real:3.1:R)
          `-(language::integer:5:Z)
@@ -479,7 +479,7 @@ let t2 : (R^3), t2 = (0, 0);
  |   |   +-(language::R_set:typename(R))
  |   |   `-(language::integer:2:Z)
  |   +-(language::name:a:R^2)
- |   `-(language::expression_list:list)
+ |   `-(language::expression_list:list(Z*R))
  |       +-(language::integer:2:Z)
  |       `-(language::real:3.1:R)
  +-(language::var_declaration:void)
@@ -489,9 +489,9 @@ let t2 : (R^3), t2 = (0, 0);
  |   |       +-(language::R_set:typename(R))
  |   |       `-(language::integer:2:Z)
  |   +-(language::name:t1:tuple(R^2))
- |   `-(language::expression_list:list)
+ |   `-(language::expression_list:list(R^2*list(Z*Z)*Z))
  |       +-(language::name:a:R^2)
- |       +-(language::tuple_expression:list)
+ |       +-(language::tuple_expression:list(Z*Z))
  |       |   +-(language::integer:1:Z)
  |       |   `-(language::integer:2:Z)
  |       `-(language::integer:0:Z)
@@ -502,7 +502,7 @@ let t2 : (R^3), t2 = (0, 0);
      |       +-(language::R_set:typename(R))
      |       `-(language::integer:3:Z)
      +-(language::name:t2:tuple(R^3))
-     `-(language::expression_list:list)
+     `-(language::expression_list:list(Z*Z))
          +-(language::integer:0:Z)
          `-(language::integer:0:Z)
 )";
@@ -523,7 +523,7 @@ let t : (string), t = ("foo", "bar");
      +-(language::tuple_type_specifier:typename(tuple(string)))
      |   `-(language::string_type:typename(string))
      +-(language::name:t:tuple(string))
-     `-(language::expression_list:list)
+     `-(language::expression_list:list(string*string))
          +-(language::literal:"foo":string)
          `-(language::literal:"bar":string)
 )";
@@ -545,7 +545,7 @@ let t : (builtin_t), t= (1,2,3);
      +-(language::tuple_type_specifier:typename(tuple(builtin_t)))
      |   `-(language::type_name_id:builtin_t)
      +-(language::name:t:tuple(builtin_t))
-     `-(language::expression_list:list)
+     `-(language::expression_list:list(Z*Z*Z))
          +-(language::integer:1:Z)
          +-(language::integer:2:Z)
          `-(language::integer:3:Z)
@@ -891,7 +891,7 @@ x = f(x);
  |   |   +-(language::R_set:typename(R))
  |   |   `-(language::integer:2:Z)
  |   +-(language::name:x:R^2)
- |   `-(language::expression_list:list)
+ |   `-(language::expression_list:list(Z*Z))
  |       +-(language::integer:1:Z)
  |       `-(language::integer:2:Z)
  `-(language::eq_op:R^2)
@@ -947,7 +947,7 @@ let  diff : R, diff = substract(3,2);
      +-(language::name:diff:R)
      `-(language::function_evaluation:R)
          +-(language::name:substract:function)
-         `-(language::function_argument_list:list)
+         `-(language::function_argument_list:list(Z*Z))
              +-(language::integer:3:Z)
              `-(language::integer:2:Z)
 )";
@@ -1042,7 +1042,7 @@ let s : string, s = cat("foo", "bar");
      +-(language::name:s:string)
      `-(language::function_evaluation:string)
          +-(language::name:cat:function)
-         `-(language::function_argument_list:list)
+         `-(language::function_argument_list:list(string*string))
              +-(language::literal:"foo":string)
              `-(language::literal:"bar":string)
 )";
@@ -1062,16 +1062,16 @@ let (x,x2) : R*R, (x,x2) = x_x2(3);
  +-(language::fct_declaration:void)
  |   `-(language::name:x_x2:function)
  `-(language::var_declaration:void)
-     +-(language::name_list:list)
+     +-(language::name_list:list(R*R))
      |   +-(language::name:x:R)
      |   `-(language::name:x2:R)
-     +-(language::type_expression:typename(list))
+     +-(language::type_expression:typename(list(typename(R)*typename(R))))
      |   +-(language::R_set:typename(R))
      |   `-(language::R_set:typename(R))
-     +-(language::name_list:list)
+     +-(language::name_list:list(R*R))
      |   +-(language::name:x:R)
      |   `-(language::name:x2:R)
-     `-(language::function_evaluation:list)
+     `-(language::function_evaluation:list(typename(R)*typename(R)))
          +-(language::name:x_x2:function)
          `-(language::integer:3:Z)
 )";
diff --git a/tests/test_ASTNodeNaturalConversionChecker.cpp b/tests/test_ASTNodeNaturalConversionChecker.cpp
index 4283d185e..f4921b042 100644
--- a/tests/test_ASTNodeNaturalConversionChecker.cpp
+++ b/tests/test_ASTNodeNaturalConversionChecker.cpp
@@ -22,7 +22,12 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
   const ASTNodeDataType void_dt             = ASTNodeDataType::build<ASTNodeDataType::void_t>();
   const ASTNodeDataType function_dt         = ASTNodeDataType::build<ASTNodeDataType::function_t>();
   const ASTNodeDataType builtin_function_dt = ASTNodeDataType::build<ASTNodeDataType::builtin_function_t>();
-  const ASTNodeDataType list_dt             = ASTNodeDataType::build<ASTNodeDataType::list_t>();
+
+  std::vector<std::shared_ptr<const ASTNodeDataType>> type_list;
+  type_list.push_back(std::make_shared<const ASTNodeDataType>(double_dt));
+  type_list.push_back(std::make_shared<const ASTNodeDataType>(int_dt));
+
+  const ASTNodeDataType list_dt = ASTNodeDataType::build<ASTNodeDataType::list_t>(type_list);
 
   SECTION("Valid conversions")
   {
-- 
GitLab