diff --git a/src/language/ast/ASTNode.hpp b/src/language/ast/ASTNode.hpp
index b3dd41ca65faae6324d040aa7f4b66c078f45f6c..a3b9bd21569d490b1bc7f450eee546279b91a681 100644
--- a/src/language/ast/ASTNode.hpp
+++ b/src/language/ast/ASTNode.hpp
@@ -45,7 +45,7 @@ class ASTNode : public parse_tree::basic_node<ASTNode>
   std::shared_ptr<SymbolTable> m_symbol_table;
   std::unique_ptr<INodeProcessor> m_node_processor;
 
-  ASTNodeDataType m_data_type{ASTNodeDataType::undefined_t};
+  ASTNodeDataType m_data_type;
 
   [[nodiscard]] PUGS_INLINE std::string
   string() const
diff --git a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp
index e27bd531d743b410ecb381e665bb4af145e4731f..66420138cd85f3fcf220ceec883f6c2b1b012759 100644
--- a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp
@@ -405,18 +405,22 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode
     };
 
     using OperatorT = std::decay_t<decltype(operator_v)>;
+
+    const ASTNodeDataType& target_data_type = n.children[0]->m_data_type;
+    const ASTNodeDataType& source_data_type = n.children[1]->m_data_type;
+
     // Special treatment dedicated to R^1 to be able to initialize them
-    if (((n.m_data_type != n.children[1]->m_data_type) and (n.m_data_type == ASTNodeDataType::vector_t) and
-         (n.m_data_type.dimension() == 1)) or
+    if (((target_data_type != source_data_type) and (target_data_type == ASTNodeDataType::vector_t) and
+         (target_data_type.dimension() == 1)) or
         // Special treatment for R^d vectors and operator *=
-        ((n.m_data_type == ASTNodeDataType::vector_t) and (n.children[1]->m_data_type != ASTNodeDataType::vector_t) and
+        ((target_data_type == ASTNodeDataType::vector_t) and (source_data_type != ASTNodeDataType::vector_t) and
          std::is_same_v<OperatorT, language::multiplyeq_op>)) {
-      ASTNodeNaturalConversionChecker{*n.children[1], ASTNodeDataType::double_t};
+      ASTNodeNaturalConversionChecker{*n.children[1], ASTNodeDataType::build<ASTNodeDataType::double_t>()};
     } else {
-      ASTNodeNaturalConversionChecker{*n.children[1], n.m_data_type};
+      ASTNodeNaturalConversionChecker{*n.children[1], target_data_type};
     }
 
-    set_affectation_processor_for_value(n.m_data_type);
+    set_affectation_processor_for_value(target_data_type);
   };
 
   if (n.is_type<language::eq_op>()) {
diff --git a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp
index 6dc726f555219b855e2a125b0ab22b586dec2dad..e3d00a40795b7057ad832c95c0093f90b98ff0a4 100644
--- a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp
@@ -316,7 +316,7 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData
 
   if (parameter_type == ASTNodeDataType::vector_t and parameter_type.dimension() == 1) {
     if (not isNaturalConversion(argument_node_sub_data_type.m_data_type, parameter_type)) {
-      ASTNodeNaturalConversionChecker{argument_node_sub_data_type, ASTNodeDataType::double_t};
+      ASTNodeNaturalConversionChecker{argument_node_sub_data_type, ASTNodeDataType::build<ASTNodeDataType::double_t>()};
     }
   } else {
     ASTNodeNaturalConversionChecker{argument_node_sub_data_type, parameter_type};
diff --git a/src/language/ast/ASTNodeDataType.cpp b/src/language/ast/ASTNodeDataType.cpp
index c77659d983c58a571ac3dd8426437be6478ceddb..a4a94d7628ea8e9f5072e95ba2c64eeba04ac89c 100644
--- a/src/language/ast/ASTNodeDataType.cpp
+++ b/src/language/ast/ASTNodeDataType.cpp
@@ -16,7 +16,7 @@ getVectorDataType(const ASTNode& type_node)
     throw ParseError("unexpected non integer constant dimension", dimension_node.begin());
   }
   const size_t dimension = std::stol(dimension_node.string());
-  return ASTNodeDataType{ASTNodeDataType::vector_t, dimension};
+  return ASTNodeDataType::build<ASTNodeDataType::vector_t>(dimension);
 }
 
 std::string
@@ -52,7 +52,7 @@ dataTypeName(const ASTNodeDataType& data_type)
     name = "string";
     break;
   case ASTNodeDataType::typename_t:
-    name = "typename";
+    name = std::string("typename(") + dataTypeName(data_type.contentType()) + ")";
     break;
   case ASTNodeDataType::type_name_id_t:
     name = "type_name_id";
@@ -88,7 +88,7 @@ dataTypePromotion(const ASTNodeDataType& data_type_1, const ASTNodeDataType& dat
              (data_type_2 == ASTNodeDataType::vector_t)) {
     return data_type_2;
   } else {
-    return ASTNodeDataType::undefined_t;
+    return ASTNodeDataType{};
   }
 }
 
diff --git a/src/language/ast/ASTNodeDataType.hpp b/src/language/ast/ASTNodeDataType.hpp
index 863a87dad0a3df9d3659b9c661336fbf5e384aca..39e8e1bfa85714625de03a7cb860171056e0822d 100644
--- a/src/language/ast/ASTNodeDataType.hpp
+++ b/src/language/ast/ASTNodeDataType.hpp
@@ -8,6 +8,15 @@
 #include <string>
 
 class ASTNode;
+class ASTNodeDataType;
+
+ASTNodeDataType getVectorDataType(const ASTNode& type_node);
+
+std::string dataTypeName(const ASTNodeDataType& data_type);
+
+ASTNodeDataType dataTypePromotion(const ASTNodeDataType& data_type_1, const ASTNodeDataType& data_type_2);
+
+bool isNaturalConversion(const ASTNodeDataType& data_type, const ASTNodeDataType& target_data_type);
 
 class ASTNodeDataType
 {
@@ -69,23 +78,48 @@ class ASTNodeDataType
   ASTNodeDataType& operator=(const ASTNodeDataType&) = default;
   ASTNodeDataType& operator=(ASTNodeDataType&&) = default;
 
-  ASTNodeDataType(DataType data_type)
-    : m_data_type{data_type}, m_content_type{nullptr}, m_dimension{1}, m_name_of_type_id{"unknown"}
-  {}
+  template <DataType data_type>
+  static ASTNodeDataType
+  build()
+  {
+    static_assert(data_type != tuple_t, "tuple_t requires sub_type");
+    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");
 
-  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{"unknown"}
-  {}
+    return ASTNodeDataType{data_type};
+  }
 
-  ASTNodeDataType(DataType data_type, size_t dimension)
-    : m_data_type{data_type}, m_content_type{nullptr}, m_dimension{dimension}, m_name_of_type_id{"unknown"}
-  {}
+  template <DataType data_type>
+  static ASTNodeDataType
+  build(const ASTNodeDataType& content_type)
+  {
+    static_assert((data_type == tuple_t) or (data_type == typename_t),
+                  "incorrect data_type construction: cannot have content");
 
-  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}
+    return ASTNodeDataType{data_type, content_type};
+  }
+
+  template <DataType data_type>
+  static ASTNodeDataType
+  build(size_t dimension)
+  {
+    static_assert((data_type == vector_t), "incorrect data_type construction: cannot have dimension");
+    return ASTNodeDataType{data_type, dimension};
+  }
+
+  template <DataType data_type>
+  static 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"}
   {}
 
   ASTNodeDataType(const ASTNodeDataType&) = default;
@@ -93,14 +127,29 @@ class ASTNodeDataType
   ASTNodeDataType(ASTNodeDataType&&) = default;
 
   ~ASTNodeDataType() = default;
-};
 
-ASTNodeDataType getVectorDataType(const ASTNode& type_node);
+ 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"}
+  {}
 
-std::string dataTypeName(const ASTNodeDataType& 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"}
+  {}
 
-ASTNodeDataType dataTypePromotion(const ASTNodeDataType& data_type_1, const ASTNodeDataType& data_type_2);
+  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"}
+  {}
 
-bool isNaturalConversion(const ASTNodeDataType& data_type, const ASTNodeDataType& target_data_type);
+  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}
+  {}
+};
 
 #endif   // AST_NODE_DATA_TYPE_HPP
diff --git a/src/language/ast/ASTNodeDataTypeBuilder.cpp b/src/language/ast/ASTNodeDataTypeBuilder.cpp
index 7da94cc5f7d00132b226f8ba0e7e5d95d4097b35..9409b4bdbaf3afe04ba216d8941a5ebce8353081 100644
--- a/src/language/ast/ASTNodeDataTypeBuilder.cpp
+++ b/src/language/ast/ASTNodeDataTypeBuilder.cpp
@@ -10,7 +10,7 @@
 ASTNodeDataType
 ASTNodeDataTypeBuilder::_buildDeclarationNodeDataTypes(ASTNode& type_node, ASTNode& name_node) const
 {
-  ASTNodeDataType data_type{ASTNodeDataType::undefined_t};
+  ASTNodeDataType data_type;
   if (type_node.is_type<language::type_expression>()) {
     if (type_node.children.size() != name_node.children.size()) {
       std::ostringstream message;
@@ -26,16 +26,16 @@ ASTNodeDataTypeBuilder::_buildDeclarationNodeDataTypes(ASTNode& type_node, ASTNo
       auto& sub_name_node = *name_node.children[i];
       _buildDeclarationNodeDataTypes(sub_type_node, sub_name_node);
     }
-    data_type = ASTNodeDataType::typename_t;
+    data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>();
   } else {
     if (type_node.is_type<language::B_set>()) {
-      data_type = ASTNodeDataType::bool_t;
+      data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
     } else if (type_node.is_type<language::Z_set>()) {
-      data_type = ASTNodeDataType::int_t;
+      data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
     } else if (type_node.is_type<language::N_set>()) {
-      data_type = ASTNodeDataType::unsigned_int_t;
+      data_type = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
     } else if (type_node.is_type<language::R_set>()) {
-      data_type = ASTNodeDataType::double_t;
+      data_type = ASTNodeDataType::build<ASTNodeDataType::double_t>();
     } else if (type_node.is_type<language::vector_type>()) {
       data_type = getVectorDataType(type_node);
     } else if (type_node.is_type<language::tuple_type_specifier>()) {
@@ -56,28 +56,28 @@ ASTNodeDataTypeBuilder::_buildDeclarationNodeDataTypes(ASTNode& type_node, ASTNo
           throw ParseError(os.str(), std::vector{content_node->begin()});
         }
 
-        content_node->m_data_type = ASTNodeDataType{ASTNodeDataType::type_id_t, type_name_id};
+        content_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::type_id_t>(type_name_id);
       } else if (content_node->is_type<language::B_set>()) {
-        content_node->m_data_type = ASTNodeDataType::bool_t;
+        content_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
       } else if (content_node->is_type<language::Z_set>()) {
-        content_node->m_data_type = ASTNodeDataType::int_t;
+        content_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
       } else if (content_node->is_type<language::N_set>()) {
-        content_node->m_data_type = ASTNodeDataType::unsigned_int_t;
+        content_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
       } else if (content_node->is_type<language::R_set>()) {
-        content_node->m_data_type = ASTNodeDataType::double_t;
+        content_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::double_t>();
       } else if (content_node->is_type<language::vector_type>()) {
         content_node->m_data_type = getVectorDataType(*type_node.children[0]);
       } else if (content_node->is_type<language::string_type>()) {
-        content_node->m_data_type = ASTNodeDataType::string_t;
+        content_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
       } else {
         // LCOV_EXCL_START
         throw UnexpectedError("unexpected content type in tuple");
         // LCOV_EXCL_STOP
       }
 
-      data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, content_node->m_data_type};
+      data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(content_node->m_data_type);
     } else if (type_node.is_type<language::string_type>()) {
-      data_type = ASTNodeDataType::string_t;
+      data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
     } else if (type_node.is_type<language::type_name_id>()) {
       const std::string& type_name_id = type_node.string();
 
@@ -93,7 +93,7 @@ ASTNodeDataTypeBuilder::_buildDeclarationNodeDataTypes(ASTNode& type_node, ASTNo
         throw ParseError(os.str(), std::vector{type_node.begin()});
       }
 
-      data_type = ASTNodeDataType{ASTNodeDataType::type_id_t, type_name_id};
+      data_type = ASTNodeDataType::build<ASTNodeDataType::type_id_t>(type_name_id);
     }
 
     if (name_node.is_type<language::name_list>()) {
@@ -128,42 +128,43 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
       const ASTNode& test_node = *n.children[1];
 
       if (not n.children[1]->is_type<language::for_test>()) {
-        ASTNodeNaturalConversionChecker{test_node, ASTNodeDataType::bool_t};
+        ASTNodeNaturalConversionChecker{test_node, ASTNodeDataType::build<ASTNodeDataType::bool_t>()};
       }   // in the case of empty for_test (not simplified node), nothing to check!
     }
 
-    n.m_data_type = ASTNodeDataType::void_t;
+    n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
   } else {
     if (n.has_content()) {
       if (n.is_type<language::import_instruction>()) {
-        n.m_data_type = ASTNodeDataType::void_t;
+        n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
       } else if (n.is_type<language::module_name>()) {
-        n.m_data_type = ASTNodeDataType::string_t;
+        n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
       } else if (n.is_type<language::true_kw>() or n.is_type<language::false_kw>()) {
-        n.m_data_type = ASTNodeDataType::bool_t;
+        n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
       } else if (n.is_type<language::real>()) {
-        n.m_data_type = ASTNodeDataType::double_t;
+        n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::double_t>();
       } else if (n.is_type<language::integer>()) {
-        n.m_data_type = ASTNodeDataType::int_t;
+        n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
       } 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::list_t;
+        n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>();
 
       } else if (n.is_type<language::literal>()) {
-        n.m_data_type = ASTNodeDataType::string_t;
+        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>()) {
-        n.m_data_type = ASTNodeDataType::void_t;
+        n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
       } else if (n.is_type<language::var_declaration>()) {
         auto& name_node = *(n.children[0]);
         auto& type_node = *(n.children[1]);
 
-        type_node.m_data_type = _buildDeclarationNodeDataTypes(type_node, name_node);
-        n.m_data_type         = type_node.m_data_type;
+        type_node.m_data_type =
+          ASTNodeDataType::build<ASTNodeDataType::typename_t>(_buildDeclarationNodeDataTypes(type_node, name_node));
+        n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
       } else if (n.is_type<language::fct_declaration>()) {
-        n.children[0]->m_data_type = ASTNodeDataType::function_t;
+        n.children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::function_t>();
 
         const std::string& symbol = n.children[0]->string();
         auto [i_symbol, success]  = n.m_symbol_table->find(symbol, n.children[0]->begin());
@@ -202,19 +203,19 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
 
         auto simple_type_allocator = [&](const ASTNode& type_node, ASTNode& symbol_node) {
           Assert(symbol_node.is_type<language::name>());
-          ASTNodeDataType data_type{ASTNodeDataType::undefined_t};
+          ASTNodeDataType data_type;
           if (type_node.is_type<language::B_set>()) {
-            data_type = ASTNodeDataType::bool_t;
+            data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
           } else if (type_node.is_type<language::Z_set>()) {
-            data_type = ASTNodeDataType::int_t;
+            data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
           } else if (type_node.is_type<language::N_set>()) {
-            data_type = ASTNodeDataType::unsigned_int_t;
+            data_type = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
           } else if (type_node.is_type<language::R_set>()) {
-            data_type = ASTNodeDataType::double_t;
+            data_type = ASTNodeDataType::build<ASTNodeDataType::double_t>();
           } else if (type_node.is_type<language::vector_type>()) {
             data_type = getVectorDataType(type_node);
           } else if (type_node.is_type<language::string_type>()) {
-            data_type = ASTNodeDataType::string_t;
+            data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
           }
 
           // LCOV_EXCL_START
@@ -239,7 +240,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
           for (size_t i = 0; i < nb_parameter_domains; ++i) {
             simple_type_allocator(*parameters_domain_node.children[i], *parameters_name_node.children[i]);
           }
-          parameters_name_node.m_data_type = ASTNodeDataType::list_t;
+          parameters_name_node.m_data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>();
         }
 
         // build types for compound types
@@ -284,19 +285,19 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
         }
 
         auto check_image_type = [&](const ASTNode& image_node) {
-          ASTNodeDataType value_type{ASTNodeDataType::undefined_t};
+          ASTNodeDataType value_type;
           if (image_node.is_type<language::B_set>()) {
-            value_type = ASTNodeDataType::bool_t;
+            value_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
           } else if (image_node.is_type<language::Z_set>()) {
-            value_type = ASTNodeDataType::int_t;
+            value_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
           } else if (image_node.is_type<language::N_set>()) {
-            value_type = ASTNodeDataType::unsigned_int_t;
+            value_type = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
           } else if (image_node.is_type<language::R_set>()) {
-            value_type = ASTNodeDataType::double_t;
+            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::string_t;
+            value_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
           }
 
           // LCOV_EXCL_START
@@ -310,12 +311,13 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
           for (size_t i = 0; i < image_domain_node.children.size(); ++i) {
             check_image_type(*image_domain_node.children[i]);
           }
-          image_domain_node.m_data_type = ASTNodeDataType::typename_t;
+          image_domain_node.m_data_type =
+            ASTNodeDataType::build<ASTNodeDataType::typename_t>(ASTNodeDataType::build<ASTNodeDataType::list_t>());
         } else {
           check_image_type(image_domain_node);
         }
 
-        n.m_data_type = ASTNodeDataType::void_t;
+        n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
         return;
       } else if (n.is_type<language::name>()) {
         std::shared_ptr<SymbolTable>& symbol_table = n.m_symbol_table;
@@ -330,56 +332,56 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
     }
 
     if (n.is_type<language::break_kw>() or n.is_type<language::continue_kw>()) {
-      n.m_data_type = ASTNodeDataType::void_t;
+      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
     } else if (n.is_type<language::eq_op>() or n.is_type<language::multiplyeq_op>() or
                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::type_mapping>() or n.is_type<language::function_definition>()) {
-      n.m_data_type = ASTNodeDataType::void_t;
+      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
     } 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::void_t;
