From 612e60d860038c761a697e0ce912594f8a4853c8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com>
Date: Sun, 28 Mar 2021 19:05:40 +0200
Subject: [PATCH] Change builtin functions mangling and their return type
 flattening

- the new mangling is more consistent with the language itself
- this allows more user-friendly error messages
---
 .../ASTNodeAffectationExpressionBuilder.cpp   |   2 +-
 src/language/ast/ASTNodeDataTypeFlattener.cpp |  13 +-
 src/language/modules/BuiltinModule.cpp        |  25 +--
 src/language/utils/ASTNodeDataType.cpp        |  25 ++-
 .../utils/BuiltinFunctionEmbedderUtils.cpp    | 160 +++++++++-----
 src/language/utils/SymbolTable.hpp            |   6 +-
 tests/test_ASTModulesImporter.cpp             |   2 +-
 ...st_ASTNodeAffectationExpressionBuilder.cpp |   4 +-
 ...STNodeBuiltinFunctionExpressionBuilder.cpp |   4 +-
 tests/test_ASTNodeDataType.cpp                |  18 +-
 tests/test_ASTNodeDataTypeBuilder.cpp         | 196 +++++++++---------
 .../test_ASTNodeNaturalConversionChecker.cpp  |  40 ++--
 tests/test_BuiltinFunctionProcessor.cpp       |  44 ++--
 tests/test_BuiltinFunctionRegister.hpp        | 102 ++++-----
 tests/test_MathModule.cpp                     |  44 ++--
 15 files changed, 358 insertions(+), 327 deletions(-)

diff --git a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp
index a97c13443..321170395 100644
--- a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp
@@ -43,6 +43,6 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode
     error_message << "undefined affectation type: ";
     error_message << rang::fgB::red << affectation_name << rang::fg::reset;
 
-    throw ParseError(error_message.str(), std::vector{node.begin()});
+    throw ParseError(error_message.str(), std::vector{node.children[0]->begin()});
   }
 }
diff --git a/src/language/ast/ASTNodeDataTypeFlattener.cpp b/src/language/ast/ASTNodeDataTypeFlattener.cpp
index 6a06c72bb..a2f83e592 100644
--- a/src/language/ast/ASTNodeDataTypeFlattener.cpp
+++ b/src/language/ast/ASTNodeDataTypeFlattener.cpp
@@ -2,6 +2,7 @@
 
 #include <language/PEGGrammar.hpp>
 #include <language/utils/BuiltinFunctionEmbedder.hpp>
+#include <language/utils/BuiltinFunctionEmbedderUtils.hpp>
 #include <language/utils/FunctionTable.hpp>
 #include <language/utils/SymbolTable.hpp>
 
