From 100859c40e1601564164ea341153f089d072c491 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Mon, 8 Jul 2019 17:47:38 +0200
Subject: [PATCH] Create class ASTSymbolInitializationChecker

This helper class is not finished, does not handle statements correctly
---
 .../ASTSymbolInitializationChecker.cpp        | 47 ++++++++++++++
 .../ASTSymbolInitializationChecker.hpp        | 15 +++++
 src/language/CMakeLists.txt                   |  1 +
 src/language/PugsParser.cpp                   | 64 +------------------
 4 files changed, 66 insertions(+), 61 deletions(-)
 create mode 100644 src/language/ASTSymbolInitializationChecker.cpp
 create mode 100644 src/language/ASTSymbolInitializationChecker.hpp

diff --git a/src/language/ASTSymbolInitializationChecker.cpp b/src/language/ASTSymbolInitializationChecker.cpp
new file mode 100644
index 000000000..2763db1ad
--- /dev/null
+++ b/src/language/ASTSymbolInitializationChecker.cpp
@@ -0,0 +1,47 @@
+#include <ASTSymbolInitializationChecker.hpp>
+
+#include <SymbolTable.hpp>
+
+#include <PEGGrammar.hpp>
+
+void
+ASTSymbolInitializationChecker::_checkSymbolInitialization(ASTNode& node)
+{
+  if (node.is<language::declaration>()) {
+    const std::string& symbol = node.children[1]->string();
+    auto [i_symbol, found]    = node.m_symbol_table->find(symbol);
+    Assert(found, "unexpected error, should have been detected through declaration checking");
+    if (node.children.size() == 3) {
+      this->_checkSymbolInitialization(*node.children[2]);
+      i_symbol->second.setIsInitialized();
+    }
+  } else if (node.is<language::eq_op>()) {
+    // first checks for right hand side
+    this->_checkSymbolInitialization(*node.children[1]);
+    // then marks left hand side as initialized
+    const std::string& symbol = node.children[0]->string();
+    auto [i_symbol, found]    = node.m_symbol_table->find(symbol);
+    Assert(found, "unexpected error, should have been detected through declaration checking");
+    i_symbol->second.setIsInitialized();
+  } else if (node.is<language::name>()) {
+    auto [i_symbol, found] = node.m_symbol_table->find(node.string());
+    Assert(found, "unexpected error, should have been detected through declaration checking");
+    if (not i_symbol->second.isInitialized()) {
+      std::ostringstream error_message;
+      error_message << "uninitialized symbol '" << rang::fg::red << node.string() << rang::fg::reset << '\'';
+      throw parse_error(error_message.str(), std::vector{node.begin()});
+    }
+  }
+
+  if ((not node.is<language::declaration>()) and (not node.is<language::eq_op>())) {
+    for (auto& child : node.children) {
+      this->_checkSymbolInitialization(*child);
+    }
+  }
+}
+
+ASTSymbolInitializationChecker::ASTSymbolInitializationChecker(ASTNode& root_node)
+{
+  Assert(root_node.is_root());
+  this->_checkSymbolInitialization(root_node);
+}
diff --git a/src/language/ASTSymbolInitializationChecker.hpp b/src/language/ASTSymbolInitializationChecker.hpp
new file mode 100644
index 000000000..7723e68c5
--- /dev/null
+++ b/src/language/ASTSymbolInitializationChecker.hpp
@@ -0,0 +1,15 @@
+#ifndef AST_SYMBOL_INITIALIZATION_CHECKER_HPP
+#define AST_SYMBOL_INITIALIZATION_CHECKER_HPP
+
+#include <ASTNode.hpp>
+
+class ASTSymbolInitializationChecker
+{
+ private:
+  void _checkSymbolInitialization(ASTNode& node);
+
+ public:
+  ASTSymbolInitializationChecker(ASTNode& root_node);
+};
+
+#endif   // AST_SYMBOL_INITIALIZATION_CHECKER_HPP
diff --git a/src/language/CMakeLists.txt b/src/language/CMakeLists.txt
index c0104ce7e..6f9d04943 100644
--- a/src/language/CMakeLists.txt
+++ b/src/language/CMakeLists.txt
@@ -14,6 +14,7 @@ add_library(
   ASTNodeUnaryOperatorExpressionBuilder.cpp
   ASTPrinter.cpp
   ASTSymbolTableBuilder.cpp
+  ASTSymbolInitializationChecker.cpp
   PugsParser.cpp)
 
 #include_directories(${PUGS_SOURCE_DIR}/utils)
