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);

Impressum / About Us