diff --git a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp index 410ab1b58dc3a8895fc243a1cfe65b3e5df6a592..7e79b35d55abf14d3540b76b3587c1db9035f8d5 100644 --- a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp @@ -280,6 +280,53 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } 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); + 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: undefined operand type for tuple affectation", diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp index a2b41c3e0037f54bc33cf7254c6b22fc6732c3f2..4c79bb5783abb2ed1c312c2ed7f68817287f0ec2 100644 --- a/src/language/node_processor/AffectationProcessor.hpp +++ b/src/language/node_processor/AffectationProcessor.hpp @@ -387,6 +387,58 @@ class AffectationToTinyVectorFromListProcessor final : public INodeProcessor } }; +template <typename OperatorT, typename ValueT> +class AffectationToTupleProcessor final : public INodeProcessor +{ + private: + ASTNode& m_node; + + DataVariant* m_lhs; + + public: + DataVariant + execute(ExecutionPolicy& exec_policy) + { + static_assert(std::is_same_v<OperatorT, language::eq_op>, "forbidden affection operator to tuples"); + DataVariant value = m_node.children[1]->execute(exec_policy); + + std::visit( + [&](auto&& v) { + using T = std::decay_t<decltype(v)>; + if constexpr (std::is_same_v<T, ValueT>) { + *m_lhs = std::vector{std::move(v)}; + } else if constexpr (std::is_arithmetic_v<ValueT> and std::is_convertible_v<T, ValueT>) { + *m_lhs = std::vector{std::move(static_cast<ValueT>(v))}; + } else if constexpr (std::is_same_v<std::string, ValueT>) { + if constexpr (std::is_arithmetic_v<T>) { + *m_lhs = std::vector{std::move(std::to_string(v))}; + } else { + std::ostringstream os; + os << v << std::ends; + *m_lhs = std::vector{os.str()}; + } + + } else { + // LCOV_EXCL_START + throw parse_error("unexpected error: unexpected right hand side type in affectation", m_node.begin()); + // LCOV_EXCL_STOP + } + }, + value); + + return {}; + } + + AffectationToTupleProcessor(ASTNode& node) : m_node{node} + { + const std::string& symbol = m_node.children[0]->string(); + auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin()); + Assert(found); + + m_lhs = &i_symbol->attributes().value(); + } +}; + template <typename OperatorT, typename ValueT> class AffectationToTupleFromListProcessor final : public INodeProcessor { @@ -401,7 +453,7 @@ class AffectationToTupleFromListProcessor final : public INodeProcessor { 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 vectors"); + 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) { diff --git a/src/language/node_processor/FunctionArgumentConverter.hpp b/src/language/node_processor/FunctionArgumentConverter.hpp index e200a475ea53d6ee3d465b30590604cc56ae5f22..c93516a86be9a75485819eb19e63132b35522182 100644 --- a/src/language/node_processor/FunctionArgumentConverter.hpp +++ b/src/language/node_processor/FunctionArgumentConverter.hpp @@ -101,7 +101,7 @@ class FunctionTupleArgumentConverter final : public IFunctionArgumentConverter convert(ExecutionPolicy& exec_policy, DataVariant&& value) { using TupleType = std::vector<ContentType>; - if constexpr (std::is_same_v<ContentType, ProvidedValueType>) { + if constexpr (std::is_convertible_v<ProvidedValueType, ContentType>) { std::visit( [&](auto&& v) { using ValueT = std::decay_t<decltype(v)>; @@ -117,6 +117,8 @@ class FunctionTupleArgumentConverter final : public IFunctionArgumentConverter } exec_policy.currentContext()[m_argument_id] = std::move(list_value); } + } else if constexpr (std::is_convertible_v<ValueT, ContentType> and not is_tiny_vector_v<ContentType>) { + exec_policy.currentContext()[m_argument_id] = std::move(TupleType{static_cast<ContentType>(v)}); } else { throw UnexpectedError(demangle<ValueT>() + " unexpected value type"); }