From c09a945c7690ec94cfcd0cbd19b76273270826a6 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Tue, 24 Dec 2024 17:34:39 +0100
Subject: [PATCH] Change strategy for modules registration to the
 ModuleRepository

Now modules register self register: ModuleRepository is unchanged
while adding new modules
---
 CMakeLists.txt                                |  3 +-
 src/language/ast/ASTModulesImporter.cpp       |  8 ++--
 src/language/ast/ASTModulesImporter.hpp       |  4 +-
 .../modules/BinaryOperatorRegisterForVh.cpp   |  2 +-
 src/language/modules/CoreModule.cpp           |  4 +-
 src/language/modules/DevUtilsModule.cpp       |  4 ++
 src/language/modules/LinearSolverModule.cpp   |  4 ++
 .../modules/MathFunctionRegisterForVh.cpp     |  1 +
 src/language/modules/MathModule.cpp           |  3 ++
 src/language/modules/MeshModule.cpp           | 37 +++++++++++--------
 src/language/modules/ModuleRepository.cpp     | 21 -----------
 src/language/modules/ModuleRepository.hpp     | 22 ++++++++++-
 src/language/modules/SchemeModule.cpp         |  5 +++
 src/language/modules/SchemeModule.hpp         |  1 -
 src/language/modules/SocketModule.cpp         |  4 ++
 .../modules/UnaryOperatorRegisterForVh.cpp    |  2 +-
 src/language/modules/WriterModule.cpp         |  8 +++-
 17 files changed, 81 insertions(+), 52 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 804752039..3a9f59557 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -400,7 +400,7 @@ if(${PUGS_HAS_MPI})
   endif()
   set(MPIEXEC_NUMPROC 3)
   set(MPIEXEC_PATH_FLAG --path)
-  set(MPI_LAUNCHER ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MPIEXEC_NUMPROC} ${MPIEXEC_PATH_FLAG} ${PUGS_BINARY_DIR} ${MPIEXEC_OPTION_FLAGS})
+  set(MPI_LAUNCHER ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MPIEXEC_NUMPROC} ${MPIEXEC_OPTION_FLAGS})
 endif()
 
 add_custom_target(all_unit_tests
@@ -427,6 +427,7 @@ endif()
 
 add_custom_target(run_mpi_unit_tests
   COMMAND ${MPI_LAUNCHER} "${PUGS_BINARY_DIR}/mpi_unit_tests"
+  WORKING_DIRECTORY ${PUGS_BINARY_DIR}
   DEPENDS run_unit_tests
   COMMENT ${RUN_MPI_UNIT_TESTS_COMMENT}
   )
diff --git a/src/language/ast/ASTModulesImporter.cpp b/src/language/ast/ASTModulesImporter.cpp
index 4cae0a921..e1dc0043e 100644
--- a/src/language/ast/ASTModulesImporter.cpp
+++ b/src/language/ast/ASTModulesImporter.cpp
@@ -26,10 +26,10 @@ ASTModulesImporter::_importModule(ASTNode& import_node)
     std::cout << " * importing '" << rang::fgB::green << module_name << rang::style::reset << "' module\n";
   }
 
-  m_module_repository.populateSymbolTable(module_name_node, m_symbol_table);
-  m_module_repository.registerOperators(module_name);
+  ModuleRepository::getInstance().populateSymbolTable(module_name_node, m_symbol_table);
+  ModuleRepository::getInstance().registerOperators(module_name);
   if (CheckpointResumeRepository::isCreated()) {
-    m_module_repository.registerCheckpointResume(module_name);
+    ModuleRepository::getInstance().registerCheckpointResume(module_name);
   }
 }
 
