diff --git a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp
index 77abdcf0305a0f9482837ca664a90a3a9d661841..9d914d7ee4799c9908253ffaa2958180a9d67bd3 100644
--- a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp
@@ -152,29 +152,11 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData
       case ASTNodeDataType::double_t: {
         return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, double>>(argument_number);
       }
-      case ASTNodeDataType::string_t: {
-        return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, std::string>>(argument_number);
-      }
-      case ASTNodeDataType::vector_t: {
-        switch (tuple_content_type.dimension()) {
-        case 1: {
-          return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, TinyVector<1>>>(argument_number);
-        }
-        case 2: {
-          return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, TinyVector<2>>>(argument_number);
-        }
-        case 3: {
-          return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, TinyVector<3>>>(argument_number);
-        }
-        default: {
-          throw UnexpectedError(dataTypeName(tuple_content_type) +
-                                " unexpected content of argument, invalid dimension of vector");
-        }
-        }
-      }
+        // LCOV_EXCL_START
       default: {
         throw UnexpectedError(dataTypeName(tuple_content_type) + " unexpected tuple content type of argument ");
       }
+        // LCOV_EXCL_STOP
       }
     }
     case ASTNodeDataType::list_t: {
@@ -195,9 +177,6 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData
     case ASTNodeDataType::double_t: {
       return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, double>>(argument_number);
     }
-    case ASTNodeDataType::string_t: {
-      return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, std::string>>(argument_number);
-    }
     case ASTNodeDataType::vector_t: {
       switch (arg_data_type.dimension()) {
       case 1: {
@@ -209,14 +188,18 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData
       case 3: {
         return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, TinyVector<3>>>(argument_number);
       }
+        // LCOV_EXCL_START
       default: {
         throw UnexpectedError(dataTypeName(arg_data_type) + " unexpected dimension of vector");
       }
+        // LCOV_EXCL_STOP
       }
     }
+      // LCOV_EXCL_START
     default: {
       throw UnexpectedError(dataTypeName(arg_data_type) + " argument to tuple ");
     }
+      // LCOV_EXCL_STOP
     }
   };
 
@@ -284,6 +267,9 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData
       case ASTNodeDataType::type_id_t: {
         return get_function_argument_to_tuple_converter(EmbeddedData{});
       }
+      case ASTNodeDataType::bool_t: {
+        return get_function_argument_to_tuple_converter(bool{});
+      }
       case ASTNodeDataType::unsigned_int_t: {
         return get_function_argument_to_tuple_converter(uint64_t{});
       }
@@ -298,15 +284,10 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData
         case 1: {
           return get_function_argument_to_tuple_converter(TinyVector<1>{});
         }
-        case 2: {
-          return get_function_argument_to_tuple_converter(TinyVector<2>{});
-        }
-        case 3: {
-          return get_function_argument_to_tuple_converter(TinyVector<3>{});
-        }
-          // LCOV_EXCL_START
+        // LCOV_EXCL_START
         default: {
-          throw parse_error("unexpected error: unexpected tuple content for function",
+          throw parse_error("unexpected error: unexpected tuple content for function: '" +
+                              dataTypeName(parameter_type) + "'",
                             std::vector{argument_node_sub_data_type.m_parent_node.begin()});
         }
           // LCOV_EXCL_STOP
@@ -315,10 +296,12 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData
       case ASTNodeDataType::string_t: {
         return get_function_argument_to_string_converter();
       }
+        // LCOV_EXCL_START
       default: {
         throw parse_error("unexpected error: unexpected tuple content type for function",
                           std::vector{argument_node_sub_data_type.m_parent_node.begin()});
       }
+        // LCOV_EXCL_STOP
       }
     }
       // LCOV_EXCL_START
@@ -331,7 +314,9 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData
   };
 
   if (parameter_type == ASTNodeDataType::vector_t and parameter_type.dimension() == 1) {
-    ASTNodeNaturalConversionChecker{argument_node_sub_data_type, ASTNodeDataType::double_t};
+    if (not isNaturalConversion(argument_node_sub_data_type.m_data_type, parameter_type)) {
+      ASTNodeNaturalConversionChecker{argument_node_sub_data_type, ASTNodeDataType::double_t};
+    }
   } else {
     ASTNodeNaturalConversionChecker{argument_node_sub_data_type, parameter_type};
   }
diff --git a/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp b/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp
index 668a77696363a23b01c01663cf9229fa3281fd45..9795ded186f5f7fee9236ec7473bd7c5f32d528b 100644
--- a/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp
+++ b/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp
@@ -8,8 +8,10 @@
 #include <language/ast/ASTNodeFunctionExpressionBuilder.hpp>
 #include <language/ast/ASTNodeTypeCleaner.hpp>
 #include <language/ast/ASTSymbolTableBuilder.hpp>
