From 9e1d457250304a71b129f39263ba2af79cc9fd98 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Fri, 21 Feb 2020 19:09:53 +0100
Subject: [PATCH] Begin MeshModule implementation

To this purpose, a type table has been added. A simple version of the import of
a `mesh` type is done.

It is just the beginning of the building of the machinery for these "dynamic"
types (loaded on demand), variables that will be built on them and
the associated functions/algorithms.
---
 src/language/BuiltinModule.cpp    | 15 +++++-
 src/language/BuiltinModule.hpp    | 13 +++++-
 src/language/CMakeLists.txt       |  1 +
 src/language/IModule.hpp          |  7 ++-
 src/language/MeshModule.cpp       |  9 ++++
 src/language/MeshModule.hpp       | 22 +++++++++
 src/language/ModuleRepository.cpp | 76 +++++++++++++++++++++++--------
 src/language/ModuleRepository.hpp | 10 +++-
 src/language/SymbolTable.hpp      | 29 ++++++++++--
 src/language/TypeDescriptor.hpp   | 22 +++++++++
 src/language/TypeTable.hpp        | 30 ++++++++++++
 11 files changed, 206 insertions(+), 28 deletions(-)
 create mode 100644 src/language/MeshModule.cpp
 create mode 100644 src/language/MeshModule.hpp
 create mode 100644 src/language/TypeDescriptor.hpp
 create mode 100644 src/language/TypeTable.hpp

diff --git a/src/language/BuiltinModule.cpp b/src/language/BuiltinModule.cpp
index 2d2b1b556..88967ad75 100644
--- a/src/language/BuiltinModule.cpp
+++ b/src/language/BuiltinModule.cpp
@@ -1,6 +1,7 @@
 #include <BuiltinModule.hpp>
 
 #include <CFunctionEmbedder.hpp>
+#include <TypeDescriptor.hpp>
 
 #include <iostream>
 
