From ae0f751d36caeb0c603b5f0696f07ca670f7a157 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com>
Date: Mon, 9 Nov 2020 16:19:26 +0100
Subject: [PATCH] Add getAST, getFunctionAST and saveASTDot functions to
 'utils'

The two first ones return a string containing the AST the later one
saves the AST to a file (its name is given as a string argument).
---
 src/language/PugsParser.cpp          | 25 ++---------
 src/language/modules/UtilsModule.cpp | 65 ++++++++++++++++++++++++++++
 tests/CMakeLists.txt                 |  2 +-
 3 files changed, 70 insertions(+), 22 deletions(-)

diff --git a/src/language/PugsParser.cpp b/src/language/PugsParser.cpp
index 352ea84e6..ed0c23107 100644
--- a/src/language/PugsParser.cpp
+++ b/src/language/PugsParser.cpp
@@ -32,6 +32,8 @@
 #include <unordered_map>
 #include <variant>
 
+const std::unique_ptr<ASTNode>* p_root_node = nullptr;
+
 void
 parser(const std::string& filename)
 {
@@ -48,6 +50,7 @@ parser(const std::string& filename)
 
   auto parse_and_execute = [](auto& input) {
     std::unique_ptr<ASTNode> root_node = ASTBuilder::build(input);
+    p_root_node                        = &root_node;
 
     ASTModulesImporter{*root_node};
     ASTNodeTypeCleaner<language::import_instruction>{*root_node};
@@ -68,35 +71,15 @@ parser(const std::string& filename)
     ASTNodeTypeCleaner<language::var_declaration>{*root_node};
     ASTNodeTypeCleaner<language::fct_declaration>{*root_node};
 
-    {
-      std::string dot_filename{"parse_tree.dot"};
-      std::ofstream fout(dot_filename);
-      ASTDotPrinter dot_printer{*root_node};
-      fout << dot_printer;
-      std::cout << "   AST dot file: " << dot_filename << '\n';
-    }
-
     ASTNodeEmptyBlockCleaner{*root_node};
 
     ASTNodeExpressionBuilder{*root_node};
 
-    std::cout << ASTPrinter{*root_node} << '\n';
-
-    auto& function_table = root_node->m_symbol_table->functionTable();
-
-    for (size_t i_function = 0; i_function < function_table.size(); ++i_function) {
-      const auto& function_descriptor = function_table[i_function];
-      std::cout << "function " << rang::fgB::magenta << function_descriptor.name() << rang::style::reset << '\n';
-      std::cout << ASTPrinter(function_descriptor.domainMappingNode());
-      std::cout << ASTPrinter(function_descriptor.definitionNode());
-      std::cout << "--------\n";
-    }
-
     ExecutionPolicy exec_all;
     root_node->execute(exec_all);
-    std::cout << *(root_node->m_symbol_table) << '\n';
 
     root_node->m_symbol_table->clearValues();
+    p_root_node = nullptr;
   };
 
   if (not SignalManager::pauseOnError()) {
diff --git a/src/language/modules/UtilsModule.cpp b/src/language/modules/UtilsModule.cpp
index ff5b2a0df..8c688e207 100644
--- a/src/language/modules/UtilsModule.cpp
+++ b/src/language/modules/UtilsModule.cpp
@@ -1,8 +1,13 @@
 #include <language/modules/UtilsModule.hpp>
 
+#include <language/utils/ASTDotPrinter.hpp>
+#include <language/utils/ASTPrinter.hpp>
 #include <language/utils/BuiltinFunctionEmbedder.hpp>
+#include <language/utils/SymbolTable.hpp>
 #include <utils/PugsUtils.hpp>
 
+extern const std::unique_ptr<ASTNode>* p_root_node;
+
 UtilsModule::UtilsModule()
 {
   this->_addBuiltinFunction("getPugsVersion", std::make_shared<BuiltinFunctionEmbedder<std::string(void)>>(
@@ -16,4 +21,64 @@ UtilsModule::UtilsModule()
                                                   []() -> std::string { return pugsBuildInfo(); }
 
                                                   ));
+
+  this->_addBuiltinFunction("getAST", std::make_shared<BuiltinFunctionEmbedder<std::string(void)>>(
+
+                                        []() -> std::string {
+                                          Assert(p_root_node != nullptr, "unable to find AST's root node");
+
+                                          const auto& root_node = *p_root_node;
+                                          std::ostringstream os;
+                                          os << ASTPrinter{*root_node};
+
+                                          return os.str();
+                                        }
+
+                                        ));
+
+  this->_addBuiltinFunction("saveASTDot", std::make_shared<BuiltinFunctionEmbedder<void(const std::string&)>>(
+
+                                            [](const std::string& dot_filename) -> void {
+                                              Assert(p_root_node != nullptr, "unable to find AST's root node");
+
+                                              const auto& root_node = *p_root_node;
+
+                                              std::ofstream fout(dot_filename);
+
+                                              if (not fout) {
+                                                std::ostringstream os;
+                                                os << "could not create file '" << dot_filename << "'\n";
+                                                throw NormalError(os.str());
+                                              }
+
+                                              ASTDotPrinter dot_printer{*root_node};
+                                              fout << dot_printer;
+
+                                              if (not fout) {
+                                                std::ostringstream os;
+                                                os << "could not write AST to '" << dot_filename << "'\n";
+                                                throw NormalError(os.str());
+                                              }
+                                            }
+
+                                            ));
+
+  this->_addBuiltinFunction("getFunctionAST",
+                            std::make_shared<BuiltinFunctionEmbedder<std::string(const FunctionSymbolId&)>>(
+
+                              [](const FunctionSymbolId& function_symbol_id) -> std::string {
+                                auto& function_table = function_symbol_id.symbolTable().functionTable();
+
+                                const auto& function_descriptor = function_table[function_symbol_id.id()];
+
+                                std::ostringstream os;
+                                os << function_descriptor.name() << ": domain mapping\n";
+                                os << ASTPrinter(function_descriptor.domainMappingNode());
+                                os << function_descriptor.name() << ": definition\n";
+                                os << ASTPrinter(function_descriptor.definitionNode());
+
+                                return os.str();
+                              }
+
+                              ));
 }
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index aaf4bfbad..746f5d7b1 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -104,11 +104,11 @@ add_library(test_Pugs_MeshDataBase
 
 target_link_libraries (unit_tests
   test_Pugs_MeshDataBase
-  PugsLanguage
   PugsLanguageAST
   PugsLanguageModules
   PugsLanguageAlgorithms
   PugsLanguageUtils
+  PugsLanguage
   PugsMesh
   PugsAlgebra
   PugsUtils
-- 
GitLab