diff --git a/rsc/lua/module.lua b/rsc/lua/module.lua index 8e240778c4609305e045aab43328507f5f8d05f2..52c2875163968d24e9286f1494c833cd2266d8d0 100644 --- a/rsc/lua/module.lua +++ b/rsc/lua/module.lua @@ -2,14 +2,6 @@ Utilities to handle the module declaration files. ]] --- Local private function: try to import options from a table into a job or a --- module declaration. -function ___tryImportOptions(thing, tbl) - if tbl["options"] and type(tbl.options) == "table" then - thing:setOptions(tbl.options) - end -end - -- Check if the type of the argument is 'table' function ___checkTable(tbl) if type(tbl) ~= "table" then @@ -17,6 +9,16 @@ function ___checkTable(tbl) end end +-- Local private function: try to import options from a table into a job or a +-- module declaration. +function ___tryImportOptions(thing, tbl) + ___checkTable(tbl) + if tbl["options"] then + ___checkTable(tbl.options) + thing:setOptions(tbl.options) + end +end + -- The option declaration block: -- DeclareOption { opt1 = val1, opt2 = val2 } function DeclareOption(opt) @@ -105,11 +107,12 @@ function DeclareModule(tbl) if tbl.description then module:setDescription(tbl.description) end if tbl.revision then module:setRevision(tbl.revision) end if tbl.imports then module:setImports(tbl.imports) end - ___tryImportOptions(module, tbl) -- A little more complicated thing - if tbl.functions then module:setFunctions(tbl.functions) end if tbl.jobs then module:setJobs(tbl.jobs) end + if tbl.functions then module:setFunctions(tbl.functions) end + + ___tryImportOptions(module, tbl) -- Register the module! module:pushToRuntime() diff --git a/src/Lib/Script/CRTPLuaScriptObject.cc b/src/Lib/Script/CRTPLuaScriptObject.cc index e696188627369f59c5b675386d482ffb2063434d..21e83d1e1f8e666026a79b4e51a9e6a880a2b5d3 100644 --- a/src/Lib/Script/CRTPLuaScriptObject.cc +++ b/src/Lib/Script/CRTPLuaScriptObject.cc @@ -10,8 +10,7 @@ FreeFunctions::print(lua_State *L) noexcept { const std::string_view arg = CHECK_STRING_VIEW(L, 1); out(LuaContext::getContext(L)) << "OUT: " << arg << "\n"; - lua_settop(L, 0); - return 0; + LUA_RETURN_NOTHING(L); } // ModuleDeclaration @@ -22,8 +21,7 @@ ModuleDeclaration::setName(lua_State *const L) noexcept auto *const self = ModuleDeclaration::CHECK(L, 1); self->moduleName = CHECK_STRING_VIEW(L, 2); Utils::trim(self->moduleName); - lua_settop(L, 0); - return 0; + LUA_RETURN_NOTHING(L); } int @@ -32,8 +30,7 @@ ModuleDeclaration::setAuthorName(lua_State *const L) noexcept auto *const self = ModuleDeclaration::CHECK(L, 1); self->authorName = CHECK_STRING_VIEW(L, 2); Utils::trim(self->authorName); - lua_settop(L, 0); - return 0; + LUA_RETURN_NOTHING(L); } int @@ -42,8 +39,7 @@ ModuleDeclaration::setRevision(lua_State *const L) noexcept auto *const self = ModuleDeclaration::CHECK(L, 1); self->revision = CHECK_STRING_VIEW(L, 2); Utils::trim(self->revision); - lua_settop(L, 0); - return 0; + LUA_RETURN_NOTHING(L); } int @@ -52,8 +48,7 @@ ModuleDeclaration::setDescription(lua_State *const L) noexcept auto *const self = ModuleDeclaration::CHECK(L, 1); self->moduleDescription = CHECK_STRING_VIEW(L, 2); Utils::trim(self->moduleDescription); - lua_settop(L, 0); - return 0; + LUA_RETURN_NOTHING(L); } int @@ -62,8 +57,7 @@ ModuleDeclaration::setImplementationFile(lua_State *const L) noexcept auto *const self = ModuleDeclaration::CHECK(L, 1); self->implementationFile = CHECK_STRING_VIEW(L, 2); Utils::trim(self->implementationFile); - lua_settop(L, 0); - return 0; + LUA_RETURN_NOTHING(L); } int @@ -78,50 +72,56 @@ ModuleDeclaration::setImports(lua_State *const L) noexcept err(context) << "Add import " << import << " for module " << self->moduleName << "\n"; return false; // Value was not popped from stack! }); - lua_settop(L, 0); - return 0; + err(context) << "Imports done!\n"; + LUA_RETURN_NOTHING(L); } int ModuleDeclaration::setOptions(lua_State *const L) noexcept { - auto *const self = ModuleDeclaration::CHECK(L, 1); - IterateOverArray(L, 2, [self, L]() noexcept -> bool { + auto *const self = ModuleDeclaration::CHECK(L, 1); + auto *const context = LuaContext::getContext(L); + IterateOverArray(L, 2, [&context, self, L]() noexcept -> bool { OptionDeclaration *const opt = OptionDeclaration::CHECK(L, -1); self->moduleOptions.emplace_back(opt); - lua_setuservalue(L, 1); // Tie the opt to the module - return true; // The value was popped from the stack + err(context) << "Add option for module " << self->moduleName << "\n"; + self->addUserValue(L, 1); // Tie the opt to the module + return true; // The value was popped from the stack }); - lua_settop(L, 0); - return 0; + err(context) << "Options done!\n"; + LUA_RETURN_NOTHING(L); } int ModuleDeclaration::setFunctions(lua_State *const L) noexcept { - auto *const self = ModuleDeclaration::CHECK(L, 1); - IterateOverArray(L, 2, [self, L]() noexcept -> bool { + auto *const self = ModuleDeclaration::CHECK(L, 1); + auto *const context = LuaContext::getContext(L); + IterateOverArray(L, 2, [&context, self, L]() noexcept -> bool { FunctionDeclaration *const fun = FunctionDeclaration::CHECK(L, -1); self->moduleFunctions.emplace_back(fun); - lua_setuservalue(L, 1); // Tie the function to the module - return true; // The value was popped from the stack + err(context) << "Add function " << fun->name << " to module " << self->moduleName << "\n"; + self->addUserValue(L, 1); // Tie the function to the module + return true; // The value was popped from the stack }); - lua_settop(L, 0); - return 0; + err(context) << "Functions done!\n"; + LUA_RETURN_NOTHING(L); } int ModuleDeclaration::setJobs(lua_State *const L) noexcept { - auto *const self = ModuleDeclaration::CHECK(L, 1); - IterateOverArray(L, 2, [self, L]() noexcept -> bool { + auto *const self = ModuleDeclaration::CHECK(L, 1); + auto *const context = LuaContext::getContext(L); + IterateOverArray(L, 2, [&context, self, L]() noexcept -> bool { JobDeclaration *const job = JobDeclaration::CHECK(L, -1); self->moduleJobs.emplace_back(job); - lua_setuservalue(L, 1); // Tie the job to the module - return true; // The value was popped from the stack + err(context) << "Add job " << job->name << " to module " << self->moduleName << "\n"; + self->addUserValue(L, 1); // Tie the job to the module + return true; // The value was popped from the stack }); - lua_settop(L, 0); - return 0; + err(context) << "Jobs done!\n"; + LUA_RETURN_NOTHING(L); } int @@ -130,8 +130,9 @@ ModuleDeclaration::pushToRuntime(lua_State *const L) noexcept ModuleDeclaration *const self = CHECK(L, 1); auto *const context = LuaContext::getContext(L); err(context) << "Register module \"" << self->moduleName << "\" in the runtime!\n"; + lua_settop(L, 1); context->registerModuleDeclaration(self); - return 0; + LUA_RETURN_NOTHING(L); } // OptionDeclaration @@ -177,8 +178,7 @@ OptionDeclaration::addOptionContent(lua_State *const L) noexcept else luaL_error(L, "Unsupported type %s", luaL_typename(L, 3)); - lua_settop(L, 0); - return 0; + LUA_RETURN_NOTHING(L); } // JobDeclaration @@ -207,8 +207,7 @@ int JobDeclaration::setName(lua_State *L) noexcept { JobDeclaration::CHECK(L, 1)->name = CHECK_STRING_VIEW(L, 2); - lua_settop(L, 0); - return 0; + LUA_RETURN_NOTHING(L); } int @@ -227,20 +226,18 @@ JobDeclaration::setOptions(lua_State *L) noexcept } job->options.push_back(opt); - lua_setuservalue(L, 1); // Tie T[i] to job and pop stack - return true; // Value was popped from the stack + job->addUserValue(L, 1); // Tie T[i] to job and pop stack + return true; // Value was popped from the stack }); - lua_settop(L, 0); - return 0; + LUA_RETURN_NOTHING(L); } int JobDeclaration::setImportFromScript(lua_State *L) noexcept { JobDeclaration::CHECK(L, 1)->parentScript = CHECK_STRING_VIEW(L, 2); - lua_settop(L, 0); - return 0; + LUA_RETURN_NOTHING(L); } // FunctionDeclaration @@ -261,14 +258,12 @@ int FunctionDeclaration::setName(lua_State *L) noexcept { FunctionDeclaration::CHECK(L, 1)->name = CHECK_STRING_VIEW(L, 2); - lua_settop(L, 0); - return 0; + LUA_RETURN_NOTHING(L); } int FunctionDeclaration::setImportFromScript(lua_State *L) noexcept { FunctionDeclaration::CHECK(L, 1)->parentScript = CHECK_STRING_VIEW(L, 2); - lua_settop(L, 0); - return 0; + LUA_RETURN_NOTHING(L); } diff --git a/src/Lib/Script/CRTPLuaScriptObject.hh b/src/Lib/Script/CRTPLuaScriptObject.hh index a1043d6b9b3f4c7e32ee13db077618ad100ec851..f255335cb942c69a6a2f91394e1ba23dd55f0af3 100644 --- a/src/Lib/Script/CRTPLuaScriptObject.hh +++ b/src/Lib/Script/CRTPLuaScriptObject.hh @@ -13,6 +13,7 @@ namespace Vivy::Script #define LUA_DECL_METHOD(class, name) luaL_Reg{ #name, class ::name } #define LUA_DECL_META_METHOD(class, meta, name) luaL_Reg{ meta, class ::name } #define LUA_DECL_CREATE(class) luaL_Reg{ "new", class ::CREATE } +#define LUA_RETURN_NOTHING(L) { lua_settop(L, 0); return 0; } // clang-format on #define script_class(theClassName) \ @@ -44,21 +45,18 @@ protected: const int countInt = static_cast<const int>(count); for (int i = 1; i <= countInt; ++i) { + luaL_checktype(L, tblIndex, LUA_TTABLE); lua_pushinteger(L, i); // i -> top stack - lua_gettable(L, tblIndex); // T[i] -> top stack + lua_gettable(L, tblIndex); // T[i] -> top stack and pop i - // Sentinel check if (lua_type(L, -1) == LUA_TNIL) - break; + break; // Sentinel check // If the callback didn't pop the object form the stack, pop // it ourself. The value will be accessible at the top of the // stack (index -1). if (!callback()) lua_pop(L, -1); - - // Pop i from the stack - lua_pop(L, -1); } } @@ -98,12 +96,12 @@ protected: static inline constexpr luaL_Reg luaRegDefaultTOSTRING = { "__tostring", TOSTRING }; public: - static Object *CHECK(lua_State *L, int index) noexcept + static Object *CHECK(lua_State *const L, const int index) noexcept { return reinterpret_cast<Object *>(luaL_checkudata(L, index, Object::className)); } - static void Register(lua_State *L) noexcept + static void Register(lua_State *const L) noexcept { // Fill the method table, newclass = {} lua_newtable(L); @@ -142,6 +140,18 @@ public: lua_pop(L, 1); // drop method-table lua_register(L, Object::className, CREATE); // Register the create method } + +private: + // The user value count + int userValueCount{ 0 }; + +protected: + // Add a user value to this object. Do not used lua_setuservalue or + // lua_setiuservalue directly, use this proxy method. + void addUserValue(lua_State *const L, const int index) noexcept + { + lua_setiuservalue(L, index, ++userValueCount); + } }; // Option declaration diff --git a/src/Lib/Script/LuaContext.cc b/src/Lib/Script/LuaContext.cc index 9585956ac6e3f73ca46ab738d80d2c1bfdddb3c0..554d104d19aab53c3c2504cdc6dd9a7d18572118 100644 --- a/src/Lib/Script/LuaContext.cc +++ b/src/Lib/Script/LuaContext.cc @@ -125,7 +125,10 @@ LuaContext::registerModuleDeclaration(const ModuleDeclaration *const mod) noexce return Code::Error; } - int r = luaL_ref(L, LUA_REGISTRYINDEX); + streamErr << "Try to register module \"" << mod->moduleName << "\"\n"; + + ModuleDeclaration::CHECK(L, -1); + const int r = luaL_ref(L, LUA_REGISTRYINDEX); modules.emplace(mod->moduleName, r); return Code::Success; } @@ -135,6 +138,7 @@ LuaContext::getModule(const std::string_view name) const noexcept { if (modules.count(name) >= 1) { 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 { diff --git a/utils/lua/sample-spec.module b/utils/lua/sample-spec.module index cdca8c8720386e2fb8fe7c32c179595452fb89d9..a6886f8da78209663e01fa5cd62297b6d9bd57e1 100644 --- a/utils/lua/sample-spec.module +++ b/utils/lua/sample-spec.module @@ -11,12 +11,6 @@ fun1 = DeclareFunction { "tripleCopySyl" } fun2 = DeclareFunction { "printFoo" } fun3 = ImportFunction { "utils", "prettyPrint" } -print(tostring(custom_opt)) -print(tostring(job3)) -print(tostring(job2)) -print(tostring(fun3)) -print(tostring(fun2)) - DeclareModule { name = "sample-spec", description = "Sample script used for the specification proposition",