diff --git a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp index 7e79b35d55abf14d3540b76b3587c1db9035f8d5..43bd40932c82310d039f851c9ddc810744c6f72b 100644 --- a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp @@ -194,7 +194,7 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode // LCOV_EXCL_STOP } } else { - throw parse_error("invalid operator for string affectation", std::vector{n.begin()}); + throw parse_error("invalid affectation operator for string", std::vector{n.begin()}); } }; @@ -215,7 +215,7 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode // LCOV_EXCL_STOP } } else { - throw parse_error("invalid operator for '" + data_type.nameOfTypeId() + "' affectation", + throw parse_error("invalid affectation operator for '" + dataTypeName(n.children[0]->m_data_type) + "'", std::vector{n.begin()}); } }; @@ -224,8 +224,7 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode const ASTNodeDataType& data_type) { using OperatorT = std::decay_t<decltype(operator_v)>; if constexpr (std::is_same_v<OperatorT, language::eq_op>) { - switch (data_type) { - case ASTNodeDataType::list_t: { + if ((data_type == ASTNodeDataType::list_t) or (data_type == ASTNodeDataType::tuple_t)) { switch (content_data_type) { case ASTNodeDataType::type_id_t: { n.m_node_processor = std::make_unique<AffectationToTupleFromListProcessor<OperatorT, EmbeddedData>>(n); @@ -274,68 +273,71 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } break; } + // LCOV_EXCL_START default: { - throw NotImplementedError(dataTypeName(content_data_type) + " argument to tuple "); + throw UnexpectedError("invalid tuple content " + dataTypeName(content_data_type)); } + // LCOV_EXCL_STOP } - break; - } - case ASTNodeDataType::type_id_t: { - n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, EmbeddedData>>(n); - break; - } - case ASTNodeDataType::bool_t: { - n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, bool>>(n); - break; - } - case ASTNodeDataType::unsigned_int_t: { - n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, uint64_t>>(n); - break; - } - case ASTNodeDataType::int_t: { - n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, int64_t>>(n); - break; - } - case ASTNodeDataType::double_t: { - n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, double>>(n); - break; - } - case ASTNodeDataType::string_t: { - n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, std::string>>(n); - break; - } - case ASTNodeDataType::vector_t: { - switch (content_data_type.dimension()) { - case 1: { - n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, TinyVector<1>>>(n); + } else { + switch (content_data_type) { + case ASTNodeDataType::type_id_t: { + n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, EmbeddedData>>(n); break; } - case 2: { - n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, TinyVector<2>>>(n); + case ASTNodeDataType::bool_t: { + n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, bool>>(n); break; } - case 3: { - n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, TinyVector<3>>>(n); + case ASTNodeDataType::unsigned_int_t: { + n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, uint64_t>>(n); break; } - // LCOV_EXCL_START + case ASTNodeDataType::int_t: { + n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, int64_t>>(n); + break; + } + case ASTNodeDataType::double_t: { + n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, double>>(n); + break; + } + case ASTNodeDataType::string_t: { + n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, std::string>>(n); + break; + } + case ASTNodeDataType::vector_t: { + switch (content_data_type.dimension()) { + case 1: { + n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, TinyVector<1>>>(n); + break; + } + case 2: { + n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, TinyVector<2>>>(n); + break; + } + case 3: { + n.m_node_processor = std::make_unique<AffectationToTupleProcessor<OperatorT, TinyVector<3>>>(n); + break; + } + // LCOV_EXCL_START + default: { + throw parse_error("unexpected error: invalid vector dimension for tuple affectation", + std::vector{n.children[1]->begin()}); + } + // LCOV_EXCL_STOP + } + break; + } + // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid vector dimension for tuple affectation", + throw parse_error("unexpected error: undefined operand type for tuple affectation", std::vector{n.children[1]->begin()}); } // LCOV_EXCL_STOP } - break; - } - // LCOV_EXCL_START - default: { - throw parse_error("unexpected error: undefined operand type for tuple affectation", - std::vector{n.children[1]->begin()}); - } - // LCOV_EXCL_STOP } } else { - throw parse_error("invalid operator for '" + data_type.nameOfTypeId() + "' affectation", + throw parse_error("invalid affectation operator for '" + dataTypeName(n.children[0]->m_data_type) + "'", std::vector{n.begin()}); } }; diff --git a/src/language/ast/ASTNodeNaturalConversionChecker.cpp b/src/language/ast/ASTNodeNaturalConversionChecker.cpp index 553ab60a1282e0b9b720e298d13fe8aad4df176c..b01ff1fc346856797b37f58a20b72039e8b49f59 100644 --- a/src/language/ast/ASTNodeNaturalConversionChecker.cpp +++ b/src/language/ast/ASTNodeNaturalConversionChecker.cpp @@ -59,12 +59,30 @@ ASTNodeNaturalConversionChecker::_checkIsNaturalExpressionConversion(const ASTNo } } else if (target_data_type == ASTNodeDataType::tuple_t) { const ASTNodeDataType& target_content_type = target_data_type.contentType(); - if (node.m_data_type == ASTNodeDataType::list_t) { - for (const auto& child : node.children) { - this->_checkIsNaturalExpressionConversion(*child, child->m_data_type, target_content_type); + if (node.m_data_type == ASTNodeDataType::tuple_t) { + this->_checkIsNaturalExpressionConversion(node, data_type.contentType(), target_content_type); + } else if (node.m_data_type == ASTNodeDataType::list_t) { + if ((target_data_type.contentType() == ASTNodeDataType::vector_t) and + (target_data_type.contentType().dimension() == 1)) { + for (const auto& child : node.children) { + if (not isNaturalConversion(child->m_data_type, target_data_type)) { + this->_checkIsNaturalExpressionConversion(*child, child->m_data_type, ASTNodeDataType::double_t); + } + } + } else { + for (const auto& child : node.children) { + this->_checkIsNaturalExpressionConversion(*child, child->m_data_type, target_content_type); + } } } else { - this->_checkIsNaturalTypeConversion(node, data_type, target_data_type); + if ((target_data_type.contentType() == ASTNodeDataType::vector_t) and + (target_data_type.contentType().dimension() == 1)) { + if (not isNaturalConversion(data_type, target_data_type)) { + this->_checkIsNaturalExpressionConversion(node, data_type, ASTNodeDataType::double_t); + } + } else { + this->_checkIsNaturalExpressionConversion(node, data_type, target_content_type); + } } } else { this->_checkIsNaturalTypeConversion(node, data_type, target_data_type); diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp index ae06f5153a7e0c70b78fe1f99ff06c972e9cba57..31e1f070f5fadc1366ad4470b49a8052977bfce2 100644 --- a/src/language/node_processor/AffectationProcessor.hpp +++ b/src/language/node_processor/AffectationProcessor.hpp @@ -417,7 +417,8 @@ class AffectationToTupleProcessor final : public INodeProcessor os << v << std::ends; *m_lhs = std::vector{os.str()}; } - + } else if constexpr (std::is_same_v<ValueT, TinyVector<1>> and std::is_arithmetic_v<T>) { + *m_lhs = std::vector{TinyVector<1>{static_cast<double>(v)}}; } else { // LCOV_EXCL_START throw parse_error("unexpected error: unexpected right hand side type in affectation", m_node.begin()); @@ -447,14 +448,9 @@ class AffectationToTupleFromListProcessor final : public INodeProcessor DataVariant* m_lhs; - public: - DataVariant - execute(ExecutionPolicy& exec_policy) + void + _copyAggregateDataVariant(const AggregateDataVariant& children_values) { - AggregateDataVariant children_values = std::get<AggregateDataVariant>(m_node.children[1]->execute(exec_policy)); - - static_assert(std::is_same_v<OperatorT, language::eq_op>, "forbidden affection operator for list to tuple"); - std::vector<ValueT> tuple_value(children_values.size()); for (size_t i = 0; i < children_values.size(); ++i) { std::visit( @@ -510,8 +506,66 @@ class AffectationToTupleFromListProcessor final : public INodeProcessor }, children_values[i]); } - *m_lhs = std::move(tuple_value); + } + + template <typename DataType> + void + _copyVector(const std::vector<DataType>& values) + { + std::vector<ValueT> v(values.size()); + if constexpr (std::is_same_v<ValueT, DataType>) { + for (size_t i = 0; i < values.size(); ++i) { + v[i] = values[i]; + } + } else if constexpr (std::is_arithmetic_v<ValueT> and std::is_convertible_v<DataType, ValueT>) { + for (size_t i = 0; i < values.size(); ++i) { + v[i] = static_cast<DataType>(values[i]); + } + } else if constexpr (std::is_same_v<ValueT, std::string>) { + if constexpr (std::is_arithmetic_v<DataType>) { + for (size_t i = 0; i < values.size(); ++i) { + v[i] = std::to_string(values[i]); + } + } else { + for (size_t i = 0; i < values.size(); ++i) { + std::ostringstream sout; + sout << values[i] << std::ends; + v[i] = sout.str(); + } + } + } else { + // LCOV_EXCL_START + throw parse_error("unexpected error: unexpected right hand side type in tuple affectation", + m_node.children[1]->begin()); + // LCOV_EXCL_STOP + } + + *m_lhs = std::move(v); + } + + public: + DataVariant + execute(ExecutionPolicy& exec_policy) + { + static_assert(std::is_same_v<OperatorT, language::eq_op>, "forbidden affection operator for list to tuple"); + + std::visit( + [&](auto&& value_list) { + using ValueListT = std::decay_t<decltype(value_list)>; + if constexpr (std::is_same_v<AggregateDataVariant, ValueListT>) { + this->_copyAggregateDataVariant(value_list); + } else if constexpr (is_std_vector_v<ValueListT>) { + this->_copyVector(value_list); + } else { + // LCOV_EXCL_START + throw parse_error("unexpected error: invalid lhs (expecting list or tuple)", + std::vector{m_node.children[1]->begin()}); + // LCOV_EXCL_STOP + } + }, + m_node.children[1]->execute(exec_policy)); + return {}; } diff --git a/src/language/node_processor/FunctionArgumentConverter.hpp b/src/language/node_processor/FunctionArgumentConverter.hpp index c93516a86be9a75485819eb19e63132b35522182..afd4373ce8dedb5cf460e77c6d4b9ba7e30035fc 100644 --- a/src/language/node_processor/FunctionArgumentConverter.hpp +++ b/src/language/node_processor/FunctionArgumentConverter.hpp @@ -107,7 +107,7 @@ class FunctionTupleArgumentConverter final : public IFunctionArgumentConverter using ValueT = std::decay_t<decltype(v)>; if constexpr (std::is_same_v<ValueT, ContentType>) { exec_policy.currentContext()[m_argument_id] = std::move(TupleType{std::move(v)}); - } else if constexpr (is_vector_v<ValueT>) { + } else if constexpr (is_std_vector_v<ValueT>) { using ContentT = typename ValueT::value_type; if constexpr (std::is_same_v<ContentT, ContentType>) { TupleType list_value; @@ -168,7 +168,7 @@ class FunctionListArgumentConverter final : public IFunctionArgumentConverter exec_policy.currentContext()[m_argument_id] = std::move(list_value); } else if constexpr (std::is_same_v<ValueT, ContentType>) { exec_policy.currentContext()[m_argument_id] = std::move(v); - } else if constexpr (is_vector_v<ValueT>) { + } else if constexpr (is_std_vector_v<ValueT>) { using ContentT = typename ValueT::value_type; if constexpr (std::is_same_v<ContentT, ContentType>) { TupleType list_value; diff --git a/src/language/utils/BuiltinFunctionEmbedder.hpp b/src/language/utils/BuiltinFunctionEmbedder.hpp index 8073a47ef7b634a17d4498522d9ecf663cbcd716..3974398e1803856585f91f09565b29da3d877533 100644 --- a/src/language/utils/BuiltinFunctionEmbedder.hpp +++ b/src/language/utils/BuiltinFunctionEmbedder.hpp @@ -80,7 +80,7 @@ class BuiltinFunctionEmbedder<FX(Args...)> : public IBuiltinFunctionEmbedder throw UnexpectedError("unexpected argument types while casting: expecting EmbeddedData"); } } else if constexpr (std::is_same_v<Vi_Type, std::vector<EmbeddedData>>) { - if constexpr (is_vector_v<Ti_Type>) { + if constexpr (is_std_vector_v<Ti_Type>) { using Ti_value_type = typename Ti_Type::value_type; if constexpr (is_shared_ptr_v<Ti_value_type>) { static_assert(is_shared_ptr_v<Ti_value_type>, "expecting shared_ptr"); diff --git a/src/language/utils/DataVariant.cpp b/src/language/utils/DataVariant.cpp index 8796833250019d10a7ab7e28b0d895c232726244..fc82eec7b805cd49daa2a097490b36fa33e0c561 100644 --- a/src/language/utils/DataVariant.cpp +++ b/src/language/utils/DataVariant.cpp @@ -11,7 +11,7 @@ operator<<(std::ostream& os, const DataVariant& v) using ValueT = std::decay_t<decltype(v)>; if constexpr (std::is_same_v<ValueT, std::monostate>) { os << "--"; - } else if constexpr (is_vector_v<ValueT>) { + } else if constexpr (is_std_vector_v<ValueT>) { os << '('; if (v.size() > 0) { os << v[0]; diff --git a/src/utils/PugsTraits.hpp b/src/utils/PugsTraits.hpp index 52acae2bb0c80aecab29fb125604b7b869fc5f3c..e34e0433bb69316af695fec1c8d571ef23e03155 100644 --- a/src/utils/PugsTraits.hpp +++ b/src/utils/PugsTraits.hpp @@ -68,13 +68,13 @@ inline constexpr bool is_std_ptr_v<std::unique_ptr<T>> = true; template <typename T> inline constexpr bool is_std_ptr_v<std::weak_ptr<T>> = true; -// Traits is_vector +// Traits is_std_vector template <typename T> -inline constexpr bool is_vector_v = false; +inline constexpr bool is_std_vector_v = false; template <typename T> -inline constexpr bool is_vector_v<std::vector<T>> = true; +inline constexpr bool is_std_vector_v<std::vector<T>> = true; // Traits is_tiny_vector diff --git a/tests/test_ASTNodeAffectationExpressionBuilder.cpp b/tests/test_ASTNodeAffectationExpressionBuilder.cpp index f439786a088c0eb293019bf8e048fc56e8eda1e8..895fa860eafe2f6216066d422597e539c1a1cd65 100644 --- a/tests/test_ASTNodeAffectationExpressionBuilder.cpp +++ b/tests/test_ASTNodeAffectationExpressionBuilder.cpp @@ -8,8 +8,11 @@ #include <language/ast/ASTNodeTypeCleaner.hpp> #include <language/ast/ASTSymbolInitializationChecker.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> +#include <language/utils/ASTNodeDataTypeTraits.hpp> #include <language/utils/ASTPrinter.hpp> +#include <language/utils/TypeDescriptor.hpp> #include <utils/Demangle.hpp> +#include <utils/Exceptions.hpp> #include <pegtl/string_input.hpp> @@ -36,6 +39,58 @@ 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> or \ + std::is_same_v<std::decay_t<decltype(expected_output)>, std::string>); \ + \ + 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())); \ + \ + auto [i_symbol_a, success_a] = symbol_table.add("a", ast->begin()); \ + if (not success_a) { \ + throw UnexpectedError("cannot add 'a' of type builtin_t for testing"); \ + } \ + i_symbol_a->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>); \ + i_symbol_a->attributes().setIsInitialized(); \ + auto [i_symbol_b, success_b] = symbol_table.add("b", ast->begin()); \ + if (not success_b) { \ + throw UnexpectedError("cannot add 'b' of type builtin_t for testing"); \ + } \ + i_symbol_b->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>); \ + i_symbol_b->attributes().setIsInitialized(); \ + \ + ASTSymbolTableBuilder{*ast}; \ + ASTNodeDataTypeBuilder{*ast}; \ + \ + ASTNodeDeclarationToAffectationConverter{*ast}; \ + ASTNodeTypeCleaner<language::var_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, expected_error) \ { \ static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>); \ @@ -54,6 +109,48 @@ REQUIRE_THROWS_WITH(ASTNodeExpressionBuilder{*ast}, expected_error); \ } +#define CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, expected_error) \ + { \ + 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_error)>, std::string_view> or \ + std::is_same_v<std::decay_t<decltype(expected_error)>, std::string>); \ + \ + 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())); \ + \ + auto [i_symbol_a, success_a] = symbol_table.add("a", ast->begin()); \ + if (not success_a) { \ + throw UnexpectedError("cannot add 'a' of type builtin_t for testing"); \ + } \ + i_symbol_a->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>); \ + i_symbol_a->attributes().setIsInitialized(); \ + auto [i_symbol_b, success_b] = symbol_table.add("b", ast->begin()); \ + if (not success_b) { \ + throw UnexpectedError("cannot add 'b' of type builtin_t for testing"); \ + } \ + i_symbol_b->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>); \ + i_symbol_b->attributes().setIsInitialized(); \ + \ + ASTSymbolTableBuilder{*ast}; \ + ASTNodeDataTypeBuilder{*ast}; \ + \ + ASTNodeDeclarationToAffectationConverter{*ast}; \ + ASTNodeTypeCleaner<language::var_declaration>{*ast}; \ + \ + REQUIRE_THROWS_WITH(ASTNodeExpressionBuilder{*ast}, expected_error); \ + } + // clazy:excludeall=non-pod-global-static TEST_CASE("ASTNodeAffectationExpressionBuilder", "[language]") @@ -545,6 +642,320 @@ let s : string, s="foo"; CHECK_AST(data, result); } } + + SECTION("type_id affectation") + { + SECTION("type_id <- type_id") + { + std::string_view data = R"( +let t : builtin_t, t=a; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationProcessor<language::eq_op, EmbeddedData, EmbeddedData>) + +-(language::name:t:NameProcessor) + `-(language::name:a:NameProcessor) +)"; + + CHECK_AST_WITH_BUILTIN(data, result); + } + } + + SECTION("tuples") + { + SECTION("B tuples") + { + std::string_view data = R"( +let t : (B), t = (true, false); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, bool>) + +-(language::name:t:NameProcessor) + `-(language::expression_list:ASTNodeExpressionListProcessor) + +-(language::true_kw:ValueProcessor) + `-(language::false_kw:ValueProcessor) +)"; + + 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:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, unsigned long>) + +-(language::name:t:NameProcessor) + `-(language::expression_list:ASTNodeExpressionListProcessor) + +-(language::integer:1:ValueProcessor) + +-(language::integer:2:ValueProcessor) + +-(language::integer:3:ValueProcessor) + `-(language::integer:5:ValueProcessor) +)"; + + 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:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>) + | +-(language::name:n:NameProcessor) + | `-(language::integer:3:ValueProcessor) + `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, long>) + +-(language::name:t:NameProcessor) + `-(language::expression_list:ASTNodeExpressionListProcessor) + +-(language::integer:2:ValueProcessor) + +-(language::name:n:NameProcessor) + `-(language::true_kw:ValueProcessor) +)"; + + 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:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, double>) + +-(language::name:t:NameProcessor) + `-(language::expression_list:ASTNodeExpressionListProcessor) + +-(language::integer:2:ValueProcessor) + +-(language::real:3.1:ValueProcessor) + `-(language::integer:5:ValueProcessor) +)"; + + 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); +let t3 : (R^1), t3 = (1, 2.3, 0); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTinyVectorFromListProcessor<language::eq_op, TinyVector<2ul, double> >) + | +-(language::name:a:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::integer:2:ValueProcessor) + | `-(language::real:3.1:ValueProcessor) + +-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, TinyVector<2ul, double> >) + | +-(language::name:t1:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::name:a:NameProcessor) + | +-(language::tuple_expression:TupleToVectorProcessor<ASTNodeExpressionListProcessor>) + | | +-(language::integer:1:ValueProcessor) + | | `-(language::integer:2:ValueProcessor) + | `-(language::integer:0:ValueProcessor) + +-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, TinyVector<3ul, double> >) + | +-(language::name:t2:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::integer:0:ValueProcessor) + | `-(language::integer:0:ValueProcessor) + `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, TinyVector<1ul, double> >) + +-(language::name:t3:NameProcessor) + `-(language::expression_list:ASTNodeExpressionListProcessor) + +-(language::integer:1:ValueProcessor) + +-(language::real:2.3:ValueProcessor) + `-(language::integer:0:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("string tuples") + { + std::string_view data = R"( +let t : (string), t = ("foo", "bar"); +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, )" + + demangled_stdstring + R"( >) + +-(language::name:t:NameProcessor) + `-(language::expression_list:ASTNodeExpressionListProcessor) + +-(language::literal:"foo":ValueProcessor) + `-(language::literal:"bar":ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("type_id tuples") + { + std::string_view data = R"( +let t : (builtin_t), t= (a,b,a); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleFromListProcessor<language::eq_op, EmbeddedData>) + +-(language::name:t:NameProcessor) + `-(language::expression_list:ASTNodeExpressionListProcessor) + +-(language::name:a:NameProcessor) + +-(language::name:b:NameProcessor) + `-(language::name:a:NameProcessor) +)"; + + CHECK_AST_WITH_BUILTIN(data, result); + } + } + + SECTION("tuples from singleton") + { + SECTION("B tuples") + { + std::string_view data = R"( +let t : (B), t = true; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, bool>) + +-(language::name:t:NameProcessor) + `-(language::true_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("N tuples") + { + std::string_view data = R"( +let t : (N), t = 1; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, unsigned long>) + +-(language::name:t:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Z tuples") + { + std::string_view data = R"( +let n : N, n = 3; +let t : (Z), t = n; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>) + | +-(language::name:n:NameProcessor) + | `-(language::integer:3:ValueProcessor) + `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, long>) + +-(language::name:t:NameProcessor) + `-(language::name:n:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R tuples") + { + std::string_view data = R"( +let t : (R), t = 3.1; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, double>) + +-(language::name:t:NameProcessor) + `-(language::real:3.1:ValueProcessor) +)"; + + 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; +let t2 : (R^3), t2 = 0; +let t3 : (R^1), t3 = 2.3; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTinyVectorFromListProcessor<language::eq_op, TinyVector<2ul, double> >) + | +-(language::name:a:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::integer:2:ValueProcessor) + | `-(language::real:3.1:ValueProcessor) + +-(language::eq_op:AffectationToTupleProcessor<language::eq_op, TinyVector<2ul, double> >) + | +-(language::name:t1:NameProcessor) + | `-(language::name:a:NameProcessor) + +-(language::eq_op:AffectationToTupleProcessor<language::eq_op, TinyVector<3ul, double> >) + | +-(language::name:t2:NameProcessor) + | `-(language::integer:0:ValueProcessor) + `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, TinyVector<1ul, double> >) + +-(language::name:t3:NameProcessor) + `-(language::real:2.3:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("string tuples") + { + std::string_view data = R"( +let t : (string), t = "foo"; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, )" + + demangled_stdstring + R"( >) + +-(language::name:t:NameProcessor) + `-(language::literal:"foo":ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("type_id tuples") + { + std::string_view data = R"( +let t : (builtin_t), t = a; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleProcessor<language::eq_op, EmbeddedData>) + +-(language::name:t:NameProcessor) + `-(language::name:a:NameProcessor) +)"; + + CHECK_AST_WITH_BUILTIN(data, result); + } + } } SECTION("+=") @@ -1147,7 +1558,7 @@ let x : R, x=1; x/=2.3; let s : string, s="foo"; s-="bar"; )"; - std::string error_message = "invalid operator for string affectation"; + std::string error_message = "invalid affectation operator for string"; CHECK_AST_THROWS_WITH(data, error_message); } @@ -1158,7 +1569,7 @@ let s : string, s="foo"; s-="bar"; let s : string, s="foo"; s*=2; )"; - std::string error_message = "invalid operator for string affectation"; + std::string error_message = "invalid affectation operator for string"; CHECK_AST_THROWS_WITH(data, error_message); } @@ -1166,15 +1577,48 @@ let s : string, s="foo"; s*=2; SECTION("string /= string") { std::string_view data = R"( -let s : string, s="foo"; s/="bar"; + let s : string, s="foo"; s/="bar"; )"; - std::string error_message = "invalid operator for string affectation"; + std::string error_message = "invalid affectation operator for string"; CHECK_AST_THROWS_WITH(data, error_message); } } + SECTION("type_id operator") + { + std::string_view data = R"( + let s :builtin_t, s = a; s *= b; +)"; + + std::string error_message = "invalid affectation operator for 'builtin_t'"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + + SECTION("Invalid tuple operator") + { + std::string_view data = R"( + let s :(R), s=(1,2,3); s *= 4; +)"; + + std::string error_message = "invalid affectation operator for 'tuple(R)'"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("Invalid tuple operator 2") + { + std::string_view data = R"( + let s : (builtin_t), s =(a,b); s *= b; +)"; + + std::string error_message = "invalid affectation operator for 'tuple(builtin_t)'"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + SECTION("Invalid R^n -> R^m affectation") { SECTION("R^3 <- R^1") diff --git a/tests/test_ASTNodeNaturalConversionChecker.cpp b/tests/test_ASTNodeNaturalConversionChecker.cpp index 1470dfc7f183c1bc802cffdc202b9e2d6f75fd95..fe29cf9d0148d7a4d0a31bd71b97d84820e63299 100644 --- a/tests/test_ASTNodeNaturalConversionChecker.cpp +++ b/tests/test_ASTNodeNaturalConversionChecker.cpp @@ -344,7 +344,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]") SECTION("R^3 -> tuple(R^3)") { - auto R3 = ASTNodeDataType{ASTNodeDataType::vector_t, 2}; + auto R3 = ASTNodeDataType{ASTNodeDataType::vector_t, 3}; data_node->m_data_type = R3; REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, R3}}); } @@ -352,14 +352,17 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]") SECTION("string -> tuple(string)") { data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::string_t}; - REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::string_t}}); + REQUIRE_NOTHROW( + ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, + ASTNodeDataType{ASTNodeDataType::string_t}}}); } SECTION("type_id_t -> tuple(type_id_t)") { auto type_id = ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"}; data_node->m_data_type = type_id; - REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, type_id}); + REQUIRE_NOTHROW( + ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, type_id}}); } SECTION("(B, B, B) -> tuple(B)") @@ -514,7 +517,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]") REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); } - SECTION("(type_id_t, type_id_t)-> tuple(type_id_t)") + SECTION("(type_id_t, type_id_t) -> tuple(type_id_t)") { auto type_id = ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"}; data_node->m_data_type = ASTNodeDataType::list_t; @@ -530,6 +533,167 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]") auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, type_id}; REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); } + + SECTION("tuple(B) -> tuple(B)") + { + data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}}; + auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}}; + + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); + } + + SECTION("tuple(B) -> tuple(N)") + { + data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}}; + auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}}; + + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); + } + + SECTION("tuple(Z) -> tuple(N)") + { + data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}}; + auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}}; + + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); + } + + SECTION("tuple(N) -> tuple(N)") + { + data_node->m_data_type = + ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}}; + auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}}; + + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); + } + + SECTION("tuple(B) -> tuple(Z)") + { + data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}}; + auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}}; + + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); + } + + SECTION("tuple(N) -> tuple(Z)") + { + data_node->m_data_type = + ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}}; + auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}}; + + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); + } + + SECTION("tuple(Z) -> tuple(Z)") + { + data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}}; + auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}}; + + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); + } + + SECTION("tuple(B) -> tuple(R)") + { + data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}}; + auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}}; + + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); + } + + SECTION("tuple(Z) -> tuple(R)") + { + data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}}; + auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}}; + + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); + } + + SECTION("tuple(N) -> tuple(R)") + { + data_node->m_data_type = + ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}}; + auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}}; + + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); + } + + SECTION("tuple(R) -> tuple(R)") + { + data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}}; + auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}}; + + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); + } + + SECTION("tuple(B) -> tuple(string)") + { + data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::bool_t}}; + auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::string_t}}; + + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); + } + + SECTION("tuple(Z) -> tuple(string)") + { + data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}}; + auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::string_t}}; + + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); + } + + SECTION("tuple(N) -> tuple(string)") + { + data_node->m_data_type = + ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::unsigned_int_t}}; + auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::string_t}}; + + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); + } + + SECTION("tuple(R) -> tuple(string)") + { + data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}}; + auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::string_t}}; + + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); + } + + SECTION("tuple(string) -> tuple(string)") + { + data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::string_t}}; + auto tuple_t = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::string_t}}; + + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t}); + } + + SECTION("tuple(R^1) -> tuple(R^1)") + { + auto R1 = ASTNodeDataType{ASTNodeDataType::vector_t, 1}; + data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, R1}; + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, R1}}); + } + + SECTION("tuple(R^2) -> tuple(R^2)") + { + auto R2 = ASTNodeDataType{ASTNodeDataType::vector_t, 2}; + data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, R2}; + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, R2}}); + } + + SECTION("tuple(R^3) -> tuple(R^3)") + { + auto R3 = ASTNodeDataType{ASTNodeDataType::vector_t, 3}; + data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, R3}; + REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, R3}}); + } + + SECTION("tuple(type_id_t) -> tuple(type_id_t)") + { + auto type_id = ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"}; + data_node->m_data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, type_id}; + REQUIRE_NOTHROW( + ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, type_id}}); + } } } @@ -724,6 +888,83 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]") ASTNodeDataType{ASTNodeDataType::vector_t, 3}}), "invalid implicit conversion: tuple(R) -> R^3"); } + + SECTION("tuple(R^1) -> tuple(R^3)") + { + auto tuple_R1 = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::vector_t, 1}}; + auto tuple_R3 = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::vector_t, 3}}; + data_node->m_data_type = tuple_R1; + REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R3}), + "invalid implicit conversion: R^1 -> R^3"); + } + + SECTION("tuple(R^2) -> tuple(R^3)") + { + auto tuple_R2 = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::vector_t, 2}}; + auto tuple_R3 = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::vector_t, 3}}; + data_node->m_data_type = tuple_R2; + REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R3}), + "invalid implicit conversion: R^2 -> R^3"); + } + + SECTION("tuple(R^2) -> tuple(R^1)") + { + auto tuple_R1 = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::vector_t, 1}}; + auto tuple_R2 = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::vector_t, 2}}; + data_node->m_data_type = tuple_R2; + REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R1}), + "invalid implicit conversion: R^2 -> R^1"); + } + + SECTION("tuple(R) -> tuple(Z)") + { + auto tuple_R = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}}; + auto tuple_Z = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::int_t}}; + data_node->m_data_type = tuple_R; + REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_Z}), + "invalid implicit conversion: R -> Z"); + } + + SECTION("tuple(R) -> tuple(R^1)") + { + auto tuple_R = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}}; + auto tuple_R1 = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::vector_t, 1}}; + data_node->m_data_type = tuple_R; + REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R1}), + "invalid implicit conversion: R -> R^1"); + } + + SECTION("tuple(string) -> tuple(R)") + { + auto tuple_string = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::string_t}}; + auto tuple_R = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}}; + data_node->m_data_type = tuple_string; + REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R}), + "invalid implicit conversion: string -> R"); + } + + SECTION("tuple(type_id) -> tuple(R)") + { + auto type_id = ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"}; + + auto tuple_type_id = ASTNodeDataType{ASTNodeDataType::tuple_t, type_id}; + auto tuple_R = ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ASTNodeDataType::double_t}}; + data_node->m_data_type = tuple_type_id; + REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R}), + "invalid implicit conversion: foo -> R"); + } + + SECTION("tuple(type_id) -> tuple(R)") + { + auto type_id0 = ASTNodeDataType{ASTNodeDataType::type_id_t, "foo"}; + auto type_id1 = ASTNodeDataType{ASTNodeDataType::type_id_t, "bar"}; + + auto tuple_type_id0 = ASTNodeDataType{ASTNodeDataType::tuple_t, type_id0}; + auto tuple_type_id1 = ASTNodeDataType{ASTNodeDataType::tuple_t, type_id1}; + data_node->m_data_type = tuple_type_id0; + REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_type_id1}), + "invalid implicit conversion: foo -> bar"); + } } SECTION("R -> R^d") @@ -1088,7 +1329,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]") REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ ASTNodeDataType::bool_t}}}), - "invalid implicit conversion: N -> tuple(B)"); + "invalid implicit conversion: N -> B"); } SECTION("Z -> tuple(B)") @@ -1097,7 +1338,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]") REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ ASTNodeDataType::bool_t}}}), - "invalid implicit conversion: Z -> tuple(B)"); + "invalid implicit conversion: Z -> B"); } SECTION("R -> tuple(B)") @@ -1106,7 +1347,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]") REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ ASTNodeDataType::bool_t}}}), - "invalid implicit conversion: R -> tuple(B)"); + "invalid implicit conversion: R -> B"); } SECTION("string -> tuple(B)") @@ -1115,7 +1356,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]") REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ ASTNodeDataType::bool_t}}}), - "invalid implicit conversion: string -> tuple(B)"); + "invalid implicit conversion: string -> B"); } SECTION("R^1 -> tuple(B)") @@ -1124,7 +1365,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]") REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ ASTNodeDataType::bool_t}}}), - "invalid implicit conversion: R^1 -> tuple(B)"); + "invalid implicit conversion: R^1 -> B"); } SECTION("R^2 -> tuple(B)") @@ -1133,7 +1374,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]") REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ ASTNodeDataType::bool_t}}}), - "invalid implicit conversion: R^2 -> tuple(B)"); + "invalid implicit conversion: R^2 -> B"); } SECTION("R^3 -> tuple(B)") @@ -1142,7 +1383,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]") REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ ASTNodeDataType::bool_t}}}), - "invalid implicit conversion: R^3 -> tuple(B)"); + "invalid implicit conversion: R^3 -> B"); } SECTION("R -> tuple(N)") @@ -1152,7 +1393,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]") ASTNodeDataType{ASTNodeDataType::tuple_t, ASTNodeDataType{ ASTNodeDataType::unsigned_int_t}}}), - "invalid implicit conversion: R -> tuple(N)"); + "invalid implicit conversion: R -> N"); } SECTION("R^1 -> tuple(R^2)") @@ -1162,7 +1403,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]") data_node->m_data_type = R1; REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, R2}}), - "invalid implicit conversion: R^1 -> tuple(R^2)"); + "incompatible dimensions in affectation"); } SECTION("R^2 -> tuple(R^3)") @@ -1172,7 +1413,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]") data_node->m_data_type = R2; REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, R3}}), - "invalid implicit conversion: R^2 -> tuple(R^3)"); + "incompatible dimensions in affectation"); } SECTION("R^3 -> tuple(R^2)") @@ -1182,7 +1423,7 @@ TEST_CASE("ASTNodeNaturalConversionChecker", "[language]") data_node->m_data_type = R3; REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType{ASTNodeDataType::tuple_t, R2}}), - "invalid implicit conversion: R^3 -> tuple(R^2)"); + "incompatible dimensions in affectation"); } SECTION("(B, R, Z) -> tuple(N)")