+#include <language/utils/ASTNodeDataTypeTraits.hpp>
 #include <language/utils/ASTPrinter.hpp>
 #include <language/utils/BuiltinFunctionEmbedder.hpp>
+#include <language/utils/TypeDescriptor.hpp>
 #include <utils/Demangle.hpp>
 
 #include <pegtl/string_input.hpp>
@@ -17,6 +19,11 @@
 #include <memory>
 #include <unordered_map>
 
+template <>
+inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> = {ASTNodeDataType::type_id_t,
+                                                                                 "builtin_t"};
+const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const double>>;
+
 namespace test_only
 {
 class BuiltinFunctionRegister
@@ -42,12 +49,110 @@ class BuiltinFunctionRegister
                                                                 [](bool b) -> double { return b; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("R2toB", std::make_shared<BuiltinFunctionEmbedder<bool(double, double)>>(
+      std::make_pair("RRtoB", 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", 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", std::make_shared<BuiltinFunctionEmbedder<TinyVector<1>(double)>>(
+                                [](double r) -> TinyVector<1> { return {r}; })));
+
+    m_name_builtin_function_map.insert(
+      std::make_pair("R1toR", std::make_shared<BuiltinFunctionEmbedder<double(TinyVector<1>)>>(
+                                [](TinyVector<1> x) -> double { return x[0]; })));
+
+    m_name_builtin_function_map.insert(
+      std::make_pair("R2toR", 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", 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",
+                     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("fidToR", std::make_shared<BuiltinFunctionEmbedder<double(const FunctionSymbolId&)>>(
+                                 [](const FunctionSymbolId&) -> double { return 0; })));
+
+    m_name_builtin_function_map.insert(
+      std::make_pair("builtinToBuiltin",
+                     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", 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", 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", 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", 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", 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",
+                     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",
+                     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",
+                     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", std::make_shared<BuiltinFunctionEmbedder<double(const std::vector<TinyVector<3>>)>>(
+                                      [](const std::vector<TinyVector<3>>&) -> double { return 0; })));
+  }
+
+  void
+  _addBuiltinTypeAndVariables(ASTNode& ast)
+  {
+    SymbolTable& symbol_table = *ast.m_symbol_table;
+    auto [i_symbol, success]  = symbol_table.add(builtin_data_type.nameOfTypeId(), ast.begin());
+    if (not success) {
+      throw UnexpectedError("cannot add '" + builtin_data_type.nameOfTypeId() + "' type for testing");
+    }
+
+    i_symbol->attributes().setDataType(ASTNodeDataType::type_name_id_t);
+    i_symbol->attributes().setIsInitialized();
+    i_symbol->attributes().value() = symbol_table.typeEmbedderTable().size();
+    symbol_table.typeEmbedderTable().add(std::make_shared<TypeDescriptor>(builtin_data_type.nameOfTypeId()));
+
+    auto [i_symbol_a, success_a] = symbol_table.add("a", ast.begin());
+    if (not success_a) {
+      throw UnexpectedError("cannot add 'a' of type builtin_t for testing");
+    }
+    i_symbol_a->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>);
+    i_symbol_a->attributes().setIsInitialized();
+    auto [i_symbol_b, success_b] = symbol_table.add("b", ast.begin());
+    if (not success_b) {
+      throw UnexpectedError("cannot add 'b' of type builtin_t for testing");
+    }
+    i_symbol_b->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>);
+    i_symbol_b->attributes().setIsInitialized();
   }
 
  public:
@@ -58,6 +163,7 @@ class BuiltinFunctionRegister
     auto& builtin_function_embedder_table = symbol_table.builtinFunctionEmbedderTable();
 
     this->_populateNameBuiltinFunctionMap();
+    this->_addBuiltinTypeAndVariables(root_node);
 
     for (const auto& [symbol_name, builtin_function] : m_name_builtin_function_map) {
       auto [i_symbol, success] = symbol_table.add(symbol_name, root_node.begin());
@@ -93,6 +199,7 @@ class BuiltinFunctionRegister
     ASTNodeDataTypeBuilder{*ast};                                                                   \
                                                                                                     \
     ASTNodeTypeCleaner<language::var_declaration>{*ast};                                            \
+    ASTNodeTypeCleaner<language::fct_declaration>{*ast};                                            \
     ASTNodeExpressionBuilder{*ast};                                                                 \
                                                                                                     \
     std::stringstream ast_output;                                                                   \
@@ -191,6 +298,268 @@ RtoR(true);
     }
   }
 
