diff --git a/src/language/ast/ASTNodeDataTypeBuilder.cpp b/src/language/ast/ASTNodeDataTypeBuilder.cpp index 404a351b5c46e946f155b25f358a18a2e94acb1d..96ff62bfc20cd9a6526f140d14a4cee7218e241d 100644 --- a/src/language/ast/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ast/ASTNodeDataTypeBuilder.cpp @@ -65,11 +65,13 @@ ASTNodeDataTypeBuilder::_buildDeclarationNodeDataTypes(ASTNode& type_node, ASTNo } else if (content_node->is_type<language::R_set>()) { content_node->m_data_type = ASTNodeDataType::double_t; } else if (content_node->is_type<language::vector_type>()) { - content_node->m_data_type = getVectorDataType(type_node); + content_node->m_data_type = getVectorDataType(*type_node.children[0]); } else if (content_node->is_type<language::string_type>()) { content_node->m_data_type = ASTNodeDataType::string_t; } else { + // LCOV_EXCL_START throw UnexpectedError("unexpected content type in tuple"); + // LCOV_EXCL_STOP } data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, content_node->m_data_type}; diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp index 4c79bb5783abb2ed1c312c2ed7f68817287f0ec2..ae06f5153a7e0c70b78fe1f99ff06c972e9cba57 100644 --- a/src/language/node_processor/AffectationProcessor.hpp +++ b/src/language/node_processor/AffectationProcessor.hpp @@ -472,10 +472,39 @@ class AffectationToTupleFromListProcessor final : public INodeProcessor os << child_value << std::ends; tuple_value[i] = os.str(); } - + } else if constexpr (is_tiny_vector_v<ValueT>) { + if constexpr (std::is_same_v<T, AggregateDataVariant>) { + ValueT& v = tuple_value[i]; + Assert(ValueT::Dimension == child_value.size()); + for (size_t j = 0; j < ValueT::Dimension; ++j) { + std::visit( + [&](auto&& vj) { + using Ti = std::decay_t<decltype(vj)>; + if constexpr (std::is_convertible_v<Ti, typename ValueT::data_type>) { + v[j] = vj; + } else { + // LCOV_EXCL_START + throw parse_error("unexpected error: unexpected right hand side type in affectation", + m_node.children[1]->children[i]->begin()); + // LCOV_EXCL_STOP + } + }, + child_value[j]); + } + } else if constexpr (std::is_same_v<T, int64_t>) { + // in this case a 0 is given + Assert(child_value == 0); + tuple_value[i] = ZeroType{}; + } else { + // LCOV_EXCL_START + throw parse_error("unexpected error: unexpected right hand side type in affectation", + m_node.children[1]->children[i]->begin()); + // LCOV_EXCL_STOP + } } else { // LCOV_EXCL_START - throw parse_error("unexpected error: unexpected right hand side type in affectation", m_node.begin()); + throw parse_error("unexpected error: unexpected right hand side type in affectation", + m_node.children[1]->children[i]->begin()); // LCOV_EXCL_STOP } }, diff --git a/tests/test_ASTNodeDataTypeBuilder.cpp b/tests/test_ASTNodeDataTypeBuilder.cpp index 96eb27f4627bf01d98f2a640966f647ee761aee3..9e44625e1ef31b116954e7b6859b1409873b6e11 100644 --- a/tests/test_ASTNodeDataTypeBuilder.cpp +++ b/tests/test_ASTNodeDataTypeBuilder.cpp @@ -3,7 +3,10 @@ #include <language/ast/ASTBuilder.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> +#include <language/utils/ASTNodeDataTypeTraits.hpp> #include <language/utils/ASTPrinter.hpp> +#include <language/utils/TypeDescriptor.hpp> +#include <utils/Exceptions.hpp> #include <pegtl/string_input.hpp> @@ -24,6 +27,39 @@ REQUIRE(ast_output.str() == expected_output); \ } +template <> +inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> = {ASTNodeDataType::type_id_t, + "builtin_t"}; +const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const double>>; + +#define CHECK_AST_WITH_BUILTIN(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>); \ + \ + string_input input{data, "test.pgs"}; \ + auto ast = ASTBuilder::build(input); \ + \ + 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::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}; \ + \ + std::stringstream ast_output; \ + ast_output << '\n' << ASTPrinter{*ast, ASTPrinter::Format::raw, {ASTPrinter::Info::data_type}}; \ + \ + REQUIRE(ast_output.str() == expected_output); \ + } + // clazy:excludeall=non-pod-global-static TEST_CASE("ASTNodeDataTypeBuilder", "[language]") @@ -330,6 +366,253 @@ let square : R -> R^3, x -> (x, x*x); SECTION("let declaration") { + SECTION("tuples") + { + SECTION("B tuples") + { + std::string_view data = R"( +let t : (B), t = (true, false); +)"; + + std::string_view result = R"( +(root:void) + `-(language::var_declaration:tuple(B)) + +-(language::name:t:tuple(B)) + +-(language::tuple_type_specifier:tuple(B)) + | `-(language::B_set:typename) + +-(language::name:t:tuple(B)) + `-(language::expression_list:list) + +-(language::true_kw:B) + `-(language::false_kw:B) +)"; + + CHECK_AST(data, result); + } + + SECTION("N tuples") + { + std::string_view data = R"( +let t : (N), t = (1, 2, 3, 5); +)"; + + std::string_view result = R"( +(root:void) + `-(language::var_declaration:tuple(N)) + +-(language::name:t:tuple(N)) + +-(language::tuple_type_specifier:tuple(N)) + | `-(language::N_set:typename) + +-(language::name:t:tuple(N)) + `-(language::expression_list:list) + +-(language::integer:1:Z) + +-(language::integer:2:Z) + +-(language::integer:3:Z) + `-(language::integer:5:Z) +)"; + + CHECK_AST(data, result); + } + + SECTION("Z tuples") + { + std::string_view data = R"( +let n : N, n = 3; +let t : (Z), t = (2, n, true); +)"; + + std::string_view result = R"( +(root:void) + +-(language::var_declaration:N) + | +-(language::name:n:N) + | +-(language::N_set:typename) + | +-(language::name:n:N) + | `-(language::integer:3:Z) + `-(language::var_declaration:tuple(Z)) + +-(language::name:t:tuple(Z)) + +-(language::tuple_type_specifier:tuple(Z)) + | `-(language::Z_set:typename) + +-(language::name:t:tuple(Z)) + `-(language::expression_list:list) + +-(language::integer:2:Z) + +-(language::name:n:N) + `-(language::true_kw:B) +)"; + + CHECK_AST(data, result); + } + + SECTION("R tuples") + { + std::string_view data = R"( +let t : (R), t = (2, 3.1, 5); +)"; + + std::string_view result = R"( +(root:void) + `-(language::var_declaration:tuple(R)) + +-(language::name:t:tuple(R)) + +-(language::tuple_type_specifier:tuple(R)) + | `-(language::R_set:typename) + +-(language::name:t:tuple(R)) + `-(language::expression_list:list) + +-(language::integer:2:Z) + +-(language::real:3.1:R) + `-(language::integer:5:Z) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^d tuples") + { + std::string_view data = R"( +let a : R^2, a = (2,3.1); +let t1 : (R^2), t1 = (a, (1,2), 0); +let t2 : (R^3), t2 = (0, 0); +)"; + + std::string_view result = R"( +(root:void) + +-(language::var_declaration:R^2) + | +-(language::name:a:R^2) + | +-(language::vector_type:typename) + | | +-(language::R_set:typename) + | | `-(language::integer:2:Z) + | +-(language::name:a:R^2) + | `-(language::expression_list:list) + | +-(language::integer:2:Z) + | `-(language::real:3.1:R) + +-(language::var_declaration:tuple(R^2)) + | +-(language::name:t1:tuple(R^2)) + | +-(language::tuple_type_specifier:tuple(R^2)) + | | `-(language::vector_type:typename) + | | +-(language::R_set:typename) + | | `-(language::integer:2:Z) + | +-(language::name:t1:tuple(R^2)) + | `-(language::expression_list:list) + | +-(language::name:a:R^2) + | +-(language::tuple_expression:list) + | | +-(language::integer:1:Z) + | | `-(language::integer:2:Z) + | `-(language::integer:0:Z) + `-(language::var_declaration:tuple(R^3)) + +-(language::name:t2:tuple(R^3)) + +-(language::tuple_type_specifier:tuple(R^3)) + | `-(language::vector_type:typename) + | +-(language::R_set:typename) + | `-(language::integer:3:Z) + +-(language::name:t2:tuple(R^3)) + `-(language::expression_list:list) + +-(language::integer:0:Z) + `-(language::integer:0:Z) +)"; + + CHECK_AST(data, result); + } + + SECTION("string tuples") + { + std::string_view data = R"( +let t : (string), t = ("foo", "bar"); +)"; + + std::string_view result = R"( +(root:void) + `-(language::var_declaration:tuple(string)) + +-(language::name:t:tuple(string)) + +-(language::tuple_type_specifier:tuple(string)) + | `-(language::string_type:typename) + +-(language::name:t:tuple(string)) + `-(language::expression_list:list) + +-(language::literal:"foo":string) + `-(language::literal:"bar":string) +)"; + + CHECK_AST(data, result); + } + + SECTION("type_id tuples") + { + std::string_view data = R"( +// invalid conversion just checking grammar +let t : (builtin_t), t= (1,2,3); +)"; + + std::string_view result = R"( +(root:void) + `-(language::var_declaration:tuple(builtin_t)) + +-(language::name:t:tuple(builtin_t)) + +-(language::tuple_type_specifier:tuple(builtin_t)) + | `-(language::type_name_id:typename) + +-(language::name:t:tuple(builtin_t)) + `-(language::expression_list:list) + +-(language::integer:1:Z) + +-(language::integer:2:Z) + `-(language::integer:3:Z) +)"; + + CHECK_AST_WITH_BUILTIN(data, result); + } + + SECTION("errors") + { + SECTION("type_id") + { + std::string_view data = R"( +let t : builtin_t; +)"; + + string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "undefined type identifier"); + } + + SECTION("type_id 2") + { + std::string_view data = R"( +let a: R, a = 3; +let t : a; +)"; + + string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, + "invalid type identifier, 'a' was previously defined as a 'R'"); + } + + SECTION("type_id tuples") + { + std::string_view data = R"( +let t : (builtin_t); +)"; + + string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "undefined type identifier"); + } + + SECTION("type_id tuples 2") + { + std::string_view data = R"( +let a: R, a = 3; +let t : (a); +)"; + + string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, + "invalid type identifier, 'a' was previously defined as a 'R'"); + } + } + } + SECTION("R^d-functions") { SECTION("vector function") @@ -942,6 +1225,25 @@ let s: string; CHECK_AST(data, result); } + SECTION("type_id") + { + std::string_view data = R"( +// invalid conversion just checking grammar +let t : builtin_t, t= 1; +)"; + + std::string_view result = R"( +(root:void) + `-(language::var_declaration:builtin_t) + +-(language::name:t:builtin_t) + +-(language::type_name_id:typename) + +-(language::name:t:builtin_t) + `-(language::integer:1:Z) +)"; + + CHECK_AST_WITH_BUILTIN(data, result); + } + SECTION("continue") { std::string_view data = R"(