#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/ASTNodeAffectationExpressionBuilder.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> #include <language/ast/ASTNodeExpressionBuilder.hpp> #include <language/ast/ASTNodeTypeCleaner.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> #include <utils/Demangle.hpp> #include <pegtl/string_input.hpp> #include <sstream> #define CHECK_WHILE_PROCESSOR_RESULT(data, variable_name, expected_value) \ { \ 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}; \ \ ASTNodeExpressionBuilder{*ast}; \ ExecutionPolicy 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); \ } #define CHECK_WHILE_PROCESSOR_THROWS_WITH(data, error_message) \ { \ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ ASTSymbolTableBuilder{*ast}; \ \ REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, error_message); \ } // clazy:excludeall=non-pod-global-static TEST_CASE("WhileProcessor", "[language]") { SECTION("simple loop") { std::string_view data = R"( let i:N, i = 3; let j:N, j = 0; while(i<10) { j++; i += j; } )"; CHECK_WHILE_PROCESSOR_RESULT(data, "i", 13ul); } SECTION("simple with break") { std::string_view data = R"( let i:N, i = 3; let j:N, j = 0; while(i<10) { j++; if (j==2) break; i += j; } )"; CHECK_WHILE_PROCESSOR_RESULT(data, "i", 4ul); } SECTION("simple with continue") { std::string_view data = R"( let i:N, i = 3; let j:N, j = 0; while(i<10) { j++; if (j<=3) continue; i += j; } )"; CHECK_WHILE_PROCESSOR_RESULT(data, "i", 12ul); } SECTION("while symbol table untouched") { std::string_view data = R"( let i:N, i = 3; while(i != 3); )"; CHECK_WHILE_PROCESSOR_RESULT(data, "i", 3ul); } SECTION("single instruction while symbol table untouched") { std::string_view data = R"( let i:N, i = 3; while (i == 3) i = 2; )"; CHECK_WHILE_PROCESSOR_RESULT(data, "i", 2ul); } SECTION("errors") { SECTION("bad test type") { std::string_view data = R"( while(1) { } )"; CHECK_WHILE_PROCESSOR_THROWS_WITH(data, "invalid implicit conversion: Z -> B"); } } }