+  SECTION("R -> R1")
+  {
+    SECTION("from R")
+    {
+      std::string_view data = R"(
+RtoR1(1.);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:RtoR1:NameProcessor)
+     `-(language::real:1.:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("from Z")
+    {
+      std::string_view data = R"(
+RtoR1(1);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:RtoR1:NameProcessor)
+     `-(language::integer:1:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("from N")
+    {
+      std::string_view data = R"(
+let n : N, n = 1;
+RtoR1(n);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:RtoR1:NameProcessor)
+     `-(language::name:n:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("from B")
+    {
+      std::string_view data = R"(
+RtoR1(true);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:RtoR1:NameProcessor)
+     `-(language::true_kw:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+  }
+
+  SECTION("R1 -> R")
+  {
+    SECTION("from R1")
+    {
+      std::string_view data = R"(
+let x : R^1, x = 2;
+R1toR(x);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:R1toR:NameProcessor)
+     `-(language::name:x:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("from R")
+    {
+      std::string_view data = R"(
+R1toR(1.);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:R1toR:NameProcessor)
+     `-(language::real:1.:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("from Z")
+    {
+      std::string_view data = R"(
+R1toR(1);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:R1toR:NameProcessor)
+     `-(language::integer:1:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("from N")
+    {
+      std::string_view data = R"(
+let n : N, n = 1;
+R1toR(n);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:R1toR:NameProcessor)
+     `-(language::name:n:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("from B")
+    {
+      std::string_view data = R"(
+R1toR(true);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:R1toR:NameProcessor)
+     `-(language::true_kw:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+  }
+
+  SECTION("R2 -> R")
+  {
+    SECTION("from 0")
+    {
+      std::string_view data = R"(
+R2toR(0);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:R2toR:NameProcessor)
+     `-(language::integer:0:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("from R^2")
+    {
+      std::string_view data = R"(
+let x:R^2, x = (1,2);
+R2toR(x);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:R2toR:NameProcessor)
+     `-(language::name:x:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("from list")
+    {
+      std::string_view data = R"(
+R2toR((1,2));
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:R2toR:NameProcessor)
+     `-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>)
+         +-(language::integer:1:ValueProcessor)
+         `-(language::integer:2:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+  }
+
+  SECTION("R3 -> R")
+  {
+    SECTION("from 0")
+    {
+      std::string_view data = R"(
+R3toR(0);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:R3toR:NameProcessor)
+     `-(language::integer:0:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("from R^3")
+    {
+      std::string_view data = R"(
+let x:R^3, x = (1,2,4);
+R3toR(x);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:R3toR:NameProcessor)
+     `-(language::name:x:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("from list")
+    {
+      std::string_view data = R"(
+R3toR((1,2,3));
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:R3toR:NameProcessor)
+     `-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>)
+         +-(language::integer:1:ValueProcessor)
+         +-(language::integer:2:ValueProcessor)
+         `-(language::integer:3:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+  }
+
   SECTION("Z -> R")
   {
     SECTION("from Z")
@@ -314,16 +683,16 @@ BtoR(true);
     }
   }
 
-  SECTION("R2 -> B")
+  SECTION("R*R -> B")
   {
     std::string_view data = R"(
-R2toB(1., 0.);
+RRtoB(1., 0.);
 )";
 
     std::string_view result = R"(
 (root:ASTNodeListProcessor)
  `-(language::function_evaluation:BuiltinFunctionProcessor)
-     +-(language::name:R2toB:NameProcessor)
+     +-(language::name:RRtoB:NameProcessor)
      `-(language::function_argument_list:ASTNodeExpressionListProcessor)
          +-(language::real:1.:ValueProcessor)
          `-(language::real:0.:ValueProcessor)
@@ -332,22 +701,634 @@ R2toB(1., 0.);
     CHECK_AST(data, result);
   }
 
-  SECTION("string -> B")
+  SECTION("R^3*R^2 -> R")
   {
-    std::string_view data = R"(
-StoB("foo");
+    SECTION("from R^3*R^2")
+    {
+      std::string_view data = R"(
+let x : R^3, x = (1,2,3);
+let y : R^2, y = (2,3);
+R3R2toR(x,y);
 )";
 
-    std::string_view result = R"(
+      std::string_view result = R"(
 (root:ASTNodeListProcessor)
  `-(language::function_evaluation:BuiltinFunctionProcessor)
-     +-(language::name:StoB:NameProcessor)
+     +-(language::name:R3R2toR:NameProcessor)
+     `-(language::function_argument_list:ASTNodeExpressionListProcessor)
+         +-(language::name:x:NameProcessor)
+         `-(language::name:y:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("from (R,R,R)*(R,R)")
+    {
+      std::string_view data = R"(
+R3R2toR((1,2,3),(3,4));
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:R3R2toR:NameProcessor)
+     `-(language::function_argument_list:ASTNodeExpressionListProcessor)
+         +-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>)
+         |   +-(language::integer:1:ValueProcessor)
+         |   +-(language::integer:2:ValueProcessor)
+         |   `-(language::integer:3:ValueProcessor)
+         `-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>)
+             +-(language::integer:3:ValueProcessor)
+             `-(language::integer:4:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("from (R,R,R)*(0)")
+    {
+      std::string_view data = R"(
+R3R2toR((1,2,3),0);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:R3R2toR:NameProcessor)
+     `-(language::function_argument_list:ASTNodeExpressionListProcessor)
+         +-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>)
+         |   +-(language::integer:1:ValueProcessor)
+         |   +-(language::integer:2:ValueProcessor)
+         |   `-(language::integer:3:ValueProcessor)
+         `-(language::integer:0:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+  }
+
+  SECTION("string -> B")
+  {
+    std::string_view data = R"(
+StoB("foo");
+)";
+
+    std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:StoB:NameProcessor)
      `-(language::literal:"foo":ValueProcessor)
 )";
 
     CHECK_AST(data, result);
   }
 
+  SECTION("builtin_t -> builtin_t")
+  {
+    std::string_view data = R"(
+builtinToBuiltin(a);
+)";
+
+    std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:builtinToBuiltin:NameProcessor)
+     `-(language::name:a:NameProcessor)
+)";
+
+    CHECK_AST(data, result);
+  }
+
+  SECTION("-> tuple")
+  {
+    SECTION("B -> tuple(Z)")
+    {
+      std::string_view data = R"(
+tuple_ZtoR(true);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_ZtoR:NameProcessor)
+     `-(language::true_kw:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("tuple(B) -> tuple(Z)")
+    {
+      std::string_view data = R"(
+let t:(B), t =(true, false);
+tuple_ZtoR(t);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_ZtoR:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("N -> tuple(Z)")
+    {
+      std::string_view data = R"(
+let n:N, n=1;
+tuple_ZtoR(n);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_ZtoR:NameProcessor)
+     `-(language::name:n:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("tuple(B) -> tuple(B)")
+    {
+      std::string_view data = R"(
+let t:(B), t=(true,false);
+tuple_BtoR(t);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_BtoR:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("tuple(N) -> tuple(N)")
+    {
+      std::string_view data = R"(
+let t:(N), t=(1,3,7);
+tuple_NtoR(t);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_NtoR:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("tuple(N) -> tuple(Z)")
+    {
+      std::string_view data = R"(
+let t:(N), t=(1,3,7);
+tuple_ZtoR(t);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_ZtoR:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("Z -> tuple(Z)")
+    {
+      std::string_view data = R"(
+tuple_ZtoR(1);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_ZtoR:NameProcessor)
+     `-(language::integer:1:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("tuple(Z) -> tuple(Z)")
+    {
+      std::string_view data = R"(
+let t:(Z), t=(1,3,7);
+tuple_ZtoR(t);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_ZtoR:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("Z -> tuple(R)")
+    {
+      std::string_view data = R"(
+tuple_RtoB(1);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_RtoB:NameProcessor)
+     `-(language::integer:1:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("tuple(Z) -> tuple(R)")
+    {
+      std::string_view data = R"(
+let t:(Z), t = (1,2,4,6);
+tuple_RtoB(t);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_RtoB:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("R -> tuple(R)")
+    {
+      std::string_view data = R"(
+tuple_RtoB(1.2);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_RtoB:NameProcessor)
+     `-(language::real:1.2:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("tuple(R) -> tuple(R)")
+    {
+      std::string_view data = R"(
+let t:(R), t = (1,2,4,6);
+tuple_RtoB(t);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_RtoB:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("list -> tuple(R)")
+    {
+      std::string_view data = R"(
+let n:N, n = 3;
+tuple_RtoB((1.2, 2, true, n));
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_RtoB:NameProcessor)
+     `-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>)
+         +-(language::real:1.2:ValueProcessor)
+         +-(language::integer:2:ValueProcessor)
+         +-(language::true_kw:ValueProcessor)
+         `-(language::name:n:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("R -> tuple(string)")
+    {
+      std::string_view data = R"(
+tuple_stringtoB(1.2);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_stringtoB:NameProcessor)
+     `-(language::real:1.2:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("string -> tuple(string)")
+    {
+      std::string_view data = R"(
+let s:string, s = "foo";
+tuple_stringtoB(s);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_stringtoB:NameProcessor)
+     `-(language::name:s:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("tuple(R) -> tuple(string)")
+    {
+      std::string_view data = R"(
+let t:(R), t = (1,2,4,6);
+tuple_stringtoB(t);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_stringtoB:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("tuple(string) -> tuple(string)")
+    {
+      std::string_view data = R"(
+let t:(string), t = ("foo", "bar", "foobar");
+tuple_stringtoB(t);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_stringtoB:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("literal -> tuple(string)")
+    {
+      std::string_view data = R"(
+tuple_stringtoB("foo");
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_stringtoB:NameProcessor)
+     `-(language::literal:"foo":ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("list -> tuple(string)")
+    {
+      std::string_view data = R"(
+tuple_stringtoB(("foo",2,"bar"));
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_stringtoB:NameProcessor)
+     `-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>)
+         +-(language::literal:"foo":ValueProcessor)
+         +-(language::integer:2:ValueProcessor)
+         `-(language::literal:"bar":ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("builtin -> tuple(builtin)")
+    {
+      std::string_view data = R"(
+tuple_builtinToB(a);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_builtinToB:NameProcessor)
+     `-(language::name:a:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("list -> tuple(builtin)")
+    {
+      std::string_view data = R"(
+tuple_builtinToB((a,b,a));
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_builtinToB:NameProcessor)
+     `-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>)
+         +-(language::name:a:NameProcessor)
+         +-(language::name:b:NameProcessor)
+         `-(language::name:a:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("tuple(builtin) -> tuple(builtin)")
+    {
+      std::string_view data = R"(
+let t:(builtin_t), t = (a,b,a);
+tuple_builtinToB(t);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_builtinToB:NameProcessor)
+     `-(language::name:t:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("Z -> tuple(R1)")
+    {
+      std::string_view data = R"(
+tuple_R1ToR(1);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_R1ToR:NameProcessor)
+     `-(language::integer:1:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("R -> tuple(R1)")
+    {
+      std::string_view data = R"(
+tuple_R1ToR(1.2);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_R1ToR:NameProcessor)
+     `-(language::real:1.2:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("R1 -> tuple(R1)")
+    {
+      std::string_view data = R"(
+let r:R^1, r = 3;
+tuple_R1ToR(r);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_R1ToR:NameProcessor)
+     `-(language::name:r:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("0 -> tuple(R2)")
+    {
+      std::string_view data = R"(
+tuple_R2ToR(0);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_R2ToR:NameProcessor)
+     `-(language::integer:0:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("R2 -> tuple(R2)")
+    {
+      std::string_view data = R"(
+let r:R^2, r = (1,2);
+tuple_R2ToR(r);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_R2ToR:NameProcessor)
+     `-(language::name:r:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("compound_list -> tuple(R2)")
+    {
+      std::string_view data = R"(
+let r:R^2, r = (1,2);
+tuple_R2ToR((r,r));
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_R2ToR:NameProcessor)
+     `-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>)
+         +-(language::name:r:NameProcessor)
+         `-(language::name:r:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("0 -> tuple(R3)")
+    {
+      std::string_view data = R"(
+tuple_R3ToR(0);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_R3ToR:NameProcessor)
+     `-(language::integer:0:ValueProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("R3 -> tuple(R3)")
+    {
+      std::string_view data = R"(
+let r:R^3, r = (1,2,3);
+tuple_R3ToR(r);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:tuple_R3ToR:NameProcessor)
+     `-(language::name:r:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+
+    SECTION("FunctionSymbolId -> R")
+    {
+      std::string_view data = R"(
+let f : R^3 -> R, x -> 0;
+fidToR(f);
+)";
+
+      std::string_view result = R"(
+(root:ASTNodeListProcessor)
+ `-(language::function_evaluation:BuiltinFunctionProcessor)
+     +-(language::name:fidToR:NameProcessor)
+     `-(language::name:f:NameProcessor)
+)";
+
+      CHECK_AST(data, result);
+    }
+  }
+
   SECTION("errors")
   {
     SECTION("bad number of arguments")
@@ -361,7 +1342,7 @@ BtoR(true, false);
     SECTION("bad number of arguments 2")
     {
       std::string_view data = R"(
-R2toB(3);
+RRtoB(3);
 )";
       CHECK_AST_THROWS_WITH(data, std::string{"bad number of arguments:"});
     }