@@ -49,7 +49,7 @@ ASTModulesImporter::ASTModulesImporter(ASTNode& root_node) : m_symbol_table{*roo
 {
   Assert(root_node.is_root());
   OperatorRepository::instance().reset();
-  m_module_repository.populateMandatoryData(root_node, m_symbol_table);
+  ModuleRepository::getInstance().populateMandatoryData(root_node, m_symbol_table);
 
   this->_importAllModules(root_node);
 
diff --git a/src/language/ast/ASTModulesImporter.hpp b/src/language/ast/ASTModulesImporter.hpp
index 566155c4a..15ba8a7dc 100644
--- a/src/language/ast/ASTModulesImporter.hpp
+++ b/src/language/ast/ASTModulesImporter.hpp
@@ -14,8 +14,6 @@ class ASTModulesImporter
   std::set<std::string> m_imported_modules;
   SymbolTable& m_symbol_table;
 
-  ModuleRepository m_module_repository;
-
   void _importModule(ASTNode& import_node);
   void _importAllModules(ASTNode& node);
 
@@ -23,7 +21,7 @@ class ASTModulesImporter
   const ModuleRepository&
   moduleRepository() const
   {
-    return m_module_repository;
+    return ModuleRepository::getInstance();
   }
 
   ASTModulesImporter(ASTNode& root_node);
diff --git a/src/language/modules/BinaryOperatorRegisterForVh.cpp b/src/language/modules/BinaryOperatorRegisterForVh.cpp
index 3eb835373..d1c20cb78 100644
--- a/src/language/modules/BinaryOperatorRegisterForVh.cpp
+++ b/src/language/modules/BinaryOperatorRegisterForVh.cpp
@@ -1,6 +1,6 @@
 #include <language/modules/BinaryOperatorRegisterForVh.hpp>
 
-#include <language/modules/SchemeModule.hpp>
+#include <language/modules/SchemeModuleTypes.hpp>
 #include <language/utils/BinaryOperatorProcessorBuilder.hpp>
 #include <language/utils/DataHandler.hpp>
 #include <language/utils/DataVariant.hpp>
diff --git a/src/language/modules/CoreModule.cpp b/src/language/modules/CoreModule.cpp
index d7b331a1d..47e018325 100644
--- a/src/language/modules/CoreModule.cpp
+++ b/src/language/modules/CoreModule.cpp
@@ -42,7 +42,7 @@
 #include <utils/checkpointing/ResumingManager.hpp>
 #include <utils/checkpointing/WriteOStream.hpp>
 
-#include <random>
+#include <language/modules/ModuleRepository.hpp>
 
 CoreModule::CoreModule() : BuiltinModule(true)
 {
@@ -219,3 +219,5 @@ CoreModule::registerCheckpointResume() const
 
 #endif   // PUGS_HAS_HDF5
 }
+
+ModuleRepository::Subscribe<CoreModule> core_module;
diff --git a/src/language/modules/DevUtilsModule.cpp b/src/language/modules/DevUtilsModule.cpp
index 361b4357e..4595ea6c9 100644
--- a/src/language/modules/DevUtilsModule.cpp
+++ b/src/language/modules/DevUtilsModule.cpp
@@ -1,5 +1,7 @@
 #include <language/modules/DevUtilsModule.hpp>
 
+#include <language/modules/ModuleRepository.hpp>
+
 #include <dev/ParallelChecker.hpp>
 #include <language/modules/MeshModuleTypes.hpp>
 #include <language/modules/SchemeModuleTypes.hpp>
@@ -126,3 +128,5 @@ DevUtilsModule::registerOperators() const
 void
 DevUtilsModule::registerCheckpointResume() const
 {}
+
+ModuleRepository::Subscribe<DevUtilsModule> dev_utils_module;
diff --git a/src/language/modules/LinearSolverModule.cpp b/src/language/modules/LinearSolverModule.cpp
index aef6470d2..d3e2de0fa 100644
--- a/src/language/modules/LinearSolverModule.cpp
+++ b/src/language/modules/LinearSolverModule.cpp
@@ -1,5 +1,7 @@
 #include <language/modules/LinearSolverModule.hpp>
 
+#include <language/modules/ModuleRepository.hpp>
+
 #include <algebra/LinearSolver.hpp>
 #include <language/utils/BuiltinFunctionEmbedder.hpp>
 #include <language/utils/TypeDescriptor.hpp>
@@ -98,3 +100,5 @@ LinearSolverModule::registerOperators() const
 void
 LinearSolverModule::registerCheckpointResume() const
 {}
+
+ModuleRepository::Subscribe<LinearSolverModule> linear_solver_module;
diff --git a/src/language/modules/MathFunctionRegisterForVh.cpp b/src/language/modules/MathFunctionRegisterForVh.cpp
index b31fe47d0..d9a30e869 100644
--- a/src/language/modules/MathFunctionRegisterForVh.cpp
+++ b/src/language/modules/MathFunctionRegisterForVh.cpp
@@ -1,6 +1,7 @@
 #include <language/modules/MathFunctionRegisterForVh.hpp>
 
 #include <language/modules/SchemeModule.hpp>
+#include <language/modules/SchemeModuleTypes.hpp>
 #include <language/utils/BuiltinFunctionEmbedder.hpp>
 #include <language/utils/EmbeddedDiscreteFunctionMathFunctions.hpp>
 #include <scheme/DiscreteFunctionVariant.hpp>
diff --git a/src/language/modules/MathModule.cpp b/src/language/modules/MathModule.cpp
index 19a35a152..1caea4524 100644
--- a/src/language/modules/MathModule.cpp
+++ b/src/language/modules/MathModule.cpp
@@ -1,5 +1,6 @@
 #include <language/modules/MathModule.hpp>
 
+#include <language/modules/ModuleRepository.hpp>
 #include <language/utils/BuiltinFunctionEmbedder.hpp>
 
 #include <cmath>
@@ -136,3 +137,5 @@ MathModule::registerOperators() const
 void
 MathModule::registerCheckpointResume() const
 {}
+
+ModuleRepository::Subscribe<MathModule> math_module;
diff --git a/src/language/modules/MeshModule.cpp b/src/language/modules/MeshModule.cpp
index c76260ce5..c060da50d 100644
--- a/src/language/modules/MeshModule.cpp
+++ b/src/language/modules/MeshModule.cpp
@@ -1,5 +1,7 @@
 #include <language/modules/MeshModule.hpp>
 
+#include <language/modules/ModuleRepository.hpp>
+
 #include <algebra/TinyVector.hpp>
 #include <language/node_processor/ExecutionPolicy.hpp>
 #include <language/utils/BinaryOperatorProcessorBuilder.hpp>
@@ -160,27 +162,28 @@ MeshModule::MeshModule()
 
                                           ));
 