@@ -16,12 +17,12 @@ ASTNodeDataTypeFlattener::ASTNodeDataTypeFlattener(ASTNode& node, FlattenedDataT
       flattened_datatype_list.push_back({node.m_data_type, node});
     } else {
       ASTNode& function_name_node = *node.children[0];
+      Assert(node.m_symbol_table->has(function_name_node.string(), node.begin()));
 
-      auto [i_function_symbol, found] = node.m_symbol_table->find(function_name_node.string(), node.begin());
-      Assert(found);
-
-      switch (i_function_symbol->attributes().dataType()) {
+      switch (function_name_node.m_data_type) {
       case ASTNodeDataType::function_t: {
+        auto [i_function_symbol, found] = node.m_symbol_table->find(function_name_node.string(), node.begin());
+
         uint64_t function_id = std::get<uint64_t>(i_function_symbol->attributes().value());
 
         FunctionDescriptor& function_descriptor = node.m_symbol_table->functionTable()[function_id];
@@ -35,10 +36,8 @@ ASTNodeDataTypeFlattener::ASTNodeDataTypeFlattener(ASTNode& node, FlattenedDataT
         break;
       }
       case ASTNodeDataType::builtin_function_t: {
-        uint64_t builtin_function_id   = std::get<uint64_t>(i_function_symbol->attributes().value());
-        auto builtin_function_embedder = node.m_symbol_table->builtinFunctionEmbedderTable()[builtin_function_id];
+        const auto& compound_data_type = getBuiltinFunctionEmbedder(node)->getReturnDataType();
 
-        const auto& compound_data_type = builtin_function_embedder->getReturnDataType();
         for (auto data_type : compound_data_type.contentTypeList()) {
           flattened_datatype_list.push_back({*data_type, node});
         }
diff --git a/src/language/modules/BuiltinModule.cpp b/src/language/modules/BuiltinModule.cpp
index e4101ee49..98d8f71c6 100644
--- a/src/language/modules/BuiltinModule.cpp
+++ b/src/language/modules/BuiltinModule.cpp
@@ -37,29 +37,8 @@ BuiltinModule::_addBuiltinFunction(const std::string& name,
 
   auto parameter_data_type_list = builtin_function_embedder->getParameterDataTypes();
 
-  std::string mangled_name = [&] {
-    std::ostringstream os;
-    os << name << '(';
-    switch (parameter_data_type_list.size()) {
-    case 0: {
-      break;
-    }
-    case 1: {
-      os << dataTypeName(parameter_data_type_list[0]);
-      break;
-    }
-    default:
-      os << dataTypeName(parameter_data_type_list[0]);
-      for (size_t i = 1; i < parameter_data_type_list.size(); ++i) {
-        os << ',' << dataTypeName(parameter_data_type_list[i]);
-      }
-    }
-    os << ')';
-    return os.str();
-  }();
-
-  auto [i_builtin_function, success] =
-    m_name_builtin_function_map.insert(std::make_pair(mangled_name, builtin_function_embedder));
+  auto [i_builtin_function, success] = m_name_builtin_function_map.insert(
+    std::make_pair(name + ':' + dataTypeName(parameter_data_type_list), builtin_function_embedder));
   if (not success) {
     throw NormalError("builtin-function '" + name + "' cannot be added!\n");
   }
diff --git a/src/language/utils/ASTNodeDataType.cpp b/src/language/utils/ASTNodeDataType.cpp
index 81f3fc81c..3550025dd 100644
--- a/src/language/utils/ASTNodeDataType.cpp
+++ b/src/language/utils/ASTNodeDataType.cpp
@@ -79,19 +79,27 @@ dataTypeName(const ASTNodeDataType& data_type)
     name = "R^" + std::to_string(data_type.nbRows()) + "x" + std::to_string(data_type.nbColumns());
     break;
   case ASTNodeDataType::tuple_t:
-    name = "tuple(" + dataTypeName(data_type.contentType()) + ')';
+    name = "(" + dataTypeName(data_type.contentType()) + "...)";
     break;
   case ASTNodeDataType::list_t: {
     std::ostringstream data_type_name_list;
     const auto& data_type_list = data_type.contentTypeList();
     if (data_type_list.size() > 0) {
-      data_type_name_list << dataTypeName(*data_type_list[0]);
+      if (*data_type_list[0] == ASTNodeDataType::list_t) {
+        data_type_name_list << '(' << dataTypeName(*data_type_list[0]) << ')';
+      } else {
+        data_type_name_list << dataTypeName(*data_type_list[0]);
+      }
       for (size_t i = 1; i < data_type_list.size(); ++i) {
-        data_type_name_list << '*' << dataTypeName(*data_type_list[i]);
+        if (*data_type_list[i] == ASTNodeDataType::list_t) {
+          data_type_name_list << "*(" << dataTypeName(*data_type_list[i]) << ')';
+        } else {
+          data_type_name_list << '*' << dataTypeName(*data_type_list[i]);
+        }
       }
-      name = "list(" + data_type_name_list.str() + ")";
+      name = data_type_name_list.str();
     } else {
-      name = "list(void)";
+      name = "void";
     }
     break;
   }
@@ -99,7 +107,7 @@ dataTypeName(const ASTNodeDataType& data_type)
     name = "string";
     break;
   case ASTNodeDataType::typename_t:
-    name = std::string("typename(") + dataTypeName(data_type.contentType()) + ")";
+    name = dataTypeName(data_type.contentType());
     break;
   case ASTNodeDataType::type_name_id_t:
     name = "type_name_id";
@@ -129,11 +137,10 @@ dataTypeName(const std::vector<ASTNodeDataType>& data_type_vector)
     return dataTypeName(data_type_vector[0]);
   } else {
     std::ostringstream os;
-    os << '(' << dataTypeName(data_type_vector[0]);
+    os << dataTypeName(data_type_vector[0]);
     for (size_t i = 1; i < data_type_vector.size(); ++i) {
-      os << ',' << dataTypeName(data_type_vector[i]);
+      os << '*' << dataTypeName(data_type_vector[i]);
     }
-    os << ')';
     return os.str();
   }
 }
diff --git a/src/language/utils/BuiltinFunctionEmbedderUtils.cpp b/src/language/utils/BuiltinFunctionEmbedderUtils.cpp
index b9fad0864..9899fee3e 100644
--- a/src/language/utils/BuiltinFunctionEmbedderUtils.cpp
+++ b/src/language/utils/BuiltinFunctionEmbedderUtils.cpp
@@ -6,18 +6,6 @@
 #include <language/utils/ParseError.hpp>
 #include <language/utils/SymbolTable.hpp>
 
-void
-flattenDataTypes(const ASTNodeDataType& data_type, std::vector<ASTNodeDataType>& arg_type_list)
-{
-  if ((data_type == ASTNodeDataType::list_t) and (*data_type.contentTypeList()[0] == ASTNodeDataType::typename_t)) {
-    for (auto data_type : data_type.contentTypeList()) {
-      arg_type_list.push_back(data_type->contentType());
-    }
-  } else {
-    arg_type_list.push_back(data_type);
-  }
-}
-
 std::shared_ptr<IBuiltinFunctionEmbedder>
 getBuiltinFunctionEmbedder(ASTNode& n)
 {
@@ -26,29 +14,69 @@ getBuiltinFunctionEmbedder(ASTNode& n)
 
   auto& args_node = *n.children[1];
 
+  auto get_argument_value_type = [](ASTNode& argument_node, std::vector<ASTNodeDataType>& arg_type_list) -> void {
+    if (argument_node.is_type<language::function_evaluation>()) {
+      ASTNode& function_node = *argument_node.children[0];
+      switch (function_node.m_data_type) {
+      case ASTNodeDataType::function_t: {
+        auto [i_function_symbol, found] =
+          argument_node.m_symbol_table->find(function_node.string(), argument_node.begin());
+        Assert(found);
+        Assert(i_function_symbol->attributes().dataType() == ASTNodeDataType::function_t);
+
+        uint64_t function_id = std::get<uint64_t>(i_function_symbol->attributes().value());
+
+        FunctionDescriptor& function_descriptor = argument_node.m_symbol_table->functionTable()[function_id];
+        ASTNode& function_image_domain          = *function_descriptor.domainMappingNode().children[1];
+
+        if (function_image_domain.children.size() > 0) {
+          for (size_t i = 0; i < function_image_domain.children.size(); ++i) {
+            arg_type_list.push_back(function_image_domain.children[i]->m_data_type);
+          }
+        } else {
+          arg_type_list.push_back(function_image_domain.m_data_type);
+        }
+        break;
+      }
+      case ASTNodeDataType::builtin_function_t: {
+        std::shared_ptr builtin_function = getBuiltinFunctionEmbedder(argument_node);
+        arg_type_list.push_back(builtin_function->getReturnDataType());
+        break;
+      }
+      default: {
+        throw UnexpectedError("unexpected function type");
+      }
+      }
+    } else {
+      arg_type_list.push_back(argument_node.m_data_type);
+    }
+  };
+
   std::vector<ASTNodeDataType> arg_type_list;
   if (args_node.is_type<language::function_argument_list>()) {
     for (auto& arg : args_node.children) {
-      flattenDataTypes(arg->m_data_type, arg_type_list);
+      get_argument_value_type(*arg, arg_type_list);
     }
   } else {
-    flattenDataTypes(args_node.m_data_type, arg_type_list);
+    get_argument_value_type(args_node, arg_type_list);
   }
 
-  std::ostringstream mangled_name;
-  mangled_name << builtin_function_name;
-  if (size(arg_type_list) == 0) {
-    mangled_name << "()";
-  } else if (size(arg_type_list) == 1) {
-    mangled_name << '(' << dataTypeName(arg_type_list[0]) << ')';
-  } else {
-    mangled_name << dataTypeName(arg_type_list);
+  // replace typenames by their values
+  for (size_t i = 0; i < arg_type_list.size(); ++i) {
+    if (arg_type_list[i] == ASTNodeDataType::typename_t) {
+      arg_type_list[i] = arg_type_list[i].contentType();
+    }
   }
 
+  std::string mangled_name = builtin_function_name + ':' + dataTypeName(args_node.m_data_type);
+
   std::vector builtin_function_candidate_list =
     symbol_table.getBuiltinFunctionSymbolList(builtin_function_name, n.begin());
 
   auto is_castable_to_vector = [](const ASTNodeDataType& arg_type, const ASTNodeDataType& target_type) {
+    if (isNaturalConversion(arg_type, target_type)) {
+      return true;
+    }
     bool is_castable = true;
     if (target_type.dimension() > 1) {
       switch (arg_type) {
@@ -76,6 +104,10 @@ getBuiltinFunctionEmbedder(ASTNode& n)
   };
 
   auto is_castable_to_matrix = [](const ASTNodeDataType& arg_type, const ASTNodeDataType& target_type) {
+    if (isNaturalConversion(arg_type, target_type)) {
+      return true;
+    }
+
     bool is_castable = true;
     if (target_type.nbRows() > 1) {
       switch (arg_type) {
@@ -109,55 +141,67 @@ getBuiltinFunctionEmbedder(ASTNode& n)
     auto& builtin_function_embedder_table     = n.m_symbol_table->builtinFunctionEmbedderTable();
     std::shared_ptr builtin_function_embedder = builtin_function_embedder_table[builtin_function_id];
 
+    bool is_castable = true;
+
     if (builtin_function_embedder->numberOfParameters() == arg_type_list.size()) {
       std::vector<ASTNodeDataType> builtin_function_parameter_type_list =
         builtin_function_embedder->getParameterDataTypes();
-      bool is_castable = true;
       for (size_t i_arg = 0; i_arg < arg_type_list.size(); ++i_arg) {
         const ASTNodeDataType& target_type = builtin_function_parameter_type_list[i_arg];
-        std::vector<ASTNodeDataType> sub_arg_type_list;
-        if (arg_type_list[i_arg] == ASTNodeDataType::list_t) {
-          for (auto& arg_type : arg_type_list[i_arg].contentTypeList()) {
-            sub_arg_type_list.push_back(*arg_type);
+        const ASTNodeDataType& arg_type    = arg_type_list[i_arg];
+
+        if (not isNaturalConversion(arg_type, target_type)) {
+          switch (target_type) {
+          case ASTNodeDataType::vector_t: {
+            is_castable &= is_castable_to_vector(arg_type, target_type);
+            break;
           }
-        } else {
-          sub_arg_type_list.push_back(arg_type_list[i_arg]);
-        }
-        for (auto arg_type : sub_arg_type_list) {
-          if (not isNaturalConversion(arg_type, target_type)) {
-            switch (target_type) {
-            case ASTNodeDataType::vector_t: {
-              is_castable &= is_castable_to_vector(arg_type, target_type);
-              break;
-            }
-            case ASTNodeDataType::matrix_t: {
-              is_castable &= is_castable_to_matrix(arg_type, target_type);
-              break;
-            }
-            case ASTNodeDataType::tuple_t: {
-              ASTNodeDataType tuple_content_type = target_type.contentType();
-              if (not isNaturalConversion(arg_type, tuple_content_type)) {
-                switch (tuple_content_type) {
-                case ASTNodeDataType::vector_t: {
+          case ASTNodeDataType::matrix_t: {
+            is_castable &= is_castable_to_matrix(arg_type, target_type);
+            break;
+          }
+          case ASTNodeDataType::tuple_t: {
+            ASTNodeDataType tuple_content_type = target_type.contentType();
+            if (not isNaturalConversion(arg_type, tuple_content_type)) {
+              switch (tuple_content_type) {
+              case ASTNodeDataType::vector_t: {
+                if (arg_type == ASTNodeDataType::list_t) {
+                  for (auto element_type : arg_type.contentTypeList()) {
+                    is_castable &= is_castable_to_vector(*element_type, tuple_content_type);
+                  }
+                } else {
                   is_castable &= is_castable_to_vector(arg_type, tuple_content_type);
-                  break;
                 }
-                case ASTNodeDataType::matrix_t: {
+                break;
+              }
+              case ASTNodeDataType::matrix_t: {
+                if (arg_type == ASTNodeDataType::list_t) {
+                  for (auto element_type : arg_type.contentTypeList()) {
+                    is_castable &= is_castable_to_matrix(*element_type, tuple_content_type);
+                  }
+                } else {
                   is_castable &= is_castable_to_matrix(arg_type, tuple_content_type);
-                  break;
                 }
-                default:
+                break;
+              }
+              default:
+                if (arg_type == ASTNodeDataType::list_t) {
+                  for (auto element_type : arg_type.contentTypeList()) {
+                    is_castable &= isNaturalConversion(*element_type, tuple_content_type);
+                  }
+                } else {
                   is_castable &= false;
                 }
               }
-              break;
-            }
-            default:
-              is_castable &= false;
             }
+            break;
+          }
+          default:
+            is_castable &= false;
           }
         }
       }
+
       if (is_castable) {
         callable_id_list.push_back(builtin_function_id);
       }
@@ -169,8 +213,8 @@ getBuiltinFunctionEmbedder(ASTNode& n)
     case 0: {
       std::ostringstream error_msg;
       error_msg << "no matching function to call " << rang::fgB::red << builtin_function_name << rang::style::reset
-                << rang::style::bold << ": " << rang::fgB::yellow << dataTypeName(arg_type_list) << rang::style::reset
-                << rang::style::bold << "\nnote: candidates are";
+                << rang::style::bold << ": " << rang::fgB::yellow << dataTypeName(args_node.m_data_type)
+                << rang::style::reset << rang::style::bold << "\nnote: candidates are";
 
       for (auto candidate : builtin_function_candidate_list) {
         uint64_t builtin_function_id = std::get<uint64_t>(candidate.attributes().value());
@@ -190,7 +234,9 @@ getBuiltinFunctionEmbedder(ASTNode& n)
     }
     default: {
       std::ostringstream error_msg;
-      error_msg << "ambiguous function to call " << mangled_name.str() << "\nnote: candidates are";
+      error_msg << "ambiguous function call " << rang::fgB::red << builtin_function_name << rang::style::reset
+                << rang::style::bold << ": " << rang::fgB::yellow << dataTypeName(args_node.m_data_type)
+                << rang::style::reset << rang::style::bold << "\nnote: candidates are";
 
       auto& builtin_function_embedder_table = n.m_symbol_table->builtinFunctionEmbedderTable();
       for (auto callable_id : callable_id_list) {
diff --git a/src/language/utils/SymbolTable.hpp b/src/language/utils/SymbolTable.hpp
index 3526e2f69..732199456 100644
--- a/src/language/utils/SymbolTable.hpp
+++ b/src/language/utils/SymbolTable.hpp
@@ -290,7 +290,7 @@ class SymbolTable
 
       // Symbol must be defined before the call
       std::string_view stored_symbol_name = i_stored_symbol.name();
-      if ((stored_symbol_name.size() > symbol.size()) and (stored_symbol_name[symbol.size()] == '(')) {
+      if ((stored_symbol_name.size() > symbol.size()) and (stored_symbol_name[symbol.size()] == ':')) {
         if (stored_symbol_name.substr(0, symbol.size()) == symbol) {
           builtin_function_symbol_list.push_back(i_stored_symbol);
         }
@@ -314,7 +314,7 @@ class SymbolTable
       // Symbol must be defined before the call
       std::string_view stored_symbol_name = i_stored_symbol.name();
       if ((stored_symbol_name.size() == symbol.size()) or
-          (stored_symbol_name.size() > symbol.size() and (stored_symbol_name[symbol.size()] == '('))) {
+          (stored_symbol_name.size() > symbol.size() and (stored_symbol_name[symbol.size()] == ':'))) {
         if (stored_symbol_name.substr(0, symbol.size()) == symbol) {
           return true;
         }
@@ -359,7 +359,7 @@ class SymbolTable
       if (stored_symbol_name.size() == symbol_name.size()) {
         if (stored_symbol_name == symbol_name) {
           return std::make_pair(i_stored_symbol, false);
-        } else if (stored_symbol_name.size() > symbol_name.size() and (stored_symbol_name[symbol_name.size()] == '(')) {
+        } else if (stored_symbol_name.size() > symbol_name.size() and (stored_symbol_name[symbol_name.size()] == ':')) {
           if (stored_symbol_name.substr(0, symbol_name.size()) == symbol_name) {
             return std::make_pair(i_stored_symbol, false);
           }
diff --git a/tests/test_ASTModulesImporter.cpp b/tests/test_ASTModulesImporter.cpp
index 3dfb86d03..4be8e087d 100644
--- a/tests/test_ASTModulesImporter.cpp
+++ b/tests/test_ASTModulesImporter.cpp
@@ -111,7 +111,7 @@ import math;
       TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"};
       auto ast = ASTBuilder::build(input);
 
-      ast->m_symbol_table->add("sin(R)", ast->begin());
+      ast->m_symbol_table->add("sin:R", ast->begin());
 
       REQUIRE_THROWS_AS(ASTModulesImporter{*ast}, ParseError);
     }
diff --git a/tests/test_ASTNodeAffectationExpressionBuilder.cpp b/tests/test_ASTNodeAffectationExpressionBuilder.cpp
index 85c443ebc..81ff4f95c 100644
--- a/tests/test_ASTNodeAffectationExpressionBuilder.cpp
+++ b/tests/test_ASTNodeAffectationExpressionBuilder.cpp
@@ -1609,7 +1609,7 @@ let s : string, s="foo"; s*=2;
  let s :(R), s=(1,2,3); s *= 4;
 )";
 
-      std::string error_message = "undefined affectation type: tuple(R) *= Z";
+      std::string error_message = "undefined affectation type: (R...) *= Z";
 
       CHECK_AST_THROWS_WITH(data, error_message);
     }
@@ -1620,7 +1620,7 @@ let s : string, s="foo"; s*=2;
  let s : (builtin_t), s =(a,b); s *= b;
 )";
 
-      std::string error_message = "undefined affectation type: tuple(builtin_t) *= builtin_t";
+      std::string error_message = "undefined affectation type: (builtin_t...) *= builtin_t";
 
       CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message);
     }
diff --git a/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp b/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp
index 84c0fa016..d7cd62afe 100644
--- a/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp
+++ b/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp
@@ -1674,7 +1674,7 @@ fidToR(f);
 BtoR(true, false);
 )";
 
-      const std::string error_msg = "no matching function to call BtoR: (B,B)\n"
+      const std::string error_msg = "no matching function to call BtoR: B*B\n"
                                     "note: candidates are\n"
                                     " BtoR: B -> R";
 
@@ -1689,7 +1689,7 @@ RRtoB(3);
 
       const std::string error_msg = "no matching function to call RRtoB: Z\n"
                                     "note: candidates are\n"
-                                    " RRtoB: (R,R) -> B";
+                                    " RRtoB: R*R -> B";
 
       CHECK_AST_THROWS_AT_BUILD_WITH(data, error_msg);
     }
diff --git a/tests/test_ASTNodeDataType.cpp b/tests/test_ASTNodeDataType.cpp
index 1f2b2a2bf..9316c27db 100644
--- a/tests/test_ASTNodeDataType.cpp
+++ b/tests/test_ASTNodeDataType.cpp
@@ -44,17 +44,17 @@ TEST_CASE("ASTNodeDataType", "[language]")
     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(ASTNodeDataType::build<ASTNodeDataType::typename_t>(double_dt)) == "R");
     REQUIRE(dataTypeName(void_dt) == "void");
     REQUIRE(dataTypeName(function_dt) == "function");
     REQUIRE(dataTypeName(builtin_function_dt) == "builtin_function");
-    REQUIRE(dataTypeName(list_dt) == "list(R*Z)");
-    REQUIRE(dataTypeName(empty_list_dt) == "list(void)");
-    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(list_dt) == "R*Z");
+    REQUIRE(dataTypeName(empty_list_dt) == "void");
+    REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt)) == "(B...)");
+    REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt)) == "(N...)");
+    REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt)) == "(Z...)");
+    REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt)) == "(R...)");
+    REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt)) == "(Z...)");
 
     REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>()) == "type_name_id");
 
@@ -74,7 +74,7 @@ TEST_CASE("ASTNodeDataType", "[language]")
 
     REQUIRE(dataTypeName(std::vector<ASTNodeDataType>{}) == "void");
     REQUIRE(dataTypeName(std::vector<ASTNodeDataType>{bool_dt}) == "B");
-    REQUIRE(dataTypeName(std::vector<ASTNodeDataType>{bool_dt, unsigned_int_dt}) == "(B,N)");
+    REQUIRE(dataTypeName(std::vector<ASTNodeDataType>{bool_dt, unsigned_int_dt}) == "B*N");
   }
 
   SECTION("promotion")
