From 8366faeb25f7d9958ababcb7459c0c8814d02555 Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Fri, 31 Jan 2020 19:24:40 +0100 Subject: [PATCH] Continue vector component affectation (still buggy) --- .../node_processor/AffectationProcessor.hpp | 135 +++++++++++++++++- 1 file changed, 131 insertions(+), 4 deletions(-) diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp index 4080f3fc8..8e30fae59 100644 --- a/src/language/node_processor/AffectationProcessor.hpp +++ b/src/language/node_processor/AffectationProcessor.hpp @@ -54,7 +54,7 @@ struct AffOp<language::minuseq_op> struct IAffectationExecutor { - virtual void affect(DataVariant&& rhs) = 0; + virtual void affect(ExecutionPolicy& exec_policy, DataVariant&& rhs) = 0; virtual ~IAffectationExecutor() = default; }; @@ -85,7 +85,7 @@ class AffectationExecutor final : public IAffectationExecutor } PUGS_INLINE void - affect(DataVariant&& rhs) + affect(ExecutionPolicy&, DataVariant&& rhs) { if constexpr (_is_defined) { if constexpr (std::is_same_v<ValueT, std::string>) { @@ -118,6 +118,84 @@ class AffectationExecutor final : public IAffectationExecutor } }; +template <typename OperatorT, typename ArrayT, typename ValueT, typename DataT> +class ComponentAffectationExecutor final : public IAffectationExecutor +{ + private: + ArrayT& m_lhs_array; + ASTNode& m_index_expression; + + static inline const bool _is_defined{[] { + if constexpr (not std::is_same_v<typename ArrayT::data_type, ValueT>) { + return false; + } else if constexpr (std::is_same_v<std::decay_t<ValueT>, bool>) { + if constexpr (not std::is_same_v<OperatorT, language::eq_op>) { + return false; + } + } + return true; + }()}; + + public: + ComponentAffectationExecutor(ASTNode& node, ArrayT& lhs_array) + : m_lhs_array{lhs_array}, m_index_expression{*node.children[1]} + { + // LCOV_EXCL_START + if constexpr (not _is_defined) { + throw parse_error("unexpected error: invalid operands to affectation expression", std::vector{node.begin()}); + } + // LCOV_EXCL_STOP + } + + PUGS_INLINE void + affect(ExecutionPolicy& exec_policy, DataVariant&& rhs) + { + if constexpr (_is_defined) { + const int64_t index_value = [&](DataVariant&& value_variant) -> int64_t { + int64_t index_value = 0; + std::visit( + [&](auto&& value) { + using IndexValueT = std::decay_t<decltype(value)>; + if constexpr (std::is_integral_v<IndexValueT>) { + index_value = value; + } else { + throw parse_error("unexpected error: invalid index type", std::vector{m_index_expression.begin()}); + } + }, + value_variant); + return index_value; + }(m_index_expression.execute(exec_policy)); + + if constexpr (std::is_same_v<ValueT, std::string>) { + if constexpr (std::is_same_v<OperatorT, language::eq_op>) { + if constexpr (std::is_same_v<std::string, DataT>) { + m_lhs_array[index_value] = std::get<DataT>(rhs); + } else { + m_lhs_array[index_value] = std::to_string(std::get<DataT>(rhs)); + } + } else { + static_assert(std::is_same_v<OperatorT, language::pluseq_op>, "unexpected operator type"); + if constexpr (std::is_same_v<std::string, DataT>) { + m_lhs_array[index_value] += std::get<std::string>(rhs); + } else { + m_lhs_array[index_value] += std::to_string(std::get<DataT>(rhs)); + } + } + } else { + if constexpr (std::is_same_v<OperatorT, language::eq_op>) { + if constexpr (std::is_same_v<ValueT, DataT>) { + m_lhs_array[index_value] = std::get<DataT>(rhs); + } else { + m_lhs_array[index_value] = static_cast<ValueT>(std::get<DataT>(rhs)); + } + } else { + AffOp<OperatorT>().eval(m_lhs_array[index_value], std::get<DataT>(rhs)); + } + } + } + } +}; + template <typename OperatorT, typename ValueT, typename DataT> class AffectationProcessor final : public INodeProcessor { @@ -130,7 +208,7 @@ class AffectationProcessor final : public INodeProcessor DataVariant execute(ExecutionPolicy& exec_policy) { - m_affectation_executor->affect(m_node.children[1]->execute(exec_policy)); + m_affectation_executor->affect(exec_policy, m_node.children[1]->execute(exec_policy)); return {}; } @@ -149,6 +227,55 @@ class AffectationProcessor final : public INodeProcessor using AffectationExecutorT = AffectationExecutor<OperatorT, ValueT, DataT>; m_affectation_executor = std::make_unique<AffectationExecutorT>(m_node, std::get<ValueT>(value)); + } else if (node.children[0]->is_type<language::subscript_expression>()) { + auto& array_subscript_expression = *node.children[0]; + + auto& array_expression = *array_subscript_expression.children[0]; + Assert(array_expression.is_type<language::name>()); + + const std::string& symbol = array_expression.string(); + + auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin()); + Assert(found); + DataVariant& value = i_symbol->attributes().value(); + + if (array_expression.m_data_type != ASTNodeDataType::vector_t) { + throw parse_error("unexpected error: invalid lhs (expecting R^d)", std::vector{node.children[0]->begin()}); + } + + switch (array_expression.m_data_type.dimension()) { + case 1: { + using ArrayTypeT = TinyVector<1>; + if (not std::holds_alternative<ArrayTypeT>(value)) { + value = ArrayTypeT{}; + } + using AffectationExecutorT = ComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>; + m_affectation_executor = std::make_unique<AffectationExecutorT>(m_node, std::get<ArrayTypeT>(value)); + break; + } + case 2: { + using ArrayTypeT = TinyVector<2>; + if (not std::holds_alternative<ArrayTypeT>(value)) { + value = ArrayTypeT{}; + } + using AffectationExecutorT = ComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>; + m_affectation_executor = std::make_unique<AffectationExecutorT>(m_node, std::get<ArrayTypeT>(value)); + break; + } + case 3: { + using ArrayTypeT = TinyVector<3>; + if (not std::holds_alternative<ArrayTypeT>(value)) { + value = ArrayTypeT{}; + } + using AffectationExecutorT = ComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>; + m_affectation_executor = std::make_unique<AffectationExecutorT>(m_node, std::get<ArrayTypeT>(value)); + break; + } + default: { + throw parse_error("unexpected error: invalid vector dimension", std::vector{node.children[0]->begin()}); + } + } + } else { throw parse_error("unexpected error: invalid lhs", std::vector{node.children[0]->begin()}); } @@ -264,7 +391,7 @@ class ListAffectationProcessor final : public INodeProcessor Assert(m_affectation_executor_list.size() == children_values.size()); for (size_t i = 0; i < m_affectation_executor_list.size(); ++i) { - m_affectation_executor_list[i]->affect(std::move(children_values[i])); + m_affectation_executor_list[i]->affect(exec_policy, std::move(children_values[i])); } return {}; -- GitLab