Lua API: Plugin execute functionality now supports named tuples in the closure

This commit is contained in:
Celtic Minstrel 2024-09-23 01:02:58 -04:00
parent 15062976ca
commit f793d8ef7e
4 changed files with 60 additions and 7 deletions

View file

@ -422,14 +422,15 @@ application_lua_kernel::request_list application_lua_kernel::thread::run_script(
results.push_back([this, lk = ctxt.execute_kernel_, data = req.data]() {
auto result = lk->run_binary_lua_tag(data);
int ref = result["ref"];
auto func = result.mandatory_child("executed");
if(auto func = result.optional_child("executed")) {
lua_rawgeti(T_, LUA_REGISTRYINDEX, ref);
luaW_copy_upvalues(T_, *func);
luaL_unref(T_, LUA_REGISTRYINDEX, ref);
lua_pop(T_, 1);
}
result.remove_children("executed");
result.remove_attribute("ref");
plugins_manager::get()->notify_event(result["name"], result);
lua_rawgeti(T_, LUA_REGISTRYINDEX, ref);
luaW_copy_upvalues(T_, func);
luaL_unref(T_, LUA_REGISTRYINDEX, ref);
lua_pop(T_, 1);
return true;
});
continue;
@ -462,6 +463,17 @@ bool luaW_copy_upvalues(lua_State* L, const config& cfg)
luaW_pushscalar(L, cfg["value"]);
lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
}
} else if(child["upvalue_type"] == "named tuple") {
auto children = upvalues->child_range(name);
std::vector<std::string> names;
for(const auto& cfg : children) {
names.push_back(cfg["name"]);
}
luaW_push_namedtuple(L, names);
for(const auto& cfg : children) {
luaW_pushscalar(L, cfg["value"]);
lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
}
} else if(child["upvalue_type"] == "config") {
luaW_pushconfig(L, child);
} else if(child["upvalue_type"] == "function") {

View file

@ -792,6 +792,19 @@ void luaW_push_namedtuple(lua_State* L, const std::vector<std::string>& names)
lua_setmetatable(L, -2);
}
std::vector<std::string> luaW_to_namedtuple(lua_State* L, int idx) {
std::vector<std::string> names;
if(luaL_getmetafield(L, idx, "__name")) {
if(lua_check<std::string>(L, -1) == "named tuple") {
luaL_getmetafield(L, idx, "__names");
names = lua_check<std::vector<std::string>>(L, -1);
lua_pop(L, 1);
}
lua_pop(L, 1);
}
return names;
}
void luaW_pushlocation(lua_State *L, const map_location& ml)
{
luaW_push_namedtuple(L, {"x", "y"});

View file

@ -101,6 +101,12 @@ void luaW_filltable(lua_State *L, const config& cfg);
*/
void luaW_push_namedtuple(lua_State* L, const std::vector<std::string>& names);
/**
* Get the keys of a "named tuple" from the stack.
* Returns an empty array if the stack element is not a named tuple.
*/
std::vector<std::string> luaW_to_namedtuple(lua_State* L, int idx);
/**
* Converts a map location object to a Lua table pushed at the top of the stack.
*/

View file

@ -1135,9 +1135,29 @@ config luaW_serialize_function(lua_State* L, int func)
case LUA_TFUNCTION:
upvalues.add_child(name, luaW_serialize_function(L, idx))["upvalue_type"] = "function";
break;
case LUA_TNIL:
upvalues.add_child(name, config{"upvalue_type", "nil"});
break;
case LUA_TTABLE:
if(config cfg; luaW_toconfig(L, idx, cfg)) {
upvalues.add_child(name, cfg)["upvalue_type"] = "config";
if(std::vector<std::string> names = luaW_to_namedtuple(L, idx); !names.empty()) {
for(size_t i = 1; i <= lua_rawlen(L, -1); i++, lua_pop(L, 1)) {
lua_rawgeti(L, idx, i);
config& cfg = upvalues.add_child(name);
luaW_toscalar(L, -1, cfg["value"]);
cfg["name"] = names[0];
cfg["upvalue_type"] = "named tuple";
names.erase(names.begin());
}
break;
} else if(config cfg; luaW_toconfig(L, idx, cfg)) {
std::vector<std::string> names;
int save_top = lua_gettop(L);
if(luaL_getmetafield(L, idx, "__name") && lua_check<std::string>(L, -1) == "named tuple") {
luaL_getmetafield(L, -2, "__names");
names = lua_check<std::vector<std::string>>(L, -1);
}
lua_settop(L, save_top);
upvalues.add_child(name, cfg)["upvalue_type"] = names.empty() ? "config" : "named tuple";
break;
} else {
for(size_t i = 1; i <= lua_rawlen(L, -1); i++, lua_pop(L, 1)) {
@ -1199,6 +1219,8 @@ bool lua_kernel_base::load_binary(const config& cfg, error_handler eh)
luaW_pushconfig(mState, child);
} else if(child["upvalue_type"] == "function") {
if(!load_binary(child, eh)) return false;
} else if(child["upvalue_type"] == "nil") {
lua_pushnil(mState);
}
} else continue;
lua_setupvalue(mState, funcindex, i);