diff --git a/tests/test_ASTNodeDataTypeBuilder.cpp b/tests/test_ASTNodeDataTypeBuilder.cpp
index b8ce32c92..79e01aef9 100644
--- a/tests/test_ASTNodeDataTypeBuilder.cpp
+++ b/tests/test_ASTNodeDataTypeBuilder.cpp
@@ -279,16 +279,16 @@ let (x,b,n,s) : R*B*N*string;
       std::string_view result = R"(
 (root:void)
  `-(language::var_declaration:void)
-     +-(language::name_list:list(R*B*N*string))
+     +-(language::name_list:R*B*N*string)
      |   +-(language::name:x:R)
      |   +-(language::name:b:B)
      |   +-(language::name:n:N)
      |   `-(language::name:s:string)
-     `-(language::type_expression:typename(list(typename(R)*typename(B)*typename(N)*typename(string))))
-         +-(language::R_set:typename(R))
-         +-(language::B_set:typename(B))
-         +-(language::N_set:typename(N))
-         `-(language::string_type:typename(string))
+     `-(language::type_expression:R*B*N*string)
+         +-(language::R_set:R)
+         +-(language::B_set:B)
+         +-(language::N_set:N)
+         `-(language::string_type:string)
 )";
 
       CHECK_AST(data, result);
@@ -418,11 +418,11 @@ let t : (B), t = (true, false);
         std::string_view result = R"(
 (root:void)
  `-(language::var_declaration:void)
-     +-(language::name:t:tuple(B))
-     +-(language::tuple_type_specifier:typename(tuple(B)))
-     |   `-(language::B_set:typename(B))
-     +-(language::name:t:tuple(B))
-     `-(language::expression_list:list(B*B))
+     +-(language::name:t:(B...))
+     +-(language::tuple_type_specifier:(B...))
+     |   `-(language::B_set:B)
+     +-(language::name:t:(B...))
+     `-(language::expression_list:B*B)
          +-(language::true_kw:B)
          `-(language::false_kw:B)
 )";
