#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"}); } } } }