+      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
     } else if (n.is_type<language::for_test>()) {
-      n.m_data_type = ASTNodeDataType::bool_t;
+      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
     } else if (n.is_type<language::statement_block>()) {
-      n.m_data_type = ASTNodeDataType::void_t;
+      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
     } else if (n.is_type<language::if_statement>() or n.is_type<language::while_statement>()) {
-      n.m_data_type = ASTNodeDataType::void_t;
+      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
 
       const ASTNode& test_node = *n.children[0];
-      ASTNodeNaturalConversionChecker{test_node, ASTNodeDataType::bool_t};
+      ASTNodeNaturalConversionChecker{test_node, ASTNodeDataType::build<ASTNodeDataType::bool_t>()};
 
     } else if (n.is_type<language::do_while_statement>()) {
-      n.m_data_type = ASTNodeDataType::void_t;
+      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
 
       const ASTNode& test_node = *n.children[1];
-      ASTNodeNaturalConversionChecker{test_node, ASTNodeDataType::bool_t};
+      ASTNodeNaturalConversionChecker{test_node, ASTNodeDataType::build<ASTNodeDataType::bool_t>()};
 
     } else if (n.is_type<language::unary_not>()) {
-      n.m_data_type = ASTNodeDataType::bool_t;
+      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
 
       const ASTNode& operand_node = *n.children[0];
-      ASTNodeNaturalConversionChecker{operand_node, ASTNodeDataType::bool_t};
+      ASTNodeNaturalConversionChecker{operand_node, ASTNodeDataType::build<ASTNodeDataType::bool_t>()};
 
     } else if (n.is_type<language::lesser_op>() or n.is_type<language::lesser_or_eq_op>() or
                n.is_type<language::greater_op>() or n.is_type<language::greater_or_eq_op>() or
                n.is_type<language::eqeq_op>() or n.is_type<language::not_eq_op>()) {
-      n.m_data_type = ASTNodeDataType::bool_t;
+      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
     } else if (n.is_type<language::and_op>() or n.is_type<language::or_op>() or n.is_type<language::xor_op>()) {
-      n.m_data_type = ASTNodeDataType::bool_t;
+      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
 
       const ASTNode& lhs_node = *n.children[0];
-      ASTNodeNaturalConversionChecker{lhs_node, ASTNodeDataType::bool_t};
+      ASTNodeNaturalConversionChecker{lhs_node, ASTNodeDataType::build<ASTNodeDataType::bool_t>()};
 
       const ASTNode& rhs_node = *n.children[1];
-      ASTNodeNaturalConversionChecker{rhs_node, ASTNodeDataType::bool_t};
+      ASTNodeNaturalConversionChecker{rhs_node, ASTNodeDataType::build<ASTNodeDataType::bool_t>()};
 
     } else if (n.is_type<language::unary_minus>()) {
       n.m_data_type = n.children[0]->m_data_type;
       if ((n.children[0]->m_data_type == ASTNodeDataType::unsigned_int_t) or
           (n.children[0]->m_data_type == ASTNodeDataType::bool_t)) {
-        n.m_data_type = ASTNodeDataType::int_t;
+        n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
       } else {
         n.m_data_type = n.children[0]->m_data_type;
       }
@@ -391,7 +393,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
       const ASTNodeDataType type_0 = n.children[0]->m_data_type;
       const ASTNodeDataType type_1 = n.children[1]->m_data_type;
       if ((type_0 == ASTNodeDataType::bool_t) and (type_1 == ASTNodeDataType::bool_t)) {
-        n.m_data_type = ASTNodeDataType::int_t;
+        n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
       } else {
         n.m_data_type = dataTypePromotion(type_0, type_1);
       }
@@ -414,28 +416,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
 
         ASTNode& image_domain_node = *function_descriptor.domainMappingNode().children[1];
 
-        ASTNodeDataType data_type{ASTNodeDataType::undefined_t};
-        if (image_domain_node.is_type<language::type_expression>()) {
-          data_type = image_domain_node.m_data_type;
-        } else {
-          if (image_domain_node.is_type<language::B_set>()) {
-            data_type = ASTNodeDataType::bool_t;
-          } else if (image_domain_node.is_type<language::Z_set>()) {
-            data_type = ASTNodeDataType::int_t;
-          } else if (image_domain_node.is_type<language::N_set>()) {
-            data_type = ASTNodeDataType::unsigned_int_t;
-          } else if (image_domain_node.is_type<language::R_set>()) {
-            data_type = ASTNodeDataType::double_t;
-          } else if (image_domain_node.is_type<language::vector_type>()) {
-            data_type = getVectorDataType(image_domain_node);
-          } else if (image_domain_node.is_type<language::string_type>()) {
-            data_type = ASTNodeDataType::string_t;
-          }
-        }
-
-        Assert(data_type != ASTNodeDataType::undefined_t);   // LCOV_EXCL_LINE
-
-        n.m_data_type = data_type;
+        n.m_data_type = image_domain_node.m_data_type.contentType();
       } else if (n.children[0]->m_data_type == ASTNodeDataType::builtin_function_t) {
         const std::string builtin_function_name = n.children[0]->string();
         auto& symbol_table                      = *n.m_symbol_table;
@@ -460,7 +441,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
       auto& array_expression = *n.children[0];
       auto& index_expression = *n.children[1];
 
-      ASTNodeNaturalConversionChecker{index_expression, ASTNodeDataType::int_t};
+      ASTNodeNaturalConversionChecker{index_expression, ASTNodeDataType::build<ASTNodeDataType::int_t>()};
       if (array_expression.m_data_type != ASTNodeDataType::vector_t) {
         std::ostringstream message;
         message << "invalid types '" << rang::fgB::yellow << dataTypeName(array_expression.m_data_type)
@@ -469,15 +450,28 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
 
         throw ParseError(message.str(), n.begin());
       } else {
-        n.m_data_type = ASTNodeDataType::double_t;
+        n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::double_t>();
       }
-    } else if (n.is_type<language::B_set>() or n.is_type<language::Z_set>() or n.is_type<language::N_set>() or
-               n.is_type<language::R_set>() or n.is_type<language::string_type>() or
-               n.is_type<language::vector_type>() or n.is_type<language::type_name_id>()) {
-      n.m_data_type = ASTNodeDataType::typename_t;
+    } else if (n.is_type<language::B_set>()) {
+      n.m_data_type =
+        ASTNodeDataType::build<ASTNodeDataType::typename_t>(ASTNodeDataType::build<ASTNodeDataType::bool_t>());
+    } else if (n.is_type<language::Z_set>()) {
+      n.m_data_type =
+        ASTNodeDataType::build<ASTNodeDataType::typename_t>(ASTNodeDataType::build<ASTNodeDataType::int_t>());
+    } else if (n.is_type<language::N_set>()) {
+      n.m_data_type =
+        ASTNodeDataType::build<ASTNodeDataType::typename_t>(ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>());
+    } else if (n.is_type<language::string_type>()) {
+      n.m_data_type =
+        ASTNodeDataType::build<ASTNodeDataType::typename_t>(ASTNodeDataType::build<ASTNodeDataType::string_t>());
+    } else if (n.is_type<language::R_set>()) {
+      n.m_data_type =
+        ASTNodeDataType::build<ASTNodeDataType::typename_t>(ASTNodeDataType::build<ASTNodeDataType::double_t>());
+    } else if (n.is_type<language::vector_type>()) {
+      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::list_t;
+      n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>();
     }
   }
 }
@@ -485,7 +479,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
 ASTNodeDataTypeBuilder::ASTNodeDataTypeBuilder(ASTNode& node)
 {
   Assert(node.is_root());
-  node.m_data_type = ASTNodeDataType::void_t;
+  node.m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
 
   this->_buildNodeDataTypes(node);
 
diff --git a/src/language/ast/ASTNodeDataTypeFlattener.cpp b/src/language/ast/ASTNodeDataTypeFlattener.cpp
index da2d064c6dd677e9eae4444cde59700c3a61ec2d..51d055836393b1ee680b7d983756bee39020d992 100644
--- a/src/language/ast/ASTNodeDataTypeFlattener.cpp
+++ b/src/language/ast/ASTNodeDataTypeFlattener.cpp
@@ -11,7 +11,7 @@ ASTNodeDataTypeFlattener::ASTNodeDataTypeFlattener(ASTNode& node, FlattenedDataT
       ASTNodeDataTypeFlattener{*child_node, flattened_datatype_list};
     }
   } else if (node.is_type<language::function_evaluation>()) {
-    if (node.m_data_type != ASTNodeDataType::typename_t) {
+    if (node.m_data_type != ASTNodeDataType::list_t) {
       flattened_datatype_list.push_back({node.m_data_type, node});
     } else {
       ASTNode& function_name_node = *node.children[0];
@@ -28,24 +28,8 @@ ASTNodeDataTypeFlattener::ASTNodeDataTypeFlattener(ASTNode& node, FlattenedDataT
         ASTNode& function_image_domain = *function_descriptor.domainMappingNode().children[1];
 
         for (auto& image_sub_domain : function_image_domain.children) {
-          ASTNodeDataType data_type = ASTNodeDataType::undefined_t;
-
-          if (image_sub_domain->is_type<language::B_set>()) {
-            data_type = ASTNodeDataType::bool_t;
-          } else if (image_sub_domain->is_type<language::Z_set>()) {
-            data_type = ASTNodeDataType::int_t;
-          } else if (image_sub_domain->is_type<language::N_set>()) {
-            data_type = ASTNodeDataType::unsigned_int_t;
-          } else if (image_sub_domain->is_type<language::R_set>()) {
-            data_type = ASTNodeDataType::double_t;
-          } else if (image_sub_domain->is_type<language::vector_type>()) {
-            data_type = getVectorDataType(*image_sub_domain);
-          } else if (image_sub_domain->is_type<language::string_type>()) {
-            data_type = ASTNodeDataType::string_t;
-          }
-
-          Assert(data_type != ASTNodeDataType::undefined_t);
-          flattened_datatype_list.push_back({data_type, node});
+          Assert(image_sub_domain->m_data_type == ASTNodeDataType::typename_t);
+          flattened_datatype_list.push_back({image_sub_domain->m_data_type.contentType(), node});
         }
         break;
       }
diff --git a/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp
index 072a2af6015eed0dab37468c0c5e7211ec887eff..de442dd57789dfc0072d7ef5d42f899ecd77cb05 100644
--- a/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp
@@ -36,7 +36,7 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy
       // LCOV_EXCL_START
     default: {
       throw ParseError("unexpected error: invalid argument type 0",
-                        std::vector{node_sub_data_type.m_parent_node.begin()});
+                       std::vector{node_sub_data_type.m_parent_node.begin()});
     }
       // LCOV_EXCL_STOP
     }
@@ -52,7 +52,7 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy
       } else {
         // LCOV_EXCL_START
         throw ParseError("unexpected error: invalid argument dimension",
-                          std::vector{node_sub_data_type.m_parent_node.begin()});
+                         std::vector{node_sub_data_type.m_parent_node.begin()});
         // LCOV_EXCL_STOP
       }
     }
@@ -62,7 +62,7 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy
       } else {
         // LCOV_EXCL_START
         throw ParseError("unexpected error: invalid argument dimension",
-                          std::vector{node_sub_data_type.m_parent_node.begin()});
+                         std::vector{node_sub_data_type.m_parent_node.begin()});
         // LCOV_EXCL_STOP
       }
     }
@@ -77,7 +77,7 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy
       // LCOV_EXCL_START
     default: {
       throw ParseError("unexpected error: invalid argument type",
-                        std::vector{node_sub_data_type.m_parent_node.begin()});
+                       std::vector{node_sub_data_type.m_parent_node.begin()});
     }
       // LCOV_EXCL_STOP
     }
@@ -218,7 +218,7 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r
       // LCOV_EXCL_START
     default: {
       throw ParseError("unexpected error: undefined expression value type for function",
-                        std::vector{node.children[1]->begin()});
+                       std::vector{node.children[1]->begin()});
     }
       // LCOV_EXCL_STOP
     }
@@ -233,7 +233,7 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r
       } else {
         // LCOV_EXCL_START
         throw ParseError("unexpected error: invalid dimension for returned vector",
-                          std::vector{function_component_expression.begin()});
+                         std::vector{function_component_expression.begin()});
         // LCOV_EXCL_STOP
       }
     }
@@ -244,7 +244,7 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r
       } else {
         // LCOV_EXCL_START
         throw ParseError("unexpected error: invalid dimension for returned vector",
-                          std::vector{function_component_expression.begin()});
+                         std::vector{function_component_expression.begin()});
         // LCOV_EXCL_STOP
       }
     }
@@ -256,13 +256,13 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r
       }
       // LCOV_EXCL_START
       throw ParseError("unexpected error: undefined expression value type for function",
-                        std::vector{function_component_expression.begin()});
+                       std::vector{function_component_expression.begin()});
       // LCOV_EXCL_STOP
     }
     // LCOV_EXCL_START
     default: {
       throw ParseError("unexpected error: undefined expression value type for function",
-                        std::vector{function_component_expression.begin()});
+                       std::vector{function_component_expression.begin()});
     }
       // LCOV_EXCL_STOP
     }