@@ -439,11 +439,11 @@ let t : (N), t = (1, 2, 3, 5);
         std::string_view result = R"(
 (root:void)
  `-(language::var_declaration:void)
-     +-(language::name:t:tuple(N))
-     +-(language::tuple_type_specifier:typename(tuple(N)))
-     |   `-(language::N_set:typename(N))
-     +-(language::name:t:tuple(N))
-     `-(language::expression_list:list(Z*Z*Z*Z))
+     +-(language::name:t:(N...))
+     +-(language::tuple_type_specifier:(N...))
+     |   `-(language::N_set:N)
+     +-(language::name:t:(N...))
+     `-(language::expression_list:Z*Z*Z*Z)
          +-(language::integer:1:Z)
          +-(language::integer:2:Z)
          +-(language::integer:3:Z)
@@ -464,15 +464,15 @@ let t : (Z), t = (2, n, true);
 (root:void)
  +-(language::var_declaration:void)
  |   +-(language::name:n:N)
- |   +-(language::N_set:typename(N))
+ |   +-(language::N_set:N)
  |   +-(language::name:n:N)
  |   `-(language::integer:3:Z)
  `-(language::var_declaration:void)
-     +-(language::name:t:tuple(Z))
-     +-(language::tuple_type_specifier:typename(tuple(Z)))
-     |   `-(language::Z_set:typename(Z))
-     +-(language::name:t:tuple(Z))
-     `-(language::expression_list:list(Z*N*B))
+     +-(language::name:t:(Z...))
+     +-(language::tuple_type_specifier:(Z...))
+     |   `-(language::Z_set:Z)
+     +-(language::name:t:(Z...))
+     `-(language::expression_list:Z*N*B)
          +-(language::integer:2:Z)
          +-(language::name:n:N)
          `-(language::true_kw:B)
@@ -490,11 +490,11 @@ let t : (R), t = (2, 3.1, 5);
         std::string_view result = R"(
 (root:void)
  `-(language::var_declaration:void)
-     +-(language::name:t:tuple(R))
-     +-(language::tuple_type_specifier:typename(tuple(R)))
-     |   `-(language::R_set:typename(R))
-     +-(language::name:t:tuple(R))
-     `-(language::expression_list:list(Z*R*Z))
+     +-(language::name:t:(R...))
+     +-(language::tuple_type_specifier:(R...))
+     |   `-(language::R_set:R)
+     +-(language::name:t:(R...))
+     `-(language::expression_list:Z*R*Z)
          +-(language::integer:2:Z)
          +-(language::real:3.1:R)
          `-(language::integer:5:Z)
@@ -515,34 +515,34 @@ let t2 : (R^3), t2 = (0, 0);
 (root:void)
  +-(language::var_declaration:void)
  |   +-(language::name:a:R^2)
- |   +-(language::vector_type:typename(R^2))
- |   |   +-(language::R_set:typename(R))
+ |   +-(language::vector_type:R^2)
+ |   |   +-(language::R_set:R)
  |   |   `-(language::integer:2:Z)
  |   +-(language::name:a:R^2)
- |   `-(language::expression_list:list(Z*R))
+ |   `-(language::expression_list:Z*R)
  |       +-(language::integer:2:Z)
  |       `-(language::real:3.1:R)
  +-(language::var_declaration:void)
- |   +-(language::name:t1:tuple(R^2))
- |   +-(language::tuple_type_specifier:typename(tuple(R^2)))
- |   |   `-(language::vector_type:typename(R^2))
- |   |       +-(language::R_set:typename(R))
+ |   +-(language::name:t1:(R^2...))
+ |   +-(language::tuple_type_specifier:(R^2...))
+ |   |   `-(language::vector_type:R^2)
+ |   |       +-(language::R_set:R)
  |   |       `-(language::integer:2:Z)
- |   +-(language::name:t1:tuple(R^2))
- |   `-(language::expression_list:list(R^2*list(Z*Z)*Z))
+ |   +-(language::name:t1:(R^2...))
+ |   `-(language::expression_list:R^2*(Z*Z)*Z)
  |       +-(language::name:a:R^2)
- |       +-(language::tuple_expression:list(Z*Z))
+ |       +-(language::tuple_expression:Z*Z)
  |       |   +-(language::integer:1:Z)
  |       |   `-(language::integer:2:Z)
  |       `-(language::integer:0:Z)
  `-(language::var_declaration:void)
-     +-(language::name:t2:tuple(R^3))
-     +-(language::tuple_type_specifier:typename(tuple(R^3)))
-     |   `-(language::vector_type:typename(R^3))
-     |       +-(language::R_set:typename(R))
+     +-(language::name:t2:(R^3...))
+     +-(language::tuple_type_specifier:(R^3...))
+     |   `-(language::vector_type:R^3)
+     |       +-(language::R_set:R)
      |       `-(language::integer:3:Z)
-     +-(language::name:t2:tuple(R^3))
-     `-(language::expression_list:list(Z*Z))
+     +-(language::name:t2:(R^3...))
+     `-(language::expression_list:Z*Z)
          +-(language::integer:0:Z)
          `-(language::integer:0:Z)
 )";
@@ -562,42 +562,42 @@ let t2 : (R^3x3), t2 = (0, 0);
 (root:void)
  +-(language::var_declaration:void)
  |   +-(language::name:a:R^2x2)
- |   +-(language::matrix_type:typename(R^2x2))
- |   |   +-(language::R_set:typename(R))
+ |   +-(language::matrix_type:R^2x2)
+ |   |   +-(language::R_set:R)
  |   |   +-(language::integer:2:Z)
  |   |   `-(language::integer:2:Z)
  |   +-(language::name:a:R^2x2)
- |   `-(language::expression_list:list(Z*R*R*Z))
+ |   `-(language::expression_list:Z*R*R*Z)
  |       +-(language::integer:2:Z)
  |       +-(language::real:3.1:R)
  |       +-(language::unary_minus:R)
  |       |   `-(language::real:1.2:R)
  |       `-(language::integer:4:Z)
  +-(language::var_declaration:void)
- |   +-(language::name:t1:tuple(R^2x2))
- |   +-(language::tuple_type_specifier:typename(tuple(R^2x2)))
- |   |   `-(language::matrix_type:typename(R^2x2))
- |   |       +-(language::R_set:typename(R))
+ |   +-(language::name:t1:(R^2x2...))
+ |   +-(language::tuple_type_specifier:(R^2x2...))
+ |   |   `-(language::matrix_type:R^2x2)
+ |   |       +-(language::R_set:R)
  |   |       +-(language::integer:2:Z)
  |   |       `-(language::integer:2:Z)
- |   +-(language::name:t1:tuple(R^2x2))
- |   `-(language::expression_list:list(R^2x2*list(Z*Z*Z*Z)*Z))
+ |   +-(language::name:t1:(R^2x2...))
+ |   `-(language::expression_list:R^2x2*(Z*Z*Z*Z)*Z)
  |       +-(language::name:a:R^2x2)
- |       +-(language::tuple_expression:list(Z*Z*Z*Z))
+ |       +-(language::tuple_expression:Z*Z*Z*Z)
  |       |   +-(language::integer:1:Z)
  |       |   +-(language::integer:2:Z)
  |       |   +-(language::integer:1:Z)
  |       |   `-(language::integer:3:Z)
  |       `-(language::integer:0:Z)
  `-(language::var_declaration:void)
-     +-(language::name:t2:tuple(R^3x3))
-     +-(language::tuple_type_specifier:typename(tuple(R^3x3)))
-     |   `-(language::matrix_type:typename(R^3x3))
-     |       +-(language::R_set:typename(R))
+     +-(language::name:t2:(R^3x3...))
+     +-(language::tuple_type_specifier:(R^3x3...))
+     |   `-(language::matrix_type:R^3x3)
+     |       +-(language::R_set:R)
      |       +-(language::integer:3:Z)
      |       `-(language::integer:3:Z)
-     +-(language::name:t2:tuple(R^3x3))
-     `-(language::expression_list:list(Z*Z))
+     +-(language::name:t2:(R^3x3...))
+     `-(language::expression_list:Z*Z)
          +-(language::integer:0:Z)
          `-(language::integer:0:Z)
 )";
@@ -614,11 +614,11 @@ let t : (string), t = ("foo", "bar");
         std::string_view result = R"(
 (root:void)
  `-(language::var_declaration:void)
-     +-(language::name:t:tuple(string))
-     +-(language::tuple_type_specifier:typename(tuple(string)))
-     |   `-(language::string_type:typename(string))
-     +-(language::name:t:tuple(string))
-     `-(language::expression_list:list(string*string))
+     +-(language::name:t:(string...))
+     +-(language::tuple_type_specifier:(string...))
+     |   `-(language::string_type:string)
+     +-(language::name:t:(string...))
+     `-(language::expression_list:string*string)
          +-(language::literal:"foo":string)
          `-(language::literal:"bar":string)
 )";
@@ -636,11 +636,11 @@ let t : (builtin_t), t= (1,2,3);
         std::string_view result = R"(
 (root:void)
  `-(language::var_declaration:void)
-     +-(language::name:t:tuple(builtin_t))
-     +-(language::tuple_type_specifier:typename(tuple(builtin_t)))
+     +-(language::name:t:(builtin_t...))
+     +-(language::tuple_type_specifier:(builtin_t...))
      |   `-(language::type_name_id:builtin_t)
-     +-(language::name:t:tuple(builtin_t))
-     `-(language::expression_list:list(Z*Z*Z))
+     +-(language::name:t:(builtin_t...))
+     `-(language::expression_list:Z*Z*Z)
          +-(language::integer:1:Z)
          +-(language::integer:2:Z)
          `-(language::integer:3:Z)
