diff --git a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp index 3f1ff4369995e7ae69f125a5e40aa1da467c0436..bf4478a52b1ace61b5014a4751a3df43dd1e3c63 100644 --- a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp @@ -42,7 +42,7 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData switch (argument_node_sub_data_type.m_data_type) { case ASTNodeDataType::vector_t: { if (argument_node_sub_data_type.m_data_type.dimension() == parameter_v.dimension()) { - return std::make_unique<FunctionArgumentConverter<ParameterT, ParameterT>>(argument_number); + return std::make_unique<FunctionTinyVectorArgumentConverter<ParameterT, ParameterT>>(argument_number); } else { // LCOV_EXCL_START throw parse_error("unexpected error: invalid argument dimension", @@ -52,7 +52,7 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } case ASTNodeDataType::list_t: { if (argument_node_sub_data_type.m_parent_node.children.size() == parameter_v.dimension()) { - return std::make_unique<FunctionArgumentConverter<ParameterT, ParameterT>>(argument_number); + return std::make_unique<FunctionTinyVectorArgumentConverter<ParameterT, ParameterT>>(argument_number); } else { // LCOV_EXCL_START throw parse_error("unexpected error: invalid argument dimension", @@ -63,7 +63,7 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData case ASTNodeDataType::int_t: { if (argument_node_sub_data_type.m_parent_node.is_type<language::integer>()) { if (std::stoi(argument_node_sub_data_type.m_parent_node.string()) == 0) { - return std::make_unique<FunctionArgumentConverter<ParameterT, ZeroType>>(argument_number); + return std::make_unique<FunctionTinyVectorArgumentConverter<ParameterT, ZeroType>>(argument_number); } } [[fallthrough]]; @@ -119,11 +119,12 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData auto get_function_argument_to_tuple_converter = [&](const auto& parameter_content_v) -> std::unique_ptr<IFunctionArgumentConverter> { - using ParameterContentT = std::decay_t<decltype(parameter_content_v)>; - switch (argument_node_sub_data_type.m_data_type) { + using ParameterContentT = std::decay_t<decltype(parameter_content_v)>; + const auto& arg_data_type = argument_node_sub_data_type.m_data_type; + switch (arg_data_type) { case ASTNodeDataType::tuple_t: { - const auto& arg_content_type = argument_node_sub_data_type.m_data_type.contentType(); - switch (arg_content_type) { + const auto& tuple_content_type = arg_data_type.contentType(); + switch (tuple_content_type) { case ASTNodeDataType::type_id_t: { return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, EmbeddedData>>(argument_number); } @@ -143,7 +144,7 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, std::string>>(argument_number); } case ASTNodeDataType::vector_t: { - switch (arg_content_type.dimension()) { + switch (tuple_content_type.dimension()) { case 1: { return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, TinyVector<1>>>(argument_number); } @@ -154,21 +155,55 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, TinyVector<3>>>(argument_number); } default: { - throw UnexpectedError(dataTypeName(arg_content_type) + + throw UnexpectedError(dataTypeName(tuple_content_type) + " unexpected content of argument, invalid dimension of vector"); } } } default: { - throw UnexpectedError(dataTypeName(arg_content_type) + " unexpected tuple content type of argument "); + throw UnexpectedError(dataTypeName(tuple_content_type) + " unexpected tuple content type of argument "); } } } case ASTNodeDataType::list_t: { return std::make_unique<FunctionListArgumentConverter<ParameterContentT, ParameterContentT>>(argument_number); } + case ASTNodeDataType::type_id_t: { + return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, EmbeddedData>>(argument_number); + } + case ASTNodeDataType::bool_t: { + return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, bool>>(argument_number); + } + case ASTNodeDataType::unsigned_int_t: { + return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, uint64_t>>(argument_number); + } + case ASTNodeDataType::int_t: { + return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, int64_t>>(argument_number); + } + 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::vector_t: { + switch (arg_data_type.dimension()) { + case 1: { + return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, TinyVector<1>>>(argument_number); + } + case 2: { + return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, TinyVector<2>>>(argument_number); + } + case 3: { + return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, TinyVector<3>>>(argument_number); + } + default: { + throw UnexpectedError(dataTypeName(arg_data_type) + " unexpected dimension of vector"); + } + } + } default: { - throw UnexpectedError(dataTypeName(argument_node_sub_data_type.m_data_type) + " argument to tuple "); + throw UnexpectedError(dataTypeName(arg_data_type) + " argument to tuple "); } } }; diff --git a/src/language/ast/ASTNodeDataType.cpp b/src/language/ast/ASTNodeDataType.cpp index 38f33ff436679e4d5aaeea976691baa148443195..18b812c0e7bb7c62466a7bce6b1dfd279eacec43 100644 --- a/src/language/ast/ASTNodeDataType.cpp +++ b/src/language/ast/ASTNodeDataType.cpp @@ -113,6 +113,8 @@ isNaturalConversion(const ASTNodeDataType& data_type, const ASTNodeDataType& tar (data_type == ASTNodeDataType::bool_t)); } else if (target_data_type == ASTNodeDataType::string_t) { return ((data_type >= ASTNodeDataType::bool_t) and (data_type < ASTNodeDataType::string_t)); + } else if (target_data_type == ASTNodeDataType::tuple_t) { + return isNaturalConversion(data_type, target_data_type.contentType()); } return false; } diff --git a/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp index 2ae74e8a6e488f0af73b75101e8a8d6c2e7c704a..027c3020f8b205757f7ea531936d8b282689831d 100644 --- a/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp @@ -48,7 +48,7 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy switch (node_sub_data_type.m_data_type) { case ASTNodeDataType::vector_t: { if (node_sub_data_type.m_data_type.dimension() == parameter_v.dimension()) { - return std::make_unique<FunctionArgumentConverter<ParameterT, ParameterT>>(parameter_id); + return std::make_unique<FunctionTinyVectorArgumentConverter<ParameterT, ParameterT>>(parameter_id); } else { // LCOV_EXCL_START throw parse_error("unexpected error: invalid argument dimension", @@ -58,7 +58,7 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy } case ASTNodeDataType::list_t: { if (node_sub_data_type.m_parent_node.children.size() == parameter_v.dimension()) { - return std::make_unique<FunctionArgumentConverter<ParameterT, ParameterT>>(parameter_id); + return std::make_unique<FunctionTinyVectorArgumentConverter<ParameterT, ParameterT>>(parameter_id); } else { // LCOV_EXCL_START throw parse_error("unexpected error: invalid argument dimension", @@ -69,7 +69,7 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy case ASTNodeDataType::int_t: { if (node_sub_data_type.m_parent_node.is_type<language::integer>()) { if (std::stoi(node_sub_data_type.m_parent_node.string()) == 0) { - return std::make_unique<FunctionArgumentConverter<ParameterT, ZeroType>>(parameter_id); + return std::make_unique<FunctionTinyVectorArgumentConverter<ParameterT, ZeroType>>(parameter_id); } } [[fallthrough]]; diff --git a/src/language/node_processor/FunctionArgumentConverter.hpp b/src/language/node_processor/FunctionArgumentConverter.hpp index 8b63a818b35e4859d59f645162223154f9557851..e200a475ea53d6ee3d465b30590604cc56ae5f22 100644 --- a/src/language/node_processor/FunctionArgumentConverter.hpp +++ b/src/language/node_processor/FunctionArgumentConverter.hpp @@ -34,8 +34,6 @@ class FunctionArgumentConverter final : public IFunctionArgumentConverter exec_policy.currentContext()[m_argument_id] = std::move(value); } else if constexpr (std::is_same_v<ExpectedValueType, std::string>) { exec_policy.currentContext()[m_argument_id] = std::move(std::to_string(std::get<ProvidedValueType>(value))); - } else if constexpr (std::is_same_v<ProvidedValueType, ZeroType>) { - exec_policy.currentContext()[m_argument_id] = ExpectedValueType{ZeroType::zero}; } else { exec_policy.currentContext()[m_argument_id] = std::move(static_cast<ExpectedValueType>(std::get<ProvidedValueType>(value))); @@ -47,7 +45,7 @@ class FunctionArgumentConverter final : public IFunctionArgumentConverter }; template <typename ExpectedValueType, typename ProvidedValueType> -class FunctionTupleArgumentConverter final : public IFunctionArgumentConverter +class FunctionTinyVectorArgumentConverter final : public IFunctionArgumentConverter { private: size_t m_argument_id; @@ -60,14 +58,59 @@ class FunctionTupleArgumentConverter final : public IFunctionArgumentConverter std::visit( [&](auto&& v) { using ValueT = std::decay_t<decltype(v)>; - if constexpr (std::is_same_v<ValueT, AggregateDataVariant>) { - throw NotImplementedError("AggregateDataVariant case"); - } else if constexpr (std::is_same_v<ValueT, ExpectedValueType>) { - exec_policy.currentContext()[m_argument_id] = std::move(v); + if constexpr (std::is_same_v<ValueT, ExpectedValueType>) { + exec_policy.currentContext()[m_argument_id] = std::move(value); + } else if constexpr (std::is_same_v<ValueT, AggregateDataVariant>) { + ExpectedValueType vector_value{}; + for (size_t i = 0; i < vector_value.dimension(); ++i) { + std::visit( + [&](auto&& v_i) { + using Vi_T = std::decay_t<decltype(v_i)>; + if constexpr (std::is_arithmetic_v<Vi_T>) { + vector_value[i] = v_i; + } else { + throw UnexpectedError(demangle<Vi_T>() + " unexpected aggregate value type"); + } + }, + v[i]); + } + exec_policy.currentContext()[m_argument_id] = std::move(vector_value); + } + }, + value); + } else if constexpr (std::is_same_v<ProvidedValueType, ZeroType>) { + exec_policy.currentContext()[m_argument_id] = ExpectedValueType{ZeroType::zero}; + } else { + exec_policy.currentContext()[m_argument_id] = + std::move(static_cast<ExpectedValueType>(std::get<ProvidedValueType>(value))); + } + return {}; + } + + FunctionTinyVectorArgumentConverter(size_t argument_id) : m_argument_id{argument_id} {} +}; + +template <typename ContentType, typename ProvidedValueType> +class FunctionTupleArgumentConverter final : public IFunctionArgumentConverter +{ + private: + size_t m_argument_id; + + public: + DataVariant + convert(ExecutionPolicy& exec_policy, DataVariant&& value) + { + using TupleType = std::vector<ContentType>; + if constexpr (std::is_same_v<ContentType, ProvidedValueType>) { + std::visit( + [&](auto&& v) { + 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>) { using ContentT = typename ValueT::value_type; - if constexpr (std::is_same_v<ContentT, ExpectedValueType>) { - std::vector<ExpectedValueType> list_value; + 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(v[i]); @@ -80,7 +123,6 @@ class FunctionTupleArgumentConverter final : public IFunctionArgumentConverter }, value); } else { - // static_assert(std::is_same_v<ExpectedValueType, ProvidedValueType>, "conversion is not implemented"); throw UnexpectedError(demangle<std::decay_t<decltype(*this)>>() + ": did nothing!"); } return {}; @@ -89,7 +131,7 @@ class FunctionTupleArgumentConverter final : public IFunctionArgumentConverter FunctionTupleArgumentConverter(size_t argument_id) : m_argument_id{argument_id} {} }; -template <typename ExpectedValueType, typename ProvidedValueType> +template <typename ContentType, typename ProvidedValueType> class FunctionListArgumentConverter final : public IFunctionArgumentConverter { private: @@ -99,20 +141,21 @@ class FunctionListArgumentConverter final : public IFunctionArgumentConverter DataVariant convert(ExecutionPolicy& exec_policy, DataVariant&& value) { - if constexpr (std::is_same_v<ExpectedValueType, ProvidedValueType>) { + using TupleType = std::vector<ContentType>; + if constexpr (std::is_same_v<ContentType, ProvidedValueType>) { std::visit( [&](auto&& v) { using ValueT = std::decay_t<decltype(v)>; if constexpr (std::is_same_v<ValueT, AggregateDataVariant>) { - std::vector<ExpectedValueType> list_value; + TupleType list_value; list_value.reserve(v.size()); for (size_t i = 0; i < v.size(); ++i) { std::visit( [&](auto&& vi) { using Vi_T = std::decay_t<decltype(vi)>; - if constexpr (is_tiny_vector_v<ExpectedValueType>) { + if constexpr (is_tiny_vector_v<ContentType>) { throw NotImplementedError("TinyVector case"); - } else if constexpr (std::is_convertible_v<Vi_T, ExpectedValueType>) { + } else if constexpr (std::is_convertible_v<Vi_T, ContentType>) { list_value.emplace_back(vi); } else { throw UnexpectedError("unexpected types"); @@ -121,12 +164,12 @@ class FunctionListArgumentConverter final : public IFunctionArgumentConverter (v[i])); } exec_policy.currentContext()[m_argument_id] = std::move(list_value); - } else if constexpr (std::is_same_v<ValueT, ExpectedValueType>) { + } 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>) { using ContentT = typename ValueT::value_type; - if constexpr (std::is_same_v<ContentT, ExpectedValueType>) { - std::vector<ExpectedValueType> list_value; + 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(v[i]); @@ -139,7 +182,7 @@ class FunctionListArgumentConverter final : public IFunctionArgumentConverter }, value); } - static_assert(std::is_same_v<ExpectedValueType, ProvidedValueType>, "conversion is not implemented"); + static_assert(std::is_same_v<ContentType, ProvidedValueType>, "conversion is not implemented"); return {}; }