# HG changeset patch # User jbe # Date 1408831243 -7200 # Node ID 3ff7cec8d3ce3d0f893a00759351a0103c0cd98e # Parent 4fc9090ada1d6dfbdf00ad462cfb1969631cc2c1 Do not respect __len metamethods diff -r 4fc9090ada1d -r 3ff7cec8d3ce README --- a/README Sat Aug 23 23:35:10 2014 +0200 +++ b/README Sun Aug 24 00:00:43 2014 +0200 @@ -5,13 +5,16 @@ * allow ``ipairs(seq)`` to accept tables as well as functions (i.e function iterators), -* add a new function ``string.concat(separator, seq)`` to concat either table - entries or function return values, +* add a new function ``string.concat(separator, seq)`` to concat either + table entries or function return values, * provide auxiliary C functions and macros to simplify iterating over both tables and iterator functions with the same statement. -In all cases, existing ``__index``, ``__len``, or ``__ipairs`` metamethods are -respected. The ``__ipairs`` metamethod takes precedence. +Existing ``__ipairs`` or ``__index`` (but not ``__len``) metamethods +are respected by the C and Lua functions as well as C macros. The +``__ipairs`` metamethod takes precedence over ``__index``, while the +``__len`` metamethod is never used. + Lua part of the library diff -r 4fc9090ada1d -r 3ff7cec8d3ce seqlua.c --- a/seqlua.c Sat Aug 23 23:35:10 2014 +0200 +++ b/seqlua.c Sun Aug 24 00:00:43 2014 +0200 @@ -2,12 +2,21 @@ #include #include "seqlualib.h" +static int seqlua_ipairsaux_raw(lua_State *L) { + lua_Integer i; + luaL_checktype(L, 1, LUA_TTABLE); + i = luaL_checkinteger(L, 2) + 1; + lua_pushinteger(L, i); + lua_rawgeti(L, 1, i); // TODO: Lua 5.3 returns type + return lua_isnil(L, -1) ? 1 : 2; +} + static int seqlua_ipairsaux_index(lua_State *L) { lua_Integer i = luaL_checkinteger(L, 2) + 1; lua_pushinteger(L, i); lua_pushinteger(L, i); lua_gettable(L, 1); // TODO: Lua 5.3 returns type - return lua_isnil(L, -1) && i > luaL_len(L, 1) ? 1 : 2; + return lua_isnil(L, -1) ? 1 : 2; } static int seqlua_ipairsaux_call(lua_State *L) { @@ -32,10 +41,10 @@ int t = lua_type(L, 1); if (t == LUA_TFUNCTION) { lua_pushcfunction(L, seqlua_ipairsaux_call); + } else if (luaL_getmetafield(L, 1, "__index")) { + lua_pushcfunction(L, seqlua_ipairsaux_index); } else { - if (t != LUA_TTABLE && !luaL_getmetafield(L, 1, "__index")) { - luaL_checktype(L, 1, LUA_TTABLE); - } + luaL_checktype(L, 1, LUA_TTABLE); lua_pushcfunction(L, seqlua_ipairsaux_index); } lua_pushvalue(L, 1); diff -r 4fc9090ada1d -r 3ff7cec8d3ce seqlualib.c --- a/seqlualib.c Sat Aug 23 23:35:10 2014 +0200 +++ b/seqlualib.c Sun Aug 24 00:00:43 2014 +0200 @@ -15,12 +15,8 @@ } else { if (lua_type(L, idx) == LUA_TFUNCTION) { iter->itertype = SEQLUA_ITERTYPE_CALL; - } else if ( - luaL_getmetafield(L, idx, "__index") || - luaL_getmetafield(L, idx, "__len") - ) { + } else if (luaL_getmetafield(L, idx, "__index")) { lua_pop(L, 1); - iter->len = luaL_len(L, idx); iter->itertype = SEQLUA_ITERTYPE_INDEX; } else { luaL_checktype(L, idx, LUA_TTABLE); @@ -56,13 +52,9 @@ lua_call(L, 0, 1); break; case SEQLUA_ITERTYPE_INDEX: - if (i > iter->len) { - lua_pop(L, 3); - return 0; - } lua_pushinteger(L, i); lua_gettable(L, iter->idx); - return 1; + break; case SEQLUA_ITERTYPE_RAW: lua_rawgeti(L, iter->idx, i); break; diff -r 4fc9090ada1d -r 3ff7cec8d3ce seqlualib.h --- a/seqlualib.h Sat Aug 23 23:35:10 2014 +0200 +++ b/seqlualib.h Sun Aug 24 00:00:43 2014 +0200 @@ -6,7 +6,6 @@ int idx; int itertype; lua_Integer i; - lua_Integer len; } seqlua_Iterator; extern void seqlua_iterinit(lua_State *L, seqlua_Iterator *iter, int idx);