@@ -1073,11 +1073,11 @@ x = f(x);
  |   `-(language::name:f:function)
  +-(language::var_declaration:void)
  |   +-(language::name:x:R^2)
- |   +-(language::vector_type:typename(R^2))
- |   |   +-(language::R_set:typename(R))
+ |   +-(language::vector_type:R^2)
+ |   |   +-(language::R_set:R)
  |   |   `-(language::integer:2:Z)
  |   +-(language::name:x:R^2)
- |   `-(language::expression_list:list(Z*Z))
+ |   `-(language::expression_list:Z*Z)
  |       +-(language::integer:1:Z)
  |       `-(language::integer:2:Z)
  `-(language::eq_op:void)
@@ -1106,7 +1106,7 @@ let x : R, x = incr(3);
  |   `-(language::name:incr:function)
  `-(language::var_declaration:void)
      +-(language::name:x:R)
-     +-(language::R_set:typename(R))
+     +-(language::R_set:R)
      +-(language::name:x:R)
      `-(language::function_evaluation:R)
          +-(language::name:incr:function)
@@ -1129,11 +1129,11 @@ let  diff : R, diff = substract(3,2);
  |   `-(language::name:substract:function)
  `-(language::var_declaration:void)
      +-(language::name:diff:R)
-     +-(language::R_set:typename(R))
+     +-(language::R_set:R)
      +-(language::name:diff:R)
      `-(language::function_evaluation:R)
          +-(language::name:substract:function)
-         `-(language::function_argument_list:list(Z*Z))
+         `-(language::function_argument_list:Z*Z)
              +-(language::integer:3:Z)
              `-(language::integer:2:Z)
 )";
@@ -1155,7 +1155,7 @@ let z : Z, z = incr(3);
  |   `-(language::name:incr:function)
  `-(language::var_declaration:void)
      +-(language::name:z:Z)
-     +-(language::Z_set:typename(Z))
+     +-(language::Z_set:Z)
      +-(language::name:z:Z)
      `-(language::function_evaluation:Z)
          +-(language::name:incr:function)
@@ -1178,7 +1178,7 @@ let n : N, n = double(3);
  |   `-(language::name:double:function)
  `-(language::var_declaration:void)
      +-(language::name:n:N)
-     +-(language::N_set:typename(N))
+     +-(language::N_set:N)
      +-(language::name:n:N)
      `-(language::function_evaluation:N)
          +-(language::name:double:function)
@@ -1201,7 +1201,7 @@ let b : B, b = greater_than_2(3);
  |   `-(language::name:greater_than_2:function)
  `-(language::var_declaration:void)
      +-(language::name:b:B)
-     +-(language::B_set:typename(B))
+     +-(language::B_set:B)
      +-(language::name:b:B)
      `-(language::function_evaluation:B)
          +-(language::name:greater_than_2:function)
@@ -1224,11 +1224,11 @@ let s : string, s = cat("foo", "bar");
  |   `-(language::name:cat:function)
  `-(language::var_declaration:void)
      +-(language::name:s:string)
-     +-(language::string_type:typename(string))
+     +-(language::string_type:string)
      +-(language::name:s:string)
      `-(language::function_evaluation:string)
          +-(language::name:cat:function)
-         `-(language::function_argument_list:list(string*string))
+         `-(language::function_argument_list:string*string)
              +-(language::literal:"foo":string)
              `-(language::literal:"bar":string)
 )";
@@ -1248,16 +1248,16 @@ let (x,x2) : R*R, (x,x2) = x_x2(3);
  +-(language::fct_declaration:void)
  |   `-(language::name:x_x2:function)
  `-(language::var_declaration:void)
-     +-(language::name_list:list(R*R))
+     +-(language::name_list:R*R)
      |   +-(language::name:x:R)
      |   `-(language::name:x2:R)
-     +-(language::type_expression:typename(list(typename(R)*typename(R))))
-     |   +-(language::R_set:typename(R))
-     |   `-(language::R_set:typename(R))
-     +-(language::name_list:list(R*R))
+     +-(language::type_expression:R*R)
+     |   +-(language::R_set:R)
+     |   `-(language::R_set:R)
+     +-(language::name_list:R*R)
      |   +-(language::name:x:R)
      |   `-(language::name:x2:R)
-     `-(language::function_evaluation:list(typename(R)*typename(R)))
+     `-(language::function_evaluation:R*R)
          +-(language::name:x_x2:function)
          `-(language::integer:3:Z)
 )";
@@ -1316,7 +1316,7 @@ for (let i : N, i=0; i<3; ++i){
  `-(language::for_statement:void)
      +-(language::var_declaration:void)
      |   +-(language::name:i:N)
-     |   +-(language::N_set:typename(N))
+     |   +-(language::N_set:N)
      |   +-(language::name:i:N)
      |   `-(language::integer:0:Z)
      +-(language::lesser_op:B)
@@ -1342,7 +1342,7 @@ let b:B;
 (root:void)
  `-(language::var_declaration:void)
      +-(language::name:b:B)
-     `-(language::B_set:typename(B))
+     `-(language::B_set:B)
 )";
 
     CHECK_AST(data, result);
@@ -1358,7 +1358,7 @@ let n :N;
 (root:void)
  `-(language::var_declaration:void)
      +-(language::name:n:N)
-     `-(language::N_set:typename(N))
+     `-(language::N_set:N)
 )";
 
     CHECK_AST(data, result);
@@ -1374,7 +1374,7 @@ let z:Z;
 (root:void)
  `-(language::var_declaration:void)
      +-(language::name:z:Z)
-     `-(language::Z_set:typename(Z))
+     `-(language::Z_set:Z)
 )";
 
     CHECK_AST(data, result);
@@ -1390,7 +1390,7 @@ let r:R;
 (root:void)
  `-(language::var_declaration:void)
      +-(language::name:r:R)
-     `-(language::R_set:typename(R))
+     `-(language::R_set:R)
 )";
 
     CHECK_AST(data, result);
@@ -1406,7 +1406,7 @@ let s: string;
 (root:void)
  `-(language::var_declaration:void)
      +-(language::name:s:string)
-     `-(language::string_type:typename(string))
+     `-(language::string_type:string)
 )";
 
     CHECK_AST(data, result);
@@ -1423,7 +1423,7 @@ let t : builtin_t, t= 1;
 (root:void)
  `-(language::var_declaration:void)
      +-(language::name:t:builtin_t)
-     +-(language::type_name_id:typename(builtin_t))
+     +-(language::type_name_id:builtin_t)
      +-(language::name:t:builtin_t)
      `-(language::integer:1:Z)
 )";
@@ -1470,7 +1470,7 @@ a = 1;
 (root:void)
  +-(language::var_declaration:void)
  |   +-(language::name:a:N)
- |   `-(language::N_set:typename(N))
+ |   `-(language::N_set:N)
  `-(language::eq_op:void)
      +-(language::name:a:N)
      `-(language::integer:1:Z)
@@ -1490,7 +1490,7 @@ a *= 1.2;
 (root:void)
  +-(language::var_declaration:void)
  |   +-(language::name:a:N)
- |   +-(language::N_set:typename(N))
+ |   +-(language::N_set:N)
  |   +-(language::name:a:N)
  |   `-(language::integer:1:Z)
  `-(language::multiplyeq_op:void)
@@ -1512,7 +1512,7 @@ a /= 2;
 (root:void)
  +-(language::var_declaration:void)
  |   +-(language::name:a:R)
- |   +-(language::R_set:typename(R))
+ |   +-(language::R_set:R)
  |   +-(language::name:a:R)
  |   `-(language::integer:3:Z)
  `-(language::divideeq_op:void)
@@ -1534,7 +1534,7 @@ a += 2;
 (root:void)
  +-(language::var_declaration:void)
  |   +-(language::name:a:Z)
- |   +-(language::Z_set:typename(Z))
+ |   +-(language::Z_set:Z)
  |   +-(language::name:a:Z)
  |   `-(language::integer:3:Z)
  `-(language::pluseq_op:void)
@@ -1556,7 +1556,7 @@ a -= 2;
 (root:void)
  +-(language::var_declaration:void)
  |   +-(language::name:a:Z)
- |   +-(language::Z_set:typename(Z))
+ |   +-(language::Z_set:Z)
  |   +-(language::name:a:Z)
  |   `-(language::integer:1:Z)
  `-(language::minuseq_op:void)
@@ -1596,7 +1596,7 @@ for (let i:Z, i=0; i<3; i += 1) { i += 2; }
  `-(language::for_statement:void)
      +-(language::var_declaration:void)
      |   +-(language::name:i:Z)
-     |   +-(language::Z_set:typename(Z))
+     |   +-(language::Z_set:Z)
      |   +-(language::name:i:Z)
      |   `-(language::integer:0:Z)
      +-(language::lesser_op:B)
diff --git a/tests/test_ASTNodeNaturalConversionChecker.cpp b/tests/test_ASTNodeNaturalConversionChecker.cpp
index d03541e6c..6852222ae 100644
--- a/tests/test_ASTNodeNaturalConversionChecker.cpp
+++ b/tests/test_ASTNodeNaturalConversionChecker.cpp
@@ -1009,7 +1009,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1,
                                                                                                                  1)}),