@@ -331,28 +331,28 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node
   std::unique_ptr function_processor = this->_buildArgumentConverter(function_descriptor, node);
 
   auto add_component_expression = [&](ASTNode& expression_node, ASTNode& domain_node) {
-    ASTNodeDataType return_value_type = ASTNodeDataType::undefined_t;
+    ASTNodeDataType return_value_type;
 
     ASTNode& image_domain_node = domain_node;
 
     if (image_domain_node.is_type<language::B_set>()) {
-      return_value_type = ASTNodeDataType::bool_t;
+      return_value_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
     } else if (image_domain_node.is_type<language::Z_set>()) {
-      return_value_type = ASTNodeDataType::int_t;
+      return_value_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
     } else if (image_domain_node.is_type<language::N_set>()) {
-      return_value_type = ASTNodeDataType::unsigned_int_t;
+      return_value_type = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
     } else if (image_domain_node.is_type<language::R_set>()) {
-      return_value_type = ASTNodeDataType::double_t;
+      return_value_type = ASTNodeDataType::build<ASTNodeDataType::double_t>();
     } else if (image_domain_node.is_type<language::vector_type>()) {
       return_value_type = getVectorDataType(image_domain_node);
     } else if (image_domain_node.is_type<language::string_type>()) {
-      return_value_type = ASTNodeDataType::string_t;
+      return_value_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
     }
 
     Assert(return_value_type != ASTNodeDataType::undefined_t);
 
     if ((return_value_type == ASTNodeDataType::vector_t) and (return_value_type.dimension() == 1)) {
-      ASTNodeNaturalConversionChecker{expression_node, ASTNodeDataType::double_t};
+      ASTNodeNaturalConversionChecker{expression_node, ASTNodeDataType::build<ASTNodeDataType::double_t>()};
     } else {
       ASTNodeNaturalConversionChecker{expression_node, return_value_type};
     }
@@ -368,7 +368,7 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node
     ASTNodeDataType vector_type = getVectorDataType(function_image_domain);
 
     if ((vector_type.dimension() == 1) and (function_expression.m_data_type != ASTNodeDataType::vector_t)) {
-      ASTNodeNaturalConversionChecker{function_expression, ASTNodeDataType::double_t};
+      ASTNodeNaturalConversionChecker{function_expression, ASTNodeDataType::build<ASTNodeDataType::double_t>()};
     } else {
       ASTNodeNaturalConversionChecker{function_expression, vector_type};
     }
@@ -377,7 +377,8 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node
 
       for (size_t i = 0; i < vector_type.dimension(); ++i) {
         function_processor->addFunctionExpressionProcessor(
-          this->_getFunctionProcessor(ASTNodeDataType::double_t, node, *function_expression.children[i]));
+          this->_getFunctionProcessor(ASTNodeDataType::build<ASTNodeDataType::double_t>(), node,
+                                      *function_expression.children[i]));
       }
 
       switch (vector_type.dimension()) {
diff --git a/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp b/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp
index daa5a0bd371150ffd3d33a60993a3d4d10c48d96..9da8319fa5119fa22b3d6ce95e6e1e1084b401f2 100644
--- a/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp
@@ -190,7 +190,7 @@ ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor(
 
   if ((value_node.m_data_type != rhs_node_sub_data_type.m_data_type) and
       (value_node.m_data_type == ASTNodeDataType::vector_t) and (value_node.m_data_type.dimension() == 1)) {
-    ASTNodeNaturalConversionChecker{rhs_node_sub_data_type, ASTNodeDataType::double_t};
+    ASTNodeNaturalConversionChecker{rhs_node_sub_data_type, ASTNodeDataType::build<ASTNodeDataType::double_t>()};
   } else {
     ASTNodeNaturalConversionChecker{rhs_node_sub_data_type, value_node.m_data_type};
   }
@@ -211,7 +211,7 @@ ASTNodeListAffectationExpressionBuilder::_buildListAffectationProcessor()
   ASTNode& name_list_node = *m_node.children[0];
 
   if (name_list_node.children.size() != flattened_rhs_data_type_list.size()) {
-    throw ParseError("incompatible list sizes in affectation", std::vector{m_node.begin()});
+    throw ParseError("incompatible list sizes in affectation", std::vector{m_node.children[0]->begin()});
   }
 
   using ListAffectationProcessorT = ListAffectationProcessor<OperatorT>;
diff --git a/src/language/ast/ASTNodeNaturalConversionChecker.cpp b/src/language/ast/ASTNodeNaturalConversionChecker.cpp
index 0faabac4fa7d0cb197ba3b8f35ffcfadce3f162a..bb04ffe65db2ebd5952d047c522b2a457afe54ff 100644
--- a/src/language/ast/ASTNodeNaturalConversionChecker.cpp
+++ b/src/language/ast/ASTNodeNaturalConversionChecker.cpp
@@ -29,20 +29,25 @@ ASTNodeNaturalConversionChecker::_checkIsNaturalExpressionConversion(const ASTNo
                                                                      const ASTNodeDataType& target_data_type) const
 {
   if (target_data_type == ASTNodeDataType::vector_t) {
-    switch (node.m_data_type) {
+    switch (data_type) {
     case ASTNodeDataType::list_t: {
       if (node.children.size() != target_data_type.dimension()) {
         throw ParseError("incompatible dimensions in affectation", std::vector{node.begin()});
       }
       for (const auto& child : node.children) {
-        this->_checkIsNaturalExpressionConversion(*child, child->m_data_type, ASTNodeDataType::double_t);
+        this->_checkIsNaturalExpressionConversion(*child, child->m_data_type,
+                                                  ASTNodeDataType::build<ASTNodeDataType::double_t>());
       }
 
       break;
     }
     case ASTNodeDataType::vector_t: {
       if (data_type.dimension() != target_data_type.dimension()) {
-        throw ParseError("incompatible dimensions in affectation", std::vector{node.begin()});
+        std::ostringstream error_message;
+        error_message << "invalid implicit conversion: ";
+        error_message << rang::fgB::red << dataTypeName(data_type) << " -> " << dataTypeName(target_data_type)
+                      << rang::fg::reset;
+        throw ParseError(error_message.str(), std::vector{node.begin()});
       }
       break;
     }
@@ -67,7 +72,8 @@ ASTNodeNaturalConversionChecker::_checkIsNaturalExpressionConversion(const ASTNo
           (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);
+            this->_checkIsNaturalExpressionConversion(*child, child->m_data_type,
+                                                      ASTNodeDataType::build<ASTNodeDataType::double_t>());
           }
         }
       } else {
@@ -79,7 +85,8 @@ ASTNodeNaturalConversionChecker::_checkIsNaturalExpressionConversion(const ASTNo
       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);
+          this->_checkIsNaturalExpressionConversion(node, data_type,
+                                                    ASTNodeDataType::build<ASTNodeDataType::double_t>());
         }
       } else {
         this->_checkIsNaturalExpressionConversion(node, data_type, target_content_type);
diff --git a/src/language/ast/ASTSymbolInitializationChecker.cpp b/src/language/ast/ASTSymbolInitializationChecker.cpp
index 3a8c846a3626a3acb815a401767d898b378f546c..4245912037c969ae63f5e970ecd1d68a338e7179 100644
--- a/src/language/ast/ASTSymbolInitializationChecker.cpp
+++ b/src/language/ast/ASTSymbolInitializationChecker.cpp
@@ -39,7 +39,6 @@ ASTSymbolInitializationChecker::_checkSymbolInitialization(ASTNode& node)
         ASTNode& def_name_list_node  = *node.children[2];
         Assert(def_name_list_node.is_type<language::name_list>());
         ASTNode& expression_list_node = *node.children[3];
-        Assert(expression_list_node.is_type<language::expression_list>());
 
         if (decl_name_list_node.children.size() != def_name_list_node.children.size()) {
           std::ostringstream os;
@@ -47,12 +46,6 @@ ASTSymbolInitializationChecker::_checkSymbolInitialization(ASTNode& node)
              << " found " << def_name_list_node.children.size() << std::ends;
           throw ParseError(os.str(), std::vector{def_name_list_node.begin()});
         }
-        if (def_name_list_node.children.size() != expression_list_node.children.size()) {
-          std::ostringstream os;
-          os << "invalid number of definition expressions, expecting " << decl_name_list_node.children.size()
-             << " found " << expression_list_node.children.size() << std::ends;
-          throw ParseError(os.str(), std::vector{expression_list_node.begin()});
-        }
 
         this->_checkSymbolInitialization(expression_list_node);
         for (size_t i = 0; i < decl_name_list_node.children.size(); ++i) {
diff --git a/src/language/modules/MeshModule.hpp b/src/language/modules/MeshModule.hpp
index f2c3d3d6360e5fd378d128d3b6b57e0de5a04509..ebb1383107ffd288001a48a5abced722ef37a4bd 100644
--- a/src/language/modules/MeshModule.hpp
+++ b/src/language/modules/MeshModule.hpp
@@ -8,7 +8,8 @@
 class IMesh;
 
 template <>
-inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const IMesh>> = {ASTNodeDataType::type_id_t, "mesh"};
+inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const IMesh>> =
+  ASTNodeDataType::build<ASTNodeDataType::type_id_t>("mesh");
 
 class MeshModule : public BuiltinModule
 {
diff --git a/src/language/modules/ModuleRepository.cpp b/src/language/modules/ModuleRepository.cpp
index aa5c1fce3ee96c5318d930d75f2047df0d209735..497ba083ac2d9d2ca0359c5d73e85e094b1fed0e 100644
--- a/src/language/modules/ModuleRepository.cpp
+++ b/src/language/modules/ModuleRepository.cpp
@@ -63,11 +63,12 @@ ModuleRepository::populateSymbolTable(const ASTNode& module_name_node, SymbolTab
     const IModule& populating_module = *i_module->second;
 
     this->_populateEmbedderTableT(module_name_node, populating_module.getNameBuiltinFunctionMap(),
-                                  ASTNodeDataType::builtin_function_t, symbol_table,
+                                  ASTNodeDataType::build<ASTNodeDataType::builtin_function_t>(), symbol_table,
                                   symbol_table.builtinFunctionEmbedderTable());
 
-    this->_populateEmbedderTableT(module_name_node, populating_module.getNameTypeMap(), ASTNodeDataType::type_name_id_t,
-                                  symbol_table, symbol_table.typeEmbedderTable());
+    this->_populateEmbedderTableT(module_name_node, populating_module.getNameTypeMap(),
+                                  ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>(), symbol_table,
+                                  symbol_table.typeEmbedderTable());
   } else {
     throw ParseError(std::string{"could not find module "} + module_name, std::vector{module_name_node.begin()});
   }
diff --git a/src/language/modules/SchemeModule.hpp b/src/language/modules/SchemeModule.hpp
index 3c70be9a2db29d634b71ea96fb60fce38183c85d..96418b1693d377641f9bd096d263d5d17c6b929d 100644
--- a/src/language/modules/SchemeModule.hpp
+++ b/src/language/modules/SchemeModule.hpp
@@ -8,12 +8,12 @@
 class IBoundaryDescriptor;
 template <>
 inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const IBoundaryDescriptor>> =
-  {ASTNodeDataType::type_id_t, "boundary"};
+  ASTNodeDataType::build<ASTNodeDataType::type_id_t>("boundary");
 
 class IBoundaryConditionDescriptor;
 template <>
 inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const IBoundaryConditionDescriptor>> =
-  {ASTNodeDataType::type_id_t, "boundary_condition"};
+  ASTNodeDataType::build<ASTNodeDataType::type_id_t>("boundary_condition");
 
 class SchemeModule : public BuiltinModule
 {
diff --git a/src/language/node_processor/ASTNodeExpressionListProcessor.hpp b/src/language/node_processor/ASTNodeExpressionListProcessor.hpp
index 7ed93683d1b6bcfd54e624385429bce4319976d5..713eda89aec0804efb4bcd323cb9a65c10b8967d 100644
--- a/src/language/node_processor/ASTNodeExpressionListProcessor.hpp
+++ b/src/language/node_processor/ASTNodeExpressionListProcessor.hpp
@@ -42,7 +42,7 @@ class ASTNodeExpressionListProcessor final : public INodeProcessor
 
     for (auto& child : m_node.children) {
       if (child->is_type<language::function_evaluation>()) {
-        if (child->m_data_type != ASTNodeDataType::typename_t) {
+        if (child->m_data_type != ASTNodeDataType::list_t) {
           ++number_of_values;
         } else {
           ASTNode& function_name_node = *child->children[0];
diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp
index 6898bb2c2b25e4fe44a8f6e9ad271930086f0a81..e15d4aa692e9ddbc54ac086317b9ce8289c28b4c 100644
--- a/src/language/node_processor/AffectationProcessor.hpp
+++ b/src/language/node_processor/AffectationProcessor.hpp
@@ -488,9 +488,13 @@ class AffectationToTupleFromListProcessor final : public INodeProcessor
                   child_value[j]);
               }
             } else if constexpr (std::is_same_v<T, int64_t>) {
-              // in this case a 0 is given
-              Assert(child_value == 0);
-              tuple_value[i] = ZeroType{};
+              if constexpr (std::is_same_v<ValueT, TinyVector<1>>) {
+                tuple_value[i][0] = child_value;
+              } else {
+                // in this case a 0 is given
+                Assert(child_value == 0);
+                tuple_value[i] = ZeroType{};
+              }
             } else {
               // LCOV_EXCL_START
               throw ParseError("unexpected error: unexpected right hand side type in affectation",
diff --git a/src/language/utils/ASTNodeDataTypeTraits.hpp b/src/language/utils/ASTNodeDataTypeTraits.hpp
index 4ee3ba31bf60d3ca4f006fd0510fae0c1fc14056..946d63483dc8a61c33ade0b223c0619a66880fdd 100644
--- a/src/language/utils/ASTNodeDataTypeTraits.hpp
+++ b/src/language/utils/ASTNodeDataTypeTraits.hpp
@@ -8,27 +8,28 @@
 #include <vector>
 
 template <typename T>
-inline ASTNodeDataType ast_node_data_type_from = ASTNodeDataType::undefined_t;
+inline ASTNodeDataType ast_node_data_type_from = ASTNodeDataType{};
 
 template <>
-inline ASTNodeDataType ast_node_data_type_from<void> = ASTNodeDataType::void_t;
+inline ASTNodeDataType ast_node_data_type_from<void> = ASTNodeDataType::build<ASTNodeDataType::void_t>();
 template <>
-inline ASTNodeDataType ast_node_data_type_from<bool> = ASTNodeDataType::bool_t;
+inline ASTNodeDataType ast_node_data_type_from<bool> = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
 template <>
-inline ASTNodeDataType ast_node_data_type_from<int64_t> = ASTNodeDataType::int_t;
+inline ASTNodeDataType ast_node_data_type_from<int64_t> = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 template <>
-inline ASTNodeDataType ast_node_data_type_from<uint64_t> = ASTNodeDataType::unsigned_int_t;
+inline ASTNodeDataType ast_node_data_type_from<uint64_t> = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
 template <>
-inline ASTNodeDataType ast_node_data_type_from<double> = ASTNodeDataType::double_t;
+inline ASTNodeDataType ast_node_data_type_from<double> = ASTNodeDataType::build<ASTNodeDataType::double_t>();
 template <>
-inline ASTNodeDataType ast_node_data_type_from<std::string> = ASTNodeDataType::string_t;
+inline ASTNodeDataType ast_node_data_type_from<std::string> = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 template <>
-inline ASTNodeDataType ast_node_data_type_from<FunctionSymbolId> = ASTNodeDataType::function_t;
+inline ASTNodeDataType ast_node_data_type_from<FunctionSymbolId> =
+  ASTNodeDataType::build<ASTNodeDataType::function_t>();
 template <size_t N>
-inline ASTNodeDataType ast_node_data_type_from<TinyVector<N>> = {ASTNodeDataType::vector_t, N};
+inline ASTNodeDataType ast_node_data_type_from<TinyVector<N>> = ASTNodeDataType::build<ASTNodeDataType::vector_t>(N);
 
 template <typename T>
 inline ASTNodeDataType ast_node_data_type_from<std::vector<T>> =
-  ASTNodeDataType{ASTNodeDataType::tuple_t, ast_node_data_type_from<T>};
+  ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ast_node_data_type_from<T>);
 
 #endif   // AST_NODE_DATA_TYPE_TRAITS_H
diff --git a/src/language/utils/BuiltinFunctionEmbedder.hpp b/src/language/utils/BuiltinFunctionEmbedder.hpp
index 3974398e1803856585f91f09565b29da3d877533..d394aa20f9721a1dc12821960890d0c1f0b6db1c 100644
--- a/src/language/utils/BuiltinFunctionEmbedder.hpp
+++ b/src/language/utils/BuiltinFunctionEmbedder.hpp
@@ -126,14 +126,8 @@ class BuiltinFunctionEmbedder<FX(Args...)> : public IBuiltinFunctionEmbedder
   PUGS_INLINE ASTNodeDataType
   _getDataType() const
   {
-    if constexpr (is_data_variant_v<T>) {
-      return ast_node_data_type_from<T>;
-    } else if constexpr (std::is_same_v<void, T>) {
-      return ASTNodeDataType::void_t;
-    } else {
-      Assert(ast_node_data_type_from<T> != ASTNodeDataType::undefined_t);
-      return ast_node_data_type_from<T>;
-    }
+    Assert(ast_node_data_type_from<T> != ASTNodeDataType::undefined_t);
+    return ast_node_data_type_from<T>;
   }
 
   template <size_t I>
@@ -262,14 +256,8 @@ class BuiltinFunctionEmbedder<FX(void)> : public IBuiltinFunctionEmbedder
   PUGS_INLINE ASTNodeDataType
   _getDataType() const
   {
-    if constexpr (is_data_variant_v<T>) {
-      return ast_node_data_type_from<T>;
-    } else if constexpr (std::is_same_v<void, T>) {
-      return ASTNodeDataType::void_t;
-    } else {
-      Assert(ast_node_data_type_from<T> != ASTNodeDataType::undefined_t);
-      return ast_node_data_type_from<T>;
-    }
+    Assert(ast_node_data_type_from<T> != ASTNodeDataType::undefined_t);
+    return ast_node_data_type_from<T>;
   }
 
  public:
diff --git a/src/language/utils/SymbolTable.hpp b/src/language/utils/SymbolTable.hpp
index 3eba77ec9c495a50183acda709abf030cbfc522b..6bcf267780884d1d8a1492b664ff492026ddd869 100644
--- a/src/language/utils/SymbolTable.hpp
+++ b/src/language/utils/SymbolTable.hpp
@@ -25,7 +25,7 @@ class SymbolTable
 
     bool m_is_initialized{false};
 
-    ASTNodeDataType m_data_type{ASTNodeDataType::undefined_t};
+    ASTNodeDataType m_data_type;
     DataVariant m_value;
 
    public:
diff --git a/tests/test_ASTNodeAffectationExpressionBuilder.cpp b/tests/test_ASTNodeAffectationExpressionBuilder.cpp
index 895fa860eafe2f6216066d422597e539c1a1cd65..64d60d9bfbed21703850f2d945092a9d5ae49fe0 100644
--- a/tests/test_ASTNodeAffectationExpressionBuilder.cpp
+++ b/tests/test_ASTNodeAffectationExpressionBuilder.cpp
@@ -40,8 +40,8 @@
   }
 
 template <>
-inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> = {ASTNodeDataType::type_id_t,
-                                                                                 "builtin_t"};
+inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> =
+  ASTNodeDataType::build<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)                                                         \
@@ -59,7 +59,7 @@ const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const dou
       throw UnexpectedError("cannot add '" + builtin_data_type.nameOfTypeId() + "' type for testing");        \
     }                                                                                                         \
                                                                                                               \
-    i_symbol->attributes().setDataType(ASTNodeDataType::type_name_id_t);                                      \
+    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())); \
@@ -124,7 +124,7 @@ const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const dou
       throw UnexpectedError("cannot add '" + builtin_data_type.nameOfTypeId() + "' type for testing");        \
     }                                                                                                         \
                                                                                                               \
-    i_symbol->attributes().setDataType(ASTNodeDataType::type_name_id_t);                                      \
+    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())); \
@@ -1530,9 +1530,9 @@ let x : R, x=1; x/=2.3;
     {
       auto ast = std::make_unique<ASTNode>();
       ast->set_type<language::eq_op>();
-      ast->m_data_type = ASTNodeDataType::int_t;
 
       ast->children.emplace_back(std::make_unique<ASTNode>());
+      ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
       ast->children.emplace_back(std::make_unique<ASTNode>());
       REQUIRE_THROWS_WITH(ASTNodeAffectationExpressionBuilder{*ast},
                           "unexpected error: invalid implicit conversion: undefined -> Z");
@@ -1542,9 +1542,9 @@ let x : R, x=1; x/=2.3;
     {
       auto ast = std::make_unique<ASTNode>();
       ast->set_type<language::eq_op>();
-      ast->m_data_type = ASTNodeDataType::string_t;
 
       ast->children.emplace_back(std::make_unique<ASTNode>());
+      ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
       ast->children.emplace_back(std::make_unique<ASTNode>());
       REQUIRE_THROWS_WITH(ASTNodeAffectationExpressionBuilder{*ast},
                           "unexpected error: invalid implicit conversion: undefined -> string");
@@ -1627,7 +1627,7 @@ let s : string, s="foo"; s*=2;
 let x : R^3; let y : R^1; x = y;
 )";
 
-        std::string error_message = "incompatible dimensions in affectation";
+        std::string error_message = "invalid implicit conversion: R^1 -> R^3";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
@@ -1638,7 +1638,7 @@ let x : R^3; let y : R^1; x = y;
 let x : R^3; let y : R^2; x = y;
 )";
 
-        std::string error_message = "incompatible dimensions in affectation";
+        std::string error_message = "invalid implicit conversion: R^2 -> R^3";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
@@ -1649,7 +1649,7 @@ let x : R^3; let y : R^2; x = y;
 let x : R^2; let y : R^1; x = y;
 )";
 
-        std::string error_message = "incompatible dimensions in affectation";
+        std::string error_message = "invalid implicit conversion: R^1 -> R^2";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
@@ -1660,7 +1660,7 @@ let x : R^2; let y : R^1; x = y;
 let x : R^2; let y : R^3; x = y;
 )";
 
-        std::string error_message = "incompatible dimensions in affectation";
+        std::string error_message = "invalid implicit conversion: R^3 -> R^2";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
@@ -1671,7 +1671,7 @@ let x : R^2; let y : R^3; x = y;
 let x : R^1; let y : R^2; x = y;
 )";
 
-        std::string error_message = "incompatible dimensions in affectation";
+        std::string error_message = "invalid implicit conversion: R^2 -> R^1";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
@@ -1679,10 +1679,10 @@ let x : R^1; let y : R^2; x = y;
       SECTION("R^1 <- R^3")
       {
         std::string_view data = R"(
-let x : R^1; let y : R^2; x = y;
+let x : R^1; let y : R^3; x = y;
 )";
 
-        std::string error_message = "incompatible dimensions in affectation";
+        std::string error_message = "invalid implicit conversion: R^3 -> R^1";
 
         CHECK_AST_THROWS_WITH(data, error_message);
       }
@@ -1799,20 +1799,6 @@ let (x,y,z):R*R*R, (x,y) = (2,3);
                           std::string{"invalid number of definition identifiers, expecting 3 found 2"});
     }
 