-  this
-    ->_addBuiltinFunction("interpolate",
-                          std::function(
+  this->_addBuiltinFunction("interpolate",
+                            std::function(
 
-                            [](std::shared_ptr<const MeshVariant> mesh_v, std::shared_ptr<const ItemType> item_type,
-                               const FunctionSymbolId& function_id) -> std::shared_ptr<const ItemValueVariant> {
-                              return ItemValueVariantFunctionInterpoler{mesh_v, *item_type, function_id}.interpolate();
-                            }
+                              [](std::shared_ptr<const MeshVariant> mesh_v, std::shared_ptr<const ItemType> item_type,
+                                 const FunctionSymbolId& function_id) -> std::shared_ptr<const ItemValueVariant> {
+                                return ItemValueVariantFunctionInterpoler{mesh_v, *item_type, function_id}
+                                  .interpolate();
+                              }
 
-                            ));
+                              ));
 
-  this->_addBuiltinFunction(
-    "interpolate_array",
-    std::function(
+  this->_addBuiltinFunction("interpolate_array",
+                            std::function(
 
-      [](std::shared_ptr<const MeshVariant> mesh_v, std::shared_ptr<const ItemType> item_type,
-         const std::vector<FunctionSymbolId>& function_id_list) -> std::shared_ptr<const ItemArrayVariant> {
-        return ItemArrayVariantFunctionInterpoler{mesh_v, *item_type, function_id_list}.interpolate();
-      }
+                              [](std::shared_ptr<const MeshVariant> mesh_v, std::shared_ptr<const ItemType> item_type,
+                                 const std::vector<FunctionSymbolId>& function_id_list)
+                                -> std::shared_ptr<const ItemArrayVariant> {
+                                return ItemArrayVariantFunctionInterpoler{mesh_v, *item_type, function_id_list}
+                                  .interpolate();
+                              }
 
-      ));
+                              ));
 
   this->_addBuiltinFunction("transform",
                             std::function(
@@ -442,3 +445,5 @@ MeshModule::registerCheckpointResume() const
 
 #endif   // PUGS_HAS_HDF5
 }
+
+ModuleRepository::Subscribe<MeshModule> mesh_module;
diff --git a/src/language/modules/ModuleRepository.cpp b/src/language/modules/ModuleRepository.cpp
index 59689fb6f..42d62fa0a 100644
--- a/src/language/modules/ModuleRepository.cpp
+++ b/src/language/modules/ModuleRepository.cpp
@@ -1,14 +1,6 @@
 #include <language/modules/ModuleRepository.hpp>
 
 #include <language/ast/ASTNode.hpp>
-#include <language/modules/CoreModule.hpp>
-#include <language/modules/DevUtilsModule.hpp>
-#include <language/modules/LinearSolverModule.hpp>
-#include <language/modules/MathModule.hpp>
-#include <language/modules/MeshModule.hpp>
-#include <language/modules/SchemeModule.hpp>
-#include <language/modules/SocketModule.hpp>
-#include <language/modules/WriterModule.hpp>
 #include <language/utils/BasicAffectationRegistrerFor.hpp>
 #include <language/utils/BuiltinFunctionEmbedder.hpp>
 #include <language/utils/CheckpointResumeRepository.hpp>
@@ -19,7 +11,6 @@
 
 #include <utils/PugsAssert.hpp>
 
-#include <algorithm>
 #include <set>
 
 void
@@ -52,18 +43,6 @@ ModuleRepository::_subscribe(std::unique_ptr<IModule> m)
   Assert(success, "module has already been subscribed");
 }
 
