diff --git a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp index 54b0970eff20190d4b57d2adfc596ba71cf174d0..cdd9c43d977c6718dc5d900dbe0b96a15de54f47 100644 --- a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp @@ -231,6 +231,9 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } case ASTNodeDataType::double_t: { return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, double>>(argument_number); + } + case ASTNodeDataType::string_t: { + return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, std::string>>(argument_number); } // LCOV_EXCL_START default: { @@ -265,6 +268,9 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData case ASTNodeDataType::double_t: { return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, double>>(argument_number); } + case ASTNodeDataType::string_t: { + return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, std::string>>(argument_number); + } case ASTNodeDataType::function_t: { const ASTNode& parent_node = argument_node_sub_data_type.m_parent_node; auto symbol_table = parent_node.m_symbol_table; @@ -457,7 +463,7 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } } case ASTNodeDataType::string_t: { - return get_function_argument_to_string_converter(); + return get_function_argument_to_tuple_converter(std::string{}); } // LCOV_EXCL_START default: { diff --git a/src/language/node_processor/ASTNodeExpressionListProcessor.hpp b/src/language/node_processor/ASTNodeExpressionListProcessor.hpp index 713eda89aec0804efb4bcd323cb9a65c10b8967d..21823176e8b7f8d9eb0c0760c52ae0fb1749f0e3 100644 --- a/src/language/node_processor/ASTNodeExpressionListProcessor.hpp +++ b/src/language/node_processor/ASTNodeExpressionListProcessor.hpp @@ -87,7 +87,7 @@ class ASTNodeExpressionListProcessor final : public INodeProcessor } Assert(list_values.size() == m_number_of_values); - return DataVariant{std::move(list_values)}; + return AggregateDataVariant{std::move(list_values)}; } ASTNodeExpressionListProcessor(ASTNode& node) : m_node{node}, m_number_of_values{this->_getNumberOfValues()} {} diff --git a/src/language/node_processor/BinaryExpressionProcessor.hpp b/src/language/node_processor/BinaryExpressionProcessor.hpp index 7f278d4c7d4a007ad5db4c9f5d444665ccca56d6..a2111464ce05a8148ff4886f9614952641ed65d5 100644 --- a/src/language/node_processor/BinaryExpressionProcessor.hpp +++ b/src/language/node_processor/BinaryExpressionProcessor.hpp @@ -314,8 +314,8 @@ struct BinaryExpressionProcessor<BinaryOpT, std::shared_ptr<ValueT>, std::shared PUGS_INLINE DataVariant _eval(const DataVariant& a, const DataVariant& b) { - if constexpr ((std::is_arithmetic_v<B_DataT>) or (is_tiny_matrix_v<B_DataT>) or (is_tiny_vector_v<B_DataT>) or - (std::is_same_v<std::string, B_DataT>)) { + if constexpr (std::is_arithmetic_v<B_DataT> or is_tiny_matrix_v<B_DataT> or is_tiny_vector_v<B_DataT> or + std::is_same_v<std::string, B_DataT> or is_std_vector_v<B_DataT>) { const auto& embedded_a = std::get<EmbeddedData>(a); const auto& b_value = std::get<B_DataT>(b); diff --git a/src/language/node_processor/FunctionArgumentConverter.hpp b/src/language/node_processor/FunctionArgumentConverter.hpp index f747672e2c036ab59402610cb7170218f96c15e3..3e22a9ae188574db47278f69cc264d0faf0c2f2c 100644 --- a/src/language/node_processor/FunctionArgumentConverter.hpp +++ b/src/language/node_processor/FunctionArgumentConverter.hpp @@ -219,6 +219,48 @@ class FunctionTupleArgumentConverter final : public IFunctionArgumentConverter } }, value); + } else if constexpr (std::is_same_v<std::string, ContentType>) { + std::visit( + [&](auto&& v) { + using ValueT = std::decay_t<decltype(v)>; + Assert(not std::is_same_v<ValueT, ContentType>, "should have been treated before"); + if constexpr (is_std_vector_v<ValueT>) { + using ContentT = typename ValueT::value_type; + if constexpr (std::is_same_v<ContentT, ContentType>) { + TupleType list_value; + list_value.reserve(v.size()); + for (size_t i = 0; i < v.size(); ++i) { + list_value.emplace_back(std::move(v[i])); + } + exec_policy.currentContext()[m_argument_id] = std::move(list_value); + } else if constexpr (not is_shared_ptr_v<ContentT>) { + TupleType list_value; + list_value.reserve(v.size()); + for (size_t i = 0; i < v.size(); ++i) { + std::ostringstream os; + const ContentT& content = v[i]; // useless helper for clang10 + os << content; + list_value.push_back(std::move(os.str())); + } + exec_policy.currentContext()[m_argument_id] = std::move(list_value); + } else { + // LCOV_EXCL_START + throw UnexpectedError(std::string{"cannot convert '"} + demangle<ValueT>() + "' to '" + + demangle<ContentType>() + "'"); + // LCOV_EXCL_STOP + } + } else if constexpr (not is_shared_ptr_v<ContentType>) { + std::ostringstream os; + os << v; + exec_policy.currentContext()[m_argument_id] = std::move(TupleType{std::move(os.str())}); + } else { + // LCOV_EXCL_START + throw UnexpectedError(std::string{"cannot convert '"} + demangle<ValueT>() + "' to '" + + demangle<ContentType>() + "'"); + // LCOV_EXCL_STOP + } + }, + value); } else { // LCOV_EXCL_START diff --git a/src/language/node_processor/FunctionProcessor.hpp b/src/language/node_processor/FunctionProcessor.hpp index c6c81d2938e9f774f0315f6a9af5c2e03c6a19e5..16e65e6e1e1ca63a7e1fa57e109856b3da25610a 100644 --- a/src/language/node_processor/FunctionProcessor.hpp +++ b/src/language/node_processor/FunctionProcessor.hpp @@ -124,7 +124,7 @@ class FunctionProcessor : public INodeProcessor for (auto& function_expression_processor : m_function_expression_processors) { list_values.emplace_back(function_expression_processor->execute(context_exec_policy)); } - return DataVariant{std::move(list_values)}; + return AggregateDataVariant{std::move(list_values)}; } } diff --git a/src/language/utils/BinaryOperatorRegisterForB.cpp b/src/language/utils/BinaryOperatorRegisterForB.cpp index dc228471d52330e486887e523c83dfa2d1917cef..7145ebab79c1b76a0877d92f87ca5b81cad62fcd 100644 --- a/src/language/utils/BinaryOperatorRegisterForB.cpp +++ b/src/language/utils/BinaryOperatorRegisterForB.cpp @@ -12,6 +12,10 @@ BinaryOperatorRegisterForB::_register_ostream() repository.addBinaryOperator<language::shift_left_op>( std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, std::shared_ptr<const OStream>, bool>>()); + + repository.addBinaryOperator<language::shift_left_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, + std::shared_ptr<const OStream>, std::vector<bool>>>()); } void diff --git a/src/language/utils/BinaryOperatorRegisterForN.cpp b/src/language/utils/BinaryOperatorRegisterForN.cpp index e32e2b53a5fb70af8b84069790dd8435a362e051..9d77d842e219e03237e4839c9fe8d3f7e027453d 100644 --- a/src/language/utils/BinaryOperatorRegisterForN.cpp +++ b/src/language/utils/BinaryOperatorRegisterForN.cpp @@ -12,6 +12,10 @@ BinaryOperatorRegisterForN::_register_ostream() repository.addBinaryOperator<language::shift_left_op>( std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, std::shared_ptr<const OStream>, uint64_t>>()); + + repository.addBinaryOperator<language::shift_left_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, + std::shared_ptr<const OStream>, std::vector<uint64_t>>>()); } void diff --git a/src/language/utils/BinaryOperatorRegisterForR.cpp b/src/language/utils/BinaryOperatorRegisterForR.cpp index cc8ba8a79dc59c447317200a308103b8d7dfc1d8..8f5d512752b2a9f7013085c3d10a5f5ec7e4aec1 100644 --- a/src/language/utils/BinaryOperatorRegisterForR.cpp +++ b/src/language/utils/BinaryOperatorRegisterForR.cpp @@ -12,6 +12,10 @@ BinaryOperatorRegisterForR::_register_ostream() repository.addBinaryOperator<language::shift_left_op>( std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, std::shared_ptr<const OStream>, double>>()); + + repository.addBinaryOperator<language::shift_left_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, + std::shared_ptr<const OStream>, std::vector<double>>>()); } void diff --git a/src/language/utils/BinaryOperatorRegisterForRn.cpp b/src/language/utils/BinaryOperatorRegisterForRn.cpp index 6e900d036871ed79eb13dfa737445becd50a1a9a..81e1d539d048a32815ec7e6749370370fc6b6f8e 100644 --- a/src/language/utils/BinaryOperatorRegisterForRn.cpp +++ b/src/language/utils/BinaryOperatorRegisterForRn.cpp @@ -16,6 +16,10 @@ BinaryOperatorRegisterForRn<Dimension>::_register_ostream() repository.addBinaryOperator<language::shift_left_op>( std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, std::shared_ptr<const OStream>, Rn>>()); + + repository.addBinaryOperator<language::shift_left_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, + std::shared_ptr<const OStream>, std::vector<Rn>>>()); } template <size_t Dimension> diff --git a/src/language/utils/BinaryOperatorRegisterForRnxn.cpp b/src/language/utils/BinaryOperatorRegisterForRnxn.cpp index f164203ddaca12e83f5ae5770dcb4848d366d3a4..4970fe434e318bdbf4ac037bd4f7fc6cedc9a006 100644 --- a/src/language/utils/BinaryOperatorRegisterForRnxn.cpp +++ b/src/language/utils/BinaryOperatorRegisterForRnxn.cpp @@ -16,6 +16,10 @@ BinaryOperatorRegisterForRnxn<Dimension>::_register_ostream() repository.addBinaryOperator<language::shift_left_op>( std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, std::shared_ptr<const OStream>, Rnxn>>()); + + repository.addBinaryOperator<language::shift_left_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, + std::shared_ptr<const OStream>, std::vector<Rnxn>>>()); } template <size_t Dimension> diff --git a/src/language/utils/BinaryOperatorRegisterForString.cpp b/src/language/utils/BinaryOperatorRegisterForString.cpp index 999950cf1b1310bbe52614cc6823f37be53f82a4..cae341bf9ad565a5fc87801526a3024dd2f945ae 100644 --- a/src/language/utils/BinaryOperatorRegisterForString.cpp +++ b/src/language/utils/BinaryOperatorRegisterForString.cpp @@ -14,6 +14,10 @@ BinaryOperatorRegisterForString::_register_ostream() repository.addBinaryOperator<language::shift_left_op>( std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, std::shared_ptr<const OStream>, std::string>>()); + + repository.addBinaryOperator<language::shift_left_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, + std::shared_ptr<const OStream>, std::vector<std::string>>>()); } void diff --git a/src/language/utils/BinaryOperatorRegisterForZ.cpp b/src/language/utils/BinaryOperatorRegisterForZ.cpp index 1d318850226beac44d27fe5f4fdba6c8e36a4e61..8174f3f493b417bf39e41cc4e3344b98abf071e4 100644 --- a/src/language/utils/BinaryOperatorRegisterForZ.cpp +++ b/src/language/utils/BinaryOperatorRegisterForZ.cpp @@ -12,6 +12,10 @@ BinaryOperatorRegisterForZ::_register_ostream() repository.addBinaryOperator<language::shift_left_op>( std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, std::shared_ptr<const OStream>, int64_t>>()); + + repository.addBinaryOperator<language::shift_left_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::shift_left_op, std::shared_ptr<const OStream>, + std::shared_ptr<const OStream>, std::vector<int64_t>>>()); } void diff --git a/src/language/utils/BuiltinFunctionEmbedder.hpp b/src/language/utils/BuiltinFunctionEmbedder.hpp index 265379a368ef3b7f847cd8de2b763a70b525f8a4..ac3ba21fe241f8ea9416192fc0ce97f865bb0883 100644 --- a/src/language/utils/BuiltinFunctionEmbedder.hpp +++ b/src/language/utils/BuiltinFunctionEmbedder.hpp @@ -204,7 +204,7 @@ class BuiltinFunctionEmbedder<FX(Args...)> : public IBuiltinFunctionEmbedder std::apply([&](auto&&... result) { ((vector_result.emplace_back(_resultToDataVariant(result))), ...); }, tuple_result); - return vector_result; + return AggregateDataVariant{std::move(vector_result)}; } public: @@ -337,7 +337,7 @@ class BuiltinFunctionEmbedder<FX(void)> : public IBuiltinFunctionEmbedder std::apply([&](auto&&... result) { ((vector_result.emplace_back(_resultToDataVariant(result))), ...); }, tuple_result); - return vector_result; + return AggregateDataVariant{std::move(vector_result)}; } public: diff --git a/src/language/utils/DataVariant.cpp b/src/language/utils/DataVariant.cpp index fc82eec7b805cd49daa2a097490b36fa33e0c561..005dda6f17f9d38cb2c9a7a63322244657f89e50 100644 --- a/src/language/utils/DataVariant.cpp +++ b/src/language/utils/DataVariant.cpp @@ -13,6 +13,9 @@ operator<<(std::ostream& os, const DataVariant& v) os << "--"; } else if constexpr (is_std_vector_v<ValueT>) { os << '('; + if constexpr (std::is_same_v<bool, typename ValueT::value_type>) { + os << std::boolalpha; + } if (v.size() > 0) { os << v[0]; } diff --git a/src/language/utils/DataVariant.hpp b/src/language/utils/DataVariant.hpp index 964044c6121478b4247c089a45eaf3ebe025195e..9a09cad6fc531b1cf8a5c3de8b09bfad5487ccf0 100644 --- a/src/language/utils/DataVariant.hpp +++ b/src/language/utils/DataVariant.hpp @@ -97,7 +97,7 @@ class AggregateDataVariant // LCOV_EXCL_LINE AggregateDataVariant& operator=(const AggregateDataVariant&) = default; AggregateDataVariant& operator=(AggregateDataVariant&&) = default; - AggregateDataVariant(std::vector<DataVariant>&& data_vector) : m_data_vector{data_vector} {} + explicit AggregateDataVariant(std::vector<DataVariant>&& data_vector) : m_data_vector{data_vector} {} AggregateDataVariant(const AggregateDataVariant&) = default; AggregateDataVariant(AggregateDataVariant&&) = default; diff --git a/tests/test_BinaryExpressionProcessor_shift.cpp b/tests/test_BinaryExpressionProcessor_shift.cpp index c1892a2ff3a793a1cdc9a48e6f1a454b090fe77d..127e90161416444f652c16206ddbd8c4f97d5718 100644 --- a/tests/test_BinaryExpressionProcessor_shift.cpp +++ b/tests/test_BinaryExpressionProcessor_shift.cpp @@ -6,6 +6,7 @@ #include <fstream> #include <netdb.h> +#include <regex> #include <unistd.h> // clazy:excludeall=non-pod-global-static @@ -24,8 +25,29 @@ TEST_CASE("BinaryExpressionProcessor shift", "[language]") data << R"(import socket;)"; data << "let fout:ostream, fout = ofstream(\"" << path.string() << "\");\n"; data << R"(fout << 2 << " " << true << " " << 2 + 3 << "\n"; -fout << createSocketServer(0);)"; - +fout << createSocketServer(0) << "\n";)"; + data << "let b:(B), b = (true,false);\n"; + data << "let n:(N), n = (1,3);\n"; + data << "let z:(Z), z = (-1,3);\n"; + data << "let r:(R), r = (2.3,4);\n"; + data << "let u1:(R^1), u1 = (2.3,4);\n"; + data << "let u2:(R^2), u2 = ((2.3,4), (3,2));\n"; + data << "let u3:(R^3), u3 = ((2.3,4,-1), (3,2,1));\n"; + data << "let A1:(R^1x1), A1 = (2.3, 4);\n"; + data << "let A2:(R^2x2), A2 = ((2.3,4,2,0.3), (3,2.3,1,-4));\n"; + data << "let A3:(R^3x3), A3 = ((2.3,4,-1,2,7,2.3,6,2,8), (3,2,1,1,2,5,2.1,3,-2.6));\n"; + data << R"(let s:(string), s = ("foo", "bar");)"; + data << R"(fout << b << "\n";)"; + data << R"(fout << n << "\n";)"; + data << R"(fout << z << "\n";)"; + data << R"(fout << r << "\n";)"; + data << R"(fout << u1 << "\n";)"; + data << R"(fout << u2 << "\n";)"; + data << R"(fout << u3 << "\n";)"; + data << R"(fout << A1 << "\n";)"; + data << R"(fout << A2 << "\n";)"; + data << R"(fout << A3 << "\n";)"; + data << R"(fout << s << "\n";)"; TAO_PEGTL_NAMESPACE::string_input input{data.str(), "test.pgs"}; auto ast = ASTBuilder::build(input); @@ -69,7 +91,9 @@ fout << createSocketServer(0);)"; auto is_int = [](const std::string& s) { for (const char& c : s) { - if (not std::isdigit(c)) { + if (c == '\n') { + break; + } else if (not std::isdigit(c)) { return false; } } @@ -79,6 +103,54 @@ fout << createSocketServer(0);)"; REQUIRE(is_int(suffix)); } + { + std::ifstream fin(filename.c_str()); + char line[1024]; + + fin.getline(line, 1023); + REQUIRE(std::string_view(line) == "2 true 5"); + + char hbuf[NI_MAXHOST]; + ::gethostname(hbuf, NI_MAXHOST); + std::ostringstream os; + os << '^' << hbuf << ":\\d+$"; + fin.getline(line, 1023); + REQUIRE(std::regex_match(line, std::regex{os.str()})); + + fin.getline(line, 1023); + REQUIRE(std::string_view(line) == "(true, false)"); + + fin.getline(line, 1023); + REQUIRE(std::string_view(line) == "(1, 3)"); + + fin.getline(line, 1023); + REQUIRE(std::string_view(line) == "(-1, 3)"); + + fin.getline(line, 1023); + REQUIRE(std::string_view(line) == "(2.3, 4)"); + + fin.getline(line, 1023); + REQUIRE(std::string_view(line) == "((2.3), (4))"); + + fin.getline(line, 1023); + REQUIRE(std::string_view(line) == "((2.3,4), (3,2))"); + + fin.getline(line, 1023); + REQUIRE(std::string_view(line) == "((2.3,4,-1), (3,2,1))"); + + fin.getline(line, 1023); + REQUIRE(std::string_view(line) == "([(2.3)], [(4)])"); + + fin.getline(line, 1023); + REQUIRE(std::string_view(line) == "([(2.3,4)(2,0.3)], [(3,2.3)(1,-4)])"); + + fin.getline(line, 1023); + REQUIRE(std::string_view(line) == "([(2.3,4,-1)(2,7,2.3)(6,2,8)], [(3,2,1)(1,2,5)(2.1,3,-2.6)])"); + + fin.getline(line, 1023); + REQUIRE(std::string_view(line) == "(foo, bar)"); + } + std::filesystem::remove(filename); REQUIRE(not std::filesystem::exists(filename)); }