summaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
authorAlexander Gavrilov2012-09-05 17:37:36 +0400
committerAlexander Gavrilov2012-09-05 17:37:36 +0400
commit27f169e298e658f3957aa2db1f76fe8aa20caef7 (patch)
tree8d48333005f504557d6708703c06abb703391f9b /library
parent9c6fcee9a9b03b42648152a549fc019f05fff468 (diff)
downloaddfhack-27f169e298e658f3957aa2db1f76fe8aa20caef7.tar.gz
dfhack-27f169e298e658f3957aa2db1f76fe8aa20caef7.tar.bz2
dfhack-27f169e298e658f3957aa2db1f76fe8aa20caef7.tar.xz
Provide a partial application utility function to lua.
Implemented in C++ for efficiency.
Diffstat (limited to 'library')
-rw-r--r--library/LuaTools.cpp34
-rw-r--r--library/lua/dfhack.lua8
2 files changed, 41 insertions, 1 deletions
diff --git a/library/LuaTools.cpp b/library/LuaTools.cpp
index 7c2c8f8d..9f047753 100644
--- a/library/LuaTools.cpp
+++ b/library/LuaTools.cpp
@@ -1211,6 +1211,39 @@ static int dfhack_open_plugin(lua_State *L)
return 0;
}
+static int dfhack_curry_wrap(lua_State *L)
+{
+ int nargs = lua_gettop(L);
+ int ncurry = lua_tointeger(L, lua_upvalueindex(1));
+ int scount = nargs + ncurry;
+
+ luaL_checkstack(L, ncurry, "stack overflow in curry");
+
+ // Insert values in O(N+M) by first shifting the existing data
+ lua_settop(L, scount);
+ for (int i = 0; i < nargs; i++)
+ lua_copy(L, nargs-i, scount-i);
+ for (int i = 1; i <= ncurry; i++)
+ lua_copy(L, lua_upvalueindex(i+1), i);
+
+ lua_callk(L, scount-1, LUA_MULTRET, 0, lua_gettop);
+
+ return lua_gettop(L);
+}
+
+static int dfhack_curry(lua_State *L)
+{
+ luaL_checkany(L, 1);
+ if (lua_isnil(L, 1))
+ luaL_argerror(L, 1, "nil function in curry");
+ if (lua_gettop(L) == 1)
+ return 1;
+ lua_pushinteger(L, lua_gettop(L));
+ lua_insert(L, 1);
+ lua_pushcclosure(L, dfhack_curry_wrap, lua_gettop(L));
+ return 1;
+}
+
bool Lua::IsCoreContext(lua_State *state)
{
// This uses a private field of the lua state to
@@ -1234,6 +1267,7 @@ static const luaL_Reg dfhack_funcs[] = {
{ "call_with_finalizer", dfhack_call_with_finalizer },
{ "with_suspend", lua_dfhack_with_suspend },
{ "open_plugin", dfhack_open_plugin },
+ { "curry", dfhack_curry },
{ NULL, NULL }
};
diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua
index 2cbd019a..a1e89976 100644
--- a/library/lua/dfhack.lua
+++ b/library/lua/dfhack.lua
@@ -46,6 +46,7 @@ end
-- Error handling
safecall = dfhack.safecall
+curry = dfhack.curry
function dfhack.pcall(f, ...)
return xpcall(f, dfhack.onerror, ...)
@@ -118,7 +119,12 @@ function defclass(class,parent)
if parent then
setmetatable(class, parent)
else
- rawset_default(class, { init_fields = rawset_default })
+ rawset_default(class, {
+ init_fields = rawset_default,
+ callback = function(self, name, ...)
+ return dfhack.curry(self[name], self, ...)
+ end
+ })
end
return class
end