Lua API: Plugin execute functionality now supports named tuples in the closure
This commit is contained in:
parent
15062976ca
commit
f793d8ef7e
4 changed files with 60 additions and 7 deletions
|
@ -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") {
|
||||
|
|
|
@ -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"});
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue