Skip to content
Snippets Groups Projects
Select Git revision
  • 7fe4f9deab64871d8796d545e0e0ca95baac91ad
  • develop default protected
  • feature/advection
  • feature/composite-scheme-other-fluxes
  • origin/stage/bouguettaia
  • save_clemence
  • feature/local-dt-fsi
  • feature/variational-hydro
  • feature/gmsh-reader
  • feature/reconstruction
  • feature/kinetic-schemes
  • feature/composite-scheme-sources
  • feature/serraille
  • feature/composite-scheme
  • hyperplastic
  • feature/polynomials
  • feature/gks
  • feature/implicit-solver-o2
  • feature/coupling_module
  • feature/implicit-solver
  • feature/merge-local-dt-fsi
  • v0.5.0 protected
  • v0.4.1 protected
  • v0.4.0 protected
  • v0.3.0 protected
  • v0.2.0 protected
  • v0.1.0 protected
  • Kidder
  • v0.0.4 protected
  • v0.0.3 protected
  • v0.0.2 protected
  • v0 protected
  • v0.0.1 protected
33 results

ASTNodeBinaryOperatorExpressionBuilder.cpp

Blame
  • test_FunctionProcessor.cpp 52.80 KiB
    #include <catch2/catch_test_macros.hpp>
    #include <catch2/matchers/catch_matchers_all.hpp>
    
    #include <language/ast/ASTBuilder.hpp>
    #include <language/ast/ASTModulesImporter.hpp>
    #include <language/ast/ASTNodeDataTypeBuilder.hpp>
    #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp>
    #include <language/ast/ASTNodeExpressionBuilder.hpp>
    #include <language/ast/ASTNodeTypeCleaner.hpp>
    #include <language/ast/ASTSymbolTableBuilder.hpp>
    #include <utils/Demangle.hpp>
    #include <utils/Stringify.hpp>
    
    #include <pegtl/string_input.hpp>
    
    #include <sstream>
    
    #define CHECK_FUNCTION_EVALUATION_RESULT(data, variable_name, expected_value) \
      {                                                                           \
        TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"};                \
        auto ast = ASTBuilder::build(input);                                      \
                                                                                  \
        ASTModulesImporter{*ast};                                                 \
        ASTNodeTypeCleaner<language::import_instruction>{*ast};                   \
                                                                                  \
        ASTSymbolTableBuilder{*ast};                                              \
        ASTNodeDataTypeBuilder{*ast};                                             \
                                                                                  \
        ASTNodeDeclarationToAffectationConverter{*ast};                           \
        ASTNodeTypeCleaner<language::var_declaration>{*ast};                      \
        ASTNodeTypeCleaner<language::fct_declaration>{*ast};                      \
                                                                                  \
        ASTNodeExpressionBuilder{*ast};                                           \
        ExecutionPolicy exec_policy;                                              \
        ast->execute(exec_policy);                                                \
                                                                                  \
        auto symbol_table = ast->m_symbol_table;                                  \
                                                                                  \
        using namespace TAO_PEGTL_NAMESPACE;                                      \
        position use_position{internal::iterator{"fixture"}, "fixture"};          \
        use_position.byte    = 10000;                                             \
        auto [symbol, found] = symbol_table->find(variable_name, use_position);   \
                                                                                  \
        auto attributes = symbol->attributes();                                   \
        auto value      = std::get<decltype(expected_value)>(attributes.value()); \
                                                                                  \
        REQUIRE(value == expected_value);                                         \
      }
    
    #define CHECK_FUNCTION_EVALUATION_THROWS(data, error_msg)      \
      {                                                            \
        TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \
        auto ast = ASTBuilder::build(input);                       \
                                                                   \
        ASTModulesImporter{*ast};                                  \
        ASTNodeTypeCleaner<language::import_instruction>{*ast};    \
                                                                   \
        ASTSymbolTableBuilder{*ast};                               \
        ASTNodeDataTypeBuilder{*ast};                              \
                                                                   \
        ASTNodeDeclarationToAffectationConverter{*ast};            \
        ASTNodeTypeCleaner<language::var_declaration>{*ast};       \
        ASTNodeTypeCleaner<language::fct_declaration>{*ast};       \
                                                                   \
        ASTNodeExpressionBuilder{*ast};                            \
        ExecutionPolicy exec_policy;                               \
        REQUIRE_THROWS_WITH(ast->execute(exec_policy), error_msg); \
      }
    
    // clazy:excludeall=non-pod-global-static
    
    TEST_CASE("FunctionProcessor", "[language]")
    {
      SECTION("Scalar functions")
      {
        SECTION("-> B")
        {
          SECTION("B -> B")
          {
            SECTION("from B")
            {
              std::string_view data = R"(
    let f : B -> B, b -> not b;
    let b:B, b = f(true);
    )";
              CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
            }
          }
    
          SECTION("N -> B")
          {
            SECTION("from B")
            {
              std::string_view data = R"(
    let f : N -> B, n -> n > 2;
    let b:B, b = f(true);
    )";
              CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
            }
    
            SECTION("from N")
            {
              std::string_view data = R"(
    let f : N -> B, n -> n > 2;
    let n:N, n = 3;
    let b:B, b = f(n);
    )";
              CHECK_FUNCTION_EVALUATION_RESULT(data, "b", true);
            }
    
            SECTION("from Z")
            {
              std::string_view data = R"(
    let f : N -> B, (n) -> (n > 2);
    let b:B, b = f(2);
    )";
              CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
            }
          }
    
          SECTION("Z -> B")
          {
            SECTION("from B")
            {
              std::string_view data = R"(
    let f : Z -> B, z -> z-3 >= 0;
    let b:B, b = f(true);
    )";
              CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
            }
    
            SECTION("from N")
            {
              std::string_view data = R"(
    let f : Z -> B, z -> z-3 >= 0;
    let n:N, n = 3;
    let b:B, b = f(n);
    )";
              CHECK_FUNCTION_EVALUATION_RESULT(data, "b", true);
            }
    
            SECTION("from Z")
            {
              std::string_view data = R"(
    let f : Z -> B, z -> (z-3 >= 0);
    let b:B, b = f(2);
    )";
              CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
            }
          }
    
          SECTION("R -> B")
          {
            SECTION("from B")
            {
              std::string_view data = R"(
    let f : R -> B, x -> x*x < 4;
    let b:B, b = f(true);
    )";
              CHECK_FUNCTION_EVALUATION_RESULT(data, "b", true);
            }
    
            SECTION("from N")
            {
              std::string_view data = R"(
    let f : R -> B, x -> x*x < 4;
    let n:N, n = 3;
    let b:B, b = f(n);
    )";
              CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
            }
    
            SECTION("from Z")
            {
              std::string_view data = R"(
    let f : R -> B, x -> x*x < 4;
    let b:B, b = f(-2);
    )";
              CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
            }
    
            SECTION("from R")
            {
              std::string_view data = R"(
    let f : R -> B, x -> x*x < 4;
    let b:B, b = f(-1.3);
    )";
              CHECK_FUNCTION_EVALUATION_RESULT(data, "b", true);
            }
          }
        }
    
        SECTION("-> N")
        {
          SECTION("from N*N")
          {
            std::string_view data = R"(
    let f : N*N -> N, (m,n) -> m*n;
    let n:N, n = f(2,4);
    )";
            CHECK_FUNCTION_EVALUATION_RESULT(data, "n", 8ul);
          }
    
          SECTION("from Z*Z")
          {
            std::string_view data = R"(
    let f : Z*Z -> N, (p,q) -> p*q;
    let n:N, n = f(-2,-4);
    )";
            CHECK_FUNCTION_EVALUATION_RESULT(data, "n", 8ul);
          }
        }
    
        SECTION("-> Z")
        {
          SECTION("from N*N")
          {
            std::string_view data = R"(
    let f : N*N -> Z, (m,n) -> m*n;
    let z:Z, z = f(2,4);
    )";
            CHECK_FUNCTION_EVALUATION_RESULT(data, "z", 8l);
          }
    
          SECTION("from Z*Z")
          {
            std::string_view data = R"(
    let f : Z*Z -> Z, (p,q) -> p*q;
    let z:Z, z = f(-2,4);
    )";
            CHECK_FUNCTION_EVALUATION_RESULT(data, "z", -8l);
          }
    
          SECTION("from R*Z")
          {
            std::string_view data = R"(
    let f : R*Z -> R, (p,q) -> p*q;
    let x:R, x = f(-0.5,8);
    )";
            CHECK_FUNCTION_EVALUATION_RESULT(data, "x", double{-0.5 * 8l});
          }
        }
    
        SECTION("-> R")
        {
          SECTION("from N*R")
          {
            std::string_view data = R"(
    let f : N*R -> R, (n,x) -> n*x;
    let r:R, r = f(2,4.2);
    )";
            CHECK_FUNCTION_EVALUATION_RESULT(data, "r", double{2ul * 4.2});
          }
    
          SECTION("from R")
          {
            std::string_view data = R"(
    let f : R -> R, x -> x*x-1;
    let r:R, r = f(4);
    )";
            CHECK_FUNCTION_EVALUATION_RESULT(data, "r", double{15});
          }
    
          SECTION("from R using global variable")
          {
            std::string_view data = R"(
    let x0:R, x0 = 3;
    let f : R -> R, x -> x-x0;
    let x:R, x = f(7.3);
    )";
            CHECK_FUNCTION_EVALUATION_RESULT(data, "x", double{7.3 - 3});
          }
        }
    
        SECTION("-> string")
        {
          SECTION("from string")
          {
            std::string_view data = R"(
    let f : string -> string, s -> s+"bar";
    let s:string, s = f("foo");
    )";
            CHECK_FUNCTION_EVALUATION_RESULT(data, "s", std::string{"foobar"});
          }
    
          SECTION("from string*N")
          {
            std::string_view data = R"(
    let f : string*N -> string, (s,n) -> s+n;
    let s:string, s = f("id", 2);
    )";
            CHECK_FUNCTION_EVALUATION_RESULT(data, "s", std::string{"id2"});
          }
    
          SECTION("from string*N (with conversion)")
          {
            std::string_view data = R"(
    let f : string*N -> string, (s,n) -> s+n;
    let s:string, s = f(3, 2);
    )";
            CHECK_FUNCTION_EVALUATION_RESULT(data, "s", std::string{"32"});
          }
    
          SECTION("from N (with conversion)")
          {
            std::string_view data = R"(
    let f : N -> string, n -> n;
    let s:string, s = f(3);
    )";
            CHECK_FUNCTION_EVALUATION_RESULT(data, "s", std::string{"3"});
          }
        }
      }
    
      SECTION("multi-expression functions")
      {
        SECTION(" -> N*R")
        {
          std::string_view data = R"(
    let f : N -> N*R, n -> (2*n, 0.3*n);
    let (n,x):N*R, (n,x) = f(2);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "n", uint64_t{4});
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", double{0.3 * int64_t{2}});
        }
    
        SECTION(" -> N*R*B")
        {
          std::string_view data = R"(
    let f : N -> N*R*B, n -> (2*n, 0.3*n, 1.4*n>n*n);
    let (n,x,b):N*R*B, (n,x,b) = f(2);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "n", uint64_t{4});
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", double{0.3 * int64_t{2}});
          CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
        }
      }
    
      SECTION("multi-expression functions with flattening")
      {
        SECTION(" -> N*R")
        {
          std::string_view data = R"(
    let f : N -> N, n -> 2*n;
    let (x,n):R*N, (x,n) = (2.3, f(3));
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "n", uint64_t{6});
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", double{2.3});
        }
    
        SECTION(" -> N*R*B")
        {
          std::string_view data = R"(
    import math;
    
    let f : N -> N*R, n -> (2*n, 0.3*n);
    let (n,x,s):N*R*R, (n,x,s) = (f(2), sin(1));
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "n", uint64_t{4});
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", double{0.3 * int64_t{2}});
          CHECK_FUNCTION_EVALUATION_RESULT(data, "s", double{std::sin(1)});
        }
      }
    
      SECTION("R^d functions (single value)")
      {
        SECTION("  R^1 -> R^1")
        {
          std::string_view data = R"(
    let f : R^1 -> R^1, x -> 2*x;
    let x:R^1, x = 3;
    
    let fx:R^1, fx = f(x);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (2 * TinyVector<1>{3}));
        }
    
        SECTION("  R^1 -> R^1 called with B argument")
        {
          std::string_view data = R"(
    let f : R^1 -> R^1, x -> 2*x;
    let fx:R^1, fx = f(true);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (2 * TinyVector<1>{true}));
        }
    
        SECTION("  R^1 -> R^1 called with N argument")
        {
          std::string_view data = R"(
    let f : R^1 -> R^1, x -> 2*x;
    let n:N, n = 3;
    let fx:R^1, fx = f(n);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (2 * TinyVector<1>{3}));
        }
    
        SECTION("  R^1 -> R^1 called with Z argument")
        {
          std::string_view data = R"(
    let f : R^1 -> R^1, x -> 2*x;
    let fx:R^1, fx = f(-2);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (2 * TinyVector<1>{-2}));
        }
    
        SECTION("  R^1 -> R^1 called with R argument")
        {
          std::string_view data = R"(
    let f : R^1 -> R^1, x -> 2*x;
    let fx:R^1, fx = f(1.3);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (2 * TinyVector<1>{1.3}));
        }
    
        SECTION("  R^2 -> R^2")
        {
          std::string_view data = R"(
    let f : R^2 -> R^2, x -> 2*x;
    let x:R^2, x = [3, 7];
    
    let fx:R^2, fx = f(x);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (2 * TinyVector<2>{3, 7}));
        }
    
        SECTION("  R^3 -> R^3")
        {
          std::string_view data = R"(
    let f : R^3 -> R^3, x -> 2*x;
    
    let fx:R^3, fx = f([2, 4, 7]);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (2 * TinyVector<3>{2, 4, 7}));
        }
    
        SECTION("  R -> R^1")
        {
          std::string_view data = R"(
    let f : R -> R^1, x -> 2*x;
    let x:R, x = 3;
    
    let fx:R^1, fx = f(x);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (2 * TinyVector<1>{3}));
        }
    
        SECTION("  R*R -> R^2")
        {
          std::string_view data = R"(
    let f : R*R -> R^2, (x,y) -> [2*x, 3*y];
    let fx:R^2, fx = f(2, 3);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (TinyVector<2>{2 * 2, 3 * 3}));
        }
    
        SECTION("  R -> R^3")
        {
          std::string_view data = R"(
    let f : R -> R^3, x -> [x, 2*x, x*x];
    
    let fx:R^3, fx = f(3);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (TinyVector<3>{3, 6, 9}));
        }
      }
    
      SECTION("R^dxd functions (single value)")
      {
        SECTION("  R^1x1 -> R^1x1")
        {
          std::string_view data = R"(
    let f : R^1x1 -> R^1x1, x -> 2*x;
    let x:R^1x1, x = 3;
    
    let fx:R^1x1, fx = f(x);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (2 * TinyMatrix<1>{3}));
        }
    
        SECTION("  R^1x1 -> R^1x1 called with B argument")
        {
          std::string_view data = R"(
    let f : R^1x1 -> R^1x1, x -> 2*x;
    let fx:R^1x1, fx = f(true);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (2 * TinyMatrix<1>{true}));
        }
    
        SECTION("  R^1x1 -> R^1x1 called with N argument")
        {
          std::string_view data = R"(
    let f : R^1x1 -> R^1x1, x -> 2*x;
    let n:N, n = 3;
    let fx:R^1x1, fx = f(n);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (2 * TinyMatrix<1>{3}));
        }
    
        SECTION("  R^1x1 -> R^1x1 called with Z argument")
        {
          std::string_view data = R"(
    let f : R^1x1 -> R^1x1, x -> 2*x;
    let fx:R^1x1, fx = f(-4);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (2 * TinyMatrix<1>{-4}));
        }
    
        SECTION("  R^1x1 -> R^1x1 called with R argument")
        {
          std::string_view data = R"(
    let f : R^1x1 -> R^1x1, x -> 2*x;
    let fx:R^1x1, fx = f(-2.3);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (2 * TinyMatrix<1>{-2.3}));
        }
    
        SECTION("  R^2x2 -> R^2x2")
        {
          std::string_view data = R"(
    let f : R^2x2 -> R^2x2, x -> 2*x;
    
    let fx:R^2x2, fx = f([[3, 7], [6, -2]]);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (2 * TinyMatrix<2>{3, 7, 6, -2}));
        }
    
        SECTION("  R^3x3 -> R^3x3")
        {
          std::string_view data = R"(
    let f : R^3x3 -> R^3x3, x -> 2*x;
    let x:R^3x3, x = [[2, 4, 7],[1, 3, 5],[-6, 2, -3]];
    
    let fx:R^3x3, fx = f(x);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (2 * TinyMatrix<3>{2, 4, 7, 1, 3, 5, -6, 2, -3}));
        }
    
        SECTION("  R -> R^1x1")
        {
          std::string_view data = R"(
    let f : R -> R^1x1, x -> 2*x;
    let x:R, x = 3;
    
    let fx:R^1x1, fx = f(x);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (2 * TinyMatrix<1>{3}));
        }
    
        SECTION("  R*R -> R^2x2")
        {
          std::string_view data = R"(
    let f : R*R -> R^2x2, (x,y) -> [[2*x, 3*y], [5*(x-y), 2*x-y]];
    let fx:R^2x2, fx = f(2, 3);
    )";
    
          const double x = 2;
          const double y = 3;
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx", (TinyMatrix<2>{2 * x, 3 * y, 5 * (x - y), 2 * x - y}));
        }
    
        SECTION("  R -> R^3x3")
        {
          std::string_view data = R"(
    let f : R -> R^3x3, x -> [[x, 2*x, x*x], [3*x, 2+x, x-1], [x+0.5, 2*x-1, 1/x]];
    
    let fx:R^3x3, fx = f(3);
    )";
    
          const double x = 3;
          CHECK_FUNCTION_EVALUATION_RESULT(data, "fx",
                                           (TinyMatrix<3>{x, 2 * x, x * x, 3 * x, 2 + x, x - 1, x + 0.5, 2 * x - 1,
                                                          1 / x}));
        }
    
        SECTION(" -> N*(R)")
        {
          std::string_view data = R"(
    let f : R -> (R)*R, x -> ((2*x, x+2, 3), x);
    let (t,x):(R)*R, (t,x) = f(3.2);
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", double{3.2});
          CHECK_FUNCTION_EVALUATION_RESULT(data, "t", (std::vector<double>{double{2 * 3.2}, double{3.2 + 2}, double{3}}));
        }
      }
    
      SECTION("multi-expression functions (using R^d)")
      {
        SECTION("  R -> R*R^1*R^2*R^3")
        {
          std::string_view data = R"(
    let f : R -> R*R^1*R^2*R^3, x -> (x+1, 2*x, [x-2, x+2], [1, 0.5*x, x*x]);
    
    let  (x, x1, x2, x3):R*R^1*R^2*R^3, (x, x1, x2, x3) = f(3);
    )";
    
          const double x = 3;
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", (double{x + 1}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x1", (TinyVector<1>{2 * x}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x2", (TinyVector<2>{x - 2, x + 2}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x3", (TinyVector<3>{1, 0.5 * x, x * x}));
        }
    
        SECTION("  R^2*R^3 -> R*R^1*R^2*R^3")
        {
          std::string_view data = R"(
    let f : R^2*R^3 -> R*R^1*R^2*R^3,
           (x2, x3) -> (x2[0]+x3[2], [x3[1]], [x3[0], x2[1]], [x3[0], x3[0]+x2[1], x3[2]]);
    
    let y2:R^2, y2 = [2.3, 4.1];
    let y3:R^3, y3 = [1.2, 1.3, 2.1];
    let(x, x1, x2, x3) : R*R^1*R^2*R^3, (x, x1, x2, x3) = f(y2, y3);
    )";
    
          TinyVector<2> y2{2.3, 4.1};
          TinyVector<3> y3{1.2, 1.3, 2.1};
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", (double{y2[0] + y3[2]}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x1", (TinyVector<1>{y3[1]}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x2", (TinyVector<2>{y3[0], y2[1]}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x3", (TinyVector<3>{y3[0], y3[0] + y2[1], y3[2]}));
        }
    
        SECTION("  R^2*R^3 -> R*R^1*R^2*R^3 [with 0 as argument]")
        {
          std::string_view data = R"(
    let f : R^2*R^3 -> R*R^1*R^2*R^3,
           (x2, x3) -> (x2[0]+x3[2], [x3[1]], [x3[0], x2[1]], [x3[0], x3[0]+x2[1], x3[2]]);
    
    let y2:R^2, y2 = [2.3, 4.1];
    let (x, x1, x2, x3) : R*R^1*R^2*R^3, (x, x1, x2, x3) = f(y2, 0);
    )";
    
          TinyVector<2> y2{2.3, 4.1};
          TinyVector<3> y3{zero};
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", (double{y2[0] + y3[2]}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x1", (TinyVector<1>{y3[1]}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x2", (TinyVector<2>{y3[0], y2[1]}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x3", (TinyVector<3>{y3[0], y3[0] + y2[1], y3[2]}));
        }
    
        SECTION("  R^2*R^3 -> R*R^1*R^2*R^3 [with 0 in result]")
        {
          std::string_view data = R"(
    let f : R^2*R^3 -> R*R^1*R^2*R^3,
           (x2, x3) -> (x2[0]+x3[2], x3[1], 0, 0);
    
    let y2:R^2, y2 = [2.3, 4.1];
    let (x, x1, x2, x3):R*R^1*R^2*R^3, (x, x1, x2, x3) = f(y2, 0);
    )";
    
          TinyVector<2> y2{2.3, 4.1};
          TinyVector<3> y3{zero};
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", (double{y2[0] + y3[2]}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x1", (TinyVector<1>{y3[1]}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x2", (TinyVector<2>{zero}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x3", (TinyVector<3>{zero}));
        }
      }
    
      SECTION("multi-expression functions (using R^dxd)")
      {
        SECTION("  R -> R*R^1x1*R^2x2*R^3x3")
        {
          std::string_view data = R"(
    let f : R -> R*R^1x1*R^2x2*R^3x3, x -> (x+1, 2*x, [[x-2, x+2], [3, 2]], [[1, 0.5*x, x*x], [x+1, 1/x, 2], [x*x, 2*x-1, 3*x]]);
    
    let  (x, x11, x22, x33):R*R^1x1*R^2x2*R^3x3, (x, x11, x22, x33) = f(3);
    )";
    
          const double x = 3;
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", (double{x + 1}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x11", (TinyMatrix<1>{2 * x}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x22", (TinyMatrix<2>{x - 2, x + 2, 3, 2}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x33",
                                           (TinyMatrix<3>{1, 0.5 * x, x * x, x + 1, 1 / x, 2, x * x, 2 * x - 1, 3 * x}));
        }
    
        SECTION("  R^2x2*R^3x3 -> R*R^1x1*R^2x2*R^3x3")
        {
          std::string_view data = R"(
    let f : R^2x2*R^3x3 -> R*R^1x1*R^2x2*R^3x3,
           (x22, x33) -> (x22[0,0]+x33[2,0], x33[1,2], [[x33[0,1], x22[1,1]], [x22[0,0], x33[2,2]]], x22[0,0]*x33);
    
    let y22:R^2x2, y22 = [[2.3, 4.1], [6, -3]];
    let y33:R^3x3, y33 = [[1.2, 1.3, 2.1], [3.2,-1.5, 2.3],[-0.2, 3.1, -2.6]];
    let(x, x11, x22, x33) : R*R^1x1*R^2x2*R^3x3, (x, x11, x22, x33) = f(y22, y33);
    )";
    
          const TinyMatrix<2> x22{2.3, 4.1, 6, -3};
          const TinyMatrix<3> x33{1.2, 1.3, 2.1, 3.2, -1.5, 2.3, -0.2, 3.1, -2.6};
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", (double{x22(0, 0) + x33(2, 0)}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x11", (TinyMatrix<1>{x33(1, 2)}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x22", (TinyMatrix<2>{x33(0, 1), x22(1, 1), x22(0, 0), x33(2, 2)}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x33", (TinyMatrix<3>{x22(0, 0) * x33}));
        }
    
        SECTION("  R^2x2*R^3x3 -> R*R^1x1*R^2x2*R^3x3 [with 0 as argument]")
        {
          std::string_view data = R"(
    let f : R^2x2*R^3x3 -> R*R^1x1*R^2x2*R^3x3,
           (x22, x33) -> (x22[0,0]+x33[2,1], x33[1,2], [[x33[0,1], x22[1,0]], [x22[0,1], x33[2,2]]],
                          [[x22[1,0], x33[0,2]+x22[1,1], x33[2,2]],
                           [x33[2,0], x33[2,0]+x22[0,0], x33[1,1]],
                           [x33[2,1], x33[1,2]+x22[1,1], x33[0,0]]]);
    
    let y22:R^2x2, y22 = [[2.3, 4.1], [3.1, 1.7]];
    let y33:R^3x3, y33 = [[2.7, 3.1, 2.1],
                          [0.3, 1.2, 1.6],
                          [1.7, 2.2, 1.4]];
    let (x, x11, x22, x33) : R*R^1x1*R^2x2*R^3x3, (x, x11, x22, x33) = f(y22, y33);
    )";
    
          TinyMatrix<2> x22{2.3, 4.1, 3.1, 1.7};
          TinyMatrix<3> x33{2.7, 3.1, 2.1, 0.3, 1.2, 1.6, 1.7, 2.2, 1.4};
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", (double{x22(0, 0) + x33(2, 1)}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x11", (TinyMatrix<1>{x33(1, 2)}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x22", (TinyMatrix<2>{x33(0, 1), x22(1, 0), x22(0, 1), x33(2, 2)}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x33",
                                           (TinyMatrix<3>{x22(1, 0), x33(0, 2) + x22(1, 1), x33(2, 2), x33(2, 0),
                                                          x33(2, 0) + x22(0, 0), x33(1, 1), x33(2, 1),
                                                          x33(1, 2) + x22(1, 1), x33(0, 0)}));
        }
    
        SECTION("  R^2x2*R^3x3 -> R*R^1x1*R^2x2*R^3x3 [with 0 in result]")
        {
          std::string_view data = R"(
    let f : R^2x2*R^3x3 -> R*R^1x1*R^2x2*R^3x3,
           (x22, x33) -> (x22[0,0]+x33[2,0], x33[1,1], 0, 0);
    
    let y22:R^2x2, y22 = [[2.3, 4.1],[3.1, 1.7]];
    let (x, x11, x22, x33):R*R^1x1*R^2x2*R^3x3, (x, x11, x22, x33) = f(y22, 0);
    )";
    
          TinyMatrix<2> x22{2.3, 4.1, 3.1, 1.7};
          TinyMatrix<3> x33{zero};
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", (double{x22(0, 0) + x33(2, 0)}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x11", (TinyMatrix<1>{x33(1, 1)}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x22", (TinyMatrix<2>{zero}));
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x33", (TinyMatrix<3>{zero}));
        }
      }
    
      SECTION("function composition")
      {
        SECTION("N -> N -> R")
        {
          std::string_view data = R"(
    let f : N -> N, n -> 2*n;
    let g : N -> R, n -> 2*n+0.5;
    
    let x:R, x = g(f(3));
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", double{(2 * 3) * 2 + 0.5});
        }
    
        SECTION("R -> R*R -> R")
        {
          std::string_view data = R"(
    import math;
    let f : N -> N, n -> 2*n;
    let g : N -> R, n -> sin(2*n)+0.5;
    
    let x:R, x = g(f(3));
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", double{std::sin((2 * 3) * 2) + 0.5});
        }
    
        SECTION("R -> R*R -> R")
        {
          std::string_view data = R"(
    import math;
    let f : R -> R*R, x -> (x+1, x*2);
    
    let x:R, x = pow(f(2));
    )";
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", double{std::pow(2. + 1, 2. * 2)});
        }
    
        SECTION("R -> R^2 -> R")
        {
          std::string_view data = R"(
    let f : R -> R^2, x -> [x+1, x*2];
    let g : R^2 -> R, x -> x[0] + x[1];
    
    let x:R, x = g(f(3));
    )";
    
          double x0 = 3;
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", double{x0 + 1 + x0 * 2});
        }
    
        SECTION("R -> R^2*R^3 -> R")
        {
          std::string_view data = R"(
    let f : R -> R^2*R^3, x -> ([x+1, x*2], [6*x, 7-x, x/2.3]);
    let g : R^2*R^3 -> R, (x, y) -> x[0]*x[1] + y[0]*y[1]-y[2];
    
    let x:R, x = g(f(3));
    )";
    
          double x0 = 3;
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", double{(x0 + 1) * x0 * 2 + 6 * x0 * (7 - x0) - x0 / 2.3});
        }
    
        SECTION("R -> R^2x2 -> R")
        {
          std::string_view data = R"(
    let f : R -> R^2x2, x -> [[x+1, x*2], [x-1, x]];
    let g : R^2x2 -> R, A -> A[0,0] + 2*A[1,1] + 3*A[0,1]+ A[1, 0];
    
    let x:R, x = g(f(3));
    )";
    
          const double x = 3;
          const TinyMatrix<2> A{x + 1, x * 2, x - 1, x};
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x", double{A(0, 0) + 2 * A(1, 1) + 3 * A(0, 1) + A(1, 0)});
        }
    
        SECTION("R -> R^2x2*R^3x3 -> R")
        {
          std::string_view data = R"(
    let f : R -> R^2x2*R^3x3, x -> ([[x+1, x*2], [x-1, x]], [[6*x, 7-x, x/2.3], [-x, 2*x, x/2.5], [x*x, 2*x, x]]);
    let g : R^2x2*R^3x3 -> R, (A22, A33) -> A22[0,0]*A22[1,1] + (A33[0,0]*A33[1,0]-A33[2,2])*A22[0,1]-A33[2,0]*A33[0,2]-A22[1,1];
    
    let x:R, x = g(f(3));
    )";
    
          const double x = 3;
          const TinyMatrix<2> A22{x + 1, x * 2, x - 1, x};
          const TinyMatrix<3> A33{6 * x, 7 - x, x / 2.3, -x, 2 * x, x / 2.5, x * x, 2 * x, x};
    
          CHECK_FUNCTION_EVALUATION_RESULT(data, "x",
                                           double{A22(0, 0) * A22(1, 1) + (A33(0, 0) * A33(1, 0) - A33(2, 2)) * A22(0, 1) -
                                                  A33(2, 0) * A33(0, 2) - A22(1, 1)});
        }
      }
    
      SECTION("tuple functions")
      {
        SECTION("-> (B)")
        {
          SECTION("from B")
          {
            std::string_view data = R"(
    let f : B -> (B), b -> not b;
    let b:(B), b = f(true);
    )";
            std::vector<bool> result{false};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "b", result);
          }
    
          SECTION("from list")
          {
            std::string_view data = R"(
    let f : B -> (B), n -> (not n, n, false);
    let t:(B), t = f(true);
    )";
            std::vector<bool> result{false, true, false};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (B)")
          {
            std::string_view data = R"(
    let a:(B), a = (true, false);
    let f : N -> (B), n -> a;
    let t:(B), t = f(true);
    )";
            std::vector<bool> result{true, false};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
        }
    
        SECTION("-> (N)")
        {
          SECTION("from B")
          {
            std::string_view data = R"(
    let f : B -> (N), n -> not n;
    let t:(N), t = f(false);
    )";
            std::vector<uint64_t> result{true};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from N")
          {
            std::string_view data = R"(
    let f : N -> (N), n -> n;
    let t:(N), t = f(7);
    )";
            std::vector<uint64_t> result{7};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from Z")
          {
            std::string_view data = R"(
    let f : Z -> (N), p -> -p;
    let t:(N), t = f(-2);
    )";
            std::vector<uint64_t> result{2};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (B)")
          {
            std::string_view data = R"(
    let l : (B), l = (true, false, true);
    let f : B -> (N), n -> l;
    let t:(N), t = f(false);
    )";
            std::vector<uint64_t> result{1, 0, 1};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (N)")
          {
            std::string_view data = R"(
    let l :(N), l = (2,3,6);
    let f : N -> (N), n -> l;
    let t :(N), t = f(2);
    )";
            std::vector<uint64_t> result{2, 3, 6};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (Z)")
          {
            std::string_view data = R"(
    let l :(Z), l = (2, 6, 7);
    let f : Z -> (N), p -> l;
    let t :(N), t = f(-2);
    )";
            std::vector<uint64_t> result{2, 6, 7};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from list")
          {
            std::string_view data = R"(
    let n : N, n = 3;
    let f : B -> (N), b -> (b, n, 12);
    let t :(N), t = f(false);
    )";
            std::vector<uint64_t> result{false, 3, 12};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
        }
    
        SECTION("-> (Z)")
        {
          SECTION("from B")
          {
            std::string_view data = R"(
    let f : B -> (Z), n -> not n;
    let t:(Z), t = f(false);
    )";
            std::vector<int64_t> result{true};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from N")
          {
            std::string_view data = R"(
    let f : N -> (Z), n -> n;
    let t:(Z), t = f(7);
    )";
            std::vector<int64_t> result{7};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from Z")
          {
            std::string_view data = R"(
    let f : Z -> (Z), p -> p;
    let t:(Z), t = f(-2);
    )";
            std::vector<int64_t> result{-2};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (B)")
          {
            std::string_view data = R"(
    let l : (B), l = (true, false, true);
    let f : B -> (Z), n -> l;
    let t:(Z), t = f(false);
    )";
            std::vector<int64_t> result{1, 0, 1};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (N)")
          {
            std::string_view data = R"(
    let l :(N), l = (2,3,6);
    let f : N -> (Z), n -> l;
    let t :(Z), t = f(2);
    )";
            std::vector<int64_t> result{2, 3, 6};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (Z)")
          {
            std::string_view data = R"(
    let l :(Z), l = (2, -6, 7);
    let f : Z -> (Z), p -> l;
    let t :(Z), t = f(-2);
    )";
            std::vector<int64_t> result{2, -6, 7};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from list")
          {
            std::string_view data = R"(
    let n : N, n = 3;
    let f : B -> (Z), b -> (b, n, -12);
    let t :(Z), t = f(false);
    )";
            std::vector<int64_t> result{false, 3, -12};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
        }
    
        SECTION("-> (R)")
        {
          SECTION("from B")
          {
            std::string_view data = R"(
    let f : B -> (R), n -> not n;
    let t:(R), t = f(false);
    )";
            std::vector<double> result{true};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from N")
          {
            std::string_view data = R"(
    let f : N -> (R), n -> n;
    let t:(R), t = f(7);
    )";
            std::vector<double> result{7};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from Z")
          {
            std::string_view data = R"(
    let f : Z -> (R), p -> p;
    let t:(R), t = f(-2);
    )";
            std::vector<double> result{-2};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from R")
          {
            std::string_view data = R"(
    let f : Z -> (R), p -> 2.3*p;
    let t:(R), t = f(-2);
    )";
            std::vector<double> result{-2l * 2.3};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (B)")
          {
            std::string_view data = R"(
    let l : (B), l = (true, false, true);
    let f : B -> (R), n -> l;
    let t:(R), t = f(false);
    )";
            std::vector<double> result{true, false, true};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (N)")
          {
            std::string_view data = R"(
    let l :(N), l = (2,3,6);
    let f : N -> (R), n -> l;
    let t :(R), t = f(2);
    )";
            std::vector<double> result{2ul, 3ul, 6ul};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (Z)")
          {
            std::string_view data = R"(
    let l :(Z), l = (2, -6, 7);
    let f : Z -> (R), p -> l;
    let t :(R), t = f(-2);
    )";
            std::vector<double> result{2l, -6l, 7l};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (R)")
          {
            std::string_view data = R"(
    let l :(R), l = (2.2, -6, 7.3);
    let f : Z -> (R), p -> l;
    let t :(R), t = f(-2);
    )";
            std::vector<double> result{2.2, -6, 7.3};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from list")
          {
            std::string_view data = R"(
    let n : N, n = 3;
    let f : B -> (R), b -> (b, n, -12, 2.3);
    let t :(R), t = f(false);
    )";
            std::vector<double> result{false, 3ul, -12l, 2.3};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
        }
    
        SECTION("-> (R^1)")
        {
          using Rd = TinyVector<1>;
          SECTION("from B")
          {
            std::string_view data = R"(
    let f : B -> (R^1), n -> not n;
    let t:(R^1), t = f(false);
    )";
            std::vector<Rd> result{Rd{true}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from N")
          {
            std::string_view data = R"(
    let f : N -> (R^1), n -> n;
    let t:(R^1), t = f(7);
    )";
            std::vector<Rd> result{Rd{7}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from Z")
          {
            std::string_view data = R"(
    let f : Z -> (R^1), p -> p;
    let t:(R^1), t = f(-2);
    )";
            std::vector<Rd> result{Rd{-2}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from R")
          {
            std::string_view data = R"(
    let f : Z -> (R^1), p -> 2.3*p;
    let t:(R^1), t = f(-2);
    )";
            std::vector<Rd> result{Rd{-2l * 2.3}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from R^1")
          {
            std::string_view data = R"(
    let f : Z -> (R^1), p -> 2.2*[p];
    let t:(R^1), t = f(-2);
    )";
            std::vector<Rd> result{Rd{-2l * 2.2}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (B)")
          {
            std::string_view data = R"(
    let l : (B), l = (true, false, true);
    let f : B -> (R^1), n -> l;
    let t:(R^1), t = f(false);
    )";
            std::vector<Rd> result{Rd{true}, Rd{false}, Rd{true}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (N)")
          {
            std::string_view data = R"(
    let l :(N), l = (2,3,6);
    let f : N -> (R^1), n -> l;
    let t :(R^1), t = f(2);
    )";
            std::vector<Rd> result{Rd{2ul}, Rd{3ul}, Rd{6ul}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (Z)")
          {
            std::string_view data = R"(
    let l :(Z), l = (2, -6, 7);
    let f : Z -> (R^1), p -> l;
    let t :(R^1), t = f(-2);
    )";
            std::vector<Rd> result{Rd{2l}, Rd{-6l}, Rd{7l}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (R)")
          {
            std::string_view data = R"(
    let l :(R), l = (2.2, -6.1, 7.4);
    let f : Z -> (R^1), p -> l;
    let t :(R^1), t = f(-2);
    )";
            std::vector<Rd> result{Rd{2.2}, Rd{-6.1}, Rd{7.4}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (R^1)")
          {
            std::string_view data = R"(
    let l :(R^1), l = ([2.2], -[6.1], [7.4]);
    let f : Z -> (R^1), p -> l;
    let t :(R^1), t = f(-2);
    )";
            std::vector<Rd> result{Rd{2.2}, Rd{-6.1}, Rd{7.4}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from list")
          {
            std::string_view data = R"(
    let n : N, n = 3;
    let f : B -> (R^1), b -> (b, n, -12, 2.3, [4.2]);
    let t :(R^1), t = f(false);
    )";
            std::vector<Rd> result{Rd{false}, Rd{3ul}, Rd{-12l}, Rd{2.3}, Rd{4.2}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
        }
    
        SECTION("-> (R^2)")
        {
          using Rd = TinyVector<2>;
          SECTION("from R^2")
          {
            std::string_view data = R"(
    let f : Z -> (R^2), p -> 2.2*[p, 2*p];
    let t:(R^2), t = f(-2);
    )";
            std::vector<Rd> result{Rd{-2l * 2.2, -4l * 2.2}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from '0'")
          {
            std::string_view data = R"(
    let f : Z -> (R^2), p -> 0;
    let t :(R^2), t = f(-2);
    )";
            std::vector<Rd> result{Rd{zero}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (R^2)")
          {
            std::string_view data = R"(
    let l :(R^2), l = ([2.2, 1.2], -[6.1, 7], [7.4, 1]);
    let f : Z -> (R^2), p -> l;
    let t :(R^2), t = f(-2);
    )";
            std::vector<Rd> result{Rd{2.2, 1.2}, -Rd{6.1, 7}, Rd{7.4, 1}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from list")
          {
            std::string_view data = R"(
    let f : B -> (R^2), b -> ([1.2, 3], 0, [4.2, 1]);
    let t :(R^2), t = f(false);
    )";
            std::vector<Rd> result{Rd{1.2, 3}, Rd{zero}, Rd{4.2, 1}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
        }
    
        SECTION("-> (R^3)")
        {
          using Rd = TinyVector<3>;
          SECTION("from R^3")
          {
            std::string_view data = R"(
    let f : Z -> (R^3), p -> 2.2*[p, 2*p, 2];
    let t:(R^3), t = f(-2);
    )";
            std::vector<Rd> result{Rd{-2l * 2.2, -4l * 2.2, 4.4}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from '0'")
          {
            std::string_view data = R"(
    let f : Z -> (R^3), p -> 0;
    let t :(R^3), t = f(-2);
    )";
            std::vector<Rd> result{Rd{zero}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (R^3)")
          {
            std::string_view data = R"(
    let l :(R^3), l = ([2.2, 1.2, 2], -[6.1, 7, 5], [7.4, 1, -1]);
    let f : Z -> (R^3), p -> l;
    let t :(R^3), t = f(-2);
    )";
            std::vector<Rd> result{Rd{2.2, 1.2, 2}, -Rd{6.1, 7, 5}, Rd{7.4, 1, -1}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from list")
          {
            std::string_view data = R"(
    let f : B -> (R^3), b -> ([1.2, 3, 1], 0, [4.2, 1, 7]);
    let t :(R^3), t = f(false);
    )";
            std::vector<Rd> result{Rd{1.2, 3, 1}, Rd{zero}, Rd{4.2, 1, 7}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
        }
    
        SECTION("-> (R^1x1)")
        {
          using Rdxd = TinyMatrix<1>;
          SECTION("from B")
          {
            std::string_view data = R"(
    let f : B -> (R^1x1), n -> not n;
    let t:(R^1x1), t = f(false);
    )";
            std::vector<Rdxd> result{Rdxd{true}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from N")
          {
            std::string_view data = R"(
    let f : N -> (R^1x1), n -> n;
    let t:(R^1x1), t = f(7);
    )";
            std::vector<Rdxd> result{Rdxd{7}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from Z")
          {
            std::string_view data = R"(
    let f : Z -> (R^1x1), p -> p;
    let t:(R^1x1), t = f(-2);
    )";
            std::vector<Rdxd> result{Rdxd{-2}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from R")
          {
            std::string_view data = R"(
    let f : Z -> (R^1x1), p -> 2.3*p;
    let t:(R^1x1), t = f(-2);
    )";
            std::vector<Rdxd> result{Rdxd{-2l * 2.3}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from R^1x1")
          {
            std::string_view data = R"(
    let f : Z -> (R^1x1), p -> 2.2*[[p]];
    let t:(R^1x1), t = f(-2);
    )";
            std::vector<Rdxd> result{Rdxd{-2l * 2.2}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (B)")
          {
            std::string_view data = R"(
    let l : (B), l = (true, false, true);
    let f : B -> (R^1x1), n -> l;
    let t:(R^1x1), t = f(false);
    )";
            std::vector<Rdxd> result{Rdxd{true}, Rdxd{false}, Rdxd{true}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (N)")
          {
            std::string_view data = R"(
    let l :(N), l = (2,3,6);
    let f : N -> (R^1x1), n -> l;
    let t :(R^1x1), t = f(2);
    )";
            std::vector<Rdxd> result{Rdxd{2ul}, Rdxd{3ul}, Rdxd{6ul}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (Z)")
          {
            std::string_view data = R"(
    let l :(Z), l = (2, -6, 7);
    let f : Z -> (R^1x1), p -> l;
    let t :(R^1x1), t = f(-2);
    )";
            std::vector<Rdxd> result{Rdxd{2l}, Rdxd{-6l}, Rdxd{7l}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (R)")
          {
            std::string_view data = R"(
    let l :(R), l = (2.2, -6.1, 7.4);
    let f : Z -> (R^1x1), p -> l;
    let t :(R^1x1), t = f(-2);
    )";
            std::vector<Rdxd> result{Rdxd{2.2}, Rdxd{-6.1}, Rdxd{7.4}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (R^1x1)")
          {
            std::string_view data = R"(
    let l :(R^1x1), l = ([[2.2]], -[[6.1]], [[7.4]]);
    let f : Z -> (R^1x1), p -> l;
    let t :(R^1x1), t = f(-2);
    )";
            std::vector<Rdxd> result{Rdxd{2.2}, Rdxd{-6.1}, Rdxd{7.4}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from list")
          {
            std::string_view data = R"(
    let n : N, n = 3;
    let f : B -> (R^1x1), b -> (b, n, -12, 2.3, [[4.2]]);
    let t :(R^1x1), t = f(false);
    )";
            std::vector<Rdxd> result{Rdxd{false}, Rdxd{3ul}, Rdxd{-12l}, Rdxd{2.3}, Rdxd{4.2}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
        }
    
        SECTION("-> (R^2x2)")
        {
          using Rdxd = TinyMatrix<2>;
          SECTION("from R^2x2")
          {
            std::string_view data = R"(
    let f : Z -> (R^2x2), p -> 2.2*[[p, 2*p], [2,3]];
    let t:(R^2x2), t = f(-2);
    )";
            std::vector<Rdxd> result{Rdxd{-2l * 2.2, -4l * 2.2, 2l * 2.2, 3l * 2.2}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from '0'")
          {
            std::string_view data = R"(
    let f : Z -> (R^2x2), p -> 0;
    let t :(R^2x2), t = f(-2);
    )";
            std::vector<Rdxd> result{Rdxd{zero}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (R^2x2)")
          {
            std::string_view data = R"(
    let l :(R^2x2), l = ([[2.2, 1.2],[6.1, 7]], [[7.4, 1],[3.4, -2]]);
    let f : Z -> (R^2x2), p -> l;
    let t :(R^2x2), t = f(-2);
    )";
            std::vector<Rdxd> result{Rdxd{2.2, 1.2, 6.1, 7}, Rdxd{7.4, 1, 3.4, -2}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from list")
          {
            std::string_view data = R"(
    let f : B -> (R^2x2), b -> ([[1.2, 3],[4.5, 6]], 0, [[4.2, 1],[1.3,-6]]);
    let t :(R^2x2), t = f(false);
    )";
            std::vector<Rdxd> result{Rdxd{1.2, 3, 4.5, 6}, Rdxd{zero}, Rdxd{4.2, 1, 1.3, -6}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
        }
    
        SECTION("-> (R^3x3)")
        {
          using Rdxd = TinyMatrix<3>;
          SECTION("from R^3x3")
          {
            std::string_view data = R"(
    let f : Z -> (R^3x3), p -> 2.2*[[p, 2*p, 2],[2,3,5],[3,6,2]];
    let t:(R^3x3), t = f(-2);
    )";
            std::vector<Rdxd> result{Rdxd{-2l * 2.2, -4l * 2.2, 2l * 2.2,   //
                                          2l * 2.2, 3l * 2.2, 5l * 2.2,     //
                                          3l * 2.2, 6l * 2.2, 2l * 2.2}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from '0'")
          {
            std::string_view data = R"(
    let f : Z -> (R^3x3), p -> 0;
    let t :(R^3x3), t = f(-2);
    )";
            std::vector<Rdxd> result{Rdxd{zero}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (R^3x3)")
          {
            std::string_view data = R"(
    let l :(R^3x3), l = ([[2.2, 1.2, 2], [-6.1, 7, 5], [7.4, 1, -1]], 0);
    let f : Z -> (R^3x3), p -> l;
    let t :(R^3x3), t = f(-2);
    )";
            std::vector<Rdxd> result{Rdxd{2.2, 1.2, 2,   //
                                          -6.1, 7, 5,    //
                                          7.4, 1, -1},
                                     Rdxd{zero}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from list")
          {
            std::string_view data = R"(
    let f : B -> (R^3x3), b -> ([[1.2, 3, 1],[1,2,3],[4.2,2,6]], 0, [[4.2, 1, 7],[2,4,6],[2,3,1]]);
    let t :(R^3x3), t = f(false);
    )";
            std::vector<Rdxd> result{Rdxd{1.2, 3, 1,   //
                                          1, 2, 3,     //
                                          4.2, 2, 6},
                                     Rdxd{zero},
                                     Rdxd{4.2, 1, 7,   //
                                          2, 4, 6,     //
                                          2, 3, 1}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
        }
    
        SECTION("-> (string)")
        {
          SECTION("from B")
          {
            std::string_view data = R"(
    let f : B -> (string), n -> not n;
    let t:(string), t = f(false);
    )";
            std::vector<std::string> result{stringify(true)};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from N")
          {
            std::string_view data = R"(
    let f : N -> (string), n -> n;
    let t:(string), t = f(7);
    )";
            std::vector<std::string> result{stringify(7)};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from Z")
          {
            std::string_view data = R"(
    let f : Z -> (string), p -> p;
    let t:(string), t = f(-2);
    )";
            std::vector<std::string> result{stringify(-2)};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from R")
          {
            std::string_view data = R"(
    let f : Z -> (string), p -> 2.3*p;
    let t:(string), t = f(-2);
    )";
            std::vector<std::string> result{stringify(-2l * 2.3)};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from R^1")
          {
            std::string_view data = R"(
    let f : Z -> (string), p -> [2.3*p];
    let t:(string), t = f(-2);
    )";
            std::vector<std::string> result{stringify(TinyVector<1>{-2l * 2.3})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from R^2")
          {
            std::string_view data = R"(
    let f : Z -> (string), p -> [2.3*p, 3];
    let t:(string), t = f(-2);
    )";
            std::vector<std::string> result{stringify(TinyVector<2>{-2l * 2.3, 3})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from R^3")
          {
            std::string_view data = R"(
    let f : Z -> (string), p -> [1, 2.3*p, 3];
    let t:(string), t = f(-2);
    )";
            std::vector<std::string> result{stringify(TinyVector<3>{1, -2l * 2.3, 3})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from R^1x1")
          {
            std::string_view data = R"(
    let f : Z -> (string), p -> [[2.3*p]];
    let t:(string), t = f(-2);
    )";
            std::vector<std::string> result{stringify(TinyMatrix<1>{-2l * 2.3})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from R^2x2")
          {
            std::string_view data = R"(
    let f : Z -> (string), p -> [[2.3*p, 3],[2, p]];
    let t:(string), t = f(-2);
    )";
            std::vector<std::string> result{stringify(TinyMatrix<2>{-2l * 2.3, 3, 2, -2})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from R^3x3")
          {
            std::string_view data = R"(
    let f : Z -> (string), p -> [[1, 2.3*p, 3],[1.2, 2.3, 0.5],[0.1, 1.4, 6]];
    let t:(string), t = f(-2);
    )";
            std::vector<std::string> result{stringify(TinyMatrix<3>{1, -2l * 2.3, 3,   //
                                                                    1.2, 2.3, 0.5,     //
                                                                    0.1, 1.4, 6})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from string")
          {
            std::string_view data = R"(
    let f : Z -> (string), p -> "foo";
    let t:(string), t = f(-2);
    )";
            std::vector<std::string> result{std::string{"foo"}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (B)")
          {
            std::string_view data = R"(
    let l : (B), l = (true, false, true);
    let f : B -> (string), n -> l;
    let t:(string), t = f(false);
    )";
            std::vector<std::string> result{stringify(std::vector<bool>{true, false, true})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (N)")
          {
            std::string_view data = R"(
    let l :(N), l = (2,3,6);
    let f : N -> (string), n -> l;
    let t :(string), t = f(2);
    )";
            std::vector<std::string> result{stringify(std::vector<double>{2ul, 3ul, 6ul})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (Z)")
          {
            std::string_view data = R"(
    let l :(Z), l = (2, -6, 7);
    let f : Z -> (string), p -> l;
    let t :(string), t = f(-2);
    )";
            std::vector<std::string> result{stringify(std::vector<double>{2l, -6l, 7l})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (R)")
          {
            std::string_view data = R"(
    let l :(R), l = (2.2, -6, 7.3);
    let f : Z -> (string), p -> l;
    let t :(string), t = f(-2);
    )";
            std::vector<std::string> result{stringify(std::vector<double>{2.2, -6, 7.3})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (R^1)")
          {
            using Rd = TinyVector<1>;
    
            std::string_view data = R"(
    let l : (R^1), l = (0, [2], [3.5]);
    let f : Z -> (string), p -> l;
    let t:(string), t = f(-2);
    )";
            std::vector<std::string> result{stringify(std::vector<Rd>{Rd{zero}, Rd{2}, Rd{3.5}})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (R^2)")
          {
            using Rd = TinyVector<2>;
    
            std::string_view data = R"(
    let l : (R^2), l = ([1, 2], 0, [2, 3.5]);
    let f : Z -> (string), p -> l;
    let t:(string), t = f(-2);
    )";
            std::vector<std::string> result{stringify(std::vector<Rd>{Rd{1, 2}, Rd{zero}, Rd{2, 3.5}})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (R^3)")
          {
            using Rd = TinyVector<3>;
    
            std::string_view data = R"(
    let l : (R^3), l = ([1, 2, 3], 0, [2, 3.5, 7]);
    let f : Z -> (string), p -> l;
    let t:(string), t = f(-2);
    )";
            std::vector<std::string> result{stringify(std::vector<Rd>{Rd{1, 2, 3}, Rd{zero}, Rd{2, 3.5, 7}})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (R^1x1)")
          {
            using Rdxd = TinyMatrix<1>;
    
            std::string_view data = R"(
    let l : (R^1x1), l = ([[1]], 0, [[3.5]]);
    let f : Z -> (string), p -> l;
    let t:(string), t = f(-2);
    )";
            std::vector<std::string> result{stringify(std::vector<Rdxd>{Rdxd{1}, Rdxd{zero}, Rdxd{3.5}})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (R^2x2)")
          {
            using Rdxd = TinyMatrix<2>;
    
            std::string_view data = R"(
    let l : (R^2x2), l = ([[1,2],[3,4]], 0, [[3.5,-5],[3.7,2.9]]);
    let f : Z -> (string), p -> l;
    let t:(string), t = f(-2);
    )";
            std::vector<std::string> result{
              stringify(std::vector<Rdxd>{Rdxd{1, 2, 3, 4}, Rdxd{zero}, Rdxd{3.5, -5, 3.7, 2.9}})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (R^3x3)")
          {
            using Rdxd = TinyMatrix<3>;
    
            std::string_view data = R"(
    let l : (R^3x3), l = ([[1,2,3],[3,5,6],[9,3,4]], 0, [[1,3,7],[3.5,-5,2.3],[2.1,3.7,2.9]]);
    let f : Z -> (string), p -> l;
    let t:(string), t = f(-2);
    )";
    
            std::vector<std::string> result{stringify(std::vector<Rdxd>{Rdxd{1, 2, 3, 3, 5, 6, 9, 3, 4},   //
                                                                        Rdxd{zero},                        //
                                                                        Rdxd{1, 3, 7, 3.5, -5, 2.3, 2.1, 3.7, 2.9}})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from (string)")
          {
            std::string_view data = R"(
    let l:(string), l = ("foo", "bar", "foobar");
    let f : Z -> (string), p -> l;
    let t:(string), t = f(-2);
    )";
            std::vector<std::string> result{std::vector<std::string>{"foo", "bar", "foobar"}};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
    
          SECTION("from list")
          {
            std::string_view data = R"(
    let n : N, n = 3;
    let f : B -> (string), b -> (b, n, -12, 2.3, "foo");
    let t :(string), t = f(false);
    )";
    
            std::vector<std::string> result{stringify(
              std::vector<std::string>{stringify(false), stringify(3ul), stringify(-12l), stringify(2.3), "foo"})};
            CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result);
          }
        }
      }
    
      SECTION("errors")
      {
        SECTION("negative value to N")
        {
          SECTION("single N argument")
          {
            std::string_view data = R"(
    let f : N -> N, n -> 2;
    f(2);
    f(-1);
    )";
    
            CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-1)");
          }
    
          SECTION("multiple N arguments")
          {
            std::string_view data = R"(
    let f : R*N -> R, (n,x) -> n*x;
    f(-2, 3);
    f(-1,-4);
    )";
    
            CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-4)");
          }
    
          SECTION("single N return value")
          {
            std::string_view data = R"(
    let f : N*N -> N, (m,n) -> m-n;
    f(2, 1);
    f(1, 3);
    )";
    
            CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-2)");
          }
    
          SECTION("compound N return value")
          {
            std::string_view data = R"(
    let f : N*N -> N*N, (m,n) -> (m+n, m-n);
    f(3, 2);
    f(1, 4);
    )";
    
            CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-3)");
          }
        }
    
        SECTION("negative value to (N)")
        {
          SECTION("return N -> (N)")
          {
            std::string_view data = R"(
    let f : N -> (N), n -> -2;
    f(2);
    )";
    
            CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-2)");
          }
    
          SECTION("return (Z) -> (N)")
          {
            std::string_view data = R"(
    let z :(Z), z = (1, 2, -3);
    let f : N -> (N), n -> z;
    f(2);
    )";
    
            CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-3)");
          }
    
          SECTION("return list")
          {
            std::string_view data = R"(
    let f : N*N -> (N), (m,n) -> (m, n, n-m);
    f(2, 1);
    f(1, 2);
    )";
    
            CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-1)");
          }
        }
      }
    }