@@ -10,7 +11,19 @@ BuiltinModule::_addFunction(const std::string& name, std::shared_ptr<ICFunctionE
   auto [i_function, success] = m_name_cfunction_map.insert(std::make_pair(name, c_function_embedder));
   // LCOV_EXCL_START
   if (not success) {
-    std::cerr << "function " << name << " cannot be add!\n";
+    std::cerr << "function " << name << " cannot be added!\n";
+    std::exit(1);
+  }
+  // LCOV_EXCL_STOP
+}
+
+void
+BuiltinModule::_addTypeDescriptor(std::shared_ptr<TypeDescriptor> type_descriptor)
+{
+  auto [i_type, success] = m_type_descriptor_map.insert(std::make_pair(type_descriptor->name(), type_descriptor));
+  // LCOV_EXCL_START
+  if (not success) {
+    std::cerr << "type '" << type_descriptor->name() << "' cannot be added!\n";
     std::exit(1);
   }
   // LCOV_EXCL_STOP
diff --git a/src/language/BuiltinModule.hpp b/src/language/BuiltinModule.hpp
index 2a076f511..67adb09e1 100644
--- a/src/language/BuiltinModule.hpp
+++ b/src/language/BuiltinModule.hpp
@@ -1,18 +1,21 @@
 #ifndef BUILTIN_MODULE_HPP
 #define BUILTIN_MODULE_HPP
 
-#include <PugsMacros.hpp>
-
 #include <IModule.hpp>
 
 class ICFunctionEmbedder;
+class TypeDescriptor;
+
 class BuiltinModule : public IModule
 {
  protected:
   NameCFunctionMap m_name_cfunction_map;
+  TypeDescriptorMap m_type_descriptor_map;
 
   void _addFunction(const std::string& name, std::shared_ptr<ICFunctionEmbedder> c_function_embedder);
 
+  void _addTypeDescriptor(std::shared_ptr<TypeDescriptor> type_descriptor);
+
  public:
   const NameCFunctionMap&
   getNameCFunctionsMap() const final
@@ -20,6 +23,12 @@ class BuiltinModule : public IModule
     return m_name_cfunction_map;
   }
 
+  const TypeDescriptorMap&
+  getTypeDescriptorMap() const final
+  {
+    return m_type_descriptor_map;
+  }
+
   BuiltinModule() = default;
 
   ~BuiltinModule() = default;
diff --git a/src/language/CMakeLists.txt b/src/language/CMakeLists.txt
index e901374f5..14f349b46 100644
--- a/src/language/CMakeLists.txt
+++ b/src/language/CMakeLists.txt
@@ -33,6 +33,7 @@ add_library(
   ASTSymbolInitializationChecker.cpp
   BuiltinModule.cpp
   MathModule.cpp
+  MeshModule.cpp
   ModuleRepository.cpp
   PugsParser.cpp)
 
diff --git a/src/language/IModule.hpp b/src/language/IModule.hpp
index 01afaca3c..459a914b9 100644
--- a/src/language/IModule.hpp
+++ b/src/language/IModule.hpp
@@ -7,17 +7,20 @@
 #include <unordered_map>
 
 class ICFunctionEmbedder;
+class TypeDescriptor;
 
 class IModule
 {
  public:
-  using NameCFunctionMap = std::unordered_map<std::string, std::shared_ptr<ICFunctionEmbedder>>;
+  using NameCFunctionMap  = std::unordered_map<std::string, std::shared_ptr<ICFunctionEmbedder>>;
+  using TypeDescriptorMap = std::unordered_map<std::string, std::shared_ptr<TypeDescriptor>>;
 
   IModule()          = default;
   IModule(IModule&&) = default;
   IModule& operator=(IModule&&) = default;
 
-  virtual const NameCFunctionMap& getNameCFunctionsMap() const = 0;
+  virtual const NameCFunctionMap& getNameCFunctionsMap() const  = 0;
+  virtual const TypeDescriptorMap& getTypeDescriptorMap() const = 0;
 
   virtual std::string_view name() const = 0;
 
diff --git a/src/language/MeshModule.cpp b/src/language/MeshModule.cpp
new file mode 100644
index 000000000..7edad9c35
--- /dev/null
+++ b/src/language/MeshModule.cpp
@@ -0,0 +1,9 @@
+#include <MeshModule.hpp>
+#include <TypeDescriptor.hpp>
+
+#include <memory>
+
+MeshModule::MeshModule()
+{
+  this->_addTypeDescriptor(std::make_shared<TypeDescriptor>(std::string{"mesh"}));
+}
diff --git a/src/language/MeshModule.hpp b/src/language/MeshModule.hpp
new file mode 100644
index 000000000..5310e54ab
--- /dev/null
+++ b/src/language/MeshModule.hpp
@@ -0,0 +1,22 @@
+#ifndef MESH_MODULE_HPP
+#define MESH_MODULE_HPP
+
+#include <PugsMacros.hpp>
+
+#include <BuiltinModule.hpp>
+
+class MeshModule : public BuiltinModule
+{
+ public:
+  std::string_view
+  name() const final
+  {
+    return "mesh";
+  }
+
+  MeshModule();
+
+  ~MeshModule() = default;
+};
+
+#endif   // MESH_MODULE_HPP
diff --git a/src/language/ModuleRepository.cpp b/src/language/ModuleRepository.cpp
index 1b3fee7d3..f6b0b0d8f 100644
--- a/src/language/ModuleRepository.cpp
+++ b/src/language/ModuleRepository.cpp
@@ -4,10 +4,11 @@
 
 #include <ASTNode.hpp>
 
+#include <CFunctionEmbedder.hpp>
 #include <SymbolTable.hpp>
 
-#include <CFunctionEmbedder.hpp>
 #include <MathModule.hpp>
+#include <MeshModule.hpp>
 
 void
 ModuleRepository::_subscribe(std::unique_ptr<IModule> m)
@@ -19,35 +20,72 @@ ModuleRepository::_subscribe(std::unique_ptr<IModule> m)
 ModuleRepository::ModuleRepository()
 {
   this->_subscribe(std::make_unique<MathModule>());
+  this->_subscribe(std::make_unique<MeshModule>());
 }
 
 void
-ModuleRepository::populateSymbolTable(const ASTNode& module_name_node, SymbolTable& symbol_table)
+ModuleRepository::_populateCFunctionsEmbedderTable(const IModule& populating_module,
+                                                   const ASTNode& module_name_node,
+                                                   SymbolTable& symbol_table)
 {
-  std::string module_name = module_name_node.string();
+  const std::string& module_name = module_name_node.string();
 
-  auto i_module = m_module_set.find(module_name);
-  if (i_module != m_module_set.end()) {
-    CFunctionEmbedderTable& c_function_embedder_table = symbol_table.cFunctionEbedderTable();
+  CFunctionEmbedderTable& c_function_embedder_table = symbol_table.cFunctionEbedderTable();
+
+  for (auto [symbol_name, c_function] : populating_module.getNameCFunctionsMap()) {
+    auto [i_symbol, success] = symbol_table.add(symbol_name, module_name_node.begin());
 
-    const IModule& m = *i_module->second;
+    if (not success) {
+      std::ostringstream error_message;
+      error_message << "importing module '" << module_name << "', cannot add symbol '" << symbol_name
+                    << "', it is already defined!";
+      throw parse_error(error_message.str(), module_name_node.begin());
+    }
+
+    i_symbol->attributes().setDataType(ASTNodeDataType::c_function_t);
+    i_symbol->attributes().setIsInitialized();
+    i_symbol->attributes().value() = c_function_embedder_table.size();
+
+    c_function_embedder_table.add(c_function);
+  }
+}
 
-    for (auto [symbol_name, c_function] : m.getNameCFunctionsMap()) {
-      auto [i_symbol, success] = symbol_table.add(symbol_name, module_name_node.begin());
+void
+ModuleRepository::_populateTypeDescriptor(const IModule& populating_module,
+                                          const ASTNode& module_name_node,
+                                          SymbolTable& symbol_table)
+{
+  const std::string& module_name = module_name_node.string();
 
-      if (not success) {
-        std::ostringstream error_message;
-        error_message << "importing module '" << module_name << "', cannot add symbol '" << symbol_name
-                      << "', it is already defined!";
-        throw parse_error(error_message.str(), module_name_node.begin());
-      }
+  TypeTable& type_table = symbol_table.typeTable();
 
-      i_symbol->attributes().setDataType(ASTNodeDataType::c_function_t);
-      i_symbol->attributes().setIsInitialized();
-      i_symbol->attributes().value() = c_function_embedder_table.size();
+  for (auto [symbol_name, type_descriptor] : populating_module.getTypeDescriptorMap()) {
+    auto [i_symbol, success] = symbol_table.add(symbol_name, module_name_node.begin());
 
-      c_function_embedder_table.add(c_function);
+    if (not success) {
+      std::ostringstream error_message;
+      error_message << "importing module '" << module_name << "', cannot add symbol '" << symbol_name
+                    << "', it is already defined!";
+      throw parse_error(error_message.str(), module_name_node.begin());
     }
+
+    i_symbol->attributes().setDataType(ASTNodeDataType::type_id_t);
+    i_symbol->attributes().setIsInitialized();
+    i_symbol->attributes().value() = type_table.size();
+
+    type_table.add(type_descriptor);
+  }
+}
+
+void
+ModuleRepository::populateSymbolTable(const ASTNode& module_name_node, SymbolTable& symbol_table)
+{
+  const std::string& module_name = module_name_node.string();
+
+  auto i_module = m_module_set.find(module_name);
+  if (i_module != m_module_set.end()) {
+    this->_populateCFunctionsEmbedderTable(*i_module->second, module_name_node, symbol_table);
+    this->_populateTypeDescriptor(*i_module->second, module_name_node, symbol_table);
   } else {
     throw parse_error(std::string{"could not find module "} + module_name, std::vector{module_name_node.begin()});
   }
diff --git a/src/language/ModuleRepository.hpp b/src/language/ModuleRepository.hpp
index 467ffdb09..e71a56587 100644
--- a/src/language/ModuleRepository.hpp
+++ b/src/language/ModuleRepository.hpp
@@ -17,8 +17,16 @@ class ModuleRepository
 
   void _subscribe(std::unique_ptr<IModule> a);
 
+  void _populateCFunctionsEmbedderTable(const IModule& populating_module,
+                                        const ASTNode& module_name_node,
+                                        SymbolTable& symbol_table);
+
+  void _populateTypeDescriptor(const IModule& populating_module,
+                               const ASTNode& module_name_node,
+                               SymbolTable& symbol_table);
+
  public:
-  void populateSymbolTable(const ASTNode& node_module_name, SymbolTable& symbol_table);
+  void populateSymbolTable(const ASTNode& module_name_node, SymbolTable& symbol_table);
 
   const ModuleRepository& operator=(const ModuleRepository&) = delete;
   const ModuleRepository& operator=(ModuleRepository&&) = delete;
diff --git a/src/language/SymbolTable.hpp b/src/language/SymbolTable.hpp
index d6a735151..4dbbc5b2c 100644
--- a/src/language/SymbolTable.hpp
+++ b/src/language/SymbolTable.hpp
@@ -13,6 +13,8 @@
 #include <CFunctionEmbedderTable.hpp>
 #include <FunctionTable.hpp>
 
+#include <TypeTable.hpp>
+
 class SymbolTable
 {
  public:
@@ -87,6 +89,8 @@ class SymbolTable
     {
       if (attributes.m_data_type == ASTNodeDataType::function_t) {
         os << "function_id:";
+      } else if (attributes.m_data_type == ASTNodeDataType::type_id_t) {
+        os << "type_id:";
       }
       std::visit(
         [&](const auto& value) {
@@ -196,6 +200,8 @@ class SymbolTable
   std::shared_ptr<FunctionTable> m_function_table;
   std::shared_ptr<CFunctionEmbedderTable> m_c_function_embedder_table;
 
+  std::shared_ptr<TypeTable> m_type_table;
+
  public:
   bool
   hasContext() const
@@ -238,6 +244,20 @@ class SymbolTable
     return *m_c_function_embedder_table;
   }
 
+  TypeTable&
+  typeTable()
+  {
+    Assert(m_type_table);
+    return *m_type_table;
+  }
+
+  const TypeTable&
+  typeTable() const
+  {
+    Assert(m_type_table);
+    return *m_type_table;
+  }
+
   friend std::ostream&
   operator<<(std::ostream& os, const SymbolTable& symbol_table)
   {
@@ -299,7 +319,8 @@ class SymbolTable
     : m_parent_table{parent_table},
       m_context{context},
       m_function_table{parent_table->m_function_table},
-      m_c_function_embedder_table{parent_table->m_c_function_embedder_table}
+      m_c_function_embedder_table{parent_table->m_c_function_embedder_table},
+      m_type_table{parent_table->m_type_table}
   {
     ;
   }
@@ -308,7 +329,8 @@ class SymbolTable
     : m_parent_table{parent_table},
       m_context{parent_table->m_context},
       m_function_table{parent_table->m_function_table},
-      m_c_function_embedder_table{parent_table->m_c_function_embedder_table}
+      m_c_function_embedder_table{parent_table->m_c_function_embedder_table},
+      m_type_table{parent_table->m_type_table}
   {
     ;
   }
@@ -317,7 +339,8 @@ class SymbolTable
     : m_parent_table{nullptr},
       m_context{nullptr},
       m_function_table{std::make_shared<FunctionTable>()},
-      m_c_function_embedder_table{std::make_shared<CFunctionEmbedderTable>()}
+      m_c_function_embedder_table{std::make_shared<CFunctionEmbedderTable>()},
+      m_type_table{std::make_shared<TypeTable>()}
   {
     ;
   }
diff --git a/src/language/TypeDescriptor.hpp b/src/language/TypeDescriptor.hpp
new file mode 100644
index 000000000..9da24e0d4
--- /dev/null
+++ b/src/language/TypeDescriptor.hpp
@@ -0,0 +1,22 @@
+#ifndef TYPE_DESCRIPTOR_HPP
+#define TYPE_DESCRIPTOR_HPP
+
+#include <string>
+
+class TypeDescriptor
+{
+ private:
+  std::string m_name;
+
+ public:
+  const std::string&
+  name() const
+  {
+    return m_name;
+  }
+
+  TypeDescriptor(std::string_view name) : m_name(name) {}
+  ~TypeDescriptor() = default;
+};
+
+#endif   // TYPE_DESCRIPTOR_HPP
diff --git a/src/language/TypeTable.hpp b/src/language/TypeTable.hpp
new file mode 100644
index 000000000..059e686e1
--- /dev/null
+++ b/src/language/TypeTable.hpp
@@ -0,0 +1,30 @@
+#ifndef TYPE_TABLE_HPP
+#define TYPE_TABLE_HPP
+
+#include <TypeDescriptor.hpp>
+
+#include <vector>
+
+class TypeTable
+{
+ private:
+  std::vector<std::shared_ptr<TypeDescriptor>> m_type_list;
+
+ public:
+  size_t
+  size() const
+  {
+    return m_type_list.size();
+  }
+
+  void
+  add(std::shared_ptr<TypeDescriptor> type_descriptor)
+  {
+    m_type_list.emplace_back(type_descriptor);
+  }
+
+  TypeTable()  = default;
+  ~TypeTable() = default;
+};
+
+#endif   // TYPE_TABLE_HPP
-- 
GitLab