-                              "invalid implicit conversion: tuple(N) -> R^1x1");
+                              "invalid implicit conversion: (N...) -> R^1x1");
         }
 
         SECTION("tuple(R) -> R^1x1")
@@ -1018,7 +1018,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1,
                                                                                                                  1)}),
-                              "invalid implicit conversion: tuple(R) -> R^1x1");
+                              "invalid implicit conversion: (R...) -> R^1x1");
         }
 
         SECTION("tuple(R) -> R^2x2")
@@ -1027,7 +1027,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2,
                                                                                                                  2)}),
-                              "invalid implicit conversion: tuple(R) -> R^2x2");
+                              "invalid implicit conversion: (R...) -> R^2x2");
         }
 
         SECTION("tuple(B) -> R^2x2")
@@ -1036,7 +1036,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2,
                                                                                                                  2)}),
-                              "invalid implicit conversion: tuple(B) -> R^2x2");
+                              "invalid implicit conversion: (B...) -> R^2x2");
         }
 
         SECTION("tuple(Z) -> R^3x2")
@@ -1045,7 +1045,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3,
                                                                                                                  3)}),
-                              "invalid implicit conversion: tuple(Z) -> R^3x3");
+                              "invalid implicit conversion: (Z...) -> R^3x3");
         }
 
         SECTION("tuple(R) -> R^3x3")
@@ -1054,7 +1054,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3,
                                                                                                                  3)}),
-                              "invalid implicit conversion: tuple(R) -> R^3x3");
+                              "invalid implicit conversion: (R...) -> R^3x3");
         }
 
         SECTION("tuple(R^1) -> tuple(R^3x3)")
@@ -1419,7 +1419,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
-                              "invalid implicit conversion: tuple(N) -> R^1");
+                              "invalid implicit conversion: (N...) -> R^1");
         }
 
         SECTION("tuple(R) -> R^1")
@@ -1427,7 +1427,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
-                              "invalid implicit conversion: tuple(R) -> R^1");
+                              "invalid implicit conversion: (R...) -> R^1");
         }
 
         SECTION("tuple(R) -> R^2")
@@ -1435,7 +1435,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
-                              "invalid implicit conversion: tuple(R) -> R^2");
+                              "invalid implicit conversion: (R...) -> R^2");
         }
 
         SECTION("tuple(B) -> R^2")
@@ -1443,7 +1443,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
-                              "invalid implicit conversion: tuple(B) -> R^2");
+                              "invalid implicit conversion: (B...) -> R^2");
         }
 
         SECTION("tuple(Z) -> R^3")
@@ -1451,7 +1451,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
-                              "invalid implicit conversion: tuple(Z) -> R^3");
+                              "invalid implicit conversion: (Z...) -> R^3");
         }
 
         SECTION("tuple(R) -> R^3")
@@ -1459,7 +1459,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
           data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
           REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
-                              "invalid implicit conversion: tuple(R) -> R^3");
+                              "invalid implicit conversion: (R...) -> R^3");
         }
 
         SECTION("tuple(R^1x1) -> tuple(R^3)")
@@ -1750,14 +1750,14 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
       {
         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");
+                            "invalid implicit conversion: (N...) -> R");
       }
 
       SECTION("tuple(R) -> R")
       {
         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");
+                            "invalid implicit conversion: (R...) -> R");
       }
     }
 
@@ -1802,14 +1802,14 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
       {
         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");
+                            "invalid implicit conversion: (N...) -> Z");
       }
 
       SECTION("tuple(Z) -> Z")
       {
         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");
+                            "invalid implicit conversion: (Z...) -> Z");
       }
     }
 
@@ -1854,14 +1854,14 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
       {
         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");
+                            "invalid implicit conversion: (Z...) -> N");
       }
 
       SECTION("tuple(N) -> N")
       {
         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");
+                            "invalid implicit conversion: (N...) -> N");
       }
     }
 
@@ -1920,14 +1920,14 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
       {
         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");
+                            "invalid implicit conversion: (Z...) -> B");
       }
 
       SECTION("tuple(B) -> B")
       {
         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");
+                            "invalid implicit conversion: (B...) -> B");
       }
     }
 
