diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7f8cd3eb99933803d286251158dcc810f0b0c194..2e09aee48cb59acd13aecf8057b8db42ed1598dc 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -47,6 +47,7 @@ add_executable (unit_tests test_ExecUntilBreakOrContinue.cpp test_FakeProcessor.cpp test_ForProcessor.cpp + test_FunctionProcessor.cpp test_FunctionTable.cpp test_IfProcessor.cpp test_IncDecExpressionProcessor.cpp diff --git a/tests/test_FunctionProcessor.cpp b/tests/test_FunctionProcessor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b4e2ea79a3462f3183c193903d6d3c27f6fb8e64 --- /dev/null +++ b/tests/test_FunctionProcessor.cpp @@ -0,0 +1,304 @@ +#include <catch2/catch.hpp> + +#include <ASTNodeValueBuilder.hpp> + +#include <ASTBuilder.hpp> +#include <ASTNodeDataTypeBuilder.hpp> + +#include <ASTNodeDeclarationToAffectationConverter.hpp> +#include <ASTNodeTypeCleaner.hpp> + +#include <ASTNodeExpressionBuilder.hpp> + +#include <ASTNodeAffectationExpressionBuilder.hpp> + +#include <ASTSymbolTableBuilder.hpp> + +#include <ASTPrinter.hpp> + +#include <Demangle.hpp> + +#include <PEGGrammar.hpp> + +#include <sstream> + +#define CHECK_FUNCTION_EVALUATION_RESULT(data, variable_name, expected_value) \ + { \ + string_input input{data, "test.pgs"}; \ + auto ast = ASTBuilder::build(input); \ + \ + ASTSymbolTableBuilder{*ast}; \ + ASTNodeDataTypeBuilder{*ast}; \ + ASTNodeValueBuilder{*ast}; \ + \ + ASTNodeDeclarationToAffectationConverter{*ast}; \ + ASTNodeTypeCleaner<language::declaration>{*ast}; \ + ASTNodeTypeCleaner<language::let_declaration>{*ast}; \ + \ + ASTNodeExpressionBuilder{*ast}; \ + ExecUntilBreakOrContinue exec_policy; \ + ast->execute(exec_policy); \ + \ + auto symbol_table = ast->m_symbol_table; \ + \ + using namespace TAO_PEGTL_NAMESPACE; \ + position use_position{internal::iterator{"fixture"}, "fixture"}; \ + use_position.byte = 10000; \ + auto [symbol, found] = symbol_table->find(variable_name, use_position); \ + \ + auto attributes = symbol->attributes(); \ + auto value = std::get<decltype(expected_value)>(attributes.value()); \ + \ + REQUIRE(value == expected_value); \ + } + +TEST_CASE("FunctionProcessor", "[language]") +{ + SECTION("Scalar functions") + { + SECTION("-> B") + { + SECTION("B -> B") + { + SECTION("from B") + { + std::string_view data = R"( +let f : B -> B, b -> not b; +B b = f(true); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false); + } + + SECTION("from N") + { + std::string_view data = R"( +let f : B -> B, b -> not b; +N n = 2; +B b = f(n); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false); + } + + SECTION("from Z") + { + std::string_view data = R"( +let f : B -> B, b -> not b; +B b = f(0); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", true); + } + + SECTION("from R") + { + std::string_view data = R"( +let f : B -> B, b -> not b; +B b = f(0.3); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false); + } + } + + SECTION("N -> B") + { + SECTION("from B") + { + std::string_view data = R"( +let f : N -> B, n -> n > 2; +B b = f(true); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false); + } + + SECTION("from N") + { + std::string_view data = R"( +let f : N -> B, n -> n > 2; +N n = 3; +B b = f(n); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", true); + } + + SECTION("from Z") + { + std::string_view data = R"( +let f : N -> B, (n) -> (n > 2); +B b = f(2); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false); + } + + SECTION("from R") + { + std::string_view data = R"( +let f : N -> B, n -> n > 2; +B b = f(2.3); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false); + } + } + + SECTION("Z -> B") + { + SECTION("from B") + { + std::string_view data = R"( +let f : Z -> B, z -> z-3 >= 0; +B b = f(true); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false); + } + + SECTION("from N") + { + std::string_view data = R"( +let f : Z -> B, z -> z-3 >= 0; +N n = 3; +B b = f(n); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", true); + } + + SECTION("from Z") + { + std::string_view data = R"( +let f : Z -> B, z -> (z-3 >= 0); +B b = f(2); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false); + } + + SECTION("from R") + { + std::string_view data = R"( +let f : Z -> B, (z) -> z-3 > 0; +B b = f(3.3); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false); + } + } + + SECTION("R -> B") + { + SECTION("from B") + { + std::string_view data = R"( +let f : R -> B, x -> x*x < 4; +B b = f(true); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", true); + } + + SECTION("from N") + { + std::string_view data = R"( +let f : R -> B, x -> x*x < 4; +N n = 3; +B b = f(n); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false); + } + + SECTION("from Z") + { + std::string_view data = R"( +let f : R -> B, x -> x*x < 4; +B b = f(-2); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false); + } + + SECTION("from R") + { + std::string_view data = R"( +let f : R -> B, x -> x*x < 4; +B b = f(-1.3); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", true); + } + } + } + + SECTION("-> N") + { + SECTION("from N*N") + { + std::string_view data = R"( +let f : N*N -> N, (m,n) -> m*n; +N n = f(2,4); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "n", 8ul); + } + + SECTION("from Z*Z") + { + std::string_view data = R"( +let f : Z*Z -> N, (p,q) -> p*q; +N n = f(-2,-4); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "n", 8ul); + } + } + + SECTION("-> Z") + { + SECTION("from N*N") + { + std::string_view data = R"( +let f : N*N -> Z, (m,n) -> m*n; +Z z = f(2,4); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "z", 8l); + } + + SECTION("from Z*Z") + { + std::string_view data = R"( +let f : Z*Z -> Z, (p,q) -> p*q; +Z z = f(-2,4); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "z", -8l); + } + + SECTION("from R*Z") + { + std::string_view data = R"( +let f : R*Z -> Z, (p,q) -> p*q; +Z z = f(-0.5,8); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "z", -4l); + } + } + + SECTION("-> R") + { + SECTION("from N*R") + { + std::string_view data = R"( +let f : N*R -> R, (n,x) -> n*x; +R r = f(2,4.2); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "r", double{2ul * 4.2}); + } + + SECTION("from R") + { + std::string_view data = R"( +let f : R -> R, x -> x*x-1; +R r = f(4); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "r", double{15}); + } + + SECTION("from R using global variable") + { + std::string_view data = R"( +R x0 = 3; +let f : R -> R, x -> x-x0; +R x = f(7.3); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "x", double{7.3 - 3}); + } + } + } +}