-    SECTION("incorrect identifier/expression number of symbols")
-    {
-      std::string_view data = R"(
-let (x,y,z):R*R*R, (x,y,z) = (2,3);
-)";
-
-      string_input input{data, "test.pgs"};
-      auto ast = ASTBuilder::build(input);
-
-      ASTSymbolTableBuilder{*ast};
-      REQUIRE_THROWS_WITH(ASTSymbolInitializationChecker{*ast},
-                          std::string{"invalid number of definition expressions, expecting 3 found 2"});
-    }
-
     SECTION("incorrect identifier/expression number of symbols")
     {
       std::string_view data = R"(
diff --git a/tests/test_ASTNodeArraySubscriptExpressionBuilder.cpp b/tests/test_ASTNodeArraySubscriptExpressionBuilder.cpp
index 941df56ac9d28de2aa5a211c61964b8d9ce05ee6..45b1303c3db5c69457921d98f76f43403274d7ed 100644
--- a/tests/test_ASTNodeArraySubscriptExpressionBuilder.cpp
+++ b/tests/test_ASTNodeArraySubscriptExpressionBuilder.cpp
@@ -18,7 +18,7 @@ TEST_CASE("ASTNodeArraySubscriptExpressionBuilder", "[language]")
     {
       {
         std::unique_ptr array_node = std::make_unique<ASTNode>();
-        array_node->m_data_type    = ASTNodeDataType{ASTNodeDataType::vector_t, 1};
+        array_node->m_data_type    = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
         node->emplace_back(std::move(array_node));
       }
       REQUIRE_NOTHROW(ASTNodeArraySubscriptExpressionBuilder{*node});
@@ -31,7 +31,7 @@ TEST_CASE("ASTNodeArraySubscriptExpressionBuilder", "[language]")
     {
       {
         std::unique_ptr array_node = std::make_unique<ASTNode>();
-        array_node->m_data_type    = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
+        array_node->m_data_type    = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
         node->emplace_back(std::move(array_node));
       }
       REQUIRE_NOTHROW(ASTNodeArraySubscriptExpressionBuilder{*node});
@@ -44,7 +44,7 @@ TEST_CASE("ASTNodeArraySubscriptExpressionBuilder", "[language]")
     {
       {
         std::unique_ptr array_node = std::make_unique<ASTNode>();
-        array_node->m_data_type    = ASTNodeDataType{ASTNodeDataType::vector_t, 3};
+        array_node->m_data_type    = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
         node->emplace_back(std::move(array_node));
       }
       REQUIRE_NOTHROW(ASTNodeArraySubscriptExpressionBuilder{*node});
@@ -62,7 +62,7 @@ TEST_CASE("ASTNodeArraySubscriptExpressionBuilder", "[language]")
     {
       {
         std::unique_ptr array_node = std::make_unique<ASTNode>();
-        array_node->m_data_type    = ASTNodeDataType{ASTNodeDataType::vector_t, 0};
+        array_node->m_data_type    = ASTNodeDataType::build<ASTNodeDataType::vector_t>(0);
         node->emplace_back(std::move(array_node));
       }
       REQUIRE_THROWS_WITH(ASTNodeArraySubscriptExpressionBuilder{*node}, "unexpected error: invalid array dimension");
@@ -71,7 +71,7 @@ TEST_CASE("ASTNodeArraySubscriptExpressionBuilder", "[language]")
     {
       {
         std::unique_ptr array_node = std::make_unique<ASTNode>();
-        array_node->m_data_type    = ASTNodeDataType{ASTNodeDataType::vector_t, 4};
+        array_node->m_data_type    = ASTNodeDataType::build<ASTNodeDataType::vector_t>(4);
         node->emplace_back(std::move(array_node));
       }
       REQUIRE_THROWS_WITH(ASTNodeArraySubscriptExpressionBuilder{*node}, "unexpected error: invalid array dimension");
diff --git a/tests/test_ASTNodeBinaryOperatorExpressionBuilder.cpp b/tests/test_ASTNodeBinaryOperatorExpressionBuilder.cpp
index 78a3f5f3b16bfdcb804421cc41e59a1c37abde4f..7226ec270bc72889cc13d37ebda069cbad7d3512 100644
--- a/tests/test_ASTNodeBinaryOperatorExpressionBuilder.cpp
+++ b/tests/test_ASTNodeBinaryOperatorExpressionBuilder.cpp
@@ -1434,8 +1434,8 @@ x!=y;
         ast->set_type<language::multiply_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::void_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1446,8 +1446,8 @@ x!=y;
         ast->set_type<language::multiply_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::string_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1458,8 +1458,8 @@ x!=y;
         ast->set_type<language::multiply_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::int_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::string_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1470,8 +1470,8 @@ x!=y;
         ast->set_type<language::divide_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::void_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1482,8 +1482,8 @@ x!=y;
         ast->set_type<language::divide_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::string_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1494,8 +1494,8 @@ x!=y;
         ast->set_type<language::divide_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::int_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::string_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1506,8 +1506,8 @@ x!=y;
         ast->set_type<language::plus_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::void_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1518,8 +1518,8 @@ x!=y;
         ast->set_type<language::plus_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::string_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::void_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1530,8 +1530,8 @@ x!=y;
         ast->set_type<language::plus_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::int_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::string_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1542,8 +1542,8 @@ x!=y;
         ast->set_type<language::minus_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::void_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1554,8 +1554,8 @@ x!=y;
         ast->set_type<language::minus_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::string_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1566,8 +1566,8 @@ x!=y;
         ast->set_type<language::minus_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::int_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::string_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1578,8 +1578,8 @@ x!=y;
         ast->set_type<language::or_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::void_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1590,8 +1590,8 @@ x!=y;
         ast->set_type<language::or_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::string_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1602,8 +1602,8 @@ x!=y;
         ast->set_type<language::or_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::int_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::string_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1614,8 +1614,8 @@ x!=y;
         ast->set_type<language::and_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::void_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1626,8 +1626,8 @@ x!=y;
         ast->set_type<language::and_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::string_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1638,8 +1638,8 @@ x!=y;
         ast->set_type<language::and_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::int_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::string_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1650,8 +1650,8 @@ x!=y;
         ast->set_type<language::xor_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::void_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1662,8 +1662,8 @@ x!=y;
         ast->set_type<language::xor_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::string_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1674,8 +1674,8 @@ x!=y;
         ast->set_type<language::xor_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::int_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::string_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1686,8 +1686,8 @@ x!=y;
         ast->set_type<language::greater_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::void_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1698,8 +1698,8 @@ x!=y;
         ast->set_type<language::greater_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::string_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1710,8 +1710,8 @@ x!=y;
         ast->set_type<language::greater_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::int_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::string_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1722,8 +1722,8 @@ x!=y;
         ast->set_type<language::lesser_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::void_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1734,8 +1734,8 @@ x!=y;
         ast->set_type<language::lesser_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::string_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1746,8 +1746,8 @@ x!=y;
         ast->set_type<language::lesser_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::int_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::string_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1758,8 +1758,8 @@ x!=y;
         ast->set_type<language::greater_or_eq_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::void_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1770,8 +1770,8 @@ x!=y;
         ast->set_type<language::greater_or_eq_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::string_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1782,8 +1782,8 @@ x!=y;
         ast->set_type<language::greater_or_eq_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::int_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::string_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1794,8 +1794,8 @@ x!=y;
         ast->set_type<language::lesser_or_eq_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::void_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1806,8 +1806,8 @@ x!=y;
         ast->set_type<language::lesser_or_eq_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::string_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1818,8 +1818,8 @@ x!=y;
         ast->set_type<language::lesser_or_eq_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::int_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::string_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1830,8 +1830,8 @@ x!=y;
         ast->set_type<language::eqeq_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::void_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1842,8 +1842,8 @@ x!=y;
         ast->set_type<language::eqeq_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::string_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1854,8 +1854,8 @@ x!=y;
         ast->set_type<language::eqeq_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::int_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::string_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1866,8 +1866,8 @@ x!=y;
         ast->set_type<language::not_eq_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::void_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1878,8 +1878,8 @@ x!=y;
         ast->set_type<language::not_eq_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::string_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::int_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
@@ -1890,8 +1890,8 @@ x!=y;
         ast->set_type<language::not_eq_op>();
         ast->children.emplace_back(std::make_unique<ASTNode>());
         ast->children.emplace_back(std::make_unique<ASTNode>());
-        ast->children[0]->m_data_type = ASTNodeDataType::int_t;
-        ast->children[1]->m_data_type = ASTNodeDataType::string_t;
+        ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+        ast->children[1]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>();
 
         REQUIRE_THROWS_WITH(ASTNodeBinaryOperatorExpressionBuilder{*ast}, "undefined operand type for binary operator");
       }
diff --git a/tests/test_ASTNodeDataType.cpp b/tests/test_ASTNodeDataType.cpp
index 5a7b09eb32ace24066a3264d1acb055c33364dc7..94c2b35450e2d4a4c76073b51aa525471b8d3009 100644
--- a/tests/test_ASTNodeDataType.cpp
+++ b/tests/test_ASTNodeDataType.cpp
@@ -15,66 +15,70 @@ struct vector_type;
 
 TEST_CASE("ASTNodeDataType", "[language]")
 {
+  const ASTNodeDataType undefined_dt        = ASTNodeDataType{};
+  const ASTNodeDataType bool_dt             = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
+  const ASTNodeDataType unsigned_int_dt     = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
+  const ASTNodeDataType int_dt              = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+  const ASTNodeDataType double_dt           = ASTNodeDataType::build<ASTNodeDataType::double_t>();
+  const ASTNodeDataType string_dt           = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+  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>();
+
   SECTION("dataTypeName")
   {
-    REQUIRE(dataTypeName(ASTNodeDataType::undefined_t) == "undefined");
-    REQUIRE(dataTypeName(ASTNodeDataType::bool_t) == "B");
-    REQUIRE(dataTypeName(ASTNodeDataType::unsigned_int_t) == "N");
-    REQUIRE(dataTypeName(ASTNodeDataType::int_t) == "Z");
-    REQUIRE(dataTypeName(ASTNodeDataType::double_t) == "R");
-    REQUIRE(dataTypeName(ASTNodeDataType::string_t) == "string");
-    REQUIRE(dataTypeName(ASTNodeDataType::typename_t) == "typename");
-    REQUIRE(dataTypeName(ASTNodeDataType::void_t) == "void");
-    REQUIRE(dataTypeName(ASTNodeDataType::function_t) == "function");
-    REQUIRE(dataTypeName(ASTNodeDataType::builtin_function_t) == "builtin_function");
-    REQUIRE(dataTypeName(ASTNodeDataType::list_t) == "list");
-    REQUIRE(dataTypeName(ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}}) ==
-            "tuple(B)");
-    REQUIRE(dataTypeName(ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}}) ==
-            "tuple(N)");
-    REQUIRE(dataTypeName(ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}}) ==
-            "tuple(Z)");
-    REQUIRE(dataTypeName(ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}}) ==
-            "tuple(R)");
-    REQUIRE(dataTypeName(ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}}) ==
-            "tuple(R)");
-
-    REQUIRE(dataTypeName(ASTNodeDataType{ASTNodeDataType::type_name_id_t, 1}) == "type_name_id");
-
-    REQUIRE(dataTypeName(ASTNodeDataType{ASTNodeDataType::type_id_t, "user_type"}) == "user_type");
-
-    REQUIRE(dataTypeName(ASTNodeDataType{ASTNodeDataType::vector_t, 1}) == "R^1");
-    REQUIRE(dataTypeName(ASTNodeDataType{ASTNodeDataType::vector_t, 2}) == "R^2");
-    REQUIRE(dataTypeName(ASTNodeDataType{ASTNodeDataType::vector_t, 3}) == "R^3");
+    REQUIRE(dataTypeName(undefined_dt) == "undefined");
+    REQUIRE(dataTypeName(bool_dt) == "B");
+    REQUIRE(dataTypeName(unsigned_int_dt) == "N");
+    REQUIRE(dataTypeName(int_dt) == "Z");
+    REQUIRE(dataTypeName(double_dt) == "R");
+    REQUIRE(dataTypeName(string_dt) == "string");
+    REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::typename_t>(double_dt)) == "typename(R)");
+    REQUIRE(dataTypeName(void_dt) == "void");
+    REQUIRE(dataTypeName(function_dt) == "function");
+    REQUIRE(dataTypeName(builtin_function_dt) == "builtin_function");
+    REQUIRE(dataTypeName(list_dt) == "list");
+    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)");
+    REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt)) == "tuple(R)");
+    REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt)) == "tuple(Z)");
+
+    REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>()) == "type_name_id");
+
+    REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::type_id_t>("user_type")) == "user_type");
+
+    REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)) == "R^1");
+    REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)) == "R^2");
+    REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)) == "R^3");
   }
 
   SECTION("promotion")
   {
-    REQUIRE(dataTypePromotion(ASTNodeDataType::undefined_t, ASTNodeDataType::undefined_t) ==
-            ASTNodeDataType::undefined_t);
-    REQUIRE(dataTypePromotion(ASTNodeDataType::void_t, ASTNodeDataType::double_t) == ASTNodeDataType::undefined_t);
-    REQUIRE(dataTypePromotion(ASTNodeDataType::int_t, ASTNodeDataType::undefined_t) == ASTNodeDataType::undefined_t);
-    REQUIRE(dataTypePromotion(ASTNodeDataType::double_t, ASTNodeDataType::bool_t) == ASTNodeDataType::double_t);
-    REQUIRE(dataTypePromotion(ASTNodeDataType::double_t, ASTNodeDataType::unsigned_int_t) == ASTNodeDataType::double_t);
-    REQUIRE(dataTypePromotion(ASTNodeDataType::double_t, ASTNodeDataType::int_t) == ASTNodeDataType::double_t);
-    REQUIRE(dataTypePromotion(ASTNodeDataType::int_t, ASTNodeDataType::unsigned_int_t) ==
-            ASTNodeDataType::unsigned_int_t);
-    REQUIRE(dataTypePromotion(ASTNodeDataType::int_t, ASTNodeDataType::bool_t) == ASTNodeDataType::int_t);
-    REQUIRE(dataTypePromotion(ASTNodeDataType::unsigned_int_t, ASTNodeDataType::bool_t) ==
-            ASTNodeDataType::unsigned_int_t);
-
-    REQUIRE(dataTypePromotion(ASTNodeDataType::string_t, ASTNodeDataType::bool_t) == ASTNodeDataType::string_t);
-    REQUIRE(dataTypePromotion(ASTNodeDataType::string_t, ASTNodeDataType::int_t) == ASTNodeDataType::string_t);
-    REQUIRE(dataTypePromotion(ASTNodeDataType::string_t, ASTNodeDataType::unsigned_int_t) == ASTNodeDataType::string_t);
-    REQUIRE(dataTypePromotion(ASTNodeDataType::string_t, ASTNodeDataType::double_t) == ASTNodeDataType::string_t);
-
-    REQUIRE(dataTypePromotion(ASTNodeDataType::bool_t, ASTNodeDataType::string_t) == ASTNodeDataType::undefined_t);
-    REQUIRE(dataTypePromotion(ASTNodeDataType::int_t, ASTNodeDataType::string_t) == ASTNodeDataType::undefined_t);
-    REQUIRE(dataTypePromotion(ASTNodeDataType::unsigned_int_t, ASTNodeDataType::string_t) ==
-            ASTNodeDataType::undefined_t);
-    REQUIRE(dataTypePromotion(ASTNodeDataType::double_t, ASTNodeDataType::string_t) == ASTNodeDataType::undefined_t);
-    REQUIRE(dataTypePromotion(ASTNodeDataType::bool_t, ASTNodeDataType::vector_t) == ASTNodeDataType::vector_t);
-    REQUIRE(dataTypePromotion(ASTNodeDataType::double_t, ASTNodeDataType::vector_t) == ASTNodeDataType::vector_t);
+    const ASTNodeDataType vector_dt = ASTNodeDataType::build<ASTNodeDataType::vector_t>(5);
+
+    REQUIRE(dataTypePromotion(undefined_dt, undefined_dt) == undefined_dt);
+    REQUIRE(dataTypePromotion(void_dt, double_dt) == undefined_dt);
+    REQUIRE(dataTypePromotion(int_dt, undefined_dt) == undefined_dt);
+    REQUIRE(dataTypePromotion(double_dt, bool_dt) == double_dt);
+    REQUIRE(dataTypePromotion(double_dt, unsigned_int_dt) == double_dt);
+    REQUIRE(dataTypePromotion(double_dt, int_dt) == double_dt);
+    REQUIRE(dataTypePromotion(int_dt, unsigned_int_dt) == unsigned_int_dt);
+    REQUIRE(dataTypePromotion(int_dt, bool_dt) == int_dt);
+    REQUIRE(dataTypePromotion(unsigned_int_dt, bool_dt) == unsigned_int_dt);
+
+    REQUIRE(dataTypePromotion(string_dt, bool_dt) == string_dt);
+    REQUIRE(dataTypePromotion(string_dt, int_dt) == string_dt);
+    REQUIRE(dataTypePromotion(string_dt, unsigned_int_dt) == string_dt);
+    REQUIRE(dataTypePromotion(string_dt, double_dt) == string_dt);
+
+    REQUIRE(dataTypePromotion(bool_dt, string_dt) == undefined_dt);
+    REQUIRE(dataTypePromotion(int_dt, string_dt) == undefined_dt);
+    REQUIRE(dataTypePromotion(unsigned_int_dt, string_dt) == undefined_dt);
+    REQUIRE(dataTypePromotion(double_dt, string_dt) == undefined_dt);
+    REQUIRE(dataTypePromotion(bool_dt, vector_dt) == vector_dt);
+    REQUIRE(dataTypePromotion(double_dt, vector_dt) == vector_dt);
   }
 
   SECTION("getVectorDataType")
@@ -96,7 +100,7 @@ TEST_CASE("ASTNodeDataType", "[language]")
 
     SECTION("good node")
     {
-      REQUIRE(getVectorDataType(*type_node) == ASTNodeDataType::vector_t);
+      REQUIRE(getVectorDataType(*type_node) == ASTNodeDataType::build<ASTNodeDataType::vector_t>(1));
       REQUIRE(getVectorDataType(*type_node).dimension() == 17);
     }
 