-ModuleRepository::ModuleRepository()
-{
-  this->_subscribe(std::make_unique<CoreModule>());
-  this->_subscribe(std::make_unique<LinearSolverModule>());
-  this->_subscribe(std::make_unique<MathModule>());
-  this->_subscribe(std::make_unique<MeshModule>());
-  this->_subscribe(std::make_unique<SchemeModule>());
-  this->_subscribe(std::make_unique<SocketModule>());
-  this->_subscribe(std::make_unique<DevUtilsModule>());
-  this->_subscribe(std::make_unique<WriterModule>());
-}
-
 template <typename NameEmbedderMapT, typename EmbedderTableT>
 void
 ModuleRepository::_populateEmbedderTableT(const ASTNode& module_node,
diff --git a/src/language/modules/ModuleRepository.hpp b/src/language/modules/ModuleRepository.hpp
index 407d7b55b..b2e217b93 100644
--- a/src/language/modules/ModuleRepository.hpp
+++ b/src/language/modules/ModuleRepository.hpp
@@ -32,6 +32,23 @@ class ModuleRepository
                             SymbolTable& symbol_table);
 
  public:
+  static ModuleRepository&
+  getInstance()
+  {
+    static ModuleRepository m_instance;
+    return m_instance;
+  }
+
+  template <typename ModuleT>
+  struct Subscribe
+  {
+    Subscribe()
+    {
+      static_assert(std::is_base_of_v<IModule, ModuleT>, "module must inherit IModule interface");
+      ModuleRepository::getInstance()._subscribe(std::make_unique<ModuleT>());
+    }
+  };
+
   void populateSymbolTable(const ASTNode& module_name_node, SymbolTable& symbol_table);
   void populateMandatoryData(const ASTNode& root_node, SymbolTable& symbol_table);
   void registerOperators(const std::string& module_name);
@@ -46,7 +63,10 @@ class ModuleRepository
   ModuleRepository(const ModuleRepository&) = delete;
   ModuleRepository(ModuleRepository&&)      = delete;
 
-  ModuleRepository();
+ private:
+  ModuleRepository() = default;
+
+ public:
   ~ModuleRepository() = default;
 };
 
