diff --git a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp index 70d8e3b3ac10456eb28c0036fdfa31eb1630bcab..54b0970eff20190d4b57d2adfc596ba71cf174d0 100644 --- a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp @@ -231,9 +231,6 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } case ASTNodeDataType::double_t: { return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, double>>(argument_number); - } - case ASTNodeDataType::function_t: { - return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, FunctionSymbolId>>(argument_number); } // LCOV_EXCL_START default: { @@ -513,11 +510,13 @@ ASTNodeBuiltinFunctionExpressionBuilder::_buildArgumentProcessors( const size_t parameters_number = parameter_type_list.size(); if (arguments_number != parameters_number) { + // LCOV_EXCL_START std::ostringstream error_message; error_message << "bad number of arguments: expecting " << rang::fgB::yellow << parameters_number << rang::style::reset << rang::style::bold << ", provided " << rang::fgB::yellow << arguments_number << rang::style::reset; - throw ParseError(error_message.str(), argument_nodes.begin()); + throw UnexpectedError(error_message.str()); + // LCOV_EXCL_STOP } for (size_t i = 0; i < arguments_number; ++i) { diff --git a/src/language/ast/ASTNodeDataTypeFlattener.cpp b/src/language/ast/ASTNodeDataTypeFlattener.cpp index 7212d6b001a12de45e6b81e2955a80fe71cd07b4..9cc1fa483196815ed97b3b8134797b79aeea770e 100644 --- a/src/language/ast/ASTNodeDataTypeFlattener.cpp +++ b/src/language/ast/ASTNodeDataTypeFlattener.cpp @@ -40,9 +40,11 @@ ASTNodeDataTypeFlattener::ASTNodeDataTypeFlattener(ASTNode& node, FlattenedDataT {ASTNodeDataType::build<ASTNodeDataType::type_id_t>(image_sub_domain->m_data_type.nameOfTypeId()), node}); break; } + // LCOV_EXCL_START default: { throw UnexpectedError("invalid data type"); } + // LCOV_EXCL_STOP } } break; diff --git a/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp index 6c1db0335b2f46a8410baed7f02e59efa6ae49c8..6a91a15d13978b423daa563c1b668c5fe0f93489 100644 --- a/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp @@ -523,9 +523,11 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node case ASTNodeDataType::type_id_t: { return ASTNodeDataType::build<ASTNodeDataType::type_id_t>(image_domain_node.m_data_type.nameOfTypeId()); } + // LCOV_EXCL_START default: { throw UnexpectedError("invalid function return type"); } + // LCOV_EXCL_STOP } }(); @@ -546,9 +548,11 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node case ASTNodeDataType::type_id_t: { return ASTNodeDataType::build<ASTNodeDataType::type_id_t>(function_image_domain.m_data_type.nameOfTypeId()); } + // LCOV_EXCL_START default: { throw UnexpectedError("invalid function return type"); } + // LCOV_EXCL_STOP } }(); diff --git a/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp b/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp index dc438e61f5aa8ea2ad0f4d3d2b0879c0e2ec0f0e..edec0c149615f28a35256afc62f3ceef3182c3e1 100644 --- a/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp @@ -133,7 +133,8 @@ ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor( // LCOV_EXCL_STOP } } else { - throw ParseError("unexpected error: undefined operator type for string affectation", std::vector{m_node.begin()}); + throw ParseError("unexpected error: undefined operator type for embedded data affectation", + std::vector{m_node.begin()}); } }; @@ -286,11 +287,11 @@ ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor( if (optional_processor_builder.has_value()) { add_affectation_processor_for_value(value_node.m_data_type, rhs_node_sub_data_type); } else { + // LCOV_EXCL_START std::ostringstream error_message; - error_message << "undefined affectation type: "; - error_message << rang::fgB::red << affectation_name << rang::fg::reset; - - throw ParseError(error_message.str(), std::vector{m_node.children[0]->begin()}); + error_message << "undefined affectation type: " << rang::fgB::red << affectation_name << rang::fg::reset; + throw UnexpectedError(error_message.str()); + // LCOV_EXCL_STOP } } diff --git a/src/language/utils/BuiltinFunctionEmbedderUtils.cpp b/src/language/utils/BuiltinFunctionEmbedderUtils.cpp index 1c7723ff1c3f2b510db742dd9b647f643b83d303..ba6658ff7b5dc901182c62f7a07c0018ed94bd5a 100644 --- a/src/language/utils/BuiltinFunctionEmbedderUtils.cpp +++ b/src/language/utils/BuiltinFunctionEmbedderUtils.cpp @@ -28,8 +28,9 @@ getBuiltinFunctionEmbedder(ASTNode& n) FunctionDescriptor& function_descriptor = argument_node.m_symbol_table->functionTable()[function_id]; ASTNode& function_image_domain = *function_descriptor.domainMappingNode().children[1]; - - if (function_image_domain.children.size() > 0) { + if (not(function_image_domain.is_type<language::vector_type>() or + function_image_domain.is_type<language::matrix_type>()) and + function_image_domain.children.size() > 0) { for (size_t i = 0; i < function_image_domain.children.size(); ++i) { arg_type_list.push_back(function_image_domain.children[i]->m_data_type); } @@ -43,9 +44,11 @@ getBuiltinFunctionEmbedder(ASTNode& n) arg_type_list.push_back(builtin_function->getReturnDataType()); break; } + // LCOV_EXCL_START default: { throw UnexpectedError("unexpected function type"); } + // LCOV_EXCL_STOP } } else { arg_type_list.push_back(argument_node.m_data_type); diff --git a/src/language/utils/SymbolTable.hpp b/src/language/utils/SymbolTable.hpp index 7321994564a8810b10e81d60503a55226abf0c56..ca674a1bb7e8053b1f2401b066d0a5c38c6f8151 100644 --- a/src/language/utils/SymbolTable.hpp +++ b/src/language/utils/SymbolTable.hpp @@ -285,14 +285,13 @@ class SymbolTable std::vector<Symbol> builtin_function_symbol_list; for (auto i_stored_symbol : m_symbol_list) { - if (use_position.byte < i_stored_symbol.attributes().position().byte) - continue; - // Symbol must be defined before the call - std::string_view stored_symbol_name = i_stored_symbol.name(); - if ((stored_symbol_name.size() > symbol.size()) and (stored_symbol_name[symbol.size()] == ':')) { - if (stored_symbol_name.substr(0, symbol.size()) == symbol) { - builtin_function_symbol_list.push_back(i_stored_symbol); + if (use_position.byte >= i_stored_symbol.attributes().position().byte) { + std::string_view stored_symbol_name = i_stored_symbol.name(); + if ((stored_symbol_name.size() > symbol.size()) and (stored_symbol_name[symbol.size()] == ':')) { + if (stored_symbol_name.substr(0, symbol.size()) == symbol) { + builtin_function_symbol_list.push_back(i_stored_symbol); + } } } } @@ -308,15 +307,14 @@ class SymbolTable has(const std::string& symbol, const TAO_PEGTL_NAMESPACE::position& use_position) { for (auto i_stored_symbol : m_symbol_list) { - if (use_position.byte < i_stored_symbol.attributes().position().byte) - continue; - // Symbol must be defined before the call - std::string_view stored_symbol_name = i_stored_symbol.name(); - if ((stored_symbol_name.size() == symbol.size()) or - (stored_symbol_name.size() > symbol.size() and (stored_symbol_name[symbol.size()] == ':'))) { - if (stored_symbol_name.substr(0, symbol.size()) == symbol) { - return true; + if (use_position.byte >= i_stored_symbol.attributes().position().byte) { + std::string_view stored_symbol_name = i_stored_symbol.name(); + if ((stored_symbol_name.size() == symbol.size()) or + (stored_symbol_name.size() > symbol.size() and (stored_symbol_name[symbol.size()] == ':'))) { + if (stored_symbol_name.substr(0, symbol.size()) == symbol) { + return true; + } } } } @@ -355,15 +353,8 @@ class SymbolTable add(const std::string& symbol_name, const TAO_PEGTL_NAMESPACE::position& symbol_position) { for (auto i_stored_symbol = m_symbol_list.begin(); i_stored_symbol != m_symbol_list.end(); ++i_stored_symbol) { - std::string_view stored_symbol_name = i_stored_symbol->name(); - if (stored_symbol_name.size() == symbol_name.size()) { - if (stored_symbol_name == symbol_name) { - return std::make_pair(i_stored_symbol, false); - } else if (stored_symbol_name.size() > symbol_name.size() and (stored_symbol_name[symbol_name.size()] == ':')) { - if (stored_symbol_name.substr(0, symbol_name.size()) == symbol_name) { - return std::make_pair(i_stored_symbol, false); - } - } + if (i_stored_symbol->name() == symbol_name) { + return std::make_pair(i_stored_symbol, false); } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 06967be54d53c7ff8e88d6ec38d675381cd8ad07..8cea83f7294e107b28db9f223cd989c33a5a6c2d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -47,6 +47,7 @@ add_executable (unit_tests test_BiCGStab.cpp test_BuildInfo.cpp test_BuiltinFunctionEmbedder.cpp + test_BuiltinFunctionEmbedderUtils.cpp test_BuiltinFunctionEmbedderTable.cpp test_BuiltinFunctionProcessor.cpp test_CastArray.cpp diff --git a/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp b/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp index d7cd62afe7e4260d14640287ad440355dab59898..7fb68cd69c16331c07db8354a40dcb029fcb5c14 100644 --- a/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp +++ b/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp @@ -1664,6 +1664,42 @@ fidToR(f); CHECK_AST(data, result); } + + SECTION("tuple(FunctionSymbolId) -> R") + { + std::string_view data = R"( +let f : R^3 -> R, x -> 0; +fidTupleToR((f,f)); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:BuiltinFunctionProcessor) + +-(language::name:fidTupleToR:FakeProcessor) + `-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>) + +-(language::name:f:NameProcessor) + `-(language::name:f:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("tuple(FunctionSymbolId) -> R [with single value tuple]") + { + std::string_view data = R"( +let f : R^3 -> R, x -> 0; +fidTupleToR(f); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:BuiltinFunctionProcessor) + +-(language::name:fidTupleToR:FakeProcessor) + `-(language::name:f:NameProcessor) +)"; + + CHECK_AST(data, result); + } } SECTION("errors") diff --git a/tests/test_ASTNodeDataTypeBuilder.cpp b/tests/test_ASTNodeDataTypeBuilder.cpp index 346807df3b58e189a7e1283850fbdda54264abbb..96af38a0b905014ea518653795ba95850e486055 100644 --- a/tests/test_ASTNodeDataTypeBuilder.cpp +++ b/tests/test_ASTNodeDataTypeBuilder.cpp @@ -1002,6 +1002,21 @@ let cat : string*N -> string, (s,n) -> s+n; CHECK_AST(data, result); } + SECTION("builtin-functions") + { + std::string_view data = R"( +let foo : builtin_t*N -> builtin_t, (b,n) -> b; +)"; + + std::string_view result = R"( +(root:void) + `-(language::fct_declaration:void) + `-(language::name:foo:function) +)"; + + CHECK_AST_WITH_BUILTIN(data, result); + } + SECTION("errors") { SECTION("wrong parameter number") @@ -1312,6 +1327,35 @@ let s : string, s = cat("foo", "bar"); CHECK_AST(data, result); } + SECTION("bultin_t-function") + { + std::string_view data = R"( +let foo : builtin_t*N -> builtin_t, (b,n) -> b; +let b0: builtin_t; +let b : builtin_t, b = foo(b0, 1); +)"; + + std::string_view result = R"( +(root:void) + +-(language::fct_declaration:void) + | `-(language::name:foo:function) + +-(language::var_declaration:void) + | +-(language::name:b0:builtin_t) + | `-(language::type_name_id:builtin_t) + `-(language::var_declaration:void) + +-(language::name:b:builtin_t) + +-(language::type_name_id:builtin_t) + +-(language::name:b:builtin_t) + `-(language::function_evaluation:builtin_t) + +-(language::name:foo:function) + `-(language::function_argument_list:builtin_t*Z) + +-(language::name:b0:builtin_t) + `-(language::integer:1:Z) +)"; + + CHECK_AST_WITH_BUILTIN(data, result); + } + SECTION("compound return function") { std::string_view data = R"( diff --git a/tests/test_ASTNodeDataTypeFlattener.cpp b/tests/test_ASTNodeDataTypeFlattener.cpp index d4b4bbe6c65e7bc0a110d70b406b24f678f82576..aaa3739b2266f45e9c62b8a606000749468c33d8 100644 --- a/tests/test_ASTNodeDataTypeFlattener.cpp +++ b/tests/test_ASTNodeDataTypeFlattener.cpp @@ -8,6 +8,9 @@ #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> #include <language/ast/ASTNodeTypeCleaner.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> +#include <language/utils/ASTNodeDataTypeTraits.hpp> +#include <language/utils/BasicAffectationRegistrerFor.hpp> +#include <language/utils/TypeDescriptor.hpp> #include <test_BuiltinFunctionRegister.hpp> @@ -106,11 +109,11 @@ f(2); REQUIRE(&flattened_datatype_list[0].m_parent_node == root_node->children[0].get()); } - SECTION("function evaluation -> N*R*B*string*Z") + SECTION("function evaluation -> N*R*B*string*Z*builtin_t") { std::string_view data = R"( -let f: N -> N*R*B*string*Z, n -> (n, 0.5*n, n>2, n, 3-n); -f(2); +let f: N*builtin_t -> N*R*B*string*Z*builtin_t, (n,b) -> (n, 0.5*n, n>2, n, 3-n, b); +f(2, b); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; @@ -118,6 +121,21 @@ f(2); ASTModulesImporter{*root_node}; ASTNodeTypeCleaner<language::import_instruction>{*root_node}; + SymbolTable& symbol_table = *root_node->m_symbol_table; + + auto [i_symbol, success] = symbol_table.add(builtin_data_type.nameOfTypeId(), root_node->begin()); + if (not success) { + throw UnexpectedError("cannot add '" + builtin_data_type.nameOfTypeId() + "' type for testing"); + } + + i_symbol->attributes().setDataType(ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>()); + i_symbol->attributes().setIsInitialized(); + i_symbol->attributes().value() = symbol_table.typeEmbedderTable().size(); + symbol_table.typeEmbedderTable().add(std::make_shared<TypeDescriptor>(builtin_data_type.nameOfTypeId())); + + auto [i_b_symbol, b_success] = symbol_table.add("b", root_node->begin()); + i_b_symbol->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>); + i_b_symbol->attributes().setIsInitialized(); ASTSymbolTableBuilder{*root_node}; ASTNodeDataTypeBuilder{*root_node}; @@ -133,12 +151,13 @@ f(2); ASTNodeDataTypeFlattener::FlattenedDataTypeList flattened_datatype_list; ASTNodeDataTypeFlattener{*root_node->children[0], flattened_datatype_list}; - REQUIRE(flattened_datatype_list.size() == 5); + REQUIRE(flattened_datatype_list.size() == 6); REQUIRE(flattened_datatype_list[0].m_data_type == ASTNodeDataType::unsigned_int_t); REQUIRE(flattened_datatype_list[1].m_data_type == ASTNodeDataType::double_t); REQUIRE(flattened_datatype_list[2].m_data_type == ASTNodeDataType::bool_t); REQUIRE(flattened_datatype_list[3].m_data_type == ASTNodeDataType::string_t); REQUIRE(flattened_datatype_list[4].m_data_type == ASTNodeDataType::int_t); + REQUIRE(flattened_datatype_list[5].m_data_type == ASTNodeDataType::type_id_t); } SECTION("function evaluation -> R*R^3") diff --git a/tests/test_ASTNodeFunctionExpressionBuilder.cpp b/tests/test_ASTNodeFunctionExpressionBuilder.cpp index d10d243a8de7b16b3b6c33bc81d55343b2298953..b37dd10869bb5665c9292b22e363af09be4b9ead 100644 --- a/tests/test_ASTNodeFunctionExpressionBuilder.cpp +++ b/tests/test_ASTNodeFunctionExpressionBuilder.cpp @@ -9,34 +9,54 @@ #include <language/ast/ASTNodeFunctionExpressionBuilder.hpp> #include <language/ast/ASTNodeTypeCleaner.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> +#include <language/utils/ASTNodeDataTypeTraits.hpp> #include <language/utils/ASTPrinter.hpp> +#include <language/utils/BasicAffectationRegistrerFor.hpp> +#include <language/utils/TypeDescriptor.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); \ +template <> +inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> = + ASTNodeDataType::build<ASTNodeDataType::type_id_t>("builtin_t"); +const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const double>>; + +#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}; \ + BasicAffectationRegisterFor<EmbeddedData>{ASTNodeDataType::build<ASTNodeDataType::type_id_t>("builtin_t")}; \ + \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + SymbolTable& symbol_table = *ast->m_symbol_table; \ + auto [i_symbol, success] = symbol_table.add(builtin_data_type.nameOfTypeId(), ast->begin()); \ + if (not success) { \ + throw UnexpectedError("cannot add '" + builtin_data_type.nameOfTypeId() + "' type for testing"); \ + } \ + \ + i_symbol->attributes().setDataType(ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>()); \ + i_symbol->attributes().setIsInitialized(); \ + i_symbol->attributes().value() = symbol_table.typeEmbedderTable().size(); \ + symbol_table.typeEmbedderTable().add(std::make_shared<TypeDescriptor>(builtin_data_type.nameOfTypeId())); \ + \ + 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) \ @@ -938,6 +958,27 @@ f(2,(1,2,3),(2,3,-1,1.3)); } } + SECTION("return a builtin_t") + { + SECTION("builtin_t argument") + { + std::string_view data = R"( +let foo : builtin_t -> builtin_t, b -> b; +let b0 : builtin_t; +foo(b0); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:foo:NameProcessor) + `-(language::name:b0:NameProcessor) +)"; + + CHECK_AST(data, result); + } + } + SECTION("errors") { SECTION("wrong argument number") diff --git a/tests/test_ASTNodeListAffectationExpressionBuilder.cpp b/tests/test_ASTNodeListAffectationExpressionBuilder.cpp index 8ae86fa804a704c10e32c3fe3e5b986987e22de0..6eab14fe5162b64a1d883cd54d8b9a70e20a5d66 100644 --- a/tests/test_ASTNodeListAffectationExpressionBuilder.cpp +++ b/tests/test_ASTNodeListAffectationExpressionBuilder.cpp @@ -9,36 +9,56 @@ #include <language/ast/ASTNodeListAffectationExpressionBuilder.hpp> #include <language/ast/ASTNodeTypeCleaner.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> +#include <language/utils/ASTNodeDataTypeTraits.hpp> #include <language/utils/ASTPrinter.hpp> +#include <language/utils/BasicAffectationRegistrerFor.hpp> +#include <language/utils/TypeDescriptor.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}; \ - \ - ASTNodeDeclarationToAffectationConverter{*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); \ +template <> +inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> = + ASTNodeDataType::build<ASTNodeDataType::type_id_t>("builtin_t"); +const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const double>>; + +#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}; \ + BasicAffectationRegisterFor<EmbeddedData>{ASTNodeDataType::build<ASTNodeDataType::type_id_t>("builtin_t")}; \ + \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + SymbolTable& symbol_table = *ast->m_symbol_table; \ + auto [i_symbol, success] = symbol_table.add(builtin_data_type.nameOfTypeId(), ast->begin()); \ + if (not success) { \ + throw UnexpectedError("cannot add '" + builtin_data_type.nameOfTypeId() + "' type for testing"); \ + } \ + \ + i_symbol->attributes().setDataType(ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>()); \ + i_symbol->attributes().setIsInitialized(); \ + i_symbol->attributes().value() = symbol_table.typeEmbedderTable().size(); \ + symbol_table.typeEmbedderTable().add(std::make_shared<TypeDescriptor>(builtin_data_type.nameOfTypeId())); \ + \ + ASTSymbolTableBuilder{*ast}; \ + ASTNodeDataTypeBuilder{*ast}; \ + \ + ASTNodeDeclarationToAffectationConverter{*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_WITH(data, error) \ @@ -375,6 +395,26 @@ let (r,s,t,u) : string*string*string*string, CHECK_AST(data, result); } + + SECTION("embedded data") + { + std::string_view data = R"( +let (b0,b1): builtin_t*builtin_t, (b0,b1) = (b0,b1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:ListAffectationProcessor<language::eq_op>) + +-(language::name_list:FakeProcessor) + | +-(language::name:b0:NameProcessor) + | `-(language::name:b1:NameProcessor) + `-(language::expression_list:ASTNodeExpressionListProcessor) + +-(language::name:b0:NameProcessor) + `-(language::name:b1:NameProcessor) +)"; + + CHECK_AST(data, result); + } } SECTION("Errors") diff --git a/tests/test_BuiltinFunctionEmbedderUtils.cpp b/tests/test_BuiltinFunctionEmbedderUtils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..965d709b97187fbab363b4cacad7cde4f8ad7b7c --- /dev/null +++ b/tests/test_BuiltinFunctionEmbedderUtils.cpp @@ -0,0 +1,1605 @@ +#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); + } + } +} diff --git a/tests/test_BuiltinFunctionRegister.hpp b/tests/test_BuiltinFunctionRegister.hpp index 7c361c9df4a6e4c3071ccef00c070313dba2bb5b..0ac5226fcac218e5ad195e5f2ecbdef6aa058cb3 100644 --- a/tests/test_BuiltinFunctionRegister.hpp +++ b/tests/test_BuiltinFunctionRegister.hpp @@ -100,6 +100,11 @@ class test_BuiltinFunctionRegister std::make_pair("fidToR:function", std::make_shared<BuiltinFunctionEmbedder<double(const FunctionSymbolId&)>>( [](const FunctionSymbolId&) -> double { return 0; }))); + m_name_builtin_function_map.insert( + std::make_pair("fidTupleToR:(function...)", + std::make_shared<BuiltinFunctionEmbedder<double(const std::vector<FunctionSymbolId>)>>( + [](const std::vector<FunctionSymbolId>&) -> double { return 0; }))); + m_name_builtin_function_map.insert( std::make_pair("builtinToBuiltin:builtin_t", std::make_shared< diff --git a/tests/test_SymbolTable.cpp b/tests/test_SymbolTable.cpp index 2be1a3d81a104e631894184eaf67f0d2d63d44d2..78cd4373b9901aa69a65bc8bceaa4a7e68c1ad0b 100644 --- a/tests/test_SymbolTable.cpp +++ b/tests/test_SymbolTable.cpp @@ -3,6 +3,7 @@ #include <language/utils/BuiltinFunctionEmbedder.hpp> #include <language/utils/SymbolTable.hpp> +#include <language/utils/TypeDescriptor.hpp> #include <pegtl/internal/iterator.hpp> @@ -186,6 +187,29 @@ TEST_CASE("SymbolTable", "[language]") value_output << symbol.attributes(); REQUIRE(value_output.str() == "function_id:2"); } + + { + const SymbolTable::Symbol symbol_decl{i_symbol_a->name(), i_symbol_a->attributes()}; + SymbolTable::Attributes attributes_b = attributes_a; + SymbolTable::Symbol symbol("foo", attributes_b); + + symbol = symbol_decl; + + std::stringstream value_output; + value_output << symbol.attributes(); + REQUIRE(value_output.str() == "function_id:2"); + } + + { + SymbolTable::Attributes attributes_b = attributes_a; + SymbolTable::Symbol symbol("foo", attributes_b); + + symbol = SymbolTable::Symbol{i_symbol_a->name(), i_symbol_a->attributes()}; + + std::stringstream value_output; + value_output << symbol.attributes(); + REQUIRE(value_output.str() == "function_id:2"); + } } SECTION("FunctionTable") @@ -220,4 +244,20 @@ TEST_CASE("SymbolTable", "[language]") REQUIRE(builtin_function_table.size() == 1); REQUIRE(const_builtin_function_table.size() == 1); } + + SECTION("TypeEmbedderTable") + { + std::shared_ptr root_st = std::make_shared<SymbolTable>(); + + auto& type_table = root_st->typeEmbedderTable(); + REQUIRE(type_table.size() == 0); + + const auto& const_type_table = static_cast<const SymbolTable&>(*root_st).typeEmbedderTable(); + REQUIRE(const_type_table.size() == 0); + + type_table.add(std::make_shared<TypeDescriptor>("a_type")); + + REQUIRE(type_table.size() == 1); + REQUIRE(const_type_table.size() == 1); + } }