diff options
| author | Alexander Gavrilov | 2012-09-05 17:37:36 +0400 |
|---|---|---|
| committer | Alexander Gavrilov | 2012-09-05 17:37:36 +0400 |
| commit | 27f169e298e658f3957aa2db1f76fe8aa20caef7 (patch) | |
| tree | 8d48333005f504557d6708703c06abb703391f9b /library | |
| parent | 9c6fcee9a9b03b42648152a549fc019f05fff468 (diff) | |
| download | dfhack-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.cpp | 34 | ||||
| -rw-r--r-- | library/lua/dfhack.lua | 8 |
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 |
