#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/ASTNode.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> #include <language/ast/ASTNodeTypeCleaner.hpp> #include <language/ast/ASTSymbolInitializationChecker.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> #include <language/utils/BuiltinFunctionEmbedder.hpp> #include <language/utils/BuiltinFunctionEmbedderUtils.hpp> #include <language/utils/SymbolTable.hpp> #include <utils/Exceptions.hpp> #include <pegtl/string_input.hpp> // clazy:excludeall=non-pod-global-static TEST_CASE("BuiltinFunctionEmbedderUtils", "[language]") { using FunctionList = std::vector<std::pair<std::string, std::shared_ptr<IBuiltinFunctionEmbedder>>>; auto register_functions = [](std::unique_ptr<ASTNode>& root_node, const FunctionList& function_list) { ASTModulesImporter{*root_node}; std::shared_ptr root_st = root_node->m_symbol_table; auto& embedder_table = root_st->builtinFunctionEmbedderTable(); for (auto&& [function_name, embedded_function] : function_list) { auto [i_symbol, success] = root_st->add(function_name + ':' + dataTypeName(embedded_function->getParameterDataTypes()), root_node->begin()); if (not success) { throw UnexpectedError("cannot build test, function already registered"); } i_symbol->attributes().setDataType(ASTNodeDataType::build<ASTNodeDataType::builtin_function_t>()); i_symbol->attributes().setIsInitialized(); i_symbol->attributes().value() = embedder_table.size(); embedder_table.add(embedded_function); } ASTSymbolTableBuilder{*root_node}; ASTNodeDataTypeBuilder{*root_node}; ASTNodeDeclarationToAffectationConverter{*root_node}; ASTNodeTypeCleaner<language::var_declaration>{*root_node}; ASTNodeTypeCleaner<language::fct_declaration>{*root_node}; }; SECTION("using simple arguments") { SECTION("builtin function R -> R") { std::string_view data = R"( foo(3); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( [](double x) -> double { return x; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); } SECTION("builtin function R*string -> R") { std::string_view data = R"( foo(3,"bar"); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( [](double x) -> double { return x; })), std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<double(double, const std::string&)>>( [](double x, const std::string&) -> double { return x; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::string_t); } SECTION("builtin function R*string -> R (using builtin function result)") { std::string_view data = R"( foo(foo(3),"bar"); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( [](double x) -> double { return x; })), std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<double(double, const std::string&)>>( [](double x, const std::string&) -> double { return x; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::string_t); } SECTION("builtin function N -> N (choosing appropriate candidate)") { std::string_view data = R"( foo(2); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( [](double x) -> double { return x; })), std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<int64_t(int64_t)>>( [](int64_t n) -> int64_t { return n; })), std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<double(double, const std::string&)>>( [](double x, const std::string&) -> double { return x; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::int_t); } SECTION("builtin function R -> R (using function result)") { std::string_view data = R"( let f: R -> R, x -> x+1; foo(f(3)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( [](double x) -> double { return x; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); } SECTION("builtin function R*string -> R (using function result)") { std::string_view data = R"( let f : R -> R*string, x -> (x,"bar"+x); foo(f(3)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( [](double x) -> double { return x; })), std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<double(double, const std::string&)>>( [](double x, const std::string&) -> double { return x; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::string_t); } } SECTION("using R^1 arguments") { SECTION("builtin function R*R^1 -> R^1") { std::string_view data = R"( let x:R^1; foo(3,x); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyVector<1>(double, const TinyVector<1>&)>>( [](double a, const TinyVector<1>& x) -> TinyVector<1> { return a * x; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getReturnDataType().dimension() == 1); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[1].dimension() == 1); } SECTION("builtin function R*R^1 -> R^2") { std::string_view data = R"( foo(3,1); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyVector<2>(double, const TinyVector<1>&)>>( [](double a, const TinyVector<1>& x) -> TinyVector<2> { return {a, x[0]}; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getReturnDataType().dimension() == 2); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[1].dimension() == 1); } SECTION("builtin function R*R^1 -> R^2") { std::string_view data = R"( let f : R -> R^1, x -> x; foo(3.1,f(1)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyVector<2>(double, const TinyVector<1>&)>>( [](double a, const TinyVector<1>& x) -> TinyVector<2> { return {a, x[0]}; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getReturnDataType().dimension() == 2); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[1].dimension() == 1); } SECTION("builtin function R^1 -> R^2 (from f: R -> R*R^1)") { std::string_view data = R"( let f : R -> R*R^1, x -> (2+x, 2*x); foo(f(2)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyVector<2>(double, const TinyVector<1>&)>>( [](double a, const TinyVector<1>& x) -> TinyVector<2> { return {a, x[0]}; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getReturnDataType().dimension() == 2); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[1].dimension() == 1); } } SECTION("using R^2 arguments") { SECTION("builtin function R*R^2 -> R^2") { std::string_view data = R"( let x:R^2; foo(3,x); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyVector<2>(double, const TinyVector<2>&)>>( [](double a, const TinyVector<2>& x) -> TinyVector<2> { return a * x; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getReturnDataType().dimension() == 2); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[1].dimension() == 2); } SECTION("builtin function R*R^2 -> R^3") { std::string_view data = R"( foo(3,0); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyVector<3>(double, const TinyVector<2>&)>>( [](double a, const TinyVector<2>& x) -> TinyVector<3> { return {a, x[0], x[1]}; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getReturnDataType().dimension() == 3); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[1].dimension() == 2); } SECTION("builtin function R*R^2 -> R^2 (R^2 from list)") { std::string_view data = R"( foo(3.1,(1,2.3)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyVector<2>(double, const TinyVector<2>&)>>( [](double a, const TinyVector<2>& x) -> TinyVector<2> { return {a * x[1], x[0]}; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getReturnDataType().dimension() == 2); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[1].dimension() == 2); } } SECTION("using R^3 arguments") { SECTION("builtin function R*R^3 -> R^2") { std::string_view data = R"( let x:R^3; foo(3,x); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyVector<2>(double, const TinyVector<3>&)>>( [](double a, const TinyVector<3>& x) -> TinyVector<2> { return {a * x[0], x[1] + x[2]}; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getReturnDataType().dimension() == 2); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[1].dimension() == 3); } SECTION("builtin function R*R^3 -> R^3") { std::string_view data = R"( foo(3,0); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyVector<3>(double, const TinyVector<3>&)>>( [](double a, const TinyVector<3>& x) -> TinyVector<3> { return {a * x}; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getReturnDataType().dimension() == 3); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[1].dimension() == 3); } SECTION("builtin function R*R^3 -> R^2 (R^3 from list)") { std::string_view data = R"( foo(3.1,(1,2.3,4)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyVector<2>(double, const TinyVector<3>&)>>( [](double a, const TinyVector<3>& x) -> TinyVector<2> { return {a * x[1], x[0] * x[2]}; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getReturnDataType().dimension() == 2); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[1].dimension() == 3); } } SECTION("using R^1x1 arguments") { SECTION("builtin function R*R^1x1 -> R^1x1") { std::string_view data = R"( let x:R^1x1; foo(3,x); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyMatrix<1>(double, const TinyMatrix<1>&)>>( [](double a, const TinyMatrix<1>& x) -> TinyMatrix<1> { return a * x; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getReturnDataType().numberOfRows() == 1); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[1].numberOfRows() == 1); } SECTION("builtin function R*R^1x1 -> R^2x2") { std::string_view data = R"( foo(3,1); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyMatrix<2>(double, const TinyMatrix<1>&)>>( [](double a, const TinyMatrix<1>& x) -> TinyMatrix<2> { return {a, x(0, 0), a * x(0, 0), x(0, 0)}; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getReturnDataType().numberOfRows() == 2); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[1].numberOfRows() == 1); } SECTION("builtin function R*R^1x1 -> R^2x2") { std::string_view data = R"( let f : R -> R^1x1, x -> x; foo(3.1,f(1)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyMatrix<2>(double, const TinyMatrix<1>&)>>( [](double a, const TinyMatrix<1>& x) -> TinyMatrix<2> { return {a, x(0, 0), 2 + x(0, 0), 1}; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getReturnDataType().numberOfRows() == 2); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[1].numberOfRows() == 1); } SECTION("builtin function R^1x1 -> R^2x2 (from f: R -> R*R^1x1)") { std::string_view data = R"( let f : R -> R*R^1x1, x -> (2+x, 2*x); foo(f(2)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyMatrix<2>(double, const TinyMatrix<1>&)>>( [](double a, const TinyMatrix<1>& x) -> TinyMatrix<2> { return {a, x(0, 0), a + x(0, 0), 1}; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getReturnDataType().numberOfColumns() == 2); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[1].numberOfRows() == 1); } } SECTION("using R^2x2 arguments") { SECTION("builtin function R*R^2x2 -> R^2x2") { std::string_view data = R"( let x:R^2x2; foo(3,x); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyMatrix<2>(double, const TinyMatrix<2>&)>>( [](double a, const TinyMatrix<2>& x) -> TinyMatrix<2> { return a * x; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getReturnDataType().numberOfRows() == 2); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[1].numberOfRows() == 2); } SECTION("builtin function R*R^2x2 -> R^3x3") { std::string_view data = R"( foo(3,0); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyMatrix<3>(double, const TinyMatrix<2>&)>>( [](double a, const TinyMatrix<2>& x) -> TinyMatrix<3> { return {a, x(0, 0), x(1, 0), // a, x(1, 0), x(1, 1), // a, x(0, 0), x(1, 1)}; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getReturnDataType().numberOfRows() == 3); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[1].numberOfRows() == 2); } SECTION("builtin function R*R^2x2 -> R^2x2 (R^2x2 from list)") { std::string_view data = R"( foo(3.1,(1,2.3,0,3)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyMatrix<2>(double, const TinyMatrix<2>&)>>( [](double a, const TinyMatrix<2>& x) -> TinyMatrix<2> { return {a * x(0, 0), x(1, 1), a, x(1, 0)}; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getReturnDataType().numberOfRows() == 2); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[1].numberOfRows() == 2); } } SECTION("using R^3x3 arguments") { SECTION("builtin function R*R^3x3 -> R^2x2") { std::string_view data = R"( let x:R^3x3; foo(3,x); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyMatrix<2>(double, const TinyMatrix<3>&)>>( [](double a, const TinyMatrix<3>& x) -> TinyMatrix<2> { return {a * x(0, 0), x(1, 0) + x(0, 1), // a, x(1, 1)}; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getReturnDataType().numberOfRows() == 2); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[1].numberOfRows() == 3); } SECTION("builtin function R*R^3x3 -> R^3x3") { std::string_view data = R"( foo(3,0); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyMatrix<3>(double, const TinyMatrix<3>&)>>( [](double a, const TinyMatrix<3>& x) -> TinyMatrix<3> { return {a * x}; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getReturnDataType().numberOfRows() == 3); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[1].numberOfRows() == 3); } SECTION("builtin function R*R^3x3 -> R^2x2 (R^3x3 from list)") { std::string_view data = R"( foo(3.1,(1, 2.3, 4, 0.3, 2.5, 4.6, 2.7, 8.1, -9)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<TinyMatrix<2>(double, const TinyMatrix<3>&)>>( [](double a, const TinyMatrix<3>& x) -> TinyMatrix<2> { return {a * x(1, 1), x(1, 0), // x(0, 1), a * x(0, 0)}; }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getReturnDataType().numberOfRows() == 2); REQUIRE(function_embedder->getParameterDataTypes().size() == 2); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[1].numberOfRows() == 3); } } SECTION("using tuple arguments") { SECTION("builtin function (R...) -> N (from (N...))") { std::string_view data = R"( let v:(N); foo(v); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<uint64_t(const std::vector<double>&)>>( [](const std::vector<double>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::double_t); } SECTION("builtin function (R...) -> N (from Z)") { std::string_view data = R"( foo(-4); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<uint64_t(const std::vector<double>&)>>( [](const std::vector<double>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::double_t); } SECTION("builtin function (R^1...) -> N (from (N...))") { std::string_view data = R"( let v:(N); foo(v); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyVector<1>>&)>>( [](const std::vector<TinyVector<1>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().dimension() == 1); } SECTION("builtin function (R^1...) -> N (from 0)") { std::string_view data = R"( foo(0); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyVector<1>>&)>>( [](const std::vector<TinyVector<1>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().dimension() == 1); } SECTION("builtin function (R...) -> N (from list)") { std::string_view data = R"( foo((1,2,3,5)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared< BuiltinFunctionEmbedder<uint64_t(const std::vector<double>&)>>( [](const std::vector<double>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::double_t); } SECTION("builtin function (R^1...) -> N (from castable list)") { std::string_view data = R"( foo((1,2,3,5)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyVector<1>>&)>>( [](const std::vector<TinyVector<1>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().dimension() == 1); } SECTION("builtin function (R^1...) -> N (from list)") { std::string_view data = R"( let x:R^1; foo((x,2*x)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyVector<1>>&)>>( [](const std::vector<TinyVector<1>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().dimension() == 1); } SECTION("builtin function (R^1x1...) -> N (from castable list)") { std::string_view data = R"( foo((1,2,3,5)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyMatrix<1>>&)>>( [](const std::vector<TinyMatrix<1>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().numberOfRows() == 1); } SECTION("builtin function (R^1x1...) -> N (from 0)") { std::string_view data = R"( foo(0); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyMatrix<1>>&)>>( [](const std::vector<TinyMatrix<1>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().numberOfRows() == 1); } SECTION("builtin function (R^1x1...) -> N (from list)") { std::string_view data = R"( let x:R^1x1; foo((x,2*x)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyMatrix<1>>&)>>( [](const std::vector<TinyMatrix<1>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().numberOfRows() == 1); } SECTION("builtin function (R^2...) -> N (from list)") { std::string_view data = R"( let x:R^2; foo((x,2*x)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyVector<2>>&)>>( [](const std::vector<TinyVector<2>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().dimension() == 2); } SECTION("builtin function (R^2...) -> N (from 0)") { std::string_view data = R"( foo(0); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyVector<2>>&)>>( [](const std::vector<TinyVector<2>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().dimension() == 2); } SECTION("builtin function (R^2x2...) -> N (from castable list)") { std::string_view data = R"( foo((1,2,3)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyMatrix<2>>&)>>( [](const std::vector<TinyMatrix<2>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().numberOfRows() == 2); } SECTION("builtin function (R^2x2...) -> N (from 0)") { std::string_view data = R"( foo(0); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyMatrix<2>>&)>>( [](const std::vector<TinyMatrix<2>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().numberOfRows() == 2); } SECTION("builtin function (R^2x2...) -> N (from list)") { std::string_view data = R"( let x:R^2x2; foo((x,2*x)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyMatrix<2>>&)>>( [](const std::vector<TinyMatrix<2>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().numberOfRows() == 2); } SECTION("builtin function (R^3...) -> N (from list)") { std::string_view data = R"( let x:R^3; foo((x,2*x)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyVector<3>>&)>>( [](const std::vector<TinyVector<3>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().dimension() == 3); } SECTION("builtin function (R^3...) -> N (from 0)") { std::string_view data = R"( foo(0); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyVector<3>>&)>>( [](const std::vector<TinyVector<3>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().dimension() == 3); } SECTION("builtin function (R^3x3...) -> N (from castable list)") { std::string_view data = R"( foo((1,2,3)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyMatrix<3>>&)>>( [](const std::vector<TinyMatrix<3>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().numberOfRows() == 3); } SECTION("builtin function (R^3x3...) -> N (from 0)") { std::string_view data = R"( foo(0); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyMatrix<3>>&)>>( [](const std::vector<TinyMatrix<3>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().numberOfRows() == 3); } SECTION("builtin function (R^3x3...) -> N (from list)") { std::string_view data = R"( let x:R^3x3; foo((x,2*x)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<TinyMatrix<3>>&)>>( [](const std::vector<TinyMatrix<3>>& x) -> uint64_t { return x.size(); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::unsigned_int_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 1); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[0].contentType().numberOfRows() == 3); } } SECTION("complete case") { std::string_view data = R"( let x:R^3x3; foo(1, "bar", (x,2*x), (2,3)); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< std::tuple<uint64_t, double, std::string>(const double&, const std::string&, const std::vector<TinyMatrix<3>>&, const TinyVector<2>&)>>( [](const double& a, const std::string& s, const std::vector<TinyMatrix<3>>& x, const TinyVector<2>& y) -> std::tuple<uint64_t, double, std::string> { return std::make_tuple(x.size(), a * y[0] + y[1], s + "_foo"); }))}); auto function_embedder = getBuiltinFunctionEmbedder(*root_node->children[0]); REQUIRE(function_embedder->getReturnDataType() == ASTNodeDataType::list_t); REQUIRE(function_embedder->getReturnDataType().contentTypeList().size() == 3); REQUIRE(*function_embedder->getReturnDataType().contentTypeList()[0] == ASTNodeDataType::unsigned_int_t); REQUIRE(*function_embedder->getReturnDataType().contentTypeList()[1] == ASTNodeDataType::double_t); REQUIRE(*function_embedder->getReturnDataType().contentTypeList()[2] == ASTNodeDataType::string_t); REQUIRE(function_embedder->getParameterDataTypes().size() == 4); REQUIRE(function_embedder->getParameterDataTypes()[0] == ASTNodeDataType::double_t); REQUIRE(function_embedder->getParameterDataTypes()[1] == ASTNodeDataType::string_t); REQUIRE(function_embedder->getParameterDataTypes()[2] == ASTNodeDataType::tuple_t); REQUIRE(function_embedder->getParameterDataTypes()[2].contentType() == ASTNodeDataType::matrix_t); REQUIRE(function_embedder->getParameterDataTypes()[2].contentType().numberOfRows() == 3); REQUIRE(function_embedder->getParameterDataTypes()[3] == ASTNodeDataType::vector_t); REQUIRE(function_embedder->getParameterDataTypes()[3].dimension() == 2); } SECTION("errors") { SECTION("R^1: invalid conversion") { std::string_view data = R"( let x:R^3; foo(x); )"; std::string error_msg = "no matching function to call foo: R^3\n" "note: candidates are\n" " foo: R^1 -> R\n" " foo: R -> R"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); REQUIRE_THROWS_WITH(register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const TinyVector<1>)>>( [](const TinyVector<1>& x) -> double { return x[0]; })), std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const double&)>>( [](const double& x) -> double { return x; }))}), error_msg); } SECTION("R^2: invalid conversion") { std::string_view data = R"( let x:R^3; foo(x); )"; std::string error_msg = "no matching function to call foo: R^3\n" "note: candidates are\n" " foo: R^2 -> R\n" " foo: R -> R"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); REQUIRE_THROWS_WITH(register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const TinyVector<2>)>>( [](const TinyVector<2>& x) -> double { return x[1]; })), std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const double&)>>( [](const double& x) -> double { return x; }))}), error_msg); } SECTION("R^3: invalid conversion") { std::string_view data = R"( let x:R^2; foo(x); )"; std::string error_msg = "no matching function to call foo: R^2\n" "note: candidates are\n" " foo: R^3 -> R\n" " foo: R -> R"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); REQUIRE_THROWS_WITH(register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const TinyVector<3>)>>( [](const TinyVector<3>& x) -> double { return x[1]; })), std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const double&)>>( [](const double& x) -> double { return x; }))}), error_msg); } SECTION("R^2: invalid argument list size") { std::string_view data = R"( foo((1,2,3,4)); )"; std::string error_msg = "no matching function to call foo: Z*Z*Z*Z\n" "note: candidates are\n" " foo: R^2 -> R\n" " foo: R -> R"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); REQUIRE_THROWS_WITH(register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const TinyVector<2>)>>( [](const TinyVector<2>& x) -> double { return x[1]; })), std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const double&)>>( [](const double& x) -> double { return x; }))}), error_msg); } SECTION("R^3: invalid argument list size") { std::string_view data = R"( foo((1,2,3,4)); )"; std::string error_msg = "no matching function to call foo: Z*Z*Z*Z\n" "note: candidates are\n" " foo: R^3 -> R\n" " foo: R -> R"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); REQUIRE_THROWS_WITH(register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const TinyVector<3>)>>( [](const TinyVector<3>& x) -> double { return x[1]; })), std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const double&)>>( [](const double& x) -> double { return x; }))}), error_msg); } SECTION("R^1x1: invalid conversion") { std::string_view data = R"( let x:R^3x3; foo(x); )"; std::string error_msg = "no matching function to call foo: R^3x3\n" "note: candidates are\n" " foo: R^1x1 -> R\n" " foo: R -> R"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); REQUIRE_THROWS_WITH(register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const TinyMatrix<1>)>>( [](const TinyMatrix<1>& x) -> double { return x(0, 0); })), std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const double&)>>( [](const double& x) -> double { return x; }))}), error_msg); } SECTION("R^2x2: invalid conversion") { std::string_view data = R"( let x:R^3x3; foo(x); )"; std::string error_msg = "no matching function to call foo: R^3x3\n" "note: candidates are\n" " foo: R^2x2 -> R\n" " foo: R -> R"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); REQUIRE_THROWS_WITH(register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const TinyMatrix<2>)>>( [](const TinyMatrix<2>& x) -> double { return x(0, 0); })), std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const double&)>>( [](const double& x) -> double { return x; }))}), error_msg); } SECTION("R^3x3: invalid conversion") { std::string_view data = R"( let x:R^2x2; foo(x); )"; std::string error_msg = "no matching function to call foo: R^2x2\n" "note: candidates are\n" " foo: R^3x3 -> R\n" " foo: R -> R"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); REQUIRE_THROWS_WITH(register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const TinyMatrix<3>)>>( [](const TinyMatrix<3>& x) -> double { return x(1, 2); })), std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const double&)>>( [](const double& x) -> double { return x; }))}), error_msg); } SECTION("R^2x2: invalid argument list size") { std::string_view data = R"( foo((1,2,3)); )"; std::string error_msg = "no matching function to call foo: Z*Z*Z\n" "note: candidates are\n" " foo: R^2x2 -> R\n" " foo: R -> R"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); REQUIRE_THROWS_WITH(register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const TinyMatrix<2>)>>( [](const TinyMatrix<2>& x) -> double { return x(0, 0); })), std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const double&)>>( [](const double& x) -> double { return x; }))}), error_msg); } SECTION("R^3x3: invalid argument list size") { std::string_view data = R"( foo((1,2,3,4)); )"; std::string error_msg = "no matching function to call foo: Z*Z*Z*Z\n" "note: candidates are\n" " foo: R^3x3 -> R\n" " foo: R -> R"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); REQUIRE_THROWS_WITH(register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const TinyMatrix<3>)>>( [](const TinyMatrix<3>& x) -> double { return x(1, 2); })), std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const double&)>>( [](const double& x) -> double { return x; }))}), error_msg); } SECTION("(N...) invalid cast") { std::string_view data = R"( foo(1.34); )"; std::string error_msg = "no matching function to call foo: R\n" "note: candidates are\n" " foo: (N...) -> N"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); REQUIRE_THROWS_WITH(register_functions(root_node, FunctionList{ std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder<uint64_t( const std::vector<uint64_t>&)>>( [](const std::vector<uint64_t>& t) -> uint64_t { return t.size(); }))}), error_msg); } SECTION("ambiguous function call") { std::string_view data = R"( foo(1); )"; std::string error_msg = "ambiguous function call foo: Z\n" "note: candidates are\n" " foo: (R...) -> R\n" " foo: R -> R\n" " foo: R^1 -> R"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); REQUIRE_THROWS_WITH(register_functions(root_node, FunctionList{std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const std::vector<double>&)>>( [](const std::vector<double>& x) -> double { return x.size(); })), std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const double&)>>( [](const double& x) -> double { return x; })), std::make_pair("foo", std::make_shared<BuiltinFunctionEmbedder< double(const TinyVector<1>&)>>( [](const TinyVector<1>& x) -> double { return x[0]; }))}), error_msg); } } }