From f56ab128f76df6bbb7685943bfea97f2b1eb5f75 Mon Sep 17 00:00:00 2001
From: Kubat <mael.martin31@gmail.com>
Date: Wed, 18 Aug 2021 10:01:16 +0200
Subject: [PATCH] SCRIPT: Implement the module:import for functions + modules

---
 src/Lib/Script/CRTPLuaScriptObject.hh         | 19 ++++++++++--
 .../FunctionDeclaration.cc                    | 10 +++++--
 .../CRTPLuaScriptObject/JobDeclaration.cc     |  6 ++++
 .../CRTPLuaScriptObject/ModuleDeclaration.cc  | 19 ++++--------
 src/Lib/Script/LuaContext.cc                  | 29 +++++++++++++++++--
 src/Lib/Script/LuaContext.hh                  |  4 ++-
 6 files changed, 67 insertions(+), 20 deletions(-)

diff --git a/src/Lib/Script/CRTPLuaScriptObject.hh b/src/Lib/Script/CRTPLuaScriptObject.hh
index 7405442e..1e6f3593 100644
--- a/src/Lib/Script/CRTPLuaScriptObject.hh
+++ b/src/Lib/Script/CRTPLuaScriptObject.hh
@@ -36,6 +36,17 @@ namespace Vivy::Script
 // CRTP to expose objects to Lua
 template <class Object> class CRTPLuaScriptObject {
 protected:
+    static bool PushFunctionFromRegistry(lua_State *const L, const int key) noexcept
+    {
+        if (key >= 0) {
+            lua_rawgeti(L, LUA_REGISTRYINDEX, key);
+            return true;
+        } else {
+            lua_pushnil(L);
+            return false;
+        }
+    }
+
     static void IterateOverArray(lua_State *const L, const int tblIndex,
                                  const auto callback) noexcept
     {
@@ -196,6 +207,7 @@ script_class (JobDeclaration) {
                             LUA_DECL_CREATE(JobDeclaration) };
 
     bool isImported{ false };
+    int functionRegisterKey{ -1 };
 
 public:
     std::string name{};
@@ -203,14 +215,15 @@ public:
     std::vector<OptionDeclaration *> options{};
 
     bool isLocalToModule() const noexcept;
+    void pushLuaFunction(lua_State *const) const noexcept;
 };
 
 // Function declaration
 script_class (FunctionDeclaration) {
     LUA_SCRIPTABLE_CLASS(FunctionDeclaration)
 
-    static int setName(lua_State *) noexcept;
-    static int setImportFromScript(lua_State *) noexcept;
+    static int setName(lua_State *const) noexcept;
+    static int setImportFromScript(lua_State *const) noexcept;
 
     static int pushToRuntime(lua_State *const) noexcept;
 
@@ -224,12 +237,14 @@ script_class (FunctionDeclaration) {
                             LUA_DECL_CREATE(FunctionDeclaration) };
 
     bool isImported{ false };
+    int functionRegisterKey{ -1 };
 
 public:
     std::string name{};
     std::string parentScript{};
 
     bool isLocalToModule() const noexcept;
+    void pushLuaFunction(lua_State *const) const noexcept;
 };
 
 // Module declaration
diff --git a/src/Lib/Script/CRTPLuaScriptObject/FunctionDeclaration.cc b/src/Lib/Script/CRTPLuaScriptObject/FunctionDeclaration.cc
index 70f2dac4..bc6c55bf 100644
--- a/src/Lib/Script/CRTPLuaScriptObject/FunctionDeclaration.cc
+++ b/src/Lib/Script/CRTPLuaScriptObject/FunctionDeclaration.cc
@@ -18,14 +18,14 @@ FunctionDeclaration::TOSTRING(lua_State *const L) noexcept
 }
 
 int
-FunctionDeclaration::setName(lua_State *L) noexcept
+FunctionDeclaration::setName(lua_State *const L) noexcept
 {
     FunctionDeclaration::CHECK(L, 1)->name = CHECK_STRING_VIEW(L, 2);
     LUA_RETURN_NOTHING(L);
 }
 
 int
-FunctionDeclaration::setImportFromScript(lua_State *L) noexcept
+FunctionDeclaration::setImportFromScript(lua_State *const L) noexcept
 {
     auto *const fun   = FunctionDeclaration::CHECK(L, 1);
     fun->parentScript = CHECK_STRING_VIEW(L, 2);
@@ -51,6 +51,12 @@ FunctionDeclaration::pushToRuntime(lua_State *const L) noexcept
     LUA_RETURN_NOTHING(L);
 }
 