diff --git a/tests/test_BuiltinFunctionProcessor.cpp b/tests/test_BuiltinFunctionProcessor.cpp
index 2f9d049eb..dda3becc1 100644
--- a/tests/test_BuiltinFunctionProcessor.cpp
+++ b/tests/test_BuiltinFunctionProcessor.cpp
@@ -81,7 +81,7 @@ TEST_CASE("BuiltinFunctionProcessor", "[language]")
 
     std::set<std::string> tested_function_set;
     {   // sqrt
-      tested_function_set.insert("sqrt(R)");
+      tested_function_set.insert("sqrt:R");
       std::string_view data = R"(
 import math;
 let x:R, x = sqrt(4);
@@ -90,7 +90,7 @@ let x:R, x = sqrt(4);
     }
 
     {   // abs
-      tested_function_set.insert("abs(R)");
+      tested_function_set.insert("abs:R");
       std::string_view data = R"(
 import math;
 let x:R, x = abs(-3.4);
@@ -99,7 +99,7 @@ let x:R, x = abs(-3.4);
     }
 
     {   // sin
-      tested_function_set.insert("sin(R)");
+      tested_function_set.insert("sin:R");
       std::string_view data = R"(
 import math;
 let x:R, x = sin(1.3);
@@ -108,7 +108,7 @@ let x:R, x = sin(1.3);
     }
 
     {   // cos
-      tested_function_set.insert("cos(R)");
+      tested_function_set.insert("cos:R");
       std::string_view data = R"(
 import math;
 let x:R, x = cos(1.3);
@@ -117,7 +117,7 @@ let x:R, x = cos(1.3);
     }
 
     {   // tan
-      tested_function_set.insert("tan(R)");
+      tested_function_set.insert("tan:R");
       std::string_view data = R"(
 import math;
 let x:R, x = tan(1.3);
@@ -126,7 +126,7 @@ let x:R, x = tan(1.3);
     }
 
     {   // asin
-      tested_function_set.insert("asin(R)");
+      tested_function_set.insert("asin:R");
       std::string_view data = R"(
 import math;
 let x:R, x = asin(0.7);
@@ -135,7 +135,7 @@ let x:R, x = asin(0.7);
     }
 
     {   // acos
-      tested_function_set.insert("acos(R)");
+      tested_function_set.insert("acos:R");
       std::string_view data = R"(
 import math;
 let x:R, x = acos(0.7);
@@ -144,7 +144,7 @@ let x:R, x = acos(0.7);
     }
 
     {   // atan
-      tested_function_set.insert("atan(R)");
+      tested_function_set.insert("atan:R");
       std::string_view data = R"(
 import math;
 let x:R, x = atan(0.7);
@@ -153,7 +153,7 @@ let x:R, x = atan(0.7);
     }
 
     {   // atan2
-      tested_function_set.insert("atan2(R,R)");
+      tested_function_set.insert("atan2:R*R");
       std::string_view data = R"(
 import math;
 let x:R, x = atan2(0.7, 0.4);
@@ -162,7 +162,7 @@ let x:R, x = atan2(0.7, 0.4);
     }
 
     {   // sinh
-      tested_function_set.insert("sinh(R)");
+      tested_function_set.insert("sinh:R");
       std::string_view data = R"(
 import math;
 let x:R, x = sinh(0.6);
@@ -171,7 +171,7 @@ let x:R, x = sinh(0.6);
     }
 
     {   // cosh
-      tested_function_set.insert("cosh(R)");
+      tested_function_set.insert("cosh:R");
       std::string_view data = R"(
 import math;
 let x:R, x = cosh(1.7);
@@ -180,7 +180,7 @@ let x:R, x = cosh(1.7);
     }
 
     {   // tanh
-      tested_function_set.insert("tanh(R)");
+      tested_function_set.insert("tanh:R");
       std::string_view data = R"(
 import math;
 let x:R, x = tanh(0.6);
@@ -189,7 +189,7 @@ let x:R, x = tanh(0.6);
     }
 
     {   // asinh
-      tested_function_set.insert("asinh(R)");
+      tested_function_set.insert("asinh:R");
       std::string_view data = R"(
 import math;
 let x:R, x = asinh(0.6);
@@ -198,7 +198,7 @@ let x:R, x = asinh(0.6);
     }
 
     {   // acosh
-      tested_function_set.insert("acosh(R)");
+      tested_function_set.insert("acosh:R");
       std::string_view data = R"(
 import math;
 let x:R, x = acosh(1.7);
@@ -207,7 +207,7 @@ let x:R, x = acosh(1.7);
     }
 
     {   // tanh
-      tested_function_set.insert("atanh(R)");
+      tested_function_set.insert("atanh:R");
       std::string_view data = R"(
 import math;
 let x:R, x = atanh(0.6);
@@ -216,7 +216,7 @@ let x:R, x = atanh(0.6);
     }
 
     {   // exp
-      tested_function_set.insert("exp(R)");
+      tested_function_set.insert("exp:R");
       std::string_view data = R"(
 import math;
 let x:R, x = exp(1.7);
@@ -225,7 +225,7 @@ let x:R, x = exp(1.7);
     }
 
     {   // log
-      tested_function_set.insert("log(R)");
+      tested_function_set.insert("log:R");
       std::string_view data = R"(
 import math;
 let x:R, x = log(1.6);
@@ -234,7 +234,7 @@ let x:R, x = log(1.6);
     }
 
     {   // pow
-      tested_function_set.insert("pow(R,R)");
+      tested_function_set.insert("pow:R*R");
       std::string_view data = R"(
 import math;
 let x:R, x = pow(1.6, 2.3);
@@ -243,7 +243,7 @@ let x:R, x = pow(1.6, 2.3);
     }
 
     {   // ceil
-      tested_function_set.insert("ceil(R)");
+      tested_function_set.insert("ceil:R");
       std::string_view data = R"(
 import math;
 let z:Z, z = ceil(-1.2);
@@ -252,7 +252,7 @@ let z:Z, z = ceil(-1.2);
     }
 
     {   // floor
-      tested_function_set.insert("floor(R)");
+      tested_function_set.insert("floor:R");
       std::string_view data = R"(
 import math;
 let z:Z, z = floor(-1.2);
@@ -261,7 +261,7 @@ let z:Z, z = floor(-1.2);
     }
 
     {   // trunc
-      tested_function_set.insert("trunc(R)");
+      tested_function_set.insert("trunc:R");
       std::string_view data = R"(
 import math;
 let z:Z, z = trunc(-0.2) + trunc(0.7);
@@ -270,7 +270,7 @@ let z:Z, z = trunc(-0.2) + trunc(0.7);
     }
 
     {   // round
-      tested_function_set.insert("round(R)");
+      tested_function_set.insert("round:R");
       std::string_view data = R"(
 import math;
 let z:Z, z = round(-1.2);
diff --git a/tests/test_BuiltinFunctionRegister.hpp b/tests/test_BuiltinFunctionRegister.hpp
index 8788d04e4..e062fcd92 100644
--- a/tests/test_BuiltinFunctionRegister.hpp
+++ b/tests/test_BuiltinFunctionRegister.hpp
@@ -3,6 +3,7 @@
 
 #include <language/utils/ASTNodeDataTypeTraits.hpp>
 #include <language/utils/BuiltinFunctionEmbedder.hpp>
+#include <language/utils/ParseError.hpp>
 #include <language/utils/TypeDescriptor.hpp>
 #include <utils/Exceptions.hpp>
 
@@ -22,141 +23,140 @@ class test_BuiltinFunctionRegister
   _populateNameBuiltinFunctionMap()
   {
     m_name_builtin_function_map.insert(
-      std::make_pair("runtimeError()", std::make_shared<BuiltinFunctionEmbedder<void(void)>>(
-                                         [](void) -> void { throw NormalError("runtime error"); })));
+      std::make_pair("runtimeError:void", std::make_shared<BuiltinFunctionEmbedder<void(void)>>(
+                                            [](void) -> void { throw NormalError("runtime error"); })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("RtoR(R)", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                  [](double x) -> double { return x + 1; })));
+      std::make_pair("RtoR:R", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                 [](double x) -> double { return x + 1; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("ZtoR(Z)", std::make_shared<BuiltinFunctionEmbedder<double(int64_t)>>(
-                                  [](int64_t z) -> double { return 0.5 * z; })));
+      std::make_pair("ZtoR:Z", std::make_shared<BuiltinFunctionEmbedder<double(int64_t)>>(
+                                 [](int64_t z) -> double { return 0.5 * z; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("NtoR(N)", std::make_shared<BuiltinFunctionEmbedder<double(uint64_t)>>(
-                                  [](uint64_t n) -> double { return 0.5 * n; })));
+      std::make_pair("NtoR:N", std::make_shared<BuiltinFunctionEmbedder<double(uint64_t)>>(
+                                 [](uint64_t n) -> double { return 0.5 * n; })));
 
-    m_name_builtin_function_map.insert(
-      std::make_pair("BtoR(B)",
-                     std::make_shared<BuiltinFunctionEmbedder<double(bool)>>([](bool b) -> double { return b; })));
+    m_name_builtin_function_map.insert(std::make_pair("BtoR:B", std::make_shared<BuiltinFunctionEmbedder<double(bool)>>(
+                                                                  [](bool b) -> double { return b; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("RRtoB(R,R)", std::make_shared<BuiltinFunctionEmbedder<bool(double, double)>>(
-                                     [](double x, double y) -> bool { return x > y; })));
+      std::make_pair("RRtoB:R*R", std::make_shared<BuiltinFunctionEmbedder<bool(double, double)>>(
+                                    [](double x, double y) -> bool { return x > y; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("StoB(string)", std::make_shared<BuiltinFunctionEmbedder<bool(std::string)>>(
-                                       [](const std::string& s) -> bool { return s.size() > 0; })));
+      std::make_pair("StoB:string", std::make_shared<BuiltinFunctionEmbedder<bool(std::string)>>(
+                                      [](const std::string& s) -> bool { return s.size() > 0; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("RtoR1(R)", std::make_shared<BuiltinFunctionEmbedder<TinyVector<1>(double)>>(
-                                   [](double r) -> TinyVector<1> { return {r}; })));
+      std::make_pair("RtoR1:R", std::make_shared<BuiltinFunctionEmbedder<TinyVector<1>(double)>>(
+                                  [](double r) -> TinyVector<1> { return {r}; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("R1toR(R^1)", std::make_shared<BuiltinFunctionEmbedder<double(TinyVector<1>)>>(
-                                     [](TinyVector<1> x) -> double { return x[0]; })));
+      std::make_pair("R1toR:R^1", std::make_shared<BuiltinFunctionEmbedder<double(TinyVector<1>)>>(
+                                    [](TinyVector<1> x) -> double { return x[0]; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("R2toR(R^2)", std::make_shared<BuiltinFunctionEmbedder<double(TinyVector<2>)>>(
-                                     [](TinyVector<2> x) -> double { return x[0] + x[1]; })));
+      std::make_pair("R2toR:R^2", std::make_shared<BuiltinFunctionEmbedder<double(TinyVector<2>)>>(
+                                    [](TinyVector<2> x) -> double { return x[0] + x[1]; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("R3toR(R^3)", std::make_shared<BuiltinFunctionEmbedder<double(const TinyVector<3>&)>>(
-                                     [](const TinyVector<3>& x) -> double { return x[0] + x[1] + x[2]; })));
+      std::make_pair("R3toR:R^3", std::make_shared<BuiltinFunctionEmbedder<double(const TinyVector<3>&)>>(
+                                    [](const TinyVector<3>& x) -> double { return x[0] + x[1] + x[2]; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("R3R2toR(R^3,R^2)",
+      std::make_pair("R3R2toR:R^3,R^2",
                      std::make_shared<BuiltinFunctionEmbedder<double(TinyVector<3>, TinyVector<2>)>>(
                        [](TinyVector<3> x, TinyVector<2> y) -> double { return x[0] * y[1] + (y[0] - x[2]) * x[1]; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("RtoR11(R)", std::make_shared<BuiltinFunctionEmbedder<TinyMatrix<1>(double)>>(
-                                    [](double r) -> TinyMatrix<1> { return {r}; })));
+      std::make_pair("RtoR11:R", std::make_shared<BuiltinFunctionEmbedder<TinyMatrix<1>(double)>>(
+                                   [](double r) -> TinyMatrix<1> { return {r}; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("R11toR(R^1x1)", std::make_shared<BuiltinFunctionEmbedder<double(TinyMatrix<1>)>>(
-                                        [](TinyMatrix<1> x) -> double { return x(0, 0); })));
+      std::make_pair("R11toR:R^1x1", std::make_shared<BuiltinFunctionEmbedder<double(TinyMatrix<1>)>>(
+                                       [](TinyMatrix<1> x) -> double { return x(0, 0); })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("R22toR(R^2x2)",
+      std::make_pair("R22toR:R^2x2",
                      std::make_shared<BuiltinFunctionEmbedder<double(TinyMatrix<2>)>>(
                        [](TinyMatrix<2> x) -> double { return x(0, 0) + x(0, 1) + x(1, 0) + x(1, 1); })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("R33toR(R^3x3)", std::make_shared<BuiltinFunctionEmbedder<double(const TinyMatrix<3>&)>>(
-                                        [](const TinyMatrix<3>& x) -> double { return x(0, 0) + x(1, 1) + x(2, 2); })));
+      std::make_pair("R33toR:R^3x3", std::make_shared<BuiltinFunctionEmbedder<double(const TinyMatrix<3>&)>>(
+                                       [](const TinyMatrix<3>& x) -> double { return x(0, 0) + x(1, 1) + x(2, 2); })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("R33R22toR(R^3x3,R^2x2)",
+      std::make_pair("R33R22toR:R^3x3*R^2x2",
                      std::make_shared<BuiltinFunctionEmbedder<double(TinyMatrix<3>, TinyMatrix<2>)>>(
                        [](TinyMatrix<3> x, TinyMatrix<2> y) -> double {
                          return (x(0, 0) + x(1, 1) + x(2, 2)) * (y(0, 0) + y(0, 1) + y(1, 0) + y(1, 1));
                        })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("fidToR(function)", std::make_shared<BuiltinFunctionEmbedder<double(const FunctionSymbolId&)>>(
-                                           [](const FunctionSymbolId&) -> double { return 0; })));
+      std::make_pair("fidToR:function", std::make_shared<BuiltinFunctionEmbedder<double(const FunctionSymbolId&)>>(
+                                          [](const FunctionSymbolId&) -> double { return 0; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("builtinToBuiltin(builtin_t)",
+      std::make_pair("builtinToBuiltin:builtin_t",
                      std::make_shared<
                        BuiltinFunctionEmbedder<std::shared_ptr<const double>(std::shared_ptr<const double>)>>(
                        [](std::shared_ptr<const double> x) -> std::shared_ptr<const double> { return x; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("tuple_BtoR(tuple(B))", std::make_shared<BuiltinFunctionEmbedder<double(std::vector<bool>)>>(
-                                               [](const std::vector<bool>&) -> double { return 0.5; })));
+      std::make_pair("tuple_BtoR:(B...)", std::make_shared<BuiltinFunctionEmbedder<double(std::vector<bool>)>>(
+                                            [](const std::vector<bool>&) -> double { return 0.5; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("tuple_NtoR(tuple(N))", std::make_shared<BuiltinFunctionEmbedder<double(std::vector<uint64_t>)>>(
-                                               [](const std::vector<uint64_t>&) -> double { return 0.5; })));
+      std::make_pair("tuple_NtoR:(N...)", std::make_shared<BuiltinFunctionEmbedder<double(std::vector<uint64_t>)>>(
+                                            [](const std::vector<uint64_t>&) -> double { return 0.5; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("tuple_ZtoR(tuple(Z))", std::make_shared<BuiltinFunctionEmbedder<double(std::vector<int64_t>)>>(
-                                               [](const std::vector<int64_t>&) -> double { return 0.5; })));
+      std::make_pair("tuple_ZtoR:(Z...)", std::make_shared<BuiltinFunctionEmbedder<double(std::vector<int64_t>)>>(
+                                            [](const std::vector<int64_t>&) -> double { return 0.5; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("tuple_RtoB(tuple(R))", std::make_shared<BuiltinFunctionEmbedder<bool(std::vector<double>)>>(
-                                               [](const std::vector<double>&) -> bool { return false; })));
+      std::make_pair("tuple_RtoB:(R...)", std::make_shared<BuiltinFunctionEmbedder<bool(std::vector<double>)>>(
+                                            [](const std::vector<double>&) -> bool { return false; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("tuple_stringtoB(tuple(string))",
+      std::make_pair("tuple_stringtoB:(string...)",
                      std::make_shared<BuiltinFunctionEmbedder<bool(std::vector<std::string>)>>(
                        [](const std::vector<std::string>&) -> bool { return true; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("tuple_builtinToB(tuple(builtin_t))",
+      std::make_pair("tuple_builtinToB:(builtin_t...)",
                      std::make_shared<BuiltinFunctionEmbedder<bool(std::vector<std::shared_ptr<const double>>)>>(
                        [](const std::vector<std::shared_ptr<const double>>&) -> bool { return true; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("tuple_R1ToR(tuple(R^1))",
+      std::make_pair("tuple_R1ToR:(R^1...)",
                      std::make_shared<BuiltinFunctionEmbedder<double(const std::vector<TinyVector<1>>&)>>(
                        [](const std::vector<TinyVector<1>>&) -> double { return 1; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("tuple_R2ToR(tuple(R^2))",
+      std::make_pair("tuple_R2ToR:(R^2...)",
                      std::make_shared<BuiltinFunctionEmbedder<double(const std::vector<TinyVector<2>>&)>>(
                        [](const std::vector<TinyVector<2>>&) -> double { return 1; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("tuple_R3ToR(tuple(R^3))",
+      std::make_pair("tuple_R3ToR:(R^3...)",
                      std::make_shared<BuiltinFunctionEmbedder<double(const std::vector<TinyVector<3>>)>>(
                        [](const std::vector<TinyVector<3>>&) -> double { return 0; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("tuple_R11ToR(tuple(R^1x1))",
+      std::make_pair("tuple_R11ToR:(R^1x1...)",
                      std::make_shared<BuiltinFunctionEmbedder<double(const std::vector<TinyMatrix<1>>&)>>(
                        [](const std::vector<TinyMatrix<1>>&) -> double { return 1; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("tuple_R22ToR(tuple(R^2x2))",
+      std::make_pair("tuple_R22ToR:(R^2x2...)",
                      std::make_shared<BuiltinFunctionEmbedder<double(const std::vector<TinyMatrix<2>>&)>>(
                        [](const std::vector<TinyMatrix<2>>&) -> double { return 1; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("tuple_R33ToR(tuple(R^3x3))",
+      std::make_pair("tuple_R33ToR:(R^3x3...)",
                      std::make_shared<BuiltinFunctionEmbedder<double(const std::vector<TinyMatrix<3>>)>>(
                        [](const std::vector<TinyMatrix<3>>&) -> double { return 0; })));
   }
diff --git a/tests/test_MathModule.cpp b/tests/test_MathModule.cpp
index 92e648538..e899190bf 100644
--- a/tests/test_MathModule.cpp
+++ b/tests/test_MathModule.cpp
@@ -23,7 +23,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("sqrt")
     {
-      auto i_function = name_builtin_function.find("sqrt(R)");
+      auto i_function = name_builtin_function.find("sqrt:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -35,7 +35,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("abs")
     {
-      auto i_function = name_builtin_function.find("abs(R)");
+      auto i_function = name_builtin_function.find("abs:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -62,7 +62,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("sin")
     {
-      auto i_function = name_builtin_function.find("sin(R)");
+      auto i_function = name_builtin_function.find("sin:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -74,7 +74,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("cos")
     {
-      auto i_function = name_builtin_function.find("cos(R)");
+      auto i_function = name_builtin_function.find("cos:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -86,7 +86,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("tan")
     {
-      auto i_function = name_builtin_function.find("tan(R)");
+      auto i_function = name_builtin_function.find("tan:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -98,7 +98,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("asin")
     {
-      auto i_function = name_builtin_function.find("asin(R)");
+      auto i_function = name_builtin_function.find("asin:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -110,7 +110,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("acos")
     {
-      auto i_function = name_builtin_function.find("acos(R)");
+      auto i_function = name_builtin_function.find("acos:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -122,7 +122,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("atan")
     {
-      auto i_function = name_builtin_function.find("atan(R)");
+      auto i_function = name_builtin_function.find("atan:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -137,7 +137,7 @@ TEST_CASE("MathModule", "[language]")
       arg         = 1.3;
       arg_variant = arg;
 
-      auto i_function = name_builtin_function.find("sinh(R)");
+      auto i_function = name_builtin_function.find("sinh:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -149,7 +149,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("cosh")
     {
-      auto i_function = name_builtin_function.find("cosh(R)");
+      auto i_function = name_builtin_function.find("cosh:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -161,7 +161,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("tanh")
     {
-      auto i_function = name_builtin_function.find("tanh(R)");
+      auto i_function = name_builtin_function.find("tanh:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -173,7 +173,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("asinh")
     {
-      auto i_function = name_builtin_function.find("asinh(R)");
+      auto i_function = name_builtin_function.find("asinh:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -188,7 +188,7 @@ TEST_CASE("MathModule", "[language]")
       arg         = 10;
       arg_variant = arg;
 
-      auto i_function = name_builtin_function.find("acosh(R)");
+      auto i_function = name_builtin_function.find("acosh:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -200,7 +200,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("atanh")
     {
-      auto i_function = name_builtin_function.find("atanh(R)");
+      auto i_function = name_builtin_function.find("atanh:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -212,7 +212,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("exp")
     {
-      auto i_function = name_builtin_function.find("exp(R)");
+      auto i_function = name_builtin_function.find("exp:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -224,7 +224,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("log")
     {
-      auto i_function = name_builtin_function.find("log(R)");
+      auto i_function = name_builtin_function.find("log:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -243,7 +243,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("ceil")
     {
-      auto i_function = name_builtin_function.find("ceil(R)");
+      auto i_function = name_builtin_function.find("ceil:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -255,7 +255,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("floor")
     {
-      auto i_function = name_builtin_function.find("floor(R)");
+      auto i_function = name_builtin_function.find("floor:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -267,7 +267,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("trunc")
     {
-      auto i_function = name_builtin_function.find("trunc(R)");
+      auto i_function = name_builtin_function.find("trunc:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -279,7 +279,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("round")
     {
-      auto i_function = name_builtin_function.find("round(R)");
+      auto i_function = name_builtin_function.find("round:R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -300,7 +300,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("atan2")
     {
-      auto i_function = name_builtin_function.find("atan2(R,R)");
+      auto i_function = name_builtin_function.find("atan2:R*R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
@@ -312,7 +312,7 @@ TEST_CASE("MathModule", "[language]")
 
     SECTION("pow")
     {
-      auto i_function = name_builtin_function.find("pow(R,R)");
+      auto i_function = name_builtin_function.find("pow:R*R");
       REQUIRE(i_function != name_builtin_function.end());
 
       IBuiltinFunctionEmbedder& function_embedder = *i_function->second;
-- 
GitLab