seqlua
diff seqlualib.c @ 8:144f0bddee2b
Pass value as argument to __call metamethod
author | jbe |
---|---|
date | Wed Aug 20 04:24:08 2014 +0200 (2014-08-20) |
parents | 2cb22d01fdd0 |
children | a95fbd16473f |
line diff
1.1 --- a/seqlualib.c Wed Aug 20 01:59:55 2014 +0200 1.2 +++ b/seqlualib.c Wed Aug 20 04:24:08 2014 +0200 1.3 @@ -2,28 +2,33 @@ 1.4 #include <lauxlib.h> 1.5 #include "seqlualib.h" 1.6 1.7 -#define SEQLUA_ITERTYPE_FUNC 1 1.8 -#define SEQLUA_ITERTYPE_META 2 1.9 -#define SEQLUA_ITERTYPE_RAW 3 1.10 +#define SEQLUA_ITERTYPE_CALL 1 1.11 +#define SEQLUA_ITERTYPE_FUNC 2 1.12 +#define SEQLUA_ITERTYPE_META 3 1.13 +#define SEQLUA_ITERTYPE_RAW 4 1.14 1.15 void seqlua_iterinit(lua_State *L, seqlua_Iterator *iter, int idx) { 1.16 luaL_checkany(L, idx); // provides better error message 1.17 iter->L = L; 1.18 if (luaL_getmetafield(L, idx, "__call")) { 1.19 if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function"); 1.20 - iter->itertype = SEQLUA_ITERTYPE_FUNC; 1.21 + iter->idx = lua_gettop(L); 1.22 + iter->callargidx = idx; 1.23 + iter->itertype = SEQLUA_ITERTYPE_CALL; 1.24 } else if (lua_type(L, idx) == LUA_TFUNCTION) { 1.25 - lua_pushvalue(L, idx); 1.26 + lua_pushnil(L); // dummy value 1.27 + iter->idx = idx; 1.28 iter->itertype = SEQLUA_ITERTYPE_FUNC; 1.29 } else { 1.30 + iter->idx = idx; 1.31 if (luaL_getmetafield(L, idx, "__index")) { 1.32 - lua_pop(L, 1); 1.33 iter->itertype = SEQLUA_ITERTYPE_META; 1.34 + // leave __index as dummy value 1.35 } else { 1.36 + lua_pushnil(L); // dummy value 1.37 luaL_checktype(L, idx, LUA_TTABLE); 1.38 iter->itertype = SEQLUA_ITERTYPE_RAW; 1.39 } 1.40 - lua_pushvalue(L, idx); 1.41 } 1.42 iter->i = 0; 1.43 } 1.44 @@ -32,19 +37,25 @@ 1.45 lua_State *L = iter->L; 1.46 lua_Integer i = ++iter->i; 1.47 switch (iter->itertype) { 1.48 + case SEQLUA_ITERTYPE_CALL: 1.49 + lua_pushvalue(L, iter->idx); 1.50 + lua_pushvalue(L, iter->callargidx); 1.51 + lua_call(L, 1, 1); 1.52 + break; 1.53 case SEQLUA_ITERTYPE_FUNC: 1.54 - lua_pushvalue(L, -1); 1.55 + lua_pushvalue(L, iter->idx); 1.56 lua_call(L, 0, 1); 1.57 break; 1.58 case SEQLUA_ITERTYPE_META: 1.59 lua_pushinteger(L, i); 1.60 - lua_gettable(L, -2); 1.61 + lua_gettable(L, iter->idx); 1.62 break; 1.63 case SEQLUA_ITERTYPE_RAW: 1.64 - lua_rawgeti(L, -1, i); 1.65 + lua_rawgeti(L, iter->idx, i); 1.66 + break; 1.67 } 1.68 if (lua_isnil(L, -1)) { 1.69 - lua_pop(L, 2); 1.70 + lua_pop(L, 2); // remove nil and dummy value 1.71 return 0; 1.72 } 1.73 return 1; 1.74 @@ -69,11 +80,21 @@ 1.75 return 1; 1.76 } 1.77 1.78 +static int seqlua_iterclosureaux_call(lua_State *L) { 1.79 + lua_pushvalue(L, lua_upvalueindex(1)); 1.80 + lua_pushvalue(L, lua_upvalueindex(2)); 1.81 + lua_call(L, 1, 1); 1.82 + return 1; 1.83 +} 1.84 + 1.85 void seqlua_iterclosure(lua_State *L, int idx) { 1.86 + luaL_checkany(L, idx); // provides better error message 1.87 if (lua_type(L, idx) == LUA_TFUNCTION) { 1.88 // do nothing 1.89 } else if (luaL_getmetafield(L, idx, "__call")) { 1.90 if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function"); 1.91 + lua_pushvalue(L, idx); 1.92 + lua_pushcclosure(L, seqlua_iterclosureaux_call, 2); 1.93 lua_replace(L, idx); 1.94 } else if (luaL_getmetafield(L, idx, "__index")) { 1.95 lua_pop(L, 1);