@@ -129,142 +133,126 @@ TEST_CASE("ASTNodeDataType", "[language]")
   {
     SECTION("-> B")
     {
-      REQUIRE(isNaturalConversion(ASTNodeDataType::bool_t, ASTNodeDataType::bool_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::unsigned_int_t, ASTNodeDataType::bool_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::int_t, ASTNodeDataType::bool_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::double_t, ASTNodeDataType::bool_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::string_t, ASTNodeDataType::bool_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::tuple_t, ASTNodeDataType::bool_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::vector_t, ASTNodeDataType::bool_t));
+      REQUIRE(isNaturalConversion(bool_dt, bool_dt));
+      REQUIRE(not isNaturalConversion(unsigned_int_dt, bool_dt));
+      REQUIRE(not isNaturalConversion(int_dt, bool_dt));
+      REQUIRE(not isNaturalConversion(double_dt, bool_dt));
+      REQUIRE(not isNaturalConversion(string_dt, bool_dt));
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt), bool_dt));
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1), bool_dt));
     }
 
     SECTION("-> N")
     {
-      REQUIRE(isNaturalConversion(ASTNodeDataType::bool_t, ASTNodeDataType::unsigned_int_t));
-      REQUIRE(isNaturalConversion(ASTNodeDataType::unsigned_int_t, ASTNodeDataType::unsigned_int_t));
-      REQUIRE(isNaturalConversion(ASTNodeDataType::int_t, ASTNodeDataType::unsigned_int_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::double_t, ASTNodeDataType::unsigned_int_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::string_t, ASTNodeDataType::unsigned_int_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::tuple_t, ASTNodeDataType::unsigned_int_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::vector_t, ASTNodeDataType::unsigned_int_t));
+      REQUIRE(isNaturalConversion(bool_dt, unsigned_int_dt));
+      REQUIRE(isNaturalConversion(unsigned_int_dt, unsigned_int_dt));
+      REQUIRE(isNaturalConversion(int_dt, unsigned_int_dt));
+      REQUIRE(not isNaturalConversion(double_dt, unsigned_int_dt));
+      REQUIRE(not isNaturalConversion(string_dt, unsigned_int_dt));
+      REQUIRE(
+        not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt), unsigned_int_dt));
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1), unsigned_int_dt));
     }
 
     SECTION("-> Z")
     {
-      REQUIRE(isNaturalConversion(ASTNodeDataType::bool_t, ASTNodeDataType::int_t));
-      REQUIRE(isNaturalConversion(ASTNodeDataType::unsigned_int_t, ASTNodeDataType::int_t));
-      REQUIRE(isNaturalConversion(ASTNodeDataType::int_t, ASTNodeDataType::int_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::double_t, ASTNodeDataType::int_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::string_t, ASTNodeDataType::int_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::tuple_t, ASTNodeDataType::int_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::vector_t, ASTNodeDataType::int_t));
+      REQUIRE(isNaturalConversion(bool_dt, int_dt));
+      REQUIRE(isNaturalConversion(unsigned_int_dt, int_dt));
+      REQUIRE(isNaturalConversion(int_dt, int_dt));
+      REQUIRE(not isNaturalConversion(double_dt, int_dt));
+      REQUIRE(not isNaturalConversion(string_dt, int_dt));
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt), int_dt));
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1), int_dt));
     }
 
     SECTION("-> R")
     {
-      REQUIRE(isNaturalConversion(ASTNodeDataType::bool_t, ASTNodeDataType::double_t));
-      REQUIRE(isNaturalConversion(ASTNodeDataType::unsigned_int_t, ASTNodeDataType::double_t));
-      REQUIRE(isNaturalConversion(ASTNodeDataType::int_t, ASTNodeDataType::double_t));
-      REQUIRE(isNaturalConversion(ASTNodeDataType::double_t, ASTNodeDataType::double_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::string_t, ASTNodeDataType::double_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::tuple_t, ASTNodeDataType::double_t));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::vector_t, ASTNodeDataType::double_t));
+      REQUIRE(isNaturalConversion(bool_dt, double_dt));
+      REQUIRE(isNaturalConversion(unsigned_int_dt, double_dt));
+      REQUIRE(isNaturalConversion(int_dt, double_dt));
+      REQUIRE(isNaturalConversion(double_dt, double_dt));
+      REQUIRE(not isNaturalConversion(string_dt, double_dt));
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt), double_dt));
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1), double_dt));
     }
 
     SECTION("-> string")
     {
-      REQUIRE(isNaturalConversion(ASTNodeDataType::bool_t, ASTNodeDataType::string_t));
-      REQUIRE(isNaturalConversion(ASTNodeDataType::unsigned_int_t, ASTNodeDataType::string_t));
-      REQUIRE(isNaturalConversion(ASTNodeDataType::int_t, ASTNodeDataType::string_t));
-      REQUIRE(isNaturalConversion(ASTNodeDataType::double_t, ASTNodeDataType::string_t));
-      REQUIRE(isNaturalConversion(ASTNodeDataType::string_t, ASTNodeDataType::string_t));
-      REQUIRE(isNaturalConversion(ASTNodeDataType::tuple_t, ASTNodeDataType::string_t));
-      REQUIRE(isNaturalConversion(ASTNodeDataType::vector_t, ASTNodeDataType::string_t));
+      REQUIRE(isNaturalConversion(bool_dt, string_dt));
+      REQUIRE(isNaturalConversion(unsigned_int_dt, string_dt));
+      REQUIRE(isNaturalConversion(int_dt, string_dt));
+      REQUIRE(isNaturalConversion(double_dt, string_dt));
+      REQUIRE(isNaturalConversion(string_dt, string_dt));
+      REQUIRE(isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt), string_dt));
+      REQUIRE(isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1), string_dt));
     }
 
     SECTION("-> tuple")
     {
-      REQUIRE(isNaturalConversion(ASTNodeDataType::bool_t,
-                                  ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}}));
-      REQUIRE(isNaturalConversion(ASTNodeDataType::bool_t,
-                                  ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                  ASTNodeDataType{ASTNodeDataType::unsigned_int_t}}));
-      REQUIRE(
-        not isNaturalConversion(ASTNodeDataType::int_t,
-                                ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}}));
-
-      REQUIRE(isNaturalConversion(ASTNodeDataType::unsigned_int_t,
-                                  ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                  ASTNodeDataType{ASTNodeDataType::unsigned_int_t}}));
-      REQUIRE(isNaturalConversion(ASTNodeDataType::unsigned_int_t,
-                                  ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}}));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::double_t,
-                                      ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                      ASTNodeDataType{ASTNodeDataType::unsigned_int_t}}));
-
-      REQUIRE(
-        isNaturalConversion(ASTNodeDataType::bool_t,
-                            ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}}));
-      REQUIRE(isNaturalConversion(ASTNodeDataType::int_t, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                          ASTNodeDataType{ASTNodeDataType::double_t}}));
-      REQUIRE(
-        isNaturalConversion(ASTNodeDataType::unsigned_int_t,
-                            ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}}));
-      REQUIRE(
-        isNaturalConversion(ASTNodeDataType::double_t,
-                            ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}}));
-      REQUIRE(
-        not isNaturalConversion(ASTNodeDataType::string_t,
-                                ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}}));
+      REQUIRE(isNaturalConversion(bool_dt, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt)));
+      REQUIRE(isNaturalConversion(bool_dt, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt)));
+      REQUIRE(not isNaturalConversion(int_dt, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt)));
+
+      REQUIRE(isNaturalConversion(unsigned_int_dt, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt)));
+      REQUIRE(isNaturalConversion(unsigned_int_dt, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt)));
+      REQUIRE(not isNaturalConversion(double_dt, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt)));
+
+      REQUIRE(isNaturalConversion(bool_dt, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt)));
+      REQUIRE(isNaturalConversion(int_dt, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt)));
+      REQUIRE(isNaturalConversion(unsigned_int_dt, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt)));
+      REQUIRE(isNaturalConversion(double_dt, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt)));
+      REQUIRE(not isNaturalConversion(string_dt, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt)));
     }
 
     SECTION("-> vector")
     {
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::bool_t, ASTNodeDataType{ASTNodeDataType::vector_t, 1}));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::unsigned_int_t, ASTNodeDataType{ASTNodeDataType::vector_t, 3}));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::int_t, ASTNodeDataType{ASTNodeDataType::vector_t, 2}));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::double_t, ASTNodeDataType{ASTNodeDataType::vector_t, 2}));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::string_t, ASTNodeDataType{ASTNodeDataType::vector_t, 3}));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::vector_t, 1}));
-
-      REQUIRE(isNaturalConversion(ASTNodeDataType{ASTNodeDataType::vector_t, 1},
-                                  ASTNodeDataType{ASTNodeDataType::vector_t, 1}));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType{ASTNodeDataType::vector_t, 2},
-                                      ASTNodeDataType{ASTNodeDataType::vector_t, 1}));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType{ASTNodeDataType::vector_t, 3},
-                                      ASTNodeDataType{ASTNodeDataType::vector_t, 1}));
-
-      REQUIRE(not isNaturalConversion(ASTNodeDataType{ASTNodeDataType::vector_t, 1},
-                                      ASTNodeDataType{ASTNodeDataType::vector_t, 2}));
-      REQUIRE(isNaturalConversion(ASTNodeDataType{ASTNodeDataType::vector_t, 2},
-                                  ASTNodeDataType{ASTNodeDataType::vector_t, 2}));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType{ASTNodeDataType::vector_t, 3},
-                                      ASTNodeDataType{ASTNodeDataType::vector_t, 2}));
-
-      REQUIRE(not isNaturalConversion(ASTNodeDataType{ASTNodeDataType::vector_t, 1},
-                                      ASTNodeDataType{ASTNodeDataType::vector_t, 3}));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType{ASTNodeDataType::vector_t, 2},
-                                      ASTNodeDataType{ASTNodeDataType::vector_t, 3}));
-      REQUIRE(isNaturalConversion(ASTNodeDataType{ASTNodeDataType::vector_t, 3},
-                                  ASTNodeDataType{ASTNodeDataType::vector_t, 3}));
+      REQUIRE(not isNaturalConversion(bool_dt, ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)));
+      REQUIRE(not isNaturalConversion(unsigned_int_dt, ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)));
+      REQUIRE(not isNaturalConversion(int_dt, ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)));
+      REQUIRE(not isNaturalConversion(double_dt, ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)));
+      REQUIRE(not isNaturalConversion(string_dt, ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)));
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt),
+                                      ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)));
+
+      REQUIRE(isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1),
+                                  ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)));
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::vector_t>(2),
+                                      ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)));
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::vector_t>(3),
+                                      ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)));
+
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1),
+                                      ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)));
+      REQUIRE(isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::vector_t>(2),
+                                  ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)));
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::vector_t>(3),
+                                      ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)));
+
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1),
+                                      ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)));
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::vector_t>(2),
+                                      ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)));
+      REQUIRE(isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::vector_t>(3),
+                                  ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)));
     }
 
     SECTION("-> type_id")
     {
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::bool_t, ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"}));
-      REQUIRE(
-        not isNaturalConversion(ASTNodeDataType::unsigned_int_t, ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"}));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::int_t, ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"}));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::double_t, ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"}));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::string_t, ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"}));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::vector_t, ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"}));
-      REQUIRE(not isNaturalConversion(ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"}));
-
-      REQUIRE(isNaturalConversion(ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"},
-                                  ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"}));
-
-      REQUIRE(not isNaturalConversion(ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"},
-                                      ASTNodeDataType{ASTNodeDataType::type_id_t, "bar"}));
+      REQUIRE(not isNaturalConversion(bool_dt, ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo")));
+      REQUIRE(not isNaturalConversion(unsigned_int_dt, ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo")));
+      REQUIRE(not isNaturalConversion(int_dt, ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo")));
+      REQUIRE(not isNaturalConversion(double_dt, ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo")));
+      REQUIRE(not isNaturalConversion(string_dt, ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo")));
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1),
+                                      ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo")));
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt),
+                                      ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo")));
+
+      REQUIRE(isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo"),
+                                  ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo")));
+
+      REQUIRE(not isNaturalConversion(ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo"),
+                                      ASTNodeDataType::build<ASTNodeDataType::type_id_t>("bar")));
     }
   }
 }
diff --git a/tests/test_ASTNodeDataTypeBuilder.cpp b/tests/test_ASTNodeDataTypeBuilder.cpp
index c5c691a28db39749f1910521b875eca0af0e8271..1fbe1a2a0527a2581adc75ca548dba884b3513ab 100644
--- a/tests/test_ASTNodeDataTypeBuilder.cpp
+++ b/tests/test_ASTNodeDataTypeBuilder.cpp
@@ -29,8 +29,8 @@
   }
 
 template <>
-inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> = {ASTNodeDataType::type_id_t,
-                                                                                 "builtin_t"};
+inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> =
+  ASTNodeDataType::build<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)                                                         \
@@ -47,7 +47,7 @@ const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const dou
       throw UnexpectedError("cannot add '" + builtin_data_type.nameOfTypeId() + "' type for testing");        \
     }                                                                                                         \
                                                                                                               \
-    i_symbol->attributes().setDataType(ASTNodeDataType::type_name_id_t);                                      \
+    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())); \
@@ -277,17 +277,17 @@ let (x,b,n,s) : R*B*N*string;
 
       std::string_view result = R"(
 (root:void)
- `-(language::var_declaration:typename)
+ `-(language::var_declaration:void)
      +-(language::name_list:list)
      |   +-(language::name:x:R)
      |   +-(language::name:b:B)
      |   +-(language::name:n:N)
      |   `-(language::name:s:string)
-     `-(language::type_expression:typename)
-         +-(language::R_set:typename)
-         +-(language::B_set:typename)
-         +-(language::N_set:typename)
-         `-(language::string_type:typename)
+     `-(language::type_expression:typename(list))
+         +-(language::R_set:typename(R))
+         +-(language::B_set:typename(B))
+         +-(language::N_set:typename(N))
+         `-(language::string_type:typename(string))
 )";
 
       CHECK_AST(data, result);
@@ -377,10 +377,10 @@ let t : (B), t = (true, false);
 
         std::string_view result = R"(
 (root:void)
- `-(language::var_declaration:tuple(B))
+ `-(language::var_declaration:void)
      +-(language::name:t:tuple(B))
-     +-(language::tuple_type_specifier:tuple(B))
-     |   `-(language::B_set:typename)
+     +-(language::tuple_type_specifier:typename(tuple(B)))
+     |   `-(language::B_set:typename(B))
      +-(language::name:t:tuple(B))
      `-(language::expression_list:list)
          +-(language::true_kw:B)
@@ -398,10 +398,10 @@ let t : (N), t = (1, 2, 3, 5);
 
         std::string_view result = R"(
 (root:void)
- `-(language::var_declaration:tuple(N))
+ `-(language::var_declaration:void)
      +-(language::name:t:tuple(N))
-     +-(language::tuple_type_specifier:tuple(N))
-     |   `-(language::N_set:typename)
+     +-(language::tuple_type_specifier:typename(tuple(N)))
+     |   `-(language::N_set:typename(N))
      +-(language::name:t:tuple(N))
      `-(language::expression_list:list)
          +-(language::integer:1:Z)
@@ -422,15 +422,15 @@ let t : (Z), t = (2, n, true);
 
         std::string_view result = R"(
 (root:void)
- +-(language::var_declaration:N)
+ +-(language::var_declaration:void)
  |   +-(language::name:n:N)
- |   +-(language::N_set:typename)
+ |   +-(language::N_set:typename(N))
  |   +-(language::name:n:N)
  |   `-(language::integer:3:Z)
- `-(language::var_declaration:tuple(Z))
+ `-(language::var_declaration:void)
      +-(language::name:t:tuple(Z))
-     +-(language::tuple_type_specifier:tuple(Z))
-     |   `-(language::Z_set:typename)
+     +-(language::tuple_type_specifier:typename(tuple(Z)))
+     |   `-(language::Z_set:typename(Z))
      +-(language::name:t:tuple(Z))
      `-(language::expression_list:list)
          +-(language::integer:2:Z)
@@ -449,10 +449,10 @@ let t : (R), t = (2, 3.1, 5);
 
         std::string_view result = R"(
 (root:void)
- `-(language::var_declaration:tuple(R))
+ `-(language::var_declaration:void)
      +-(language::name:t:tuple(R))
-     +-(language::tuple_type_specifier:tuple(R))
-     |   `-(language::R_set:typename)
+     +-(language::tuple_type_specifier:typename(tuple(R)))
+     |   `-(language::R_set:typename(R))
      +-(language::name:t:tuple(R))
      `-(language::expression_list:list)
          +-(language::integer:2:Z)
@@ -473,20 +473,20 @@ let t2 : (R^3), t2 = (0, 0);
 
         std::string_view result = R"(
 (root:void)
- +-(language::var_declaration:R^2)
+ +-(language::var_declaration:void)
  |   +-(language::name:a:R^2)
- |   +-(language::vector_type:typename)
- |   |   +-(language::R_set:typename)
+ |   +-(language::vector_type:typename(R^2))
+ |   |   +-(language::R_set:typename(R))
  |   |   `-(language::integer:2:Z)
  |   +-(language::name:a:R^2)
  |   `-(language::expression_list:list)
  |       +-(language::integer:2:Z)
  |       `-(language::real:3.1:R)
- +-(language::var_declaration:tuple(R^2))
+ +-(language::var_declaration:void)
  |   +-(language::name:t1:tuple(R^2))
- |   +-(language::tuple_type_specifier:tuple(R^2))
- |   |   `-(language::vector_type:typename)
- |   |       +-(language::R_set:typename)
+ |   +-(language::tuple_type_specifier:typename(tuple(R^2)))
+ |   |   `-(language::vector_type:typename(R^2))
+ |   |       +-(language::R_set:typename(R))
  |   |       `-(language::integer:2:Z)
  |   +-(language::name:t1:tuple(R^2))
  |   `-(language::expression_list:list)
@@ -495,11 +495,11 @@ let t2 : (R^3), t2 = (0, 0);
  |       |   +-(language::integer:1:Z)
  |       |   `-(language::integer:2:Z)
  |       `-(language::integer:0:Z)
- `-(language::var_declaration:tuple(R^3))
+ `-(language::var_declaration:void)
      +-(language::name:t2:tuple(R^3))
-     +-(language::tuple_type_specifier:tuple(R^3))
-     |   `-(language::vector_type:typename)
-     |       +-(language::R_set:typename)
+     +-(language::tuple_type_specifier:typename(tuple(R^3)))
+     |   `-(language::vector_type:typename(R^3))
+     |       +-(language::R_set:typename(R))
      |       `-(language::integer:3:Z)
      +-(language::name:t2:tuple(R^3))
      `-(language::expression_list:list)
@@ -518,10 +518,10 @@ let t : (string), t = ("foo", "bar");
 
         std::string_view result = R"(
 (root:void)
- `-(language::var_declaration:tuple(string))
+ `-(language::var_declaration:void)
      +-(language::name:t:tuple(string))
-     +-(language::tuple_type_specifier:tuple(string))
-     |   `-(language::string_type:typename)
+     +-(language::tuple_type_specifier:typename(tuple(string)))
+     |   `-(language::string_type:typename(string))
      +-(language::name:t:tuple(string))
      `-(language::expression_list:list)
          +-(language::literal:"foo":string)
@@ -540,10 +540,10 @@ let t : (builtin_t), t= (1,2,3);
 
         std::string_view result = R"(
 (root:void)
- `-(language::var_declaration:tuple(builtin_t))
+ `-(language::var_declaration:void)
      +-(language::name:t:tuple(builtin_t))
-     +-(language::tuple_type_specifier:tuple(builtin_t))
-     |   `-(language::type_name_id:typename)
+     +-(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::integer:1:Z)
@@ -885,10 +885,10 @@ x = f(x);
 (root:void)
  +-(language::fct_declaration:void)
  |   `-(language::name:f:function)
- +-(language::var_declaration:R^2)
+ +-(language::var_declaration:void)
  |   +-(language::name:x:R^2)
- |   +-(language::vector_type:typename)
- |   |   +-(language::R_set:typename)
+ |   +-(language::vector_type:typename(R^2))
+ |   |   +-(language::R_set:typename(R))
  |   |   `-(language::integer:2:Z)
  |   +-(language::name:x:R^2)
  |   `-(language::expression_list:list)
@@ -918,9 +918,9 @@ let x : R, x = incr(3);
 (root:void)
  +-(language::fct_declaration:void)
  |   `-(language::name:incr:function)
- `-(language::var_declaration:R)
+ `-(language::var_declaration:void)
      +-(language::name:x:R)
-     +-(language::R_set:typename)
+     +-(language::R_set:typename(R))
      +-(language::name:x:R)
      `-(language::function_evaluation:R)
          +-(language::name:incr:function)
@@ -941,9 +941,9 @@ let  diff : R, diff = substract(3,2);
 (root:void)
  +-(language::fct_declaration:void)
  |   `-(language::name:substract:function)
- `-(language::var_declaration:R)
+ `-(language::var_declaration:void)
      +-(language::name:diff:R)
-     +-(language::R_set:typename)
+     +-(language::R_set:typename(R))
      +-(language::name:diff:R)
      `-(language::function_evaluation:R)
          +-(language::name:substract:function)
@@ -967,9 +967,9 @@ let z : Z, z = incr(3);
 (root:void)
  +-(language::fct_declaration:void)
  |   `-(language::name:incr:function)
- `-(language::var_declaration:Z)
+ `-(language::var_declaration:void)
      +-(language::name:z:Z)
-     +-(language::Z_set:typename)
+     +-(language::Z_set:typename(Z))
      +-(language::name:z:Z)
      `-(language::function_evaluation:Z)
          +-(language::name:incr:function)
@@ -990,9 +990,9 @@ let n : N, n = double(3);
 (root:void)
  +-(language::fct_declaration:void)
  |   `-(language::name:double:function)
- `-(language::var_declaration:N)
+ `-(language::var_declaration:void)
      +-(language::name:n:N)
-     +-(language::N_set:typename)
+     +-(language::N_set:typename(N))
      +-(language::name:n:N)
      `-(language::function_evaluation:N)
          +-(language::name:double:function)
@@ -1013,9 +1013,9 @@ let b : B, b = greater_than_2(3);
 (root:void)
  +-(language::fct_declaration:void)
  |   `-(language::name:greater_than_2:function)
- `-(language::var_declaration:B)
+ `-(language::var_declaration:void)
      +-(language::name:b:B)
-     +-(language::B_set:typename)
+     +-(language::B_set:typename(B))
      +-(language::name:b:B)
      `-(language::function_evaluation:B)
          +-(language::name:greater_than_2:function)
@@ -1036,9 +1036,9 @@ let s : string, s = cat("foo", "bar");
 (root:void)
  +-(language::fct_declaration:void)
  |   `-(language::name:cat:function)
- `-(language::var_declaration:string)
+ `-(language::var_declaration:void)
      +-(language::name:s:string)
-     +-(language::string_type:typename)
+     +-(language::string_type:typename(string))
      +-(language::name:s:string)
      `-(language::function_evaluation:string)
          +-(language::name:cat:function)
@@ -1061,17 +1061,17 @@ let (x,x2) : R*R, (x,x2) = x_x2(3);
 (root:void)
  +-(language::fct_declaration:void)
  |   `-(language::name:x_x2:function)
- `-(language::var_declaration:typename)
+ `-(language::var_declaration:void)
      +-(language::name_list:list)
      |   +-(language::name:x:R)
      |   `-(language::name:x2:R)
-     +-(language::type_expression:typename)
-     |   +-(language::R_set:typename)
-     |   `-(language::R_set:typename)
+     +-(language::type_expression:typename(list))
+     |   +-(language::R_set:typename(R))
+     |   `-(language::R_set:typename(R))
      +-(language::name_list:list)
      |   +-(language::name:x:R)
      |   `-(language::name:x2:R)
-     `-(language::function_evaluation:typename)
+     `-(language::function_evaluation:list)
          +-(language::name:x_x2:function)
          `-(language::integer:3:Z)
 )";
@@ -1128,9 +1128,9 @@ for (let i : N, i=0; i<3; ++i){
     std::string_view result = R"(
 (root:void)
  `-(language::for_statement:void)
-     +-(language::var_declaration:N)
+     +-(language::var_declaration:void)
      |   +-(language::name:i:N)
-     |   +-(language::N_set:typename)
+     |   +-(language::N_set:typename(N))
      |   +-(language::name:i:N)
      |   `-(language::integer:0:Z)
      +-(language::lesser_op:B)
@@ -1154,9 +1154,9 @@ let b:B;
 
     std::string_view result = R"(
 (root:void)
- `-(language::var_declaration:B)
+ `-(language::var_declaration:void)
      +-(language::name:b:B)
-     `-(language::B_set:typename)
+     `-(language::B_set:typename(B))
 )";
 
     CHECK_AST(data, result);
@@ -1170,9 +1170,9 @@ let n :N;
 
     std::string_view result = R"(
 (root:void)
- `-(language::var_declaration:N)
+ `-(language::var_declaration:void)
      +-(language::name:n:N)
-     `-(language::N_set:typename)
+     `-(language::N_set:typename(N))
 )";
 
     CHECK_AST(data, result);
@@ -1186,9 +1186,9 @@ let z:Z;
 
     std::string_view result = R"(
 (root:void)
- `-(language::var_declaration:Z)
+ `-(language::var_declaration:void)
      +-(language::name:z:Z)
-     `-(language::Z_set:typename)
+     `-(language::Z_set:typename(Z))
 )";
 
     CHECK_AST(data, result);
@@ -1202,9 +1202,9 @@ let r:R;
 
     std::string_view result = R"(
 (root:void)
- `-(language::var_declaration:R)
+ `-(language::var_declaration:void)
      +-(language::name:r:R)
-     `-(language::R_set:typename)
+     `-(language::R_set:typename(R))
 )";
 
     CHECK_AST(data, result);
@@ -1218,9 +1218,9 @@ let s: string;
 
     std::string_view result = R"(
 (root:void)
- `-(language::var_declaration:string)
+ `-(language::var_declaration:void)
      +-(language::name:s:string)
-     `-(language::string_type:typename)
+     `-(language::string_type:typename(string))
 )";
 
     CHECK_AST(data, result);
@@ -1235,9 +1235,9 @@ let t : builtin_t, t= 1;
 
     std::string_view result = R"(
 (root:void)
- `-(language::var_declaration:builtin_t)
+ `-(language::var_declaration:void)
      +-(language::name:t:builtin_t)
