seqlua
diff seqlua.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 | 47f9b323d68c |
| children | 03ed3361f332 |
line diff
1.1 --- a/seqlua.c Wed Aug 20 01:59:55 2014 +0200 1.2 +++ b/seqlua.c Wed Aug 20 04:24:08 2014 +0200 1.3 @@ -1,6 +1,12 @@ 1.4 #include <lua.h> 1.5 #include <lauxlib.h> 1.6 -#include "seqlualib.h" 1.7 + 1.8 +static int seqlua_aux_call(lua_State *L) { 1.9 + lua_pushvalue(L, lua_upvalueindex(1)); 1.10 + lua_pushvalue(L, lua_upvalueindex(2)); 1.11 + lua_call(L, 1, 1); 1.12 + return 1; 1.13 +} 1.14 1.15 static int seqlua_ipairsaux_raw(lua_State *L) { 1.16 lua_Integer i; 1.17 @@ -35,7 +41,7 @@ 1.18 } 1.19 } 1.20 1.21 -static int seqlua_ipairsaux_funcclosure(lua_State *L) { 1.22 +static int seqlua_ipairsaux_triplet(lua_State *L) { 1.23 lua_Integer i = lua_tointeger(L, lua_upvalueindex(4)) + 1; 1.24 lua_settop(L, 0); 1.25 lua_pushinteger(L, i); 1.26 @@ -57,18 +63,22 @@ 1.27 } 1.28 1.29 static int seqlua_ipairs(lua_State *L) { 1.30 - if (luaL_getmetafield(L, 1, "__call")) { 1.31 - if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function"); 1.32 - lua_replace(L, 1); 1.33 - } 1.34 + luaL_checkany(L, 1); // provides better error message 1.35 if (lua_type(L, 1) == LUA_TFUNCTION) { 1.36 + seqlua_ipairs_function: 1.37 if (!lua_isnoneornil(L, 2) || !lua_isnoneornil(L, 3)) { 1.38 lua_settop(L, 3); 1.39 lua_pushinteger(L, 0); 1.40 - lua_pushcclosure(L, seqlua_ipairsaux_funcclosure, 4); 1.41 + lua_pushcclosure(L, seqlua_ipairsaux_triplet, 4); 1.42 return 1; 1.43 } 1.44 lua_pushcfunction(L, seqlua_ipairsaux_func); 1.45 + } else if (luaL_getmetafield(L, 1, "__call")) { 1.46 + if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function"); 1.47 + lua_pushvalue(L, 1); 1.48 + lua_pushcclosure(L, seqlua_aux_call, 2); 1.49 + lua_replace(L, 1); 1.50 + goto seqlua_ipairs_function; 1.51 } else if (luaL_getmetafield(L, 1, "__index")) { 1.52 lua_pushcfunction(L, seqlua_ipairsaux_meta); 1.53 } else { 1.54 @@ -80,7 +90,26 @@ 1.55 return 3; 1.56 } 1.57 1.58 -static int seqlua_iteratoraux(lua_State *L) { 1.59 +static int seqlua_iteratoraux_raw(lua_State *L) { 1.60 + lua_Integer i = lua_tointeger(L, lua_upvalueindex(2)) + 1; 1.61 + lua_rawgeti(L, lua_upvalueindex(1), i); 1.62 + if (lua_isnil(L, -1)) return 1; 1.63 + lua_pushinteger(L, i); 1.64 + lua_replace(L, lua_upvalueindex(2)); 1.65 + return 1; 1.66 +} 1.67 + 1.68 +static int seqlua_iteratoraux_meta(lua_State *L) { 1.69 + lua_Integer i = lua_tointeger(L, lua_upvalueindex(2)) + 1; 1.70 + lua_pushinteger(L, i); 1.71 + lua_gettable(L, lua_upvalueindex(1)); 1.72 + if (lua_isnil(L, -1)) return 1; 1.73 + lua_pushinteger(L, i); 1.74 + lua_replace(L, lua_upvalueindex(2)); 1.75 + return 1; 1.76 +} 1.77 + 1.78 +static int seqlua_iteratoraux_triplet(lua_State *L) { 1.79 lua_settop(L, 0); 1.80 lua_pushvalue(L, lua_upvalueindex(1)); 1.81 lua_pushvalue(L, lua_upvalueindex(2)); 1.82 @@ -95,21 +124,31 @@ 1.83 return lua_gettop(L); 1.84 } 1.85 1.86 -static int seqlua_iterator(lua_State *L) { 1.87 - if (luaL_getmetafield(L, 1, "__call")) { 1.88 - if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function"); 1.89 - lua_replace(L, 1); 1.90 - } 1.91 +int seqlua_iterator(lua_State *L) { 1.92 + luaL_checkany(L, 1); // provides better error message 1.93 + lua_settop(L, 3); 1.94 if (lua_type(L, 1) == LUA_TFUNCTION) { 1.95 - if (lua_isnoneornil(L, 2) && lua_isnoneornil(L, 3)) { 1.96 + seqlua_iterator_function: 1.97 + if (lua_isnil(L, 2) && lua_isnil(L, 3)) { 1.98 lua_settop(L, 1); 1.99 } else { 1.100 - lua_settop(L, 3); 1.101 - lua_pushcclosure(L, seqlua_iteratoraux, 3); 1.102 + lua_pushcclosure(L, seqlua_iteratoraux_triplet, 3); 1.103 } 1.104 + } else if (luaL_getmetafield(L, 1, "__call")) { 1.105 + if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function"); 1.106 + lua_pushvalue(L, 1); 1.107 + lua_pushcclosure(L, seqlua_aux_call, 2); 1.108 + lua_replace(L, 1); 1.109 + goto seqlua_iterator_function; 1.110 + } else if (luaL_getmetafield(L, 1, "__index")) { 1.111 + lua_pushvalue(L, 1); 1.112 + lua_pushinteger(L, 0); 1.113 + lua_pushcclosure(L, seqlua_iteratoraux_raw, 2); 1.114 } else { 1.115 - seqlua_iterclosure(L, 1); 1.116 - lua_settop(L, 1); 1.117 + luaL_checktype(L, 1, LUA_TTABLE); 1.118 + lua_pushvalue(L, 1); 1.119 + lua_pushinteger(L, 0); 1.120 + lua_pushcclosure(L, seqlua_iteratoraux_meta, 2); 1.121 } 1.122 return 1; 1.123 }