+void
+FunctionDeclaration::pushLuaFunction(lua_State *const L) const noexcept
+{
+    [[maybe_unused]] bool ok = PushFunctionFromRegistry(L, functionRegisterKey);
+}
+
 bool
 FunctionDeclaration::isLocalToModule() const noexcept
 {
diff --git a/src/Lib/Script/CRTPLuaScriptObject/JobDeclaration.cc b/src/Lib/Script/CRTPLuaScriptObject/JobDeclaration.cc
index 5c16cfe0..538d1cef 100644
--- a/src/Lib/Script/CRTPLuaScriptObject/JobDeclaration.cc
+++ b/src/Lib/Script/CRTPLuaScriptObject/JobDeclaration.cc
@@ -87,3 +87,9 @@ JobDeclaration::isLocalToModule() const noexcept
 {
     return parentScript.size() == 0;
 }
+
+void
+JobDeclaration::pushLuaFunction(lua_State *const L) const noexcept
+{
+    [[maybe_unused]] bool ok = PushFunctionFromRegistry(L, functionRegisterKey);
+}
diff --git a/src/Lib/Script/CRTPLuaScriptObject/ModuleDeclaration.cc b/src/Lib/Script/CRTPLuaScriptObject/ModuleDeclaration.cc
index 2b97727c..04f76add 100644
--- a/src/Lib/Script/CRTPLuaScriptObject/ModuleDeclaration.cc
+++ b/src/Lib/Script/CRTPLuaScriptObject/ModuleDeclaration.cc
@@ -23,7 +23,6 @@ ModuleDeclaration::resolvModules(LuaContext *const context) noexcept
 int
 ModuleDeclaration::importMethod(lua_State *const L) noexcept
 {
-    auto *const self    = CHECK(L, 1);
     auto *const context = LuaContext::getContext(L);
     luaL_checktype(L, 2, LUA_TTABLE);
 
@@ -33,25 +32,19 @@ ModuleDeclaration::importMethod(lua_State *const L) noexcept
     const std::string_view mod = CHECK_STRING_VIEW(L, 3);
 
     // Import a module
-    err(context) << "Importing a module...";
-    const ModuleDeclaration *const module = context->getModule(mod);
-    if (module == nullptr) {
-        err(context) << "Failed to load module " << mod << "\n";
-        return 1; // Stack is { top: nil, str, table, self }
-    }
-
-    // Stack is { top: module, str, table, self }
+    context->getModule(mod); // Stack is { top: nil | module, str, table, self }
 
     // Import a function if needed
     if (lua_rawlen(L, 2) == 2) {
         lua_pushinteger(L, 2); // Stack is { top: int, module, str, table, self }
         lua_gettable(L, 2);    // Stack is { top: str, module, str, table, self }
-        const std::string_view func = CHECK_STRING_VIEW(L, 5);
-        err(context) << "Load function " << func << " but not implemented, pushing nil\n";
-        lua_pushnil(L);
-        // Stack is { top: nil | function, str, module, str, table, self }
+        const std::string_view func         = CHECK_STRING_VIEW(L, 5);
+        FunctionDeclaration *const function = context->getFunction(mod, func);
+        function->pushLuaFunction(L);
+        // Stack is { top: nil | function, FunctionDeclaration, str, module, str, table, self }
     }
 
+    // Top of stack is nil | function | module
     return 1;
 }
 
diff --git a/src/Lib/Script/LuaContext.cc b/src/Lib/Script/LuaContext.cc
index 13166066..81887832 100644
--- a/src/Lib/Script/LuaContext.cc
+++ b/src/Lib/Script/LuaContext.cc
@@ -194,12 +194,11 @@ LuaContext::registerDeclaration(const ModuleDeclaration *const mod) noexcept
     return Code::Success;
 }
 
-const ModuleDeclaration *
+ModuleDeclaration *
 LuaContext::getModule(const std::string_view name) const noexcept
 {
     if (moduleExists(name)) {
         const int r = modules.at(name);
-        streamErr << "Try to get module \"" << name << "\" with register key " << r << "\n";
         lua_rawgeti(L, LUA_REGISTRYINDEX, r);
         return ModuleDeclaration::CHECK(L, -1);
     } else {
@@ -208,6 +207,32 @@ LuaContext::getModule(const std::string_view name) const noexcept
     }
 }
 
+FunctionDeclaration *
+LuaContext::getFunction(const std::string_view module, const std::string_view name) const noexcept
+{
+    if (moduleExists(module)) {
+        const int r = functions.at({ module, name });
+        lua_rawgeti(L, LUA_REGISTRYINDEX, r);
+        return FunctionDeclaration::CHECK(L, -1);
+    } else {
+        lua_pushnil(L);
+        return nullptr;
+    }
+}
+
+JobDeclaration *
+LuaContext::getJob(const std::string_view module, const std::string_view name) const noexcept
+{
+    if (moduleExists(module)) {
+        const int r = jobs.at({ module, name });
+        lua_rawgeti(L, LUA_REGISTRYINDEX, r);
+        return JobDeclaration::CHECK(L, -1);
+    } else {
+        lua_pushnil(L);
+        return nullptr;
+    }
+}
+
 const std::vector<std::string_view>
 LuaContext::getAllModuleName() const noexcept
 {
diff --git a/src/Lib/Script/LuaContext.hh b/src/Lib/Script/LuaContext.hh
index 314aad64..a852aac6 100644
--- a/src/Lib/Script/LuaContext.hh
+++ b/src/Lib/Script/LuaContext.hh
@@ -68,7 +68,9 @@ public:
     Code registerDeclaration(const JobDeclaration *const) noexcept;
 
     // Returns the module or `nullptr` if not found.
-    const ModuleDeclaration *getModule(const std::string_view) const noexcept;
+    ModuleDeclaration *getModule(const std::string_view) const noexcept;
+    FunctionDeclaration *getFunction(const std::string_view, const std::string_view) const noexcept;
+    JobDeclaration *getJob(const std::string_view, const std::string_view) const noexcept;
     const std::vector<std::string_view> getAllModuleName() const noexcept;
 
     // Some verifications gone wrong, this is not a Lua error, this is a script
-- 
GitLab