diff --git a/src/language/modules/SchemeModule.cpp b/src/language/modules/SchemeModule.cpp
index f1a7d8d73..40cc703cc 100644
--- a/src/language/modules/SchemeModule.cpp
+++ b/src/language/modules/SchemeModule.cpp
@@ -1,4 +1,7 @@
 #include <language/modules/SchemeModule.hpp>
+#include <language/modules/SchemeModuleTypes.hpp>
+
+#include <language/modules/ModuleRepository.hpp>
 
 #include <analysis/GaussLegendreQuadratureDescriptor.hpp>
 #include <analysis/GaussLobattoQuadratureDescriptor.hpp>
@@ -809,3 +812,5 @@ SchemeModule::registerCheckpointResume() const
 
 #endif   // PUGS_HAS_HDF5
 }
+
+ModuleRepository::Subscribe<SchemeModule> scheme_module;
diff --git a/src/language/modules/SchemeModule.hpp b/src/language/modules/SchemeModule.hpp
index c61b30844..cf169175c 100644
--- a/src/language/modules/SchemeModule.hpp
+++ b/src/language/modules/SchemeModule.hpp
@@ -2,7 +2,6 @@
 #define SCHEME_MODULE_HPP
 
 #include <language/modules/BuiltinModule.hpp>
-#include <language/modules/SchemeModuleTypes.hpp>
 
 class SchemeModule : public BuiltinModule
 {
diff --git a/src/language/modules/SocketModule.cpp b/src/language/modules/SocketModule.cpp
index 79321d088..9c2ecdbe1 100644
--- a/src/language/modules/SocketModule.cpp
+++ b/src/language/modules/SocketModule.cpp
@@ -1,5 +1,7 @@
 #include <language/modules/SocketModule.hpp>
 
+#include <language/modules/ModuleRepository.hpp>
+
 #include <language/utils/BinaryOperatorProcessorBuilder.hpp>
 #include <language/utils/BuiltinFunctionEmbedder.hpp>
 #include <language/utils/CheckpointResumeRepository.hpp>
@@ -271,3 +273,5 @@ SocketModule::registerCheckpointResume() const
                            throw NotImplementedError("checkpoint/resume with sockets");
                          }));
 }
+
+ModuleRepository::Subscribe<SocketModule> socket_module;
diff --git a/src/language/modules/UnaryOperatorRegisterForVh.cpp b/src/language/modules/UnaryOperatorRegisterForVh.cpp
index e2e9c2db9..3d52ab546 100644
--- a/src/language/modules/UnaryOperatorRegisterForVh.cpp
+++ b/src/language/modules/UnaryOperatorRegisterForVh.cpp
@@ -1,6 +1,6 @@
 #include <language/modules/UnaryOperatorRegisterForVh.hpp>
 
-#include <language/modules/SchemeModule.hpp>
+#include <language/modules/SchemeModuleTypes.hpp>
 #include <language/utils/DataHandler.hpp>
 #include <language/utils/DataVariant.hpp>
 #include <language/utils/EmbeddedDiscreteFunctionOperators.hpp>
diff --git a/src/language/modules/WriterModule.cpp b/src/language/modules/WriterModule.cpp
index 6d8450650..e524a8856 100644
--- a/src/language/modules/WriterModule.cpp
+++ b/src/language/modules/WriterModule.cpp
@@ -1,7 +1,9 @@
 #include <language/modules/WriterModule.hpp>
 
-#include <language/modules/MeshModule.hpp>
-#include <language/modules/SchemeModule.hpp>
+#include <language/modules/ModuleRepository.hpp>
+
+#include <language/modules/MeshModuleTypes.hpp>
+#include <language/modules/SchemeModuleTypes.hpp>
 #include <language/utils/BuiltinFunctionEmbedder.hpp>
 #include <language/utils/CheckpointResumeRepository.hpp>
 #include <language/utils/TypeDescriptor.hpp>
@@ -242,3 +244,5 @@ WriterModule::registerCheckpointResume() const
 
 #endif   // PUGS_HAS_HDF5
 }
+
+ModuleRepository::Subscribe<WriterModule> writer_module{};
-- 
GitLab