From 96b0b3428adf034f08c90384c8aa4a63a8392a5e Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Thu, 26 Sep 2019 14:50:46 +0200
Subject: [PATCH] Prepare function evaluation mechanisms

- create a global function table, which will contain functions described by
  their domains mapping and their definition

- this table will be directly accessed by the id of the function which will be
  associated to the function variable. These ids will be stored as uint64_t (for
  the sake of simplicity) in the ASTNodeDataVariant, but use of a FunctionId
  type could be considered (cleaner approach) ...
---
 src/language/ASTSymbolTableBuilder.cpp |  3 +-
 src/language/FunctionTable.hpp         | 60 ++++++++++++++++++++++++++
 src/language/SymbolTable.hpp           | 12 +++++-
 tests/test_SymbolTable.cpp             |  6 ++-
 4 files changed, 77 insertions(+), 4 deletions(-)
 create mode 100644 src/language/FunctionTable.hpp

diff --git a/src/language/ASTSymbolTableBuilder.cpp b/src/language/ASTSymbolTableBuilder.cpp
index 441b8a242..e078f079f 100644
--- a/src/language/ASTSymbolTableBuilder.cpp
+++ b/src/language/ASTSymbolTableBuilder.cpp
@@ -79,7 +79,8 @@ ASTSymbolTableBuilder::buildSymbolTable(ASTNode& n, std::shared_ptr<SymbolTable>
 ASTSymbolTableBuilder::ASTSymbolTableBuilder(ASTNode& node)
 {
   Assert(node.is_root());
-  std::shared_ptr symbol_table = std::make_shared<SymbolTable>();
+  std::shared_ptr function_table = std::make_shared<FunctionTable>();
+  std::shared_ptr symbol_table   = std::make_shared<SymbolTable>(function_table);
 
   node.m_symbol_table = symbol_table;
 
diff --git a/src/language/FunctionTable.hpp b/src/language/FunctionTable.hpp
new file mode 100644
index 000000000..0471969b4
--- /dev/null
+++ b/src/language/FunctionTable.hpp
@@ -0,0 +1,60 @@
+#ifndef FUNCTION_TABLE_HPP
+#define FUNCTION_TABLE_HPP
+
+#include <ASTNodeDataType.hpp>
+#include <ASTNodeDataVariant.hpp>
+
+#include <ASTNode.hpp>
+
+#include <PugsAssert.hpp>
+
+#include <pegtl/position.hpp>
+
+#include <iostream>
+
+class FunctionTable
+{
+  class FunctionDescriptor
+  {
+    std::unique_ptr<ASTNode> m_domain_mapping_node;
+    std::unique_ptr<ASTNode> m_expression_node;
+
+   public:
+    FunctionDescriptor& operator=(const FunctionDescriptor&) = default;
+    FunctionDescriptor& operator=(FunctionDescriptor&&) = default;
+
+    FunctionDescriptor(FunctionDescriptor&&) = default;
+    FunctionDescriptor()                     = default;
+    ~FunctionDescriptor()                    = default;
+  };
+
+ private:
+  std::vector<FunctionDescriptor> m_function_descriptor_list;
+
+ public:
+  PUGS_INLINE
+  FunctionDescriptor& operator[](size_t function_id)
+  {
+    Assert(function_id < m_function_descriptor_list.size());
+    return m_function_descriptor_list[function_id];
+  }
+
+  PUGS_INLINE
+  const FunctionDescriptor& operator[](size_t function_id) const
+  {
+    Assert(function_id < m_function_descriptor_list.size());
+    return m_function_descriptor_list[function_id];
+  }
+
+  size_t
+  add(FunctionDescriptor&& function_descriptor)
+  {
+    m_function_descriptor_list.emplace_back(std::move(function_descriptor));
+    return m_function_descriptor_list.size() - 1;
+  }
+
+  FunctionTable()  = default;
+  ~FunctionTable() = default;
+};
+
+#endif   // FUNCTION_TABLE_HPP
diff --git a/src/language/SymbolTable.hpp b/src/language/SymbolTable.hpp
index f955d45d3..193dac31f 100644
--- a/src/language/SymbolTable.hpp
+++ b/src/language/SymbolTable.hpp
@@ -10,6 +10,8 @@
 
 #include <iostream>
 
+#include <FunctionTable.hpp>
+
 class SymbolTable
 {
  public:
@@ -129,6 +131,7 @@ class SymbolTable
  private:
   std::vector<Symbol> m_symbol_list;
   std::shared_ptr<SymbolTable> m_parent_table;
+  std::shared_ptr<FunctionTable> m_function_table;
 
  public:
   friend std::ostream&
@@ -177,7 +180,14 @@ class SymbolTable
                           true);
   }
 
-  SymbolTable(const std::shared_ptr<SymbolTable>& parent_table = nullptr) : m_parent_table(parent_table)
+  SymbolTable(const std::shared_ptr<SymbolTable>& parent_table)
+    : m_parent_table(parent_table), m_function_table(parent_table->m_function_table)
+  {
+    ;
+  }
+
+  SymbolTable(const std::shared_ptr<FunctionTable>& function_table)
+    : m_parent_table(nullptr), m_function_table(function_table)
   {
     ;
   }
diff --git a/tests/test_SymbolTable.cpp b/tests/test_SymbolTable.cpp
index 1bf8a63b8..b3f466a76 100644
--- a/tests/test_SymbolTable.cpp
+++ b/tests/test_SymbolTable.cpp
@@ -9,7 +9,8 @@ TEST_CASE("SymbolTable", "[language]")
 {
   SECTION("Simple Symbol Table")
   {
-    std::shared_ptr root_st = std::make_shared<SymbolTable>();
+    std::shared_ptr function_table = std::make_shared<FunctionTable>();
+    std::shared_ptr root_st        = std::make_shared<SymbolTable>(function_table);
 
     using namespace TAO_PEGTL_NAMESPACE;
     position begin_position{internal::iterator{"fixture"}, "fixture"};
@@ -97,7 +98,8 @@ TEST_CASE("SymbolTable", "[language]")
 
   SECTION("Hierarchy Symbol Table")
   {
-    std::shared_ptr root_st = std::make_shared<SymbolTable>();
+    std::shared_ptr function_table = std::make_shared<FunctionTable>();
+    std::shared_ptr root_st        = std::make_shared<SymbolTable>(function_table);
 
     using namespace TAO_PEGTL_NAMESPACE;
     position begin_position{internal::iterator{"fixture"}, "fixture"};
-- 
GitLab