-     +-(language::type_name_id:typename)
+     +-(language::type_name_id:typename(builtin_t))
      +-(language::name:t:builtin_t)
      `-(language::integer:1:Z)
 )";
@@ -1282,9 +1282,9 @@ a = 1;
 
     std::string_view result = R"(
 (root:void)
- +-(language::var_declaration:N)
+ +-(language::var_declaration:void)
  |   +-(language::name:a:N)
- |   `-(language::N_set:typename)
+ |   `-(language::N_set:typename(N))
  `-(language::eq_op:N)
      +-(language::name:a:N)
      `-(language::integer:1:Z)
@@ -1302,9 +1302,9 @@ a *= 1.2;
 
     std::string_view result = R"(
 (root:void)
- +-(language::var_declaration:N)
+ +-(language::var_declaration:void)
  |   +-(language::name:a:N)
- |   +-(language::N_set:typename)
+ |   +-(language::N_set:typename(N))
  |   +-(language::name:a:N)
  |   `-(language::integer:1:Z)
  `-(language::multiplyeq_op:N)
@@ -1324,9 +1324,9 @@ a /= 2;
 
     std::string_view result = R"(
 (root:void)
- +-(language::var_declaration:R)
+ +-(language::var_declaration:void)
  |   +-(language::name:a:R)
- |   +-(language::R_set:typename)
+ |   +-(language::R_set:typename(R))
  |   +-(language::name:a:R)
  |   `-(language::integer:3:Z)
  `-(language::divideeq_op:R)
@@ -1346,9 +1346,9 @@ a += 2;
 
     std::string_view result = R"(
 (root:void)
- +-(language::var_declaration:Z)
+ +-(language::var_declaration:void)
  |   +-(language::name:a:Z)
- |   +-(language::Z_set:typename)
+ |   +-(language::Z_set:typename(Z))
  |   +-(language::name:a:Z)
  |   `-(language::integer:3:Z)
  `-(language::pluseq_op:Z)
@@ -1368,9 +1368,9 @@ a -= 2;
 
     std::string_view result = R"(
 (root:void)
- +-(language::var_declaration:Z)
+ +-(language::var_declaration:void)
  |   +-(language::name:a:Z)
- |   +-(language::Z_set:typename)
+ |   +-(language::Z_set:typename(Z))
  |   +-(language::name:a:Z)
  |   `-(language::integer:1:Z)
  `-(language::minuseq_op:Z)
@@ -1408,9 +1408,9 @@ for (let i:Z, i=0; i<3; i += 1) { i += 2; }
     std::string_view result = R"(
 (root:void)
  `-(language::for_statement:void)
-     +-(language::var_declaration:Z)
+     +-(language::var_declaration:void)
      |   +-(language::name:i:Z)
