Browse Source

'ipairs' respects metamethods

pull/9/head
Roberto Ierusalimschy 10 years ago
parent
commit
f9037ae8c1
  1. 46
      lbaselib.c
  2. 3
      ltests.h
  3. 7
      luaconf.h

46
lbaselib.c

@ -1,5 +1,5 @@
/* /*
** $Id: lbaselib.c,v 1.291 2014/07/16 13:56:59 roberto Exp roberto $ ** $Id: lbaselib.c,v 1.292 2014/07/17 13:53:37 roberto Exp roberto $
** Basic library ** Basic library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -244,17 +244,53 @@ static int luaB_pairs (lua_State *L) {
} }
static int ipairsaux (lua_State *L) { /*
int i = luaL_checkint(L, 2); ** Traversal function for 'ipairs' for raw tables
*/
static int ipairsaux_raw (lua_State *L) {
int i = luaL_checkint(L, 2) + 1;
luaL_checktype(L, 1, LUA_TTABLE); luaL_checktype(L, 1, LUA_TTABLE);
i++; /* next value */
lua_pushinteger(L, i); lua_pushinteger(L, i);
return (lua_rawgeti(L, 1, i) == LUA_TNIL) ? 1 : 2; return (lua_rawgeti(L, 1, i) == LUA_TNIL) ? 1 : 2;
} }
/*
** Traversal function for 'ipairs' for tables with metamethods
*/
static int ipairsaux (lua_State *L) {
int i = luaL_checkint(L, 2) + 1;
if (i > luaL_len(L, 1)) { /* larger than length? */
lua_pushnil(L); /* end traversal */
return 1;
}
else {
lua_pushinteger(L, i);
lua_pushinteger(L, i); /* key for indexing table */
lua_gettable(L, 1);
return 2;
}
}
/*
** This function will use either 'ipairsaux' or 'ipairsaux_raw' to
** traverse a table, depending on whether the table has metamethods
** that can affect the traversal.
*/
static int luaB_ipairs (lua_State *L) { static int luaB_ipairs (lua_State *L) {
return pairsmeta(L, "__ipairs", 1, ipairsaux); lua_CFunction iter =
(luaL_getmetafield(L, 1, "__len") ||
luaL_getmetafield(L, 1, "__index"))
? ipairsaux : ipairsaux_raw;
#if defined(LUA_COMPAT_IPAIRS)
return pairsmeta(L, "__ipairs", 1, iter);
#else
lua_pushcfunction(L, iter); /* iteration function */
lua_pushvalue(L, 1); /* state */
lua_pushinteger(L, 0); /* initial value */
return 3;
#endif
} }

3
ltests.h

@ -1,5 +1,5 @@
/* /*
** $Id: ltests.h,v 2.37 2014/07/23 17:16:50 roberto Exp roberto $ ** $Id: ltests.h,v 2.38 2014/07/24 14:00:16 roberto Exp roberto $
** Internal Header for Debugging of the Lua Implementation ** Internal Header for Debugging of the Lua Implementation
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -12,6 +12,7 @@
/* test Lua with no compatibility code */ /* test Lua with no compatibility code */
#undef LUA_COMPAT_MATHLIB #undef LUA_COMPAT_MATHLIB
#undef LUA_COMPAT_IPAIRS
#undef LUA_COMPAT_BITLIB #undef LUA_COMPAT_BITLIB
#undef LUA_COMPAT_APIUNSIGNED #undef LUA_COMPAT_APIUNSIGNED
#undef LUA_COMPAT_FLOATSTRING #undef LUA_COMPAT_FLOATSTRING

7
luaconf.h

@ -1,5 +1,5 @@
/* /*
** $Id: luaconf.h,v 1.210 2014/07/17 13:53:37 roberto Exp roberto $ ** $Id: luaconf.h,v 1.211 2014/07/24 14:00:16 roberto Exp roberto $
** Configuration file for Lua ** Configuration file for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -304,6 +304,11 @@
*/ */
#define LUA_COMPAT_BITLIB #define LUA_COMPAT_BITLIB
/*
@@ LUA_COMPAT_IPAIRS controls the effectivness of the __ipairs metamethod.
*/
#define LUA_COMPAT_IPAIRS
/* /*
@@ LUA_COMPAT_APIUNSIGNED controls the presence of macros for @@ LUA_COMPAT_APIUNSIGNED controls the presence of macros for
** manipulating unsigned integers (lua_pushunsigned, lua_tounsigned, etc.) ** manipulating unsigned integers (lua_pushunsigned, lua_tounsigned, etc.)

Loading…
Cancel
Save