Skip to content
Snippets Groups Projects
Select Git revision
  • 6ddf3e50679bf8a46314c10a7f852a79f65d8815
  • develop default protected
  • feature/variational-hydro
  • origin/stage/bouguettaia
  • feature/gmsh-reader
  • feature/reconstruction
  • save_clemence
  • feature/kinetic-schemes
  • feature/local-dt-fsi
  • feature/composite-scheme-sources
  • feature/composite-scheme-other-fluxes
  • 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
  • master protected
  • 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

test_main.cpp

Blame
  • test_ASTNodeFunctionExpressionBuilder.cpp 33.07 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/ASTNodeExpressionBuilder.hpp>
    #include <language/ast/ASTNodeFunctionEvaluationExpressionBuilder.hpp>
    #include <language/ast/ASTNodeFunctionExpressionBuilder.hpp>
    #include <language/ast/ASTNodeTypeCleaner.hpp>
    #include <language/ast/ASTSymbolTableBuilder.hpp>
    #include <language/utils/ASTPrinter.hpp>
    #include <utils/Demangle.hpp>
    
    #include <pegtl/string_input.hpp>
    
    #define CHECK_AST(data, expected_output)                                                            \
      {                                                                                                 \
        static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>);                  \
        static_assert((std::is_same_v<std::decay_t<decltype(expected_output)>, std::string_view>) or    \
                      (std::is_same_v<std::decay_t<decltype(expected_output)>, std::string>));          \
                                                                                                        \
        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};                                                                   \
                                                                                                        \
        ASTNodeTypeCleaner<language::var_declaration>{*ast};                                            \
        ASTNodeTypeCleaner<language::fct_declaration>{*ast};                                            \
        ASTNodeExpressionBuilder{*ast};                                                                 \
                                                                                                        \
        std::stringstream ast_output;                                                                   \
        ast_output << '\n' << ASTPrinter{*ast, ASTPrinter::Format::raw, {ASTPrinter::Info::exec_type}}; \
                                                                                                        \
        REQUIRE(ast_output.str() == expected_output);                                                   \
      }
    
    #define CHECK_AST_THROWS(data)                                                     \
      {                                                                                \
        static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>); \
                                                                                       \
        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};                                                  \
                                                                                       \
        ASTNodeTypeCleaner<language::var_declaration>{*ast};                           \
        ASTNodeTypeCleaner<language::fct_declaration>{*ast};                           \
        REQUIRE_THROWS_AS(ASTNodeExpressionBuilder{*ast}, ParseError);                 \
      }
    
    #define CHECK_TYPE_BUILDER_THROWS_WITH(data, error)                                \
      {                                                                                \
        static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>); \
        static_assert(std::is_same_v<std::decay_t<decltype(error)>, std::string>);     \
                                                                                       \
        TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"};                     \
        auto ast = ASTBuilder::build(input);                                           \
                                                                                       \
        ASTModulesImporter{*ast};                                                      \
        ASTNodeTypeCleaner<language::import_instruction>{*ast};                        \
                                                                                       \
        ASTSymbolTableBuilder{*ast};                                                   \
        REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, error);                      \
      }
    
    #define CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, error)                          \
      {                                                                                \
        static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>); \
        static_assert(std::is_same_v<std::decay_t<decltype(error)>, std::string>);     \
                                                                                       \
        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};                                                  \
                                                                                       \
        ASTNodeTypeCleaner<language::var_declaration>{*ast};                           \
        ASTNodeTypeCleaner<language::fct_declaration>{*ast};                           \
        REQUIRE_THROWS_WITH(ASTNodeExpressionBuilder{*ast}, error);                    \
      }
    
    // clazy:excludeall=non-pod-global-static
    
    TEST_CASE("ASTNodeFunctionExpressionBuilder", "[language]")
    {
      SECTION("return a B")
      {
        SECTION("B argument")
        {
          SECTION("B parameter")
          {
            std::string_view data = R"(
    let not_v : B -> B, a -> not a;
    not_v(true);
    )";
    
            std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:not_v:NameProcessor)
         `-(language::true_kw:ValueProcessor)
    )";
    
            CHECK_AST(data, result);
          }
        }
    
        SECTION("N argument")
        {
          std::string_view data = R"(
    let test : N -> B, n -> n<10;
    test(2);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:test:NameProcessor)
         `-(language::integer:2:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Z argument")
        {
          std::string_view data = R"(
    let test : Z -> B, z -> z>3;
    test(2);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:test:NameProcessor)
         `-(language::integer:2:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("R argument")
        {
          std::string_view data = R"(
    let test : R -> B, x -> x>2.3;
    test(2.1);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:test:NameProcessor)
         `-(language::real:2.1:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
      }
    
      SECTION("return a N")
      {
        SECTION("N argument")
        {
          std::string_view data = R"(
    let test : N -> N, n -> n+2;
    test(2);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:test:NameProcessor)
         `-(language::integer:2:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Z argument")
        {
          std::string_view data = R"(
    let absolute : Z -> N, z -> (z>0)*z -(z<=0)*z;
    absolute(-2);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:absolute:NameProcessor)
         `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>)
             `-(language::integer:2:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
      }
    
      SECTION("return a Z")
      {
        SECTION("N argument")
        {
          std::string_view data = R"(
    let minus : N -> Z, n -> -n;
    minus(true);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:minus:NameProcessor)
         `-(language::true_kw:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Z argument")
        {
          std::string_view data = R"(
    let times_2 : Z -> Z, z -> z*2;
    times_2(-2);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:times_2:NameProcessor)
         `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>)
             `-(language::integer:2:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
      }
    
      SECTION("return a string")
      {
        SECTION("string argument")
        {
          std::string_view data = R"(
    let cat : string*string -> string, (s1,s2) -> s1+s2;
    cat("foo", "bar");
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:cat:NameProcessor)
         `-(language::function_argument_list:ASTNodeExpressionListProcessor)
             +-(language::literal:"foo":ValueProcessor)
             `-(language::literal:"bar":ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("B argument conversion")
        {
          std::string_view data = R"(
    let cat : string*string -> string, (s1,s2) -> s1+s2;
    cat("foo", true);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:cat:NameProcessor)
         `-(language::function_argument_list:ASTNodeExpressionListProcessor)
             +-(language::literal:"foo":ValueProcessor)
             `-(language::true_kw:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("N argument conversion")
        {
          std::string_view data = R"(
    let cat : string*string -> string, (s1,s2) -> s1+s2;
    let n : N, n = 2;
    cat("foo", n);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:cat:NameProcessor)
         `-(language::function_argument_list:ASTNodeExpressionListProcessor)
             +-(language::literal:"foo":ValueProcessor)
             `-(language::name:n:NameProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Z argument conversion")
        {
          std::string_view data = R"(
    let cat : string*string -> string, (s1,s2) -> s1+s2;
    cat("foo", -1);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:cat:NameProcessor)
         `-(language::function_argument_list:ASTNodeExpressionListProcessor)
             +-(language::literal:"foo":ValueProcessor)
             `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>)
                 `-(language::integer:1:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("R argument conversion")
        {
          std::string_view data = R"(
    let cat : string*string -> string, (s1,s2) -> s1+s2;
    cat("foo", 2.5e-3);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:cat:NameProcessor)
         `-(language::function_argument_list:ASTNodeExpressionListProcessor)
             +-(language::literal:"foo":ValueProcessor)
             `-(language::real:2.5e-3:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return R^1 -> R^1")
        {
          std::string_view data = R"(
    let f : R^1 -> R^1, x -> x+x;
    let x : R^1, x = 1;
    f(x);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::name:x:NameProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return R^2 -> R^2")
        {
          std::string_view data = R"(
    let f : R^2 -> R^2, x -> x+x;
    let x : R^2, x = (1,2);
    f(x);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::name:x:NameProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return R^3 -> R^3")
        {
          std::string_view data = R"(
    let f : R^3 -> R^3, x -> x+x;
    let x : R^3, x = (1,2,3);
    f(x);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::name:x:NameProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return R^1x1 -> R^1x1")
        {
          std::string_view data = R"(
    let f : R^1x1 -> R^1x1, x -> x+x;
    let x : R^1x1, x = 1;
    f(x);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::name:x:NameProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return R^2x2 -> R^2x2")
        {
          std::string_view data = R"(
    let f : R^2x2 -> R^2x2, x -> x+x;
    let x : R^2x2, x = (1,2,3,4);
    f(x);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::name:x:NameProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return R^3x3 -> R^3x3")
        {
          std::string_view data = R"(
    let f : R^3x3 -> R^3x3, x -> x+x;
    let x : R^3x3, x = (1,2,3,4,5,6,7,8,9);
    f(x);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::name:x:NameProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return scalar -> R^1")
        {
          std::string_view data = R"(
    let f : R -> R^1, x -> x+1;
    f(1);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::integer:1:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return tuple -> R^2")
        {
          std::string_view data = R"(
    let f : R*R -> R^2, (x,y) -> (x,y);
    f(1,2);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:TupleToTinyVectorProcessor<FunctionProcessor, 2ul>)
         +-(language::name:f:NameProcessor)
         `-(language::function_argument_list:ASTNodeExpressionListProcessor)
             +-(language::integer:1:ValueProcessor)
             `-(language::integer:2:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return tuple -> R^3")
        {
          std::string_view data = R"(
    let f : R*R*R -> R^3, (x,y,z) -> (x,y,z);
    f(1,2,3);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:TupleToTinyVectorProcessor<FunctionProcessor, 3ul>)
         +-(language::name:f:NameProcessor)
         `-(language::function_argument_list:ASTNodeExpressionListProcessor)
             +-(language::integer:1:ValueProcessor)
             +-(language::integer:2:ValueProcessor)
             `-(language::integer:3:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return scalar -> R^1x1")
        {
          std::string_view data = R"(
    let f : R -> R^1x1, x -> x+1;
    f(1);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::integer:1:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return tuple -> R^2x2")
        {
          std::string_view data = R"(
    let f : R*R*R*R -> R^2x2, (x,y,z,t) -> (x,y,z,t);
    f(1,2,3,4);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:TupleToTinyMatrixProcessor<FunctionProcessor, 2ul>)
         +-(language::name:f:NameProcessor)
         `-(language::function_argument_list:ASTNodeExpressionListProcessor)
             +-(language::integer:1:ValueProcessor)
             +-(language::integer:2:ValueProcessor)
             +-(language::integer:3:ValueProcessor)
             `-(language::integer:4:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return tuple -> R^3x3")
        {
          std::string_view data = R"(
    let f : R^3*R^3*R^3 -> R^3x3, (x,y,z) -> (x[0],x[1],x[2],y[0],y[1],y[2],z[0],z[1],z[2]);
    f((1,2,3),(4,5,6),(7,8,9));
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:TupleToTinyMatrixProcessor<FunctionProcessor, 3ul>)
         +-(language::name:f: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:4:ValueProcessor)
             |   +-(language::integer:5:ValueProcessor)
             |   `-(language::integer:6:ValueProcessor)
             `-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>)
                 +-(language::integer:7:ValueProcessor)
                 +-(language::integer:8:ValueProcessor)
                 `-(language::integer:9:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return '0' -> R^1")
        {
          std::string_view data = R"(
    let f : R -> R^1, x -> 0;
    f(1);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionExpressionProcessor<TinyVector<1ul, double>, ZeroType>)
         +-(language::name:f:NameProcessor)
         `-(language::integer:1:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return '0' -> R^2")
        {
          std::string_view data = R"(
    let f : R -> R^2, x -> 0;
    f(1);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionExpressionProcessor<TinyVector<2ul, double>, ZeroType>)
         +-(language::name:f:NameProcessor)
         `-(language::integer:1:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return '0' -> R^3")
        {
          std::string_view data = R"(
    let f : R -> R^3, x -> 0;
    f(1);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionExpressionProcessor<TinyVector<3ul, double>, ZeroType>)
         +-(language::name:f:NameProcessor)
         `-(language::integer:1:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return '0' -> R^1x1")
        {
          std::string_view data = R"(
    let f : R -> R^1x1, x -> 0;
    f(1);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionExpressionProcessor<TinyMatrix<1ul, double>, ZeroType>)
         +-(language::name:f:NameProcessor)
         `-(language::integer:1:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return '0' -> R^2x2")
        {
          std::string_view data = R"(
    let f : R -> R^2x2, x -> 0;
    f(1);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionExpressionProcessor<TinyMatrix<2ul, double>, ZeroType>)
         +-(language::name:f:NameProcessor)
         `-(language::integer:1:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return '0' -> R^3x3")
        {
          std::string_view data = R"(
    let f : R -> R^3x3, x -> 0;
    f(1);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionExpressionProcessor<TinyMatrix<3ul, double>, ZeroType>)
         +-(language::name:f:NameProcessor)
         `-(language::integer:1:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return embedded R^d compound")
        {
          std::string_view data = R"(
    let f : R*R*R*R -> R*R^1*R^2*R^3, (x,y,z,t) -> (t, (x), (x,y), (x,y,z));
    f(1,2,3,4);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::function_argument_list:ASTNodeExpressionListProcessor)
             +-(language::integer:1:ValueProcessor)
             +-(language::integer:2:ValueProcessor)
             +-(language::integer:3:ValueProcessor)
             `-(language::integer:4:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return embedded R^dxd compound")
        {
          std::string_view data = R"(
    let f : R*R*R*R -> R*R^1x1*R^2x2*R^3x3, (x,y,z,t) -> (t, (x), (x,y,z,t), (x,y,z, x,x,x, t,t,t));
    f(1,2,3,4);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::function_argument_list:ASTNodeExpressionListProcessor)
             +-(language::integer:1:ValueProcessor)
             +-(language::integer:2:ValueProcessor)
             +-(language::integer:3:ValueProcessor)
             `-(language::integer:4:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return embedded R^d compound with '0'")
        {
          std::string_view data = R"(
    let f : R*R*R*R -> R*R^1*R^2*R^3, (x,y,z,t) -> (t, 0, 0, (x,y,z));
    f(1,2,3,4);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::function_argument_list:ASTNodeExpressionListProcessor)
             +-(language::integer:1:ValueProcessor)
             +-(language::integer:2:ValueProcessor)
             +-(language::integer:3:ValueProcessor)
             `-(language::integer:4:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Return embedded R^dxd compound with '0'")
        {
          std::string_view data = R"(
    let f : R*R*R*R -> R*R^1x1*R^2x2*R^3x3, (x,y,z,t) -> (t, 0, 0, (x, y, z, t, x, y, z, t, x));
    f(1,2,3,4);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::function_argument_list:ASTNodeExpressionListProcessor)
             +-(language::integer:1:ValueProcessor)
             +-(language::integer:2:ValueProcessor)
             +-(language::integer:3:ValueProcessor)
             `-(language::integer:4:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Arguments '0' -> R^1")
        {
          std::string_view data = R"(
    let f : R^1 -> R^1, x -> x;
    f(0);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::integer:0:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Arguments '0' -> R^2")
        {
          std::string_view data = R"(
    let f : R^2 -> R^2, x -> x;
    f(0);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::integer:0:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Arguments '0' -> R^3")
        {
          std::string_view data = R"(
    let f : R^3 -> R^3, x -> x;
    f(0);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::integer:0:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Arguments '0' -> R^1x1")
        {
          std::string_view data = R"(
    let f : R^1x1 -> R^1x1, x -> x;
    f(0);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::integer:0:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Arguments '0' -> R^2x2")
        {
          std::string_view data = R"(
    let f : R^2x2 -> R^2x2, x -> x;
    f(0);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::integer:0:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Arguments '0' -> R^3x3")
        {
          std::string_view data = R"(
    let f : R^3x3 -> R^3x3, x -> x;
    f(0);
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::integer:0:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Arguments tuple -> R^d")
        {
          std::string_view data = R"(
    let f: R^3 -> R, x -> x[0]+x[1]+x[2];
    f((1,2,3));
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>)
             +-(language::integer:1:ValueProcessor)
             +-(language::integer:2:ValueProcessor)
             `-(language::integer:3:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Arguments tuple -> R^dxd")
        {
          std::string_view data = R"(
    let f: R^3x3 -> R, x -> x[0,0]+x[0,1]+x[0,2];
    f((1,2,3,4,5,6,7,8,9));
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>)
             +-(language::integer:1:ValueProcessor)
             +-(language::integer:2:ValueProcessor)
             +-(language::integer:3:ValueProcessor)
             +-(language::integer:4:ValueProcessor)
             +-(language::integer:5:ValueProcessor)
             +-(language::integer:6:ValueProcessor)
             +-(language::integer:7:ValueProcessor)
             +-(language::integer:8:ValueProcessor)
             `-(language::integer:9:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
    
        SECTION("Arguments compound with tuple")
        {
          std::string_view data = R"(
    let f: R*R^3*R^2x2->R, (t,x,y) -> t*(x[0]+x[1]+x[2])*y[0,0]+y[1,1];
    f(2,(1,2,3),(2,3,-1,1.3));
    )";
    
          std::string_view result = R"(
    (root:ASTNodeListProcessor)
     `-(language::function_evaluation:FunctionProcessor)
         +-(language::name:f:NameProcessor)
         `-(language::function_argument_list:ASTNodeExpressionListProcessor)
             +-(language::integer:2:ValueProcessor)
             +-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>)
             |   +-(language::integer:1:ValueProcessor)
             |   +-(language::integer:2:ValueProcessor)
             |   `-(language::integer:3:ValueProcessor)
             `-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>)
                 +-(language::integer:2:ValueProcessor)
                 +-(language::integer:3:ValueProcessor)
                 +-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>)
                 |   `-(language::integer:1:ValueProcessor)
                 `-(language::real:1.3:ValueProcessor)
    )";
    
          CHECK_AST(data, result);
        }
      }
    
      SECTION("errors")
      {
        SECTION("wrong argument number")
        {
          std::string_view data = R"(
    let Id : Z -> Z, z -> z;
    Id(2,3);
    )";
    
          CHECK_AST_THROWS(data);
        }
    
        SECTION("wrong argument number 2")
        {
          std::string_view data = R"(
    let sum : R*R -> R, (x,y) -> x+y;
    sum(2);
    )";
    
          CHECK_AST_THROWS(data);
        }
    
        SECTION("invalid return implicit conversion")
        {
          SECTION("string -> R")
          {
            std::string_view data = R"(
    let bad_conv : string -> R, s -> s;
    )";
    
            CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R"});
          }
    
          SECTION("R -> B")
          {
            std::string_view data = R"(
    let bad_B : R -> B, x -> x;
    )";
    
            CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> B"});
          }
    
          SECTION("R -> N")
          {
            std::string_view data = R"(
    let next : R -> N, x -> x;
    )";
    
            CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> N"});
          }
    
          SECTION("R -> Z")
          {
            std::string_view data = R"(
    let prev : R -> Z, x -> x;
    )";
    
            CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> Z"});
          }
    
          SECTION("N -> B")
          {
            std::string_view data = R"(
    let bad_B : N -> B, n -> n;
    )";
    
            CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> B"});
          }
    
          SECTION("Z -> B")
          {
            std::string_view data = R"(
    let bad_B : Z -> B, n -> n;
    )";
    
            CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> B"});
          }
        }
    
        SECTION("invalid argument implicit conversion")
        {
          SECTION("N -> B")
          {
            std::string_view data = R"(
    let negate : B -> B, b -> not b;
    let n : N, n = 2;
    negate(n);
    )";
    
            CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> B"});
          }
    
          SECTION("Z -> B")
          {
            std::string_view data = R"(
    let negate : B -> B, b -> not b;
    negate(3-4);
    )";
    
            CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> B"});
          }
    
          SECTION("R -> B")
          {
            std::string_view data = R"(
    let negate : B -> B, b -> not b;
    negate(3.24);
    )";
    
            CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> B"});
          }
    
          SECTION("R -> N")
          {
            std::string_view data = R"(
    let next : N -> N, n -> n+1;
    next(3.24);
    )";
    
            CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> N"});
          }
    
          SECTION("R -> Z")
          {
            std::string_view data = R"(
    let prev : Z -> Z, z -> z-1;
    prev(3 + .24);
    )";
    
            CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> Z"});
          }
        }
    
        SECTION("arguments invalid tuple -> R^d conversion")
        {
          SECTION("tuple[3] -> R^2")
          {
            std::string_view data = R"(
    let f : R^2 -> R, x->x[0];
    f((1,2,3));
    )";
    
            CHECK_EXPRESSION_BUILDER_THROWS_WITH(data,
                                                 std::string{
                                                   "incompatible dimensions in affectation: expecting 2, but provided 3"});
          }
    
          SECTION("tuple[2] -> R^3")
          {
            std::string_view data = R"(
    let f : R^3 -> R, x->x[0];
    f((1,2));
    )";
    
            CHECK_EXPRESSION_BUILDER_THROWS_WITH(data,
                                                 std::string{
                                                   "incompatible dimensions in affectation: expecting 3, but provided 2"});
          }
    
          SECTION("compound tuple[3] -> R^2")
          {
            std::string_view data = R"(
    let f : R*R^2 -> R, (t,x)->x[0];
    f(1,(1,2,3));
    )";
    
            CHECK_EXPRESSION_BUILDER_THROWS_WITH(data,
                                                 std::string{
                                                   "incompatible dimensions in affectation: expecting 2, but provided 3"});
          }
    
          SECTION("compound tuple[2] -> R^3")
          {
            std::string_view data = R"(
    let f : R^3*R^2 -> R, (x,y)->x[0]*y[1];
    f((1,2),(3,4));
    )";
    
            CHECK_EXPRESSION_BUILDER_THROWS_WITH(data,
                                                 std::string{
                                                   "incompatible dimensions in affectation: expecting 3, but provided 2"});
          }
    
          SECTION("list instead of tuple -> R^3")
          {
            std::string_view data = R"(
    let f : R^3 -> R, x -> x[0]*x[1];
    f(1,2,3);
    )";
    
            CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"bad number of arguments: expecting 1, provided 3"});
          }
    
          SECTION("list instead of tuple -> R^3*R^2")
          {
            std::string_view data = R"(
    let f : R^3*R^2 -> R, (x,y) -> x[0]*x[1]-y[0];
    f((1,2,3),2,3);
    )";
    
            CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"bad number of arguments: expecting 2, provided 3"});
          }
        }
      }
    }