-     |   +-(language::Z_set:typename)
+     |   +-(language::Z_set:typename(Z))
      |   +-(language::name:i:Z)
      |   `-(language::integer:0:Z)
      +-(language::lesser_op:B)
diff --git a/tests/test_ASTNodeDataTypeChecker.cpp b/tests/test_ASTNodeDataTypeChecker.cpp
index e016e1087281b3175eba0076cb21aaab7234c89b..60dfc787a65b6af66f3463fe0871bb0b0a79116d 100644
--- a/tests/test_ASTNodeDataTypeChecker.cpp
+++ b/tests/test_ASTNodeDataTypeChecker.cpp
@@ -45,7 +45,7 @@ for(let i:Z, i=0; i<10; ++i) {
     ASTSymbolTableBuilder{*ast};
     ASTNodeDataTypeBuilder{*ast};
 
-    ast->children[0]->m_data_type = ASTNodeDataType::undefined_t;
+    ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::undefined_t>();
 
     REQUIRE_THROWS_AS(ASTNodeDataTypeChecker{*ast}, ParseError);
   }
diff --git a/tests/test_ASTNodeIncDecExpressionBuilder.cpp b/tests/test_ASTNodeIncDecExpressionBuilder.cpp
index 60ce2489fd8b1b93996cd2904b8bf9852b8a1c79..627d6f96606a13a97907d01d314339f846049892 100644
--- a/tests/test_ASTNodeIncDecExpressionBuilder.cpp
+++ b/tests/test_ASTNodeIncDecExpressionBuilder.cpp
@@ -310,7 +310,7 @@ x--;
     {
       auto ast = std::make_unique<ASTNode>();
       ast->set_type<language::unary_plusplus>();
-      ast->m_data_type = ASTNodeDataType::undefined_t;
+      ast->m_data_type = ASTNodeDataType::build<ASTNodeDataType::undefined_t>();
 
       ast->children.emplace_back(std::make_unique<ASTNode>());
 
diff --git a/tests/test_ASTNodeJumpPlacementChecker.cpp b/tests/test_ASTNodeJumpPlacementChecker.cpp
index 631b172775f381405bbc8ff830d19aad92b9c8e5..040c2db1c3d7b0ee3be8c663a5c701827e230fb2 100644
--- a/tests/test_ASTNodeJumpPlacementChecker.cpp
+++ b/tests/test_ASTNodeJumpPlacementChecker.cpp
@@ -75,7 +75,7 @@ do {
       ASTSymbolTableBuilder{*ast};
       ASTNodeDataTypeBuilder{*ast};
 
-      ast->children[0]->m_data_type = ASTNodeDataType::undefined_t;
+      ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::undefined_t>();
 
       REQUIRE_THROWS_AS(ASTNodeJumpPlacementChecker{*ast}, ParseError);
     }
@@ -144,7 +144,7 @@ do {
       ASTSymbolTableBuilder{*ast};
       ASTNodeDataTypeBuilder{*ast};
 
-      ast->children[0]->m_data_type = ASTNodeDataType::undefined_t;
+      ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::undefined_t>();
 
       REQUIRE_THROWS_AS(ASTNodeJumpPlacementChecker{*ast}, ParseError);
     }
diff --git a/tests/test_ASTNodeListAffectationExpressionBuilder.cpp b/tests/test_ASTNodeListAffectationExpressionBuilder.cpp
index 333b98bd998124e676c885025ef1d646ba517829..c15be1db66c0bbbe9a5e9eee4c895f21f3bb30d7 100644
--- a/tests/test_ASTNodeListAffectationExpressionBuilder.cpp
+++ b/tests/test_ASTNodeListAffectationExpressionBuilder.cpp
@@ -385,7 +385,7 @@ let x:R^2, x = (1,2);
 let y:R^3, y = x;
 )";
 
-      CHECK_AST_THROWS_WITH(data, std::string{"incompatible dimensions in affectation"});
+      CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R^3"});
     }
 
     SECTION("invalid Z -> R^d conversion (non-zero)")
diff --git a/tests/test_ASTNodeNaturalConversionChecker.cpp b/tests/test_ASTNodeNaturalConversionChecker.cpp
index fe29cf9d0148d7a4d0a31bd71b97d84820e63299..4283d185e83da4e9404574d4c49d0302abdaa7f4 100644
--- a/tests/test_ASTNodeNaturalConversionChecker.cpp
+++ b/tests/test_ASTNodeNaturalConversionChecker.cpp
@@ -13,6 +13,17 @@ struct integer;
 
 TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
 {
+  const ASTNodeDataType undefined_dt        = ASTNodeDataType{};
+  const ASTNodeDataType bool_dt             = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
+  const ASTNodeDataType unsigned_int_dt     = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
+  const ASTNodeDataType int_dt              = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+  const ASTNodeDataType double_dt           = ASTNodeDataType::build<ASTNodeDataType::double_t>();
+  const ASTNodeDataType string_dt           = ASTNodeDataType::build<ASTNodeDataType::string_t>();
+  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>();
+
   SECTION("Valid conversions")
   {
     std::unique_ptr data_node = std::make_unique<ASTNode>();
@@ -21,50 +32,50 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
     {
       SECTION("string -> string")
       {
-        data_node->m_data_type = ASTNodeDataType::string_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::string_t});
+        data_node->m_data_type = string_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, string_dt});
       }
 
       SECTION("R^d -> string")
       {
-        data_node->m_data_type = ASTNodeDataType::vector_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::string_t});
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(5);
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, string_dt});
       }
 
       SECTION("R -> string")
       {
-        data_node->m_data_type = ASTNodeDataType::double_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::string_t});
+        data_node->m_data_type = double_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, string_dt});
       }
 
       SECTION("Z -> string")
       {
-        data_node->m_data_type = ASTNodeDataType::int_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::string_t});
+        data_node->m_data_type = int_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, string_dt});
       }
 
       SECTION("N -> string")
       {
-        data_node->m_data_type = ASTNodeDataType::unsigned_int_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::string_t});
+        data_node->m_data_type = unsigned_int_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, string_dt});
       }
 
       SECTION("B -> string")
       {
-        data_node->m_data_type = ASTNodeDataType::bool_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::string_t});
+        data_node->m_data_type = bool_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, string_dt});
       }
 
       SECTION("list -> string")
       {
-        data_node->m_data_type = ASTNodeDataType::list_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::string_t});
+        data_node->m_data_type = list_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, string_dt});
       }
 
       SECTION("tuple -> string")
       {
-        data_node->m_data_type = ASTNodeDataType::tuple_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::string_t});
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(undefined_dt);
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, string_dt});
       }
     }
 
@@ -72,24 +83,26 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
     {
       SECTION("R^1 -> R^1")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 1};
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::vector_t, 1}});
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
+        REQUIRE_NOTHROW(
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)});
       }
 
       SECTION("list -> R^1")
       {
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
-          list0_node->m_data_type    = ASTNodeDataType::double_t;
+          list0_node->m_data_type    = double_dt;
           data_node->emplace_back(std::move(list0_node));
         }
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::vector_t, 1}});
+        REQUIRE_NOTHROW(
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)});
       }
 
       SECTION("'0' -> R^d")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::int_t, 1};
+        data_node->m_data_type = int_dt;
         data_node->set_type<language::integer>();
         data_node->source  = "0";
         auto& source       = data_node->source;
@@ -98,62 +111,69 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
 
         SECTION("d = 1")
         {
-          REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::vector_t, 1}});
+          REQUIRE_NOTHROW(
+            ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)});
         }
         SECTION("d = 2")
         {
-          REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::vector_t, 2}});
+          REQUIRE_NOTHROW(
+            ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)});
         }
         SECTION("d = 3")
         {
-          REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::vector_t, 3}});
+          REQUIRE_NOTHROW(
+            ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)});
         }
       }
 
       SECTION("R^2 -> R^2")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::vector_t, 2}});
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
+        REQUIRE_NOTHROW(
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)});
       }
 
       SECTION("list -> R^2")
       {
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
-          list0_node->m_data_type    = ASTNodeDataType::double_t;
+          list0_node->m_data_type    = double_dt;
           data_node->emplace_back(std::move(list0_node));
 
           std::unique_ptr list1_node = std::make_unique<ASTNode>();
-          list1_node->m_data_type    = ASTNodeDataType::unsigned_int_t;
+          list1_node->m_data_type    = unsigned_int_dt;
           data_node->emplace_back(std::move(list1_node));
         }
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::vector_t, 2}});
+        REQUIRE_NOTHROW(
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)});
       }
 
       SECTION("R^3 -> R^3")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 3};
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::vector_t, 3}});
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
+        REQUIRE_NOTHROW(
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)});
       }
 
       SECTION("list -> R^3")
       {
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
-          list0_node->m_data_type    = ASTNodeDataType::double_t;
+          list0_node->m_data_type    = double_dt;
           data_node->emplace_back(std::move(list0_node));
 
           std::unique_ptr list1_node = std::make_unique<ASTNode>();
-          list1_node->m_data_type    = ASTNodeDataType::unsigned_int_t;
+          list1_node->m_data_type    = unsigned_int_dt;
           data_node->emplace_back(std::move(list1_node));
 
           std::unique_ptr list2_node = std::make_unique<ASTNode>();
-          list2_node->m_data_type    = ASTNodeDataType::int_t;
+          list2_node->m_data_type    = int_dt;
           data_node->emplace_back(std::move(list2_node));
         }
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::vector_t, 3}});
+        REQUIRE_NOTHROW(
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)});
       }
     }
 
@@ -161,26 +181,26 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
     {
       SECTION("R -> R")
       {
-        data_node->m_data_type = ASTNodeDataType::double_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::double_t});
+        data_node->m_data_type = double_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, double_dt});
       }
 
       SECTION("Z -> R")
       {
-        data_node->m_data_type = ASTNodeDataType::int_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::double_t});
+        data_node->m_data_type = int_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, double_dt});
       }
 
       SECTION("N -> R")
       {
-        data_node->m_data_type = ASTNodeDataType::unsigned_int_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::double_t});
+        data_node->m_data_type = unsigned_int_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, double_dt});
       }
 
       SECTION("B -> R")
       {
-        data_node->m_data_type = ASTNodeDataType::bool_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::double_t});
+        data_node->m_data_type = bool_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, double_dt});
       }
     }
 
@@ -188,20 +208,20 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
     {
       SECTION("Z -> Z")
       {
-        data_node->m_data_type = ASTNodeDataType::int_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::int_t});
+        data_node->m_data_type = int_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, int_dt});
       }
 
       SECTION("N -> Z")
       {
-        data_node->m_data_type = ASTNodeDataType::unsigned_int_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::int_t});
+        data_node->m_data_type = unsigned_int_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, int_dt});
       }
 
       SECTION("B -> Z")
       {
-        data_node->m_data_type = ASTNodeDataType::bool_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::int_t});
+        data_node->m_data_type = bool_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, int_dt});
       }
     }
 
@@ -209,20 +229,20 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
     {
       SECTION("Z -> N")
       {
-        data_node->m_data_type = ASTNodeDataType::int_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::unsigned_int_t});
+        data_node->m_data_type = int_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt});
       }
 
       SECTION("N -> N")
       {
-        data_node->m_data_type = ASTNodeDataType::unsigned_int_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::unsigned_int_t});
+        data_node->m_data_type = unsigned_int_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt});
       }
 
       SECTION("B -> N")
       {
-        data_node->m_data_type = ASTNodeDataType::bool_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::unsigned_int_t});
+        data_node->m_data_type = bool_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt});
       }
     }
 
@@ -230,8 +250,8 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
     {
       SECTION("B -> B")
       {
-        data_node->m_data_type = ASTNodeDataType::bool_t;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::bool_t});
+        data_node->m_data_type = bool_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, bool_dt});
       }
     }
 
@@ -239,216 +259,204 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
     {
       SECTION("B -> tuple(B)")
       {
-        data_node->m_data_type = ASTNodeDataType::bool_t;
+        data_node->m_data_type = bool_dt;
         REQUIRE_NOTHROW(
-          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                      ASTNodeDataType{ASTNodeDataType::bool_t}}});
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt)});
       }
 
       SECTION("B -> tuple(N)")
       {
-        data_node->m_data_type = ASTNodeDataType::bool_t;
-        REQUIRE_NOTHROW(
-          ASTNodeNaturalConversionChecker{*data_node,
-                                          ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                          ASTNodeDataType{ASTNodeDataType::unsigned_int_t}}});
+        data_node->m_data_type = bool_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
+                                                                      unsigned_int_dt)});
       }
 
       SECTION("N -> tuple(N)")
       {
-        data_node->m_data_type = ASTNodeDataType::unsigned_int_t;
-        REQUIRE_NOTHROW(
-          ASTNodeNaturalConversionChecker{*data_node,
-                                          ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                          ASTNodeDataType{ASTNodeDataType::unsigned_int_t}}});
+        data_node->m_data_type = unsigned_int_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
+                                                                      unsigned_int_dt)});
       }
 
       SECTION("Z -> tuple(N)")
       {
-        data_node->m_data_type = ASTNodeDataType::int_t;
-        REQUIRE_NOTHROW(
-          ASTNodeNaturalConversionChecker{*data_node,
-                                          ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                          ASTNodeDataType{ASTNodeDataType::unsigned_int_t}}});
+        data_node->m_data_type = int_dt;
+        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
+                                                                      unsigned_int_dt)});
       }
 
       SECTION("B -> tuple(Z)")
       {
-        data_node->m_data_type = ASTNodeDataType::bool_t;
+        data_node->m_data_type = bool_dt;
         REQUIRE_NOTHROW(
-          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                      ASTNodeDataType{ASTNodeDataType::int_t}}});
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt)});
       }
 
       SECTION("N -> tuple(Z)")
       {
-        data_node->m_data_type = ASTNodeDataType::unsigned_int_t;
+        data_node->m_data_type = unsigned_int_dt;
         REQUIRE_NOTHROW(
-          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                      ASTNodeDataType{ASTNodeDataType::int_t}}});
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt)});
       }
 
       SECTION("Z -> tuple(Z)")
       {
-        data_node->m_data_type = ASTNodeDataType::int_t;
+        data_node->m_data_type = int_dt;
         REQUIRE_NOTHROW(
-          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                      ASTNodeDataType{ASTNodeDataType::int_t}}});
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt)});
       }
 
       SECTION("B -> tuple(R)")
       {
-        data_node->m_data_type = ASTNodeDataType::bool_t;
+        data_node->m_data_type = bool_dt;
         REQUIRE_NOTHROW(
-          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                      ASTNodeDataType{ASTNodeDataType::double_t}}});
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt)});
       }
 
       SECTION("N -> tuple(R)")
       {
-        data_node->m_data_type = ASTNodeDataType::unsigned_int_t;
+        data_node->m_data_type = unsigned_int_dt;
         REQUIRE_NOTHROW(
-          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                      ASTNodeDataType{ASTNodeDataType::double_t}}});
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt)});
       }
 
       SECTION("Z -> tuple(R)")
       {
-        data_node->m_data_type = ASTNodeDataType::int_t;
+        data_node->m_data_type = int_dt;
         REQUIRE_NOTHROW(
-          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                      ASTNodeDataType{ASTNodeDataType::double_t}}});
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt)});
       }
 
       SECTION("R -> tuple(R)")
       {
-        data_node->m_data_type = ASTNodeDataType::double_t;
+        data_node->m_data_type = double_dt;
         REQUIRE_NOTHROW(
-          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                      ASTNodeDataType{ASTNodeDataType::double_t}}});
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt)});
       }
 
       SECTION("R^1 -> tuple(R^1)")
       {
-        auto R1                = ASTNodeDataType{ASTNodeDataType::vector_t, 1};
+        auto R1                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
         data_node->m_data_type = R1;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, R1}});
+        REQUIRE_NOTHROW(
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1)});
       }
 
       SECTION("R^2 -> tuple(R^2)")
       {
-        auto R2                = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
+        auto R2                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
         data_node->m_data_type = R2;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, R2}});
+        REQUIRE_NOTHROW(
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2)});
       }
 
       SECTION("R^3 -> tuple(R^3)")
       {
-        auto R3                = ASTNodeDataType{ASTNodeDataType::vector_t, 3};
+        auto R3                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
         data_node->m_data_type = R3;
-        REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, R3}});
+        REQUIRE_NOTHROW(
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R3)});
       }
 
       SECTION("string -> tuple(string)")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::string_t};
+        data_node->m_data_type = string_dt;
         REQUIRE_NOTHROW(
-          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                      ASTNodeDataType{ASTNodeDataType::string_t}}});
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt)});
       }
 
       SECTION("type_id_t -> tuple(type_id_t)")
       {
-        auto type_id           = ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"};
+        auto type_id           = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo");
         data_node->m_data_type = type_id;
         REQUIRE_NOTHROW(
-          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, type_id}});
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(type_id)});
       }
 
       SECTION("(B, B, B) -> tuple(B)")
       {
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
-          list0_node->m_data_type    = ASTNodeDataType::bool_t;
+          list0_node->m_data_type    = bool_dt;
           data_node->emplace_back(std::move(list0_node));
 
           std::unique_ptr list1_node = std::make_unique<ASTNode>();
-          list1_node->m_data_type    = ASTNodeDataType::bool_t;
+          list1_node->m_data_type    = bool_dt;
           data_node->emplace_back(std::move(list1_node));
 
           std::unique_ptr list2_node = std::make_unique<ASTNode>();
-          list2_node->m_data_type    = ASTNodeDataType::bool_t;
+          list2_node->m_data_type    = bool_dt;
           data_node->emplace_back(std::move(list2_node));
         }
-        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}};
+        auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
         REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
       }
 
       SECTION("(B, N, Z) -> tuple(N)")
       {
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
-          list0_node->m_data_type    = ASTNodeDataType::bool_t;
+          list0_node->m_data_type    = bool_dt;
           data_node->emplace_back(std::move(list0_node));
 
           std::unique_ptr list1_node = std::make_unique<ASTNode>();
-          list1_node->m_data_type    = ASTNodeDataType::unsigned_int_t;
+          list1_node->m_data_type    = unsigned_int_dt;
           data_node->emplace_back(std::move(list1_node));
 
           std::unique_ptr list2_node = std::make_unique<ASTNode>();
-          list2_node->m_data_type    = ASTNodeDataType::int_t;
+          list2_node->m_data_type    = int_dt;
           data_node->emplace_back(std::move(list2_node));
         }
-        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}};
+        auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
         REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
       }
 
       SECTION("(B, N, Z) -> tuple(Z)")
       {
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
-          list0_node->m_data_type    = ASTNodeDataType::bool_t;
+          list0_node->m_data_type    = bool_dt;
           data_node->emplace_back(std::move(list0_node));
 
           std::unique_ptr list1_node = std::make_unique<ASTNode>();
-          list1_node->m_data_type    = ASTNodeDataType::unsigned_int_t;
+          list1_node->m_data_type    = unsigned_int_dt;
           data_node->emplace_back(std::move(list1_node));
 
           std::unique_ptr list2_node = std::make_unique<ASTNode>();
-          list2_node->m_data_type    = ASTNodeDataType::int_t;
+          list2_node->m_data_type    = int_dt;
           data_node->emplace_back(std::move(list2_node));
         }
-        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}};
+        auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
         REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
       }
 
       SECTION("(R, N, Z) -> tuple(R)")
       {
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
-          list0_node->m_data_type    = ASTNodeDataType::double_t;
+          list0_node->m_data_type    = double_dt;
           data_node->emplace_back(std::move(list0_node));
 
           std::unique_ptr list1_node = std::make_unique<ASTNode>();
-          list1_node->m_data_type    = ASTNodeDataType::unsigned_int_t;
+          list1_node->m_data_type    = unsigned_int_dt;
           data_node->emplace_back(std::move(list1_node));
 
           std::unique_ptr list2_node = std::make_unique<ASTNode>();
-          list2_node->m_data_type    = ASTNodeDataType::int_t;
+          list2_node->m_data_type    = int_dt;
           data_node->emplace_back(std::move(list2_node));
         }
-        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}};
+        auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
         REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
       }
 
       SECTION("(R^1, R^1) -> tuple(R^1)")
       {
-        auto R1                = ASTNodeDataType{ASTNodeDataType::vector_t, 1};
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        auto R1                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
           list0_node->m_data_type    = R1;
@@ -458,14 +466,14 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           list1_node->m_data_type    = R1;
           data_node->emplace_back(std::move(list1_node));
         }
-        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, R1};
+        auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1);
         REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
       }
 
       SECTION("(R^2, R^2, R^2) -> tuple(R^2)")
       {
-        auto R2                = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        auto R2                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
           list0_node->m_data_type    = R2;
@@ -479,14 +487,14 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           list2_node->m_data_type    = R2;
           data_node->emplace_back(std::move(list2_node));
         }
-        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, R2};
+        auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2);
         REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
       }
 
       SECTION("(R^3, R^3) -> tuple(R^3)")
       {
-        auto R3                = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        auto R3                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
           list0_node->m_data_type    = R3;
@@ -496,14 +504,14 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           list1_node->m_data_type    = R3;
           data_node->emplace_back(std::move(list1_node));
         }
-        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, R3};
+        auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R3);
         REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
       }
 
       SECTION("(string, string) -> tuple(string)")
       {
-        auto str_t             = ASTNodeDataType{ASTNodeDataType::string_t};
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        auto str_t             = string_dt;
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
           list0_node->m_data_type    = str_t;
@@ -513,14 +521,14 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           list1_node->m_data_type    = str_t;
           data_node->emplace_back(std::move(list1_node));
         }
-        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, str_t};
+        auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(str_t);
         REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_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;
+        auto type_id           = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo");
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
           list0_node->m_data_type    = type_id;
@@ -530,169 +538,168 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           list1_node->m_data_type    = type_id;
           data_node->emplace_back(std::move(list1_node));
         }
-        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, type_id};
+        auto tuple_t = ASTNodeDataType::build<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}};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
+        auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
 
         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}};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
+        auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
 
         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}};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
+        auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
 
         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}};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
+        auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
 
         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}};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
+        auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
 
         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}};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
+        auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
 
         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}};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
+        auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
 
         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}};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
+        auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
 
         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}};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
+        auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
 
         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}};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
+        auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
 
         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}};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
+        auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
 
         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}};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
+        auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt);
 
         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}};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
+        auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt);
 
         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}};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
+        auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt);
 
         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}};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
+        auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt);
 
         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}};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt);
+        auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt);
 
         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}});
+        auto R1                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1);
+        REQUIRE_NOTHROW(
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<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}});
+        auto R2                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2);
+        REQUIRE_NOTHROW(
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<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}});
+        auto R3                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R3);
+        REQUIRE_NOTHROW(
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<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};
+        auto type_id           = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo");
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(type_id);
         REQUIRE_NOTHROW(
-          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, type_id}});
+          ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(type_id)});
       }
     }
   }
@@ -705,132 +712,132 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
     {
       SECTION("R^2 -> R^1")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                             ASTNodeDataType{ASTNodeDataType::vector_t, 1}}),
-                            "incompatible dimensions in affectation");
+                                                             ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
+                            "invalid implicit conversion: R^2 -> R^1");
       }
 
       SECTION("R^3 -> R^1")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 3};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                             ASTNodeDataType{ASTNodeDataType::vector_t, 1}}),
-                            "incompatible dimensions in affectation");
+                                                             ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
+                            "invalid implicit conversion: R^3 -> R^1");
       }
 
       SECTION("R^1 -> R^2")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 1};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                             ASTNodeDataType{ASTNodeDataType::vector_t, 2}}),
-                            "incompatible dimensions in affectation");
+                                                             ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
+                            "invalid implicit conversion: R^1 -> R^2");
       }
 
       SECTION("R^3 -> R^2")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 3};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                             ASTNodeDataType{ASTNodeDataType::vector_t, 2}}),
-                            "incompatible dimensions in affectation");
+                                                             ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
+                            "invalid implicit conversion: R^3 -> R^2");
       }
 
       SECTION("R^1 -> R^3")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 1};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                             ASTNodeDataType{ASTNodeDataType::vector_t, 3}}),
-                            "incompatible dimensions in affectation");
+                                                             ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
+                            "invalid implicit conversion: R^1 -> R^3");
       }
 
       SECTION("R^2 -> R^3")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                             ASTNodeDataType{ASTNodeDataType::vector_t, 3}}),
-                            "incompatible dimensions in affectation");
+                                                             ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
+                            "invalid implicit conversion: R^2 -> R^3");
       }
 
       SECTION("list1 -> R^d")
       {
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
-          list0_node->m_data_type    = ASTNodeDataType::double_t;
+          list0_node->m_data_type    = double_dt;
           data_node->emplace_back(std::move(list0_node));
         }
 
         SECTION("d=2")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 2}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                               "incompatible dimensions in affectation");
         }
 
         SECTION("d=3")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 3}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                               "incompatible dimensions in affectation");
         }
       }
 
       SECTION("list2 -> R^d")
       {
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
-          list0_node->m_data_type    = ASTNodeDataType::double_t;
+          list0_node->m_data_type    = double_dt;
           data_node->emplace_back(std::move(list0_node));
 
           std::unique_ptr list1_node = std::make_unique<ASTNode>();
-          list1_node->m_data_type    = ASTNodeDataType::unsigned_int_t;
+          list1_node->m_data_type    = unsigned_int_dt;
           data_node->emplace_back(std::move(list1_node));
         }
 
         SECTION("d=1")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 1}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                               "incompatible dimensions in affectation");
         }
 
         SECTION("d=3")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 3}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                               "incompatible dimensions in affectation");
         }
       }
 
       SECTION("list3 -> R^d")
       {
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
-          list0_node->m_data_type    = ASTNodeDataType::double_t;
+          list0_node->m_data_type    = double_dt;
           data_node->emplace_back(std::move(list0_node));
 
           std::unique_ptr list1_node = std::make_unique<ASTNode>();
-          list1_node->m_data_type    = ASTNodeDataType::unsigned_int_t;
+          list1_node->m_data_type    = unsigned_int_dt;
           data_node->emplace_back(std::move(list1_node));
 
           std::unique_ptr list2_node = std::make_unique<ASTNode>();
-          list2_node->m_data_type    = ASTNodeDataType::int_t;
+          list2_node->m_data_type    = int_dt;
           data_node->emplace_back(std::move(list2_node));
         }
 
         SECTION("d=1")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 1}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                               "incompatible dimensions in affectation");
         }
 
         SECTION("d=2")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 2}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                               "incompatible dimensions in affectation");
         }
       }
@@ -839,60 +846,58 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
       {
         SECTION("tuple(N) -> R^1")
         {
-          data_node->m_data_type =
-            ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}};
+          data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 1}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                               "invalid implicit conversion: tuple(N) -> R^1");
         }
 
         SECTION("tuple(R) -> R^1")
         {
-          data_node->m_data_type =
-            ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}};
+          data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 1}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                               "invalid implicit conversion: tuple(R) -> R^1");
         }
 
         SECTION("tuple(R) -> R^2")
         {
-          data_node->m_data_type =
-            ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}};
+          data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 2}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                               "invalid implicit conversion: tuple(R) -> R^2");
         }
 
         SECTION("tuple(B) -> R^2")
         {
-          data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}};
+          data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 2}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                               "invalid implicit conversion: tuple(B) -> R^2");
         }
 
         SECTION("tuple(Z) -> R^3")
         {
-          data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}};
+          data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 3}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                               "invalid implicit conversion: tuple(Z) -> R^3");
         }
 
         SECTION("tuple(R) -> R^3")
         {
-          data_node->m_data_type =
-            ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}};
+          data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 3}}),
+                                                               ASTNodeDataType::build<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}};
+          auto tuple_R1 =
+            ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1));
+          auto tuple_R3 =
+            ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<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");
@@ -900,8 +905,10 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
 
         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}};
+          auto tuple_R2 =
+            ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::vector_t>(2));
+          auto tuple_R3 =
+            ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<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");
@@ -909,8 +916,10 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
 
         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}};
+          auto tuple_R1 =
+            ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1));
+          auto tuple_R2 =
+            ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<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");
@@ -918,8 +927,8 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
 
         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}};
+          auto tuple_R           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
+          auto tuple_Z           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
           data_node->m_data_type = tuple_R;
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_Z}),
                               "invalid implicit conversion: R -> Z");
@@ -927,8 +936,9 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
 
         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}};
+          auto tuple_R = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
+          auto tuple_R1 =
+            ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<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");
@@ -936,8 +946,8 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
 
         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}};
+          auto tuple_string      = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt);
+          auto tuple_R           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
           data_node->m_data_type = tuple_string;
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R}),
                               "invalid implicit conversion: string -> R");
@@ -945,10 +955,10 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
 
         SECTION("tuple(type_id) -> tuple(R)")
         {
-          auto type_id = ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"};
+          auto type_id = ASTNodeDataType::build<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}};
+          auto tuple_type_id     = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(type_id);
+          auto tuple_R           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
           data_node->m_data_type = tuple_type_id;
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R}),
                               "invalid implicit conversion: foo -> R");
@@ -956,11 +966,11 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
 
         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 type_id0 = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo");
+          auto type_id1 = ASTNodeDataType::build<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};
+          auto tuple_type_id0    = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(type_id0);
+          auto tuple_type_id1    = ASTNodeDataType::build<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");
@@ -969,33 +979,33 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
 
       SECTION("R -> R^d")
       {
-        data_node->m_data_type = ASTNodeDataType::double_t;
+        data_node->m_data_type = double_dt;
 
         SECTION("d=1")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 1}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                               "invalid implicit conversion: R -> R^1");
         }
 
         SECTION("d=2")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 2}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                               "invalid implicit conversion: R -> R^2");
         }
 
         SECTION("d=3")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 3}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                               "invalid implicit conversion: R -> R^3");
         }
       }
 
       SECTION("Z -> R^d (non-zero)")
       {
-        data_node->m_data_type = ASTNodeDataType::int_t;
+        data_node->m_data_type = int_dt;
         data_node->set_type<language::integer>();
         data_node->source  = "1";
         auto& source       = data_node->source;
@@ -1005,99 +1015,99 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
         SECTION("d=1")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 1}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                               "invalid implicit conversion: Z -> R^1");
         }
 
         SECTION("d=2")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 2}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                               "invalid implicit conversion: Z -> R^2");
         }
 
         SECTION("d=3")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 3}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                               "invalid implicit conversion: Z -> R^3");
         }
       }
 
       SECTION("N -> R^d")
       {
-        data_node->m_data_type = ASTNodeDataType::unsigned_int_t;
+        data_node->m_data_type = unsigned_int_dt;
 
         SECTION("d=1")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 1}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                               "invalid implicit conversion: N -> R^1");
         }
 
         SECTION("d=2")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 2}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                               "invalid implicit conversion: N -> R^2");
         }
 
         SECTION("d=3")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 3}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                               "invalid implicit conversion: N -> R^3");
         }
       }
 
       SECTION("B -> R^d")
       {
-        data_node->m_data_type = ASTNodeDataType::bool_t;
+        data_node->m_data_type = bool_dt;
 
         SECTION("d=1")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 1}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                               "invalid implicit conversion: B -> R^1");
         }
 
         SECTION("d=2")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 2}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                               "invalid implicit conversion: B -> R^2");
         }
 
         SECTION("d=3")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 3}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                               "invalid implicit conversion: B -> R^3");
         }
       }
 
       SECTION("string -> R^d")
       {
-        data_node->m_data_type = ASTNodeDataType::string_t;
+        data_node->m_data_type = string_dt;
 
         SECTION("d=1")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 1}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                               "invalid implicit conversion: string -> R^1");
         }
 
         SECTION("d=2")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 2}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                               "invalid implicit conversion: string -> R^2");
         }
 
         SECTION("d=3")
         {
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                               ASTNodeDataType{ASTNodeDataType::vector_t, 3}}),
+                                                               ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                               "invalid implicit conversion: string -> R^3");
         }
       }
@@ -1107,44 +1117,43 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
     {
       SECTION("string -> R")
       {
-        data_node->m_data_type = ASTNodeDataType::string_t;
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::double_t}),
+        data_node->m_data_type = string_dt;
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, double_dt}),
                             "invalid implicit conversion: string -> R");
       }
 
       SECTION("R^1 -> R")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 1};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::double_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, double_dt}),
                             "invalid implicit conversion: R^1 -> R");
       }
 
       SECTION("R^2 -> R")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::double_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, double_dt}),
                             "invalid implicit conversion: R^2 -> R");
       }
 
       SECTION("R^3 -> R")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 3};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::double_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, double_dt}),
                             "invalid implicit conversion: R^3 -> R");
       }
 
       SECTION("tuple(N) -> R")
       {
-        data_node->m_data_type =
-          ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::double_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, double_dt}),
                             "invalid implicit conversion: tuple(N) -> R");
       }
 
       SECTION("tuple(R) -> R")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::double_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, double_dt}),
                             "invalid implicit conversion: tuple(R) -> R");
       }
     }
@@ -1153,51 +1162,50 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
     {
       SECTION("string -> Z")
       {
-        data_node->m_data_type = ASTNodeDataType::string_t;
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::int_t}),
+        data_node->m_data_type = string_dt;
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, int_dt}),
                             "invalid implicit conversion: string -> Z");
       }
 
       SECTION("R^1 -> Z")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 1};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::int_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, int_dt}),
                             "invalid implicit conversion: R^1 -> Z");
       }
 
       SECTION("R^2 -> Z")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::int_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, int_dt}),
                             "invalid implicit conversion: R^2 -> Z");
       }
 
       SECTION("R^3 -> Z")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 3};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::int_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, int_dt}),
                             "invalid implicit conversion: R^3 -> Z");
       }
 
       SECTION("R -> Z")
       {
-        data_node->m_data_type = ASTNodeDataType::double_t;
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::int_t}),
+        data_node->m_data_type = double_dt;
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, int_dt}),
                             "invalid implicit conversion: R -> Z");
       }
 
       SECTION("tuple(N) -> Z")
       {
-        data_node->m_data_type =
-          ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::int_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, int_dt}),
                             "invalid implicit conversion: tuple(N) -> Z");
       }
 
       SECTION("tuple(Z) -> Z")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::int_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, int_dt}),
                             "invalid implicit conversion: tuple(Z) -> Z");
       }
     }
@@ -1206,51 +1214,50 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
     {
       SECTION("string -> N")
       {
-        data_node->m_data_type = ASTNodeDataType::string_t;
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::unsigned_int_t}),
+        data_node->m_data_type = string_dt;
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt}),
                             "invalid implicit conversion: string -> N");
       }
 
       SECTION("R^1 -> N")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 1};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::unsigned_int_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt}),
                             "invalid implicit conversion: R^1 -> N");
       }
 
       SECTION("R^2 -> N")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::unsigned_int_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt}),
                             "invalid implicit conversion: R^2 -> N");
       }
 
       SECTION("R^3 -> N")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 3};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::unsigned_int_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt}),
                             "invalid implicit conversion: R^3 -> N");
       }
 
       SECTION("R -> N")
       {
-        data_node->m_data_type = ASTNodeDataType::double_t;
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::unsigned_int_t}),
+        data_node->m_data_type = double_dt;
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt}),
                             "invalid implicit conversion: R -> N");
       }
 
       SECTION("tuple(Z) -> N")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::unsigned_int_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt}),
                             "invalid implicit conversion: tuple(Z) -> N");
       }
 
       SECTION("tuple(N) -> N")
       {
-        data_node->m_data_type =
-          ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::unsigned_int_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt}),
                             "invalid implicit conversion: tuple(N) -> N");
       }
     }
@@ -1259,64 +1266,64 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
     {
       SECTION("string -> B")
       {
-        data_node->m_data_type = ASTNodeDataType::string_t;
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::bool_t}),
+        data_node->m_data_type = string_dt;
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                             "invalid implicit conversion: string -> B");
       }
 
       SECTION("R^1 -> B")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 1};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::bool_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                             "invalid implicit conversion: R^1 -> B");
       }
 
       SECTION("R^2 -> B")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::bool_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                             "invalid implicit conversion: R^2 -> B");
       }
 
       SECTION("R^3 -> B")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 3};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::bool_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                             "invalid implicit conversion: R^3 -> B");
       }
 
       SECTION("R -> B")
       {
-        data_node->m_data_type = ASTNodeDataType::double_t;
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::bool_t}),
+        data_node->m_data_type = double_dt;
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                             "invalid implicit conversion: R -> B");
       }
 
       SECTION("Z -> B")
       {
-        data_node->m_data_type = ASTNodeDataType::int_t;
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::bool_t}),
+        data_node->m_data_type = int_dt;
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                             "invalid implicit conversion: Z -> B");
       }
 
       SECTION("N -> B")
       {
-        data_node->m_data_type = ASTNodeDataType::unsigned_int_t;
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::bool_t}),
+        data_node->m_data_type = unsigned_int_dt;
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                             "invalid implicit conversion: N -> B");
       }
 
       SECTION("tuple(Z) -> B")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::bool_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                             "invalid implicit conversion: tuple(Z) -> B");
       }
 
       SECTION("tuple(B) -> B")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::bool_t}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                             "invalid implicit conversion: tuple(B) -> B");
       }
     }
@@ -1325,166 +1332,165 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
     {
       SECTION("N -> tuple(B)")
       {
-        data_node->m_data_type = ASTNodeDataType::unsigned_int_t;
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                                         ASTNodeDataType{
-                                                                                           ASTNodeDataType::bool_t}}}),
+        data_node->m_data_type = unsigned_int_dt;
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
+                                                             ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
+                                                               bool_dt)}),
                             "invalid implicit conversion: N -> B");
       }
 
       SECTION("Z -> tuple(B)")
       {
-        data_node->m_data_type = ASTNodeDataType::int_t;
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                                         ASTNodeDataType{
-                                                                                           ASTNodeDataType::bool_t}}}),
+        data_node->m_data_type = int_dt;
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
+                                                             ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
+                                                               bool_dt)}),
                             "invalid implicit conversion: Z -> B");
       }
 
       SECTION("R -> tuple(B)")
       {
-        data_node->m_data_type = ASTNodeDataType::double_t;
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                                         ASTNodeDataType{
-                                                                                           ASTNodeDataType::bool_t}}}),
+        data_node->m_data_type = double_dt;
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
+                                                             ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
+                                                               bool_dt)}),
                             "invalid implicit conversion: R -> B");
       }
 
       SECTION("string -> tuple(B)")
       {
-        data_node->m_data_type = ASTNodeDataType::string_t;
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                                         ASTNodeDataType{
-                                                                                           ASTNodeDataType::bool_t}}}),
+        data_node->m_data_type = string_dt;
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
+                                                             ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
+                                                               bool_dt)}),
                             "invalid implicit conversion: string -> B");
       }
 
       SECTION("R^1 -> tuple(B)")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 1};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                                         ASTNodeDataType{
-                                                                                           ASTNodeDataType::bool_t}}}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
+                                                             ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
+                                                               bool_dt)}),
                             "invalid implicit conversion: R^1 -> B");
       }
 
       SECTION("R^2 -> tuple(B)")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                                         ASTNodeDataType{
-                                                                                           ASTNodeDataType::bool_t}}}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
+                                                             ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
+                                                               bool_dt)}),
                             "invalid implicit conversion: R^2 -> B");
       }
 
       SECTION("R^3 -> tuple(B)")
       {
-        data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::vector_t, 3};
-        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                                         ASTNodeDataType{
-                                                                                           ASTNodeDataType::bool_t}}}),
+        data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
+        REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
+                                                             ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
+                                                               bool_dt)}),
                             "invalid implicit conversion: R^3 -> B");
       }
 
       SECTION("R -> tuple(N)")
       {
-        data_node->m_data_type = ASTNodeDataType::double_t;
+        data_node->m_data_type = double_dt;
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                             ASTNodeDataType{ASTNodeDataType::tuple_t,
-                                                                             ASTNodeDataType{
-                                                                               ASTNodeDataType::unsigned_int_t}}}),
+                                                             ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
+                                                               unsigned_int_dt)}),
                             "invalid implicit conversion: R -> N");
       }
 
       SECTION("R^1 -> tuple(R^2)")
       {
-        auto R1                = ASTNodeDataType{ASTNodeDataType::vector_t, 1};
-        auto R2                = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
+        auto R1                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
+        auto R2                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
         data_node->m_data_type = R1;
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                             ASTNodeDataType{ASTNodeDataType::tuple_t, R2}}),
-                            "incompatible dimensions in affectation");
+                                                             ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2)}),
+                            "invalid implicit conversion: R^1 -> R^2");
       }
 
       SECTION("R^2 -> tuple(R^3)")
       {
-        auto R2                = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
-        auto R3                = ASTNodeDataType{ASTNodeDataType::vector_t, 3};
+        auto R2                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
+        auto R3                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
         data_node->m_data_type = R2;
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                             ASTNodeDataType{ASTNodeDataType::tuple_t, R3}}),
-                            "incompatible dimensions in affectation");
+                                                             ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R3)}),
+                            "invalid implicit conversion: R^2 -> R^3");
       }
 
       SECTION("R^3 -> tuple(R^2)")
       {
-        auto R3                = ASTNodeDataType{ASTNodeDataType::vector_t, 3};
-        auto R2                = ASTNodeDataType{ASTNodeDataType::vector_t, 2};
+        auto R3                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
+        auto R2                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
         data_node->m_data_type = R3;
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
-                                                             ASTNodeDataType{ASTNodeDataType::tuple_t, R2}}),
-                            "incompatible dimensions in affectation");
+                                                             ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2)}),
+                            "invalid implicit conversion: R^3 -> R^2");
       }
 
       SECTION("(B, R, Z) -> tuple(N)")
       {
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
-          list0_node->m_data_type    = ASTNodeDataType::bool_t;
+          list0_node->m_data_type    = bool_dt;
           data_node->emplace_back(std::move(list0_node));
 
           std::unique_ptr list1_node = std::make_unique<ASTNode>();
-          list1_node->m_data_type    = ASTNodeDataType::double_t;
+          list1_node->m_data_type    = double_dt;
           data_node->emplace_back(std::move(list1_node));
 
           std::unique_ptr list2_node = std::make_unique<ASTNode>();
-          list2_node->m_data_type    = ASTNodeDataType::int_t;
+          list2_node->m_data_type    = int_dt;
           data_node->emplace_back(std::move(list2_node));
         }
-        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}};
+        auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_t}),
                             "invalid implicit conversion: R -> N");
       }
 
       SECTION("(R, N, Z) -> tuple(Z)")
       {
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
-          list0_node->m_data_type    = ASTNodeDataType::double_t;
+          list0_node->m_data_type    = double_dt;
           data_node->emplace_back(std::move(list0_node));
 
           std::unique_ptr list1_node = std::make_unique<ASTNode>();
-          list1_node->m_data_type    = ASTNodeDataType::unsigned_int_t;
+          list1_node->m_data_type    = unsigned_int_dt;
           data_node->emplace_back(std::move(list1_node));
 
           std::unique_ptr list2_node = std::make_unique<ASTNode>();
-          list2_node->m_data_type    = ASTNodeDataType::int_t;
+          list2_node->m_data_type    = int_dt;
           data_node->emplace_back(std::move(list2_node));
         }
-        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}};
+        auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_t}),
                             "invalid implicit conversion: R -> Z");
       }
 
       SECTION("(B, N, R) -> tuple(N)")
       {
-        data_node->m_data_type = ASTNodeDataType::list_t;
+        data_node->m_data_type = list_dt;
         {
           std::unique_ptr list0_node = std::make_unique<ASTNode>();
-          list0_node->m_data_type    = ASTNodeDataType::bool_t;
+          list0_node->m_data_type    = bool_dt;
           data_node->emplace_back(std::move(list0_node));
 
           std::unique_ptr list1_node = std::make_unique<ASTNode>();
-          list1_node->m_data_type    = ASTNodeDataType::unsigned_int_t;
+          list1_node->m_data_type    = unsigned_int_dt;
           data_node->emplace_back(std::move(list1_node));
 
           std::unique_ptr list2_node = std::make_unique<ASTNode>();
-          list2_node->m_data_type    = ASTNodeDataType::double_t;
+          list2_node->m_data_type    = double_dt;
           data_node->emplace_back(std::move(list2_node));
         }
-        auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}};
+        auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
         REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_t}),
                             "invalid implicit conversion: R -> N");
       }
@@ -1492,9 +1498,9 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
 
     SECTION("(type_id_t, type_id_t) -> tuple(type_id_t)")
     {
-      auto type_id1          = ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"};
-      auto type_id2          = ASTNodeDataType{ASTNodeDataType::type_id_t, "bar"};
-      data_node->m_data_type = ASTNodeDataType::list_t;
+      auto type_id1          = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo");
+      auto type_id2          = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("bar");
+      data_node->m_data_type = list_dt;
       {
         std::unique_ptr list0_node = std::make_unique<ASTNode>();
         list0_node->m_data_type    = type_id1;
@@ -1504,7 +1510,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
         list1_node->m_data_type    = type_id2;
         data_node->emplace_back(std::move(list1_node));
       }
-      auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, type_id2};
+      auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(type_id2);
       REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_t}),
                           "invalid implicit conversion: foo -> bar");
     }
diff --git a/tests/test_ASTNodeUnaryOperatorExpressionBuilder.cpp b/tests/test_ASTNodeUnaryOperatorExpressionBuilder.cpp
index 6c30d3f0a9e8470f7156fe6aa8239002f065aee5..cc31b56706d9bdf952bcfdb5b4ab6e209e2be1df 100644
--- a/tests/test_ASTNodeUnaryOperatorExpressionBuilder.cpp
+++ b/tests/test_ASTNodeUnaryOperatorExpressionBuilder.cpp
@@ -235,7 +235,7 @@ not b;
     {
       auto ast = std::make_unique<ASTNode>();
       ast->set_type<language::unary_minus>();
-      ast->m_data_type = ASTNodeDataType::int_t;
+      ast->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
       ast->children.emplace_back(std::make_unique<ASTNode>());
 
       REQUIRE_THROWS_WITH(ASTNodeUnaryOperatorExpressionBuilder{*ast},
diff --git a/tests/test_AffectationProcessor.cpp b/tests/test_AffectationProcessor.cpp
index c94ecdb7d9a1d320dce9f00a7bd70755fd425749..75ba801b59cc8d06b213fd56b2dc18dbb74b7c45 100644
--- a/tests/test_AffectationProcessor.cpp
+++ b/tests/test_AffectationProcessor.cpp
@@ -395,19 +395,19 @@ TEST_CASE("AffectationProcessor", "[language]")
         CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = 3;", "invalid implicit conversion: Z -> R^3");
 
         CHECK_AFFECTATION_THROWS_WITH("let x : R^1, x = 0; let y : R^2, y = x;",
-                                      "incompatible dimensions in affectation");
+                                      "invalid implicit conversion: R^1 -> R^2");
         CHECK_AFFECTATION_THROWS_WITH("let x : R^1, x = 0; let y : R^3, y = x;",
-                                      "incompatible dimensions in affectation");
+                                      "invalid implicit conversion: R^1 -> R^3");
 
         CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = 0; let y : R^1, y = x;",
-                                      "incompatible dimensions in affectation");
+                                      "invalid implicit conversion: R^2 -> R^1");
         CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = 0; let y : R^3, y = x;",
-                                      "incompatible dimensions in affectation");
+                                      "invalid implicit conversion: R^2 -> R^3");
 
         CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = 0; let y : R^1, y = x;",
-                                      "incompatible dimensions in affectation");
+                                      "invalid implicit conversion: R^3 -> R^1");
         CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = 0; let y : R^2, y = x;",
-                                      "incompatible dimensions in affectation");
+                                      "invalid implicit conversion: R^3 -> R^2");
       }
     }
   }
diff --git a/tests/test_BuiltinFunctionEmbedder.cpp b/tests/test_BuiltinFunctionEmbedder.cpp
index bf0445d6aadf5cfdbefed9134dafe0e89dd8d290..00f757fa68d935cdffbff876205e4ba5a16d1e68 100644
--- a/tests/test_BuiltinFunctionEmbedder.cpp
+++ b/tests/test_BuiltinFunctionEmbedder.cpp
@@ -5,15 +5,16 @@
 // clazy:excludeall=non-pod-global-static
 
 template <>
-inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> = {ASTNodeDataType::type_id_t,
-                                                                                 "shared_const_double"};
+inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> =
+  ASTNodeDataType::build<ASTNodeDataType::type_id_t>("shared_const_double");
 
 template <>
-inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<double>> = {ASTNodeDataType::type_id_t, "shared_double"};
+inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<double>> =
+  ASTNodeDataType::build<ASTNodeDataType::type_id_t>("shared_double");
 
 template <>
-inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<uint64_t>> = {ASTNodeDataType::type_id_t,
-                                                                             "shared_uint64_t"};
+inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<uint64_t>> =
+  ASTNodeDataType::build<ASTNodeDataType::type_id_t>("shared_uint64_t");
 
 TEST_CASE("BuiltinFunctionEmbedder", "[language]")
 {
diff --git a/tests/test_BuiltinFunctionRegister.hpp b/tests/test_BuiltinFunctionRegister.hpp
index 1583f1df99d7eddefc3337529611a5d5720912a0..c1c1eb29b74fb9c5e6f8a170f76c7b4b2157c7b7 100644
--- a/tests/test_BuiltinFunctionRegister.hpp
+++ b/tests/test_BuiltinFunctionRegister.hpp
@@ -7,8 +7,8 @@
 #include <utils/Exceptions.hpp>
 
 template <>
-inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> = {ASTNodeDataType::type_id_t,
-                                                                                 "builtin_t"};
+inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> =
+  ASTNodeDataType::build<ASTNodeDataType::type_id_t>("builtin_t");
 const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const double>>;
 
 namespace test_only
@@ -127,7 +127,7 @@ class test_BuiltinFunctionRegister
       throw UnexpectedError("cannot add '" + builtin_data_type.nameOfTypeId() + "' type for testing");
     }
 
-    i_symbol->attributes().setDataType(ASTNodeDataType::type_name_id_t);
+    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()));
@@ -165,7 +165,7 @@ class test_BuiltinFunctionRegister
         throw ParseError(error_message.str(), root_node.begin());
       }
 
-      i_symbol->attributes().setDataType(ASTNodeDataType::builtin_function_t);
+      i_symbol->attributes().setDataType(ASTNodeDataType::build<ASTNodeDataType::builtin_function_t>());
       i_symbol->attributes().setIsInitialized();
       i_symbol->attributes().value() = builtin_function_embedder_table.size();
 
diff --git a/tests/test_FunctionTable.cpp b/tests/test_FunctionTable.cpp
index c6ae9ab2f856457aaff70aaf2e35146661fde1b0..eae87ca79ac45e18da301fef72e1bd2fd35f90cf 100644
--- a/tests/test_FunctionTable.cpp
+++ b/tests/test_FunctionTable.cpp
@@ -11,14 +11,14 @@ TEST_CASE("FunctionTable", "[language]")
   SECTION("FunctionDescriptor")
   {
     std::unique_ptr domain_mapping_node = std::make_unique<ASTNode>();
-    domain_mapping_node->m_data_type    = ASTNodeDataType::unsigned_int_t;
+    domain_mapping_node->m_data_type    = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
 
     std::unique_ptr definition_node = std::make_unique<ASTNode>();
-    definition_node->m_data_type    = ASTNodeDataType::double_t;
+    definition_node->m_data_type    = ASTNodeDataType::build<ASTNodeDataType::double_t>();
     FunctionDescriptor f{"f", std::move(domain_mapping_node), std::move(definition_node)};
 
-    REQUIRE(f.domainMappingNode().m_data_type == ASTNodeDataType::unsigned_int_t);
-    REQUIRE(f.definitionNode().m_data_type == ASTNodeDataType::double_t);
+    REQUIRE(f.domainMappingNode().m_data_type == ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>());
+    REQUIRE(f.definitionNode().m_data_type == ASTNodeDataType::build<ASTNodeDataType::double_t>());
 
     REQUIRE(domain_mapping_node == nullptr);
     REQUIRE(definition_node == nullptr);
@@ -28,10 +28,10 @@ TEST_CASE("FunctionTable", "[language]")
   SECTION("uninitialized FunctionDescriptor")
   {
     std::unique_ptr domain_mapping_node = std::make_unique<ASTNode>();
-    domain_mapping_node->m_data_type    = ASTNodeDataType::unsigned_int_t;
+    domain_mapping_node->m_data_type    = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
 
     std::unique_ptr definition_node = std::make_unique<ASTNode>();
-    definition_node->m_data_type    = ASTNodeDataType::double_t;
+    definition_node->m_data_type    = ASTNodeDataType::build<ASTNodeDataType::double_t>();
 
     SECTION("nothing initialized")
     {
@@ -44,7 +44,7 @@ TEST_CASE("FunctionTable", "[language]")
     {
       FunctionDescriptor f{"function", nullptr, std::move(definition_node)};
       REQUIRE_THROWS_AS(f.domainMappingNode(), AssertError);
-      REQUIRE(f.definitionNode().m_data_type == ASTNodeDataType::double_t);
+      REQUIRE(f.definitionNode().m_data_type == ASTNodeDataType::build<ASTNodeDataType::double_t>());
       REQUIRE(definition_node == nullptr);
     }
 
@@ -52,7 +52,7 @@ TEST_CASE("FunctionTable", "[language]")
     {
       FunctionDescriptor f{"function", std::move(domain_mapping_node), nullptr};
       REQUIRE_THROWS_AS(f.definitionNode(), AssertError);
-      REQUIRE(f.domainMappingNode().m_data_type == ASTNodeDataType::unsigned_int_t);
+      REQUIRE(f.domainMappingNode().m_data_type == ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>());
       REQUIRE(domain_mapping_node == nullptr);
     }
   }
@@ -63,10 +63,10 @@ TEST_CASE("FunctionTable", "[language]")
   REQUIRE(table.size() == 0);
 
   std::unique_ptr domain_mapping_node = std::make_unique<ASTNode>();
-  domain_mapping_node->m_data_type    = ASTNodeDataType::unsigned_int_t;
+  domain_mapping_node->m_data_type    = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
 
   std::unique_ptr definition_node = std::make_unique<ASTNode>();
-  definition_node->m_data_type    = ASTNodeDataType::double_t;
+  definition_node->m_data_type    = ASTNodeDataType::build<ASTNodeDataType::double_t>();
 
   size_t function_id =
     table.add(FunctionDescriptor{"function", std::move(domain_mapping_node), std::move(definition_node)});
@@ -82,8 +82,8 @@ TEST_CASE("FunctionTable", "[language]")
 
   auto& f = table[function_id];
   REQUIRE(f.name() == "function");
-  REQUIRE(f.domainMappingNode().m_data_type == ASTNodeDataType::unsigned_int_t);
-  REQUIRE(f.definitionNode().m_data_type == ASTNodeDataType::double_t);
+  REQUIRE(f.domainMappingNode().m_data_type == ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>());
+  REQUIRE(f.definitionNode().m_data_type == ASTNodeDataType::build<ASTNodeDataType::double_t>());
 
   const auto& const_f = const_table[function_id];
   REQUIRE(const_f.name() == "function");
diff --git a/tests/test_SymbolTable.cpp b/tests/test_SymbolTable.cpp
index bb80c4999781e59f3585f1ff64eba3ac3b71bcac..fed694f752f4b87ce79a88ae97547800bb4d35c2 100644
--- a/tests/test_SymbolTable.cpp
+++ b/tests/test_SymbolTable.cpp
@@ -67,8 +67,8 @@ TEST_CASE("SymbolTable", "[language]")
       attributes_a.setIsInitialized();
       REQUIRE(attributes_a.isInitialized());
 
-      attributes_a.setDataType(ASTNodeDataType::double_t);
-      REQUIRE(attributes_a.dataType() == ASTNodeDataType::double_t);
+      attributes_a.setDataType(ASTNodeDataType::build<ASTNodeDataType::double_t>());
+      REQUIRE(attributes_a.dataType() == ASTNodeDataType::build<ASTNodeDataType::double_t>());
 
       attributes_a.value() = 2.3;
 
@@ -166,8 +166,8 @@ TEST_CASE("SymbolTable", "[language]")
     attributes_a.setIsInitialized();
     REQUIRE(attributes_a.isInitialized());
 
-    attributes_a.setDataType(ASTNodeDataType::function_t);
-    REQUIRE(attributes_a.dataType() == ASTNodeDataType::function_t);
+    attributes_a.setDataType(ASTNodeDataType::build<ASTNodeDataType::function_t>());
+    REQUIRE(attributes_a.dataType() == ASTNodeDataType::build<ASTNodeDataType::function_t>());
 
     attributes_a.value() = static_cast<uint64_t>(2);