From 9b0c7f9db3e31d3d1043f6f1ca45f3c11dad7cc8 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Fri, 31 Jan 2020 18:36:27 +0100
Subject: [PATCH] Prepare component affectation

- grammar is ready (list case is not treated)
- improve (old) variable case treatment
- slight clean-up in ASTBuilder
---
 src/language/ASTBuilder.cpp                   | 160 ++++++++++--------
 src/language/PEGGrammar.hpp                   |   4 +-
 .../node_processor/AffectationProcessor.hpp   |  59 ++++---
 3 files changed, 131 insertions(+), 92 deletions(-)

diff --git a/src/language/ASTBuilder.cpp b/src/language/ASTBuilder.cpp
index 869b708e0..686a7208b 100644
--- a/src/language/ASTBuilder.cpp
+++ b/src/language/ASTBuilder.cpp
@@ -9,8 +9,6 @@ using namespace TAO_PEGTL_NAMESPACE;
 
 #include <SymbolTable.hpp>
 
-using namespace language;
-
 struct ASTBuilder::rearrange : parse_tree::apply<ASTBuilder::rearrange>
 {
   template <typename... States>
@@ -61,18 +59,19 @@ struct ASTBuilder::simplify_unary : parse_tree::apply<ASTBuilder::simplify_unary
   transform(std::unique_ptr<ASTNode>& n, States&&... st)
   {
     if (n->children.size() == 1) {
-      if (n->is_type<unary_expression>() or n->is_type<type_expression>()) {
+      if (n->is_type<language::unary_expression>() or n->is_type<language::type_expression>() or
+          n->is_type<language::name_subscript_expression>()) {
         n = std::move(n->children.back());
         transform(n, st...);
-      } else if (n->is_type<unary_minus>()) {
+      } else if (n->is_type<language::unary_minus>()) {
         auto& child = n->children[0];
-        if (child->is_type<unary_minus>()) {
+        if (child->is_type<language::unary_minus>()) {
           n = std::move(child->children[0]);
           transform(n, st...);
         }
-      } else if (n->is_type<unary_not>()) {
+      } else if (n->is_type<language::unary_not>()) {
         auto& child = n->children[0];
-        if (child->is_type<unary_not>()) {
+        if (child->is_type<language::unary_not>()) {
           n = std::move(child->children[0]);
           transform(n, st...);
         }
@@ -104,7 +103,14 @@ struct ASTBuilder::simplify_unary : parse_tree::apply<ASTBuilder::simplify_unary
 
           n = std::move(unary_operator);
           transform(n->children[0], st...);
-        } else if (n->children[1]->is_type<language::subscript_expression>()) {
+        }
+      }
+    }
+
+    if ((n->is_type<language::unary_expression>()) or (n->is_type<language::name_subscript_expression>())) {
+      const size_t child_nb = n->children.size();
+      if (child_nb > 1) {
+        if (n->children[1]->is_type<language::subscript_expression>()) {
           auto expression = std::move(n->children[0]);
           for (size_t i = 0; i < child_nb - 1; ++i) {
             n->children[i] = std::move(n->children[i + 1]);
@@ -229,69 +235,81 @@ struct ASTBuilder::simplify_stream_statement : parse_tree::apply<ASTBuilder::sim
 template <typename Rule>
 using selector = parse_tree::selector<
   Rule,
-  parse_tree::store_content::on<import_instruction,
-                                module_name,
-                                true_kw,
-                                false_kw,
-                                integer,
-                                real,
-                                literal,
-                                name,
-                                B_set,
-                                N_set,
-                                Z_set,
-                                R_set,
-                                tuple_expression,
-                                vector_type,
-                                string_type,
-                                cout_kw,
-                                cerr_kw,
-                                clog_kw,
-                                declaration,
-                                let_declaration,
-                                type_mapping,
-                                function_definition,
-                                if_statement,
-                                do_while_statement,
-                                while_statement,
-                                for_statement,
-                                function_evaluation,
-                                break_kw,
-                                continue_kw>,
-  ASTBuilder::rearrange::
-    on<logical_or, logical_and, bitwise_xor, equality, compare, sum, product, affectation, expression>,
-  ASTBuilder::simplify_unary::
-    on<unary_minus, unary_plus, unary_not, subscript_expression, type_expression, unary_expression>,
-  parse_tree::remove_content::on<plus_op,
-                                 minus_op,
-                                 multiply_op,
-                                 divide_op,
-                                 lesser_op,
-                                 lesser_or_eq_op,
-                                 greater_op,
-                                 greater_or_eq_op,
-                                 eqeq_op,
-                                 not_eq_op,
-                                 and_op,
-                                 or_op,
-                                 xor_op,
-                                 eq_op,
-                                 multiplyeq_op,
-                                 divideeq_op,
-                                 pluseq_op,
-                                 minuseq_op,
-                                 unary_plusplus,
-                                 unary_minusminus,
-                                 post_minusminus,
-                                 post_plusplus>,
-  ASTBuilder::simplify_for_statement_block::on<for_statement_block>,
-  parse_tree::discard_empty::on<ignored, semicol, block>,
-  ASTBuilder::simplify_node_list::on<name_list, function_argument_list, expression_list>,
-  ASTBuilder::simplify_statement_block::on<statement_block>,
-  ASTBuilder::simplify_for_init::on<for_init>,
-  ASTBuilder::simplify_for_test::on<for_test>,
-  ASTBuilder::simplify_for_post::on<for_post>,
-  ASTBuilder::simplify_stream_statement::on<ostream_statement>>;
+  parse_tree::store_content::on<language::import_instruction,
+                                language::module_name,
+                                language::true_kw,
+                                language::false_kw,
+                                language::integer,
+                                language::real,
+                                language::literal,
+                                language::name,
+                                language::B_set,
+                                language::N_set,
+                                language::Z_set,
+                                language::R_set,
+                                language::tuple_expression,
+                                language::vector_type,
+                                language::string_type,
+                                language::cout_kw,
+                                language::cerr_kw,
+                                language::clog_kw,
+                                language::declaration,
+                                language::let_declaration,
+                                language::type_mapping,
+                                language::function_definition,
+                                language::if_statement,
+                                language::do_while_statement,
+                                language::while_statement,
+                                language::for_statement,
+                                language::function_evaluation,
+                                language::break_kw,
+                                language::continue_kw>,
+  ASTBuilder::rearrange::on<language::logical_or,
+                            language::logical_and,
+                            language::bitwise_xor,
+                            language::equality,
+                            language::compare,
+                            language::sum,
+                            language::product,
+                            language::affectation,
+                            language::expression>,
+  ASTBuilder::simplify_unary::on<language::unary_minus,
+                                 language::unary_plus,
+                                 language::unary_not,
+                                 language::subscript_expression,
+                                 language::type_expression,
+                                 language::unary_expression,
+                                 language::name_subscript_expression>,
+  parse_tree::remove_content::on<language::plus_op,
+                                 language::minus_op,
+                                 language::multiply_op,
+                                 language::divide_op,
+                                 language::lesser_op,
+                                 language::lesser_or_eq_op,
+                                 language::greater_op,
+                                 language::greater_or_eq_op,
+                                 language::eqeq_op,
+                                 language::not_eq_op,
+                                 language::and_op,
+                                 language::or_op,
+                                 language::xor_op,
+                                 language::eq_op,
+                                 language::multiplyeq_op,
+                                 language::divideeq_op,
+                                 language::pluseq_op,
+                                 language::minuseq_op,
+                                 language::unary_plusplus,
+                                 language::unary_minusminus,
+                                 language::post_minusminus,
+                                 language::post_plusplus>,
+  ASTBuilder::simplify_for_statement_block::on<language::for_statement_block>,
+  parse_tree::discard_empty::on<language::ignored, language::semicol, language::block>,
+  ASTBuilder::simplify_node_list::on<language::name_list, language::function_argument_list, language::expression_list>,
+  ASTBuilder::simplify_statement_block::on<language::statement_block>,
+  ASTBuilder::simplify_for_init::on<language::for_init>,
+  ASTBuilder::simplify_for_test::on<language::for_test>,
+  ASTBuilder::simplify_for_post::on<language::for_post>,
+  ASTBuilder::simplify_stream_statement::on<language::ostream_statement>>;
 
 template <typename InputT>
 std::unique_ptr<ASTNode>
diff --git a/src/language/PEGGrammar.hpp b/src/language/PEGGrammar.hpp
index 5e87e8500..2baa69521 100644
--- a/src/language/PEGGrammar.hpp
+++ b/src/language/PEGGrammar.hpp
@@ -224,9 +224,11 @@ struct expression_list : seq< open_parent, sor< tuple_expression, expression >,
 
 struct affect_op : sor< eq_op, multiplyeq_op, divideeq_op, pluseq_op, minuseq_op > {};
 
+struct name_subscript_expression : seq< NAME, plus< subscript_expression > >{};
+
 struct name_list;
 
-struct affectation : seq< sor< NAME, name_list >, if_must< affect_op,  sor< expression_list, expression > > >{};
+struct affectation : seq< sor< name_subscript_expression, NAME, name_list >, if_must< affect_op,  sor< expression_list, expression > > >{};
 
 struct declaration : if_must< TYPE_EXPRESSION, sor< NAME, name_list>, opt< if_must< seq< one< '=' >, ignored >, sor< expression_list, expression > > > >{};
 
diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp
index a84e42c76..4080f3fc8 100644
--- a/src/language/node_processor/AffectationProcessor.hpp
+++ b/src/language/node_processor/AffectationProcessor.hpp
@@ -63,7 +63,7 @@ template <typename OperatorT, typename ValueT, typename DataT>
 class AffectationExecutor final : public IAffectationExecutor
 {
  private:
-  DataVariant* m_lhs{nullptr};
+  ValueT& m_lhs;
 
   static inline const bool _is_defined{[] {
     if constexpr (std::is_same_v<std::decay_t<ValueT>, bool>) {
@@ -75,7 +75,7 @@ class AffectationExecutor final : public IAffectationExecutor
   }()};
 
  public:
-  AffectationExecutor(ASTNode& node, DataVariant* lhs) : m_lhs(lhs)
+  AffectationExecutor(ASTNode& node, ValueT& lhs) : m_lhs(lhs)
   {
     // LCOV_EXCL_START
     if constexpr (not _is_defined) {
@@ -91,27 +91,27 @@ class AffectationExecutor final : public IAffectationExecutor
       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 = rhs;
+            m_lhs = std::get<DataT>(rhs);
           } else {
-            *m_lhs = std::to_string(std::get<DataT>(rhs));
+            m_lhs = 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>) {
-            std::get<std::string>(*m_lhs) += std::get<std::string>(rhs);
+            m_lhs += std::get<std::string>(rhs);
           } else {
-            std::get<std::string>(*m_lhs) += std::to_string(std::get<DataT>(rhs));
+            m_lhs += 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 = rhs;
+            m_lhs = std::get<DataT>(rhs);
           } else {
-            *m_lhs = static_cast<ValueT>(std::get<DataT>(rhs));
+            m_lhs = static_cast<ValueT>(std::get<DataT>(rhs));
           }
         } else {
-          AffOp<OperatorT>().eval(std::get<ValueT>(*m_lhs), std::get<DataT>(rhs));
+          AffOp<OperatorT>().eval(m_lhs, std::get<DataT>(rhs));
         }
       }
     }
@@ -124,8 +124,7 @@ class AffectationProcessor final : public INodeProcessor
  private:
   ASTNode& m_node;
 
-  using AffectationExecutorT = AffectationExecutor<OperatorT, ValueT, DataT>;
-  std::unique_ptr<AffectationExecutorT> m_affectation_executor;
+  std::unique_ptr<IAffectationExecutor> m_affectation_executor;
 
  public:
   DataVariant
@@ -138,11 +137,21 @@ class AffectationProcessor final : public INodeProcessor
 
   AffectationProcessor(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);
+    if (node.children[0]->is_type<language::name>()) {
+      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);
+      DataVariant& value = i_symbol->attributes().value();
+
+      if (not std::holds_alternative<ValueT>(value)) {
+        value = ValueT{};
+      }
 
-    m_affectation_executor = std::make_unique<AffectationExecutorT>(m_node, &i_symbol->attributes().value());
+      using AffectationExecutorT = AffectationExecutor<OperatorT, ValueT, DataT>;
+      m_affectation_executor     = std::make_unique<AffectationExecutorT>(m_node, std::get<ValueT>(value));
+    } else {
+      throw parse_error("unexpected error: invalid lhs", std::vector{node.children[0]->begin()});
+    }
   }
 };
 
@@ -230,12 +239,22 @@ class ListAffectationProcessor final : public INodeProcessor
   void
   add(ASTNode& lhs_node)
   {
-    const std::string& symbol = lhs_node.string();
-    auto [i_symbol, found]    = m_node.m_symbol_table->find(symbol, m_node.children[0]->end());
-    Assert(found);
+    using AffectationExecutorT = AffectationExecutor<OperatorT, ValueT, DataT>;
+
+    if (lhs_node.is_type<language::name>()) {
+      const std::string& symbol = lhs_node.string();
+      auto [i_symbol, found]    = m_node.m_symbol_table->find(symbol, m_node.children[0]->end());
+      Assert(found);
+      DataVariant& value = i_symbol->attributes().value();
 
-    m_affectation_executor_list.emplace_back(
-      std::make_unique<AffectationExecutor<OperatorT, ValueT, DataT>>(m_node, &i_symbol->attributes().value()));
+      if (not std::holds_alternative<ValueT>(value)) {
+        value = ValueT{};
+      }
+
+      m_affectation_executor_list.emplace_back(std::make_unique<AffectationExecutorT>(m_node, std::get<ValueT>(value)));
+    } else {
+      throw parse_error("not yet implemented", std::vector{lhs_node.begin()});
+    }
   }
 
   DataVariant
-- 
GitLab