seqlua

diff seqlua.c @ 30:367fc70acc15

Respect the __ipairs and __len metamethods
author jbe
date Sat Aug 23 23:13:17 2014 +0200 (2014-08-23)
parents 44880bcfc323
children 3ff7cec8d3ce
line diff
     1.1 --- a/seqlua.c	Fri Aug 22 12:27:25 2014 +0200
     1.2 +++ b/seqlua.c	Sat Aug 23 23:13:17 2014 +0200
     1.3 @@ -2,28 +2,18 @@
     1.4  #include <lauxlib.h>
     1.5  #include "seqlualib.h"
     1.6  
     1.7 -static int seqlua_ipairsaux_raw(lua_State *L) {
     1.8 -  lua_Integer i;
     1.9 -  luaL_checktype(L, 1, LUA_TTABLE);
    1.10 -  i = luaL_checkinteger(L, 2) + 1;
    1.11 -  lua_pushinteger(L, i);
    1.12 -  lua_rawgeti(L, 1, i);  // TODO: Lua 5.3 returns type
    1.13 -  return lua_isnil(L, -1) ? 1 : 2;
    1.14 -}
    1.15 -
    1.16 -static int seqlua_ipairsaux_meta(lua_State *L) {
    1.17 -  lua_Integer i;
    1.18 -  i = luaL_checkinteger(L, 2) + 1;
    1.19 +static int seqlua_ipairsaux_index(lua_State *L) {
    1.20 +  lua_Integer i = luaL_checkinteger(L, 2) + 1;
    1.21    lua_pushinteger(L, i);
    1.22    lua_pushinteger(L, i);
    1.23    lua_gettable(L, 1);  // TODO: Lua 5.3 returns type
    1.24 -  return lua_isnil(L, -1) ? 1 : 2;
    1.25 +  return lua_isnil(L, -1) && i > luaL_len(L, 1) ? 1 : 2;
    1.26  }
    1.27  
    1.28 -static int seqlua_ipairsaux_func(lua_State *L) {
    1.29 +static int seqlua_ipairsaux_call(lua_State *L) {
    1.30    lua_pushinteger(L, luaL_checkinteger(L, 2) + 1);
    1.31 -  lua_insert(L, 1);
    1.32 -  lua_settop(L, 2);
    1.33 +  lua_insert(L, 1);  // integer on stack index 1
    1.34 +  lua_settop(L, 2);  // function on stack index 2
    1.35    lua_call(L, 0, LUA_MULTRET);
    1.36    if (lua_isnoneornil(L, 2)) {
    1.37      lua_settop(L, 0);
    1.38 @@ -35,20 +25,22 @@
    1.39  }
    1.40  
    1.41  static int seqlua_ipairs(lua_State *L) {
    1.42 -  luaL_checkany(L, 1);  // provides better error message
    1.43 -  if (
    1.44 -    lua_type(L, 1) == LUA_TFUNCTION ||
    1.45 -    (luaL_getmetafield(L, 1, "__call") && (lua_pop(L, 1), 1))
    1.46 -  ) {
    1.47 -    lua_pushcfunction(L, seqlua_ipairsaux_func);
    1.48 -  } else if (luaL_getmetafield(L, 1, "__index")) {
    1.49 -    lua_pushcfunction(L, seqlua_ipairsaux_meta);
    1.50 +  if (luaL_getmetafield(L, 1, "__ipairs")) {
    1.51 +    lua_pushvalue(L, 1);
    1.52 +    lua_call(L, 1, 3);
    1.53    } else {
    1.54 -    luaL_checktype(L, 1, LUA_TTABLE);
    1.55 -    lua_pushcfunction(L, seqlua_ipairsaux_raw);
    1.56 +    int t = lua_type(L, 1);
    1.57 +    if (t == LUA_TFUNCTION) {
    1.58 +      lua_pushcfunction(L, seqlua_ipairsaux_call);
    1.59 +    } else {
    1.60 +      if (t != LUA_TTABLE && !luaL_getmetafield(L, 1, "__index")) {
    1.61 +        luaL_checktype(L, 1, LUA_TTABLE);
    1.62 +      }
    1.63 +      lua_pushcfunction(L, seqlua_ipairsaux_index);
    1.64 +    }
    1.65 +    lua_pushvalue(L, 1);
    1.66 +    lua_pushinteger(L, 0);
    1.67    }
    1.68 -  lua_pushvalue(L, 1);
    1.69 -  lua_pushinteger(L, 0);
    1.70    return 3;
    1.71  }
    1.72  

Impressum / About Us