From e00fe905e89c0d13463023eb4f292af7a15e4632 Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Fri, 24 Jan 2020 17:45:39 +0100 Subject: [PATCH] Terminate R^d vectors declarations and affectation One can now write `` R^3 u = (1, 2, 3); R^3 v = u; R^3 w = 0; // One cannot give another scalar value: just the constant value 0 // that is `R^3 w = 1-1;` is an error! w += u; // w and u belong to the same space R^d (with d=3 here) v *= 2.5-1;// the right hand side is a scalar expression that can be naturally // cast to an R v -= u; `` These constructions are allowed for small vectors: valid types are `R^1`, `R^2` and `R^3`. Remark: tuples are only allowed in initialization: `` R^2 v = (0,1); // ok R^2 w ; w = (2,3); // ok w += (1,4); // forbidden `` --- .../ASTNodeAffectationExpressionBuilder.cpp | 100 ++++++++++++++++-- src/language/ASTNodeDataType.cpp | 2 +- .../node_processor/AffectationProcessor.hpp | 71 +++++++++++++ 3 files changed, 165 insertions(+), 8 deletions(-) diff --git a/src/language/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ASTNodeAffectationExpressionBuilder.cpp index e30b0380a..8c615e6e2 100644 --- a/src/language/ASTNodeAffectationExpressionBuilder.cpp +++ b/src/language/ASTNodeAffectationExpressionBuilder.cpp @@ -44,21 +44,91 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode using OperatorT = std::decay_t<decltype(operator_v)>; using ValueT = std::decay_t<decltype(value)>; - if constexpr (std::is_same_v<OperatorT, language::eq_op> or std::is_same_v<OperatorT, language::pluseq_op>) { + if constexpr (std::is_same_v<OperatorT, language::eq_op>) { switch (data_type) { case ASTNodeDataType::vector_t: { n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, ValueT>>(n); break; + } + case ASTNodeDataType::list_t: { + n.m_node_processor = std::make_unique<AffectationFromListProcessor<OperatorT, ValueT>>(n); + break; + } + case ASTNodeDataType::bool_t: { + if constexpr (std::is_same_v<ValueT, TinyVector<1>>) { + n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, bool>>(n); + break; + } + } + case ASTNodeDataType::unsigned_int_t: { + if constexpr (std::is_same_v<ValueT, TinyVector<1>>) { + n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, uint64_t>>(n); + break; + } + } + case ASTNodeDataType::int_t: { + if constexpr (std::is_same_v<ValueT, TinyVector<1>>) { + n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, int64_t>>(n); + break; + } else { + if (n.children[1]->is_type<language::integer>()) { + if (std::stoi(n.children[1]->string()) == 0) { + n.m_node_processor = std::make_unique<AffectationFromZeroProcessor<ValueT>>(n); + break; + } + } + } + throw parse_error("invalid operand value", std::vector{n.children[1]->begin()}); + } + case ASTNodeDataType::double_t: { + if constexpr (std::is_same_v<ValueT, TinyVector<1>>) { + n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, double>>(n); + break; + } } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: undefined operand type for vector affectation", - std::vector{n.children[1]->begin()}); + throw parse_error("invalid operand type", std::vector{n.children[1]->begin()}); } // LCOV_EXCL_STOP } + } else if constexpr (std::is_same_v<OperatorT, language::pluseq_op> or + std::is_same_v<OperatorT, language::minuseq_op>) { + switch (data_type) { + case ASTNodeDataType::vector_t: { + n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, ValueT>>(n); + break; + } + // LCOV_EXCL_START + default: { + throw parse_error("invalid operand type", std::vector{n.children[1]->begin()}); + } + // LCOV_EXCL_STOP + } + } else if constexpr (std::is_same_v<OperatorT, language::multiplyeq_op>) { + switch (data_type) { + case ASTNodeDataType::bool_t: { + n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, bool>>(n); + break; + } + case ASTNodeDataType::unsigned_int_t: { + n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, uint64_t>>(n); + break; + } + case ASTNodeDataType::int_t: { + n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, int64_t>>(n); + break; + } + case ASTNodeDataType::double_t: { + n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, double>>(n); + break; + } + default: { + throw parse_error("invalid operand", std::vector{n.children[1]->begin()}); + } + } } else { - throw parse_error("unexpected error: undefined operator type", std::vector{n.children[0]->begin()}); + throw parse_error("invalid operator type", std::vector{n.begin()}); } }; @@ -120,7 +190,23 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode break; } case ASTNodeDataType::vector_t: { - set_affectation_processor_for_vector_data(TinyVector<3>{}, data_type); + switch (value_type.dimension()) { + case 1: { + set_affectation_processor_for_vector_data(TinyVector<1>{}, data_type); + break; + } + case 2: { + set_affectation_processor_for_vector_data(TinyVector<2>{}, data_type); + break; + } + case 3: { + set_affectation_processor_for_vector_data(TinyVector<3>{}, data_type); + break; + } + default: { + throw parse_error("unexpected error: unexpected vector dimension", std::vector{n.begin()}); + } + } break; } case ASTNodeDataType::string_t: { @@ -144,16 +230,16 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode for (const auto& child : data_node.children) { ASTNodeNaturalConversionChecker{n, child->m_data_type, ASTNodeDataType::double_t}; } + break; } case ASTNodeDataType::vector_t: { - if (data_node.children.size() != n.m_data_type.dimension()) { + if (data_node.m_data_type.dimension() != n.m_data_type.dimension()) { throw parse_error("incompatible dimensions in affectation", std::vector{n.begin()}); } break; } default: { - throw parse_error("invalid operand for affectation", std::vector{n.children[1]->begin()}); } } } else { diff --git a/src/language/ASTNodeDataType.cpp b/src/language/ASTNodeDataType.cpp index 9e5dc669a..faf26caef 100644 --- a/src/language/ASTNodeDataType.cpp +++ b/src/language/ASTNodeDataType.cpp @@ -21,7 +21,7 @@ dataTypeName(const ASTNodeDataType& data_type) name = "R"; break; case ASTNodeDataType::vector_t: - name = "vector"; + name = "vector[" + std::to_string(data_type.dimension()) + "]"; break; case ASTNodeDataType::string_t: name = "string"; diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp index 0c9b751ea..a84e42c76 100644 --- a/src/language/node_processor/AffectationProcessor.hpp +++ b/src/language/node_processor/AffectationProcessor.hpp @@ -146,6 +146,77 @@ class AffectationProcessor final : public INodeProcessor } }; +template <typename OperatorT, typename ValueT> +class AffectationFromListProcessor final : public INodeProcessor +{ + private: + ASTNode& m_node; + + DataVariant* m_lhs; + + public: + DataVariant + execute(ExecutionPolicy& exec_policy) + { + 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"); + + ValueT v; + for (size_t i = 0; i < v.dimension(); ++i) { + std::visit( + [&](auto&& child_value) { + using T = std::decay_t<decltype(child_value)>; + if constexpr (std::is_same_v<T, bool> or std::is_same_v<T, uint64_t> or std::is_same_v<T, int64_t> or + std::is_same_v<T, double>) { + v[i] = child_value; + } else { + throw parse_error("unexpected error: unexpected right hand side type in affectation", m_node.begin()); + } + }, + children_values[i]); + } + + *m_lhs = v; + return {}; + } + + AffectationFromListProcessor(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 ValueT> +class AffectationFromZeroProcessor final : public INodeProcessor +{ + private: + ASTNode& m_node; + + DataVariant* m_lhs; + + public: + DataVariant + execute(ExecutionPolicy&) + { + *m_lhs = ValueT{zero}; + return {}; + } + + AffectationFromZeroProcessor(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> class ListAffectationProcessor final : public INodeProcessor { -- GitLab