diff --git a/src/language/PugsParser.cpp b/src/language/PugsParser.cpp
index fcd2261c2..bdc4b8703 100644
--- a/src/language/PugsParser.cpp
+++ b/src/language/PugsParser.cpp
@@ -23,6 +23,7 @@
 
 #include <ASTNodeExpressionBuilder.hpp>
 
+#include <ASTSymbolInitializationChecker.hpp>
 #include <ASTSymbolTableBuilder.hpp>
 
 #include <ASTPrinter.hpp>
@@ -67,66 +68,6 @@ print_dot(std::ostream& os, const ASTNode& n)
   os << "}\n";
 }
 
-namespace internal
-{
-void
-check_symbol_initialization(const ASTNode& n, std::shared_ptr<SymbolTable>& symbol_table)
-{
-  if (n.is<language::bloc>() or n.is<language::for_statement>()) {
-    if (!n.children.empty()) {
-      std::shared_ptr bloc_symbol_table = std::make_shared<SymbolTable>(symbol_table);
-      for (auto& child : n.children) {
-        check_symbol_initialization(*child, bloc_symbol_table);
-      }
-    }
-  } else {
-    if (n.is<language::declaration>()) {
-      const std::string& symbol = n.children[1]->string();
-      auto [i_symbol, success]  = symbol_table->add(symbol);
-      Assert(success, "unexpected error, should have been detected through declaration checking");
-      if (n.children.size() == 3) {
-        check_symbol_initialization(*n.children[2], symbol_table);
-        i_symbol->second.setIsInitialized();
-      }
-    } else if (n.is<language::eq_op>()) {
-      // first checks for right hand side
-      check_symbol_initialization(*n.children[1], symbol_table);
-      // then marks left hand side as initialized
-      const std::string& symbol = n.children[0]->string();
-      auto [i_symbol, found]    = symbol_table->find(symbol);
-      Assert(found, "unexpected error, should have been detected through declaration checking");
-      i_symbol->second.setIsInitialized();
-    } else if (n.is<language::name>()) {
-      auto [i_symbol, found] = symbol_table->find(n.string());
-      Assert(found, "unexpected error, should have been detected through declaration checking");
-      if (not i_symbol->second.isInitialized()) {
-        std::ostringstream error_message;
-        error_message << "uninitialized symbol '" << rang::fg::red << n.string() << rang::fg::reset << '\'';
-        throw parse_error(error_message.str(), std::vector{n.begin()});
-      }
-    }
-
-    if ((not n.is<language::declaration>()) and (not n.is<language::eq_op>())) {
-      for (auto& child : n.children) {
-        check_symbol_initialization(*child, symbol_table);
-      }
-    }
-  }
-}
-}   // namespace internal
-
-void
-check_symbol_initialization(const ASTNode& n)
-{
-  std::cerr << rang::fgB::yellow << "warning:" << rang::fg::reset
-            << " symbol initialization checking not finished"
-               "if and loops statements are not correctly evaluated\n";
-  Assert(n.is_root());
-  std::shared_ptr symbol_table = std::make_shared<SymbolTable>();
-  internal::check_symbol_initialization(n, symbol_table);
-  std::cout << " - checked symbols initialization\n";
-}
-
 namespace internal
 {
 void
@@ -418,7 +359,8 @@ parser(const std::string& filename)
 
     ASTSymbolTableBuilder{*root_node};
 
-    language::check_symbol_initialization(*root_node);
+    ASTSymbolInitializationChecker{*root_node};
+
     {
       std::string dot_filename{"parse_tree.dot"};
       std::ofstream fout(dot_filename);
-- 
GitLab