diff --git a/tests/test_UnaryExpressionProcessor.cpp b/tests/test_UnaryExpressionProcessor.cpp index f63e45d1fa9912f1d007f83a2759bfc5b7316b42..bb6b28540bfd915c6314c9e176c78d09bffd7ade 100644 --- a/tests/test_UnaryExpressionProcessor.cpp +++ b/tests/test_UnaryExpressionProcessor.cpp @@ -8,6 +8,14 @@ #include <language/ast/ASTNodeExpressionBuilder.hpp> #include <language/ast/ASTNodeTypeCleaner.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> +#include <language/node_processor/UnaryExpressionProcessor.hpp> +#include <language/utils/ASTNodeDataTypeTraits.hpp> +#include <language/utils/AffectationProcessorBuilder.hpp> +#include <language/utils/BasicAffectationRegistrerFor.hpp> +#include <language/utils/DataHandler.hpp> +#include <language/utils/OperatorRepository.hpp> +#include <language/utils/TypeDescriptor.hpp> +#include <language/utils/UnaryOperatorProcessorBuilder.hpp> #include <utils/Demangle.hpp> #include <pegtl/string_input.hpp> @@ -55,6 +63,17 @@ REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, error_message); \ } +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>>; + +inline std::shared_ptr<const double> +operator-(const std::shared_ptr<const double>& p_a) +{ + return std::make_shared<double>(-*p_a); +} + // clazy:excludeall=non-pod-global-static TEST_CASE("UnaryExpressionProcessor", "[language]") @@ -66,37 +85,98 @@ TEST_CASE("UnaryExpressionProcessor", "[language]") CHECK_UNARY_EXPRESSION_RESULT(R"(let r:R, r = 2; r = -r;)", "r", -2.); } + SECTION("unary minus [builtin]") + { + std::string_view data = R"(let r:builtin_t, r = -bt;)"; + + 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")}; + + OperatorRepository& repository = OperatorRepository::instance(); + + repository.addUnaryOperator<language::unary_minus>( + std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, std::shared_ptr<const double>, + std::shared_ptr<const double>>>()); + + 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())); + + auto [i_symbol_bt, success_bt] = symbol_table.add("bt", ast->begin()); + if (not success_bt) { + throw UnexpectedError("cannot add 'bt' of type builtin_t for testing"); + } + i_symbol_bt->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>); + i_symbol_bt->attributes().setIsInitialized(); + i_symbol_bt->attributes().value() = + EmbeddedData(std::make_shared<DataHandler<const double>>(std::make_shared<double>(3.2))); + + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeDeclarationToAffectationConverter{*ast}; + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + + ASTNodeExpressionBuilder{*ast}; + ExecutionPolicy exec_policy; + ast->execute(exec_policy); + + using namespace TAO_PEGTL_NAMESPACE; + position use_position{internal::iterator{"fixture"}, "fixture"}; + use_position.byte = 10000; + auto [symbol, found] = symbol_table.find("r", use_position); + + auto attributes = symbol->attributes(); + auto embedded_value = std::get<EmbeddedData>(attributes.value()); + + double value = *dynamic_cast<const DataHandler<const double>&>(embedded_value.get()).data_ptr(); + REQUIRE(value == double{-3.2}); + } + SECTION("unary not") { CHECK_UNARY_EXPRESSION_RESULT(R"(let b:B, b = false; b = not b;)", "b", true); CHECK_UNARY_EXPRESSION_RESULT(R"(let b:B, b = true; b = not b;)", "b", false); + } - SECTION("errors") + SECTION("errors") + { + SECTION("undefined not operator") { - SECTION("undefined not operator") - { - auto error_message = [](std::string type_name) { - return std::string{R"(undefined unary operator + auto error_message = [](std::string type_name) { + return std::string{R"(undefined unary operator note: unexpected operand type )"} + - type_name; - }; - - CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(let n:N, n = 0; not n;)", error_message("N")); - CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(not 1;)", error_message("Z")); - CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(not 1.3;)", error_message("R")); - CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(not "foo";)", error_message("string")); - } - - SECTION("undefined unary minus operator") - { - auto error_message = [](std::string type_name) { - return std::string{R"(undefined unary operator + type_name; + }; + + CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(let n:N, n = 0; not n;)", error_message("N")); + CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(not 1;)", error_message("Z")); + CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(not 1.3;)", error_message("R")); + CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(not "foo";)", error_message("string")); + } + + SECTION("undefined unary minus operator") + { + auto error_message = [](std::string type_name) { + return std::string{R"(undefined unary operator note: unexpected operand type )"} + - type_name; - }; + type_name; + }; - CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(-"foo";)", error_message("string")); - } + CHECK_UNARY_EXPRESSION_THROWS_WITH(R"(-"foo";)", error_message("string")); } } }