seqlua

changeset 0:47f9b323d68c

Initial commit
author jbe
date Wed Aug 20 00:39:10 2014 +0200 (2014-08-20)
parents
children 158dfce546c0
files LICENSE Makefile README seqlua.c seqlua_c_example.c seqlua_c_example_test.lua seqlualib.c seqlualib.h
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/LICENSE	Wed Aug 20 00:39:10 2014 +0200
     1.3 @@ -0,0 +1,19 @@
     1.4 +Copyright (c) 2014 Public Software Group e. V., Berlin, Germany
     1.5 +
     1.6 +Permission is hereby granted, free of charge, to any person obtaining a
     1.7 +copy of this software and associated documentation files (the "Software"),
     1.8 +to deal in the Software without restriction, including without limitation
     1.9 +the rights to use, copy, modify, merge, publish, distribute, sublicense,
    1.10 +and/or sell copies of the Software, and to permit persons to whom the
    1.11 +Software is furnished to do so, subject to the following conditions:
    1.12 +
    1.13 +The above copyright notice and this permission notice shall be included in
    1.14 +all copies or substantial portions of the Software.
    1.15 +
    1.16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    1.17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    1.18 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    1.19 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    1.20 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    1.21 +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    1.22 +DEALINGS IN THE SOFTWARE.
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/Makefile	Wed Aug 20 00:39:10 2014 +0200
     2.3 @@ -0,0 +1,24 @@
     2.4 +LUA_INCLUDE=/usr/local/include/lua52
     2.5 +
     2.6 +all:: seqlualib.so seqlua.so seqlua_c_example.so
     2.7 +
     2.8 +seqlualib.so: seqlualib.o
     2.9 +	ld -shared -o seqlualib.so seqlualib.o
    2.10 +
    2.11 +seqlualib.o: seqlualib.c seqlualib.h
    2.12 +	cc -O2 -c -fpic -I $(LUA_INCLUDE) -o seqlualib.o seqlualib.c
    2.13 +
    2.14 +seqlua.so: seqlua.o seqlualib.o
    2.15 +	ld -shared -o seqlua.so seqlua.o seqlualib.o
    2.16 +
    2.17 +seqlua.o: seqlua.c seqlualib.h
    2.18 +	cc -O2 -c -fpic -I $(LUA_INCLUDE) -o seqlua.o seqlua.c
    2.19 +
    2.20 +seqlua_c_example.so: seqlua_c_example.o seqlua.o
    2.21 +	ld -shared -o seqlua_c_example.so seqlua_c_example.o seqlualib.o
    2.22 +
    2.23 +seqlua_c_example.o: seqlua_c_example.c seqlualib.h
    2.24 +	cc -O2 -c -fpic -I $(LUA_INCLUDE) -o seqlua_c_example.o seqlua_c_example.c
    2.25 +
    2.26 +clean::
    2.27 +	rm -f *.o *.so
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/README	Wed Aug 20 00:39:10 2014 +0200
     3.3 @@ -0,0 +1,141 @@
     3.4 +seqlua: Extended sequences and iterators in Lua
     3.5 +===============================================
     3.6 +
     3.7 +This is an experimental package to extend Lua in the following manner:
     3.8 +
     3.9 +* allow ipairs(...) to accept tables as well as functions or iterator triplets,
    3.10 +* provide a function iterator(...) that returns single functions unmodified,
    3.11 +  but converts
    3.12 +    * iterator triplets into closures, and
    3.13 +    * tables into a function closure that iterates over the elements,
    3.14 +* provide the auxiliary C functions and macros to simplify iterating over both
    3.15 +  tables and iterator functions with the same statement.
    3.16 +
    3.17 +This library completely ignores the ``__ipairs`` metamethod (as it is
    3.18 +deprecated since Lua 5.3.0-alpha). It respects, however, any ``__call``
    3.19 +metamethods (this may cause unexpected behavior when passing callable tables
    3.20 +to ``ipairs``).
    3.21 +
    3.22 +
    3.23 +
    3.24 +Lua part of the library
    3.25 +-----------------------
    3.26 +
    3.27 +The new ``ipairs(...)`` function works as follows:
    3.28 +
    3.29 +    require "seqlua"
    3.30 +
    3.31 +    t = {"a", "b", "c"}
    3.32 +
    3.33 +    for i, v in ipairs(t) do
    3.34 +      print(i, v)
    3.35 +    end
    3.36 +    -- prints:
    3.37 +    --  1   a
    3.38 +    --  2   b
    3.39 +    --  3   c
    3.40 +
    3.41 +    function alphabet()
    3.42 +      local letter = nil
    3.43 +      return function()
    3.44 +        if letter == nil then
    3.45 +          letter = "a"
    3.46 +        elseif letter == "z" then
    3.47 +          return nil
    3.48 +        else
    3.49 +          letter = string.char(string.byte(letter) + 1)
    3.50 +        end
    3.51 +        return letter
    3.52 +      end
    3.53 +    end
    3.54 +
    3.55 +    f = alphabet()
    3.56 +
    3.57 +    for i, v in ipairs(f) do
    3.58 +      print(i, v)
    3.59 +    end
    3.60 +    -- prints:
    3.61 +    --  1   a
    3.62 +    --  2   b
    3.63 +    --  3   c
    3.64 +    --  ...
    3.65 +    --  25  y
    3.66 +    --  26  z
    3.67 +
    3.68 +    set = {apple = true, banana = true}
    3.69 +    for i, k, v in ipairs(pairs(set)) do
    3.70 +      print(i, k, v)
    3.71 +    end
    3.72 +    -- prints:
    3.73 +    --  1   banana  true
    3.74 +    --  2   apple   true
    3.75 +    -- (order of "apple" and "banana" may vary)
    3.76 +
    3.77 +The function ``iterator(...)`` may be used to convert any table, any function,
    3.78 +or any iterator triplet into a single function (possibly creating a closure):
    3.79 +
    3.80 +    function filter_strings(...)
    3.81 +      nextvalue = iterator(...)
    3.82 +      return function()
    3.83 +        local value
    3.84 +        repeat
    3.85 +          value = nextvalue()
    3.86 +        until value == nil or type(value) == "string"
    3.87 +        return value
    3.88 +      end
    3.89 +    end
    3.90 +
    3.91 +    for i, v in ipairs(filter_strings{"Hello", true, "World"}) do
    3.92 +      print(i, v)
    3.93 +    end
    3.94 +    -- prints:
    3.95 +    --  1   Hello
    3.96 +    --  2   World
    3.97 +
    3.98 +    tbl = {apple = true, banana = true, [1] = "array entry"}
    3.99 +    for v in filter_strings(pairs(tbl)) do
   3.100 +      print(v)
   3.101 +    end
   3.102 +    -- prints:
   3.103 +    --   banana
   3.104 +    --   apple
   3.105 +    -- (order may vary)
   3.106 +
   3.107 +
   3.108 +
   3.109 +C part of the library
   3.110 +---------------------
   3.111 +
   3.112 +In ``seqlualib.h``, the following macro is defined:
   3.113 +
   3.114 +    #define seqlua_iterloop(L, iter, idx) \
   3.115 +      for ( \
   3.116 +        seqlua_iterinit((L), (iter), (idx)); \
   3.117 +        seqlua_iternext(iter); \
   3.118 +        lua_pop((L), 1) \
   3.119 +      )
   3.120 +
   3.121 +This macro allows iteration over either tables or iterator functions (but not
   3.122 +iterator triplets) as the following example function demonstrates:
   3.123 +
   3.124 +    int printcsv(lua_State *L) {
   3.125 +      seqlua_Iterator iter;
   3.126 +      seqlua_iterloop(L, &iter, 1) {
   3.127 +        if (seqlua_itercount(&iter) > 1) fputs(",", stdout);
   3.128 +        fputs(luaL_tolstring(L, -1, NULL), stdout);
   3.129 +        lua_pop(L, 1);
   3.130 +      }
   3.131 +      fputs("\n", stdout);
   3.132 +      return 0;
   3.133 +    }
   3.134 +
   3.135 +    printcsv{"a", "b", "c"}  -- prints: a,b,c
   3.136 +
   3.137 +Additionally, ``seqlualib`` includes a function ``seqlua_iterclosure(L, idx)``,
   3.138 +which converts a table at a given stack index into a function closure (stored
   3.139 +on the same stack index) that iterates over the elements of the table. If the
   3.140 +value at the given stack index is already a function, it leaves the value
   3.141 +unchanged. If the value is convertible to a function using ``__ipairs,`` then
   3.142 +the function is replaced by its ``__ipairs`` metamethod.
   3.143 +
   3.144 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/seqlua.c	Wed Aug 20 00:39:10 2014 +0200
     4.3 @@ -0,0 +1,123 @@
     4.4 +#include <lua.h>
     4.5 +#include <lauxlib.h>
     4.6 +#include "seqlualib.h"
     4.7 +
     4.8 +static int seqlua_ipairsaux_raw(lua_State *L) {
     4.9 +  lua_Integer i;
    4.10 +  luaL_checktype(L, 1, LUA_TTABLE);
    4.11 +  i = luaL_checkinteger(L, 2) + 1;
    4.12 +  lua_pushinteger(L, i);
    4.13 +  lua_rawgeti(L, 1, i);  // TODO: Lua 5.3 returns type
    4.14 +  return lua_isnil(L, -1) ? 1 : 2;
    4.15 +}
    4.16 +
    4.17 +static int seqlua_ipairsaux_meta(lua_State *L) {
    4.18 +  lua_Integer i;
    4.19 +  i = luaL_checkinteger(L, 2) + 1;
    4.20 +  lua_pushinteger(L, i);
    4.21 +  lua_pushinteger(L, i);
    4.22 +  lua_gettable(L, 1);  // TODO: Lua 5.3 returns type
    4.23 +  return lua_isnil(L, -1) ? 1 : 2;
    4.24 +}
    4.25 +
    4.26 +static int seqlua_ipairsaux_func(lua_State *L) {
    4.27 +  luaL_checktype(L, 1, LUA_TFUNCTION);
    4.28 +  lua_pushinteger(L, luaL_checkinteger(L, 2) + 1);
    4.29 +  lua_insert(L, 1);
    4.30 +  lua_settop(L, 2);
    4.31 +  lua_call(L, 0, LUA_MULTRET);
    4.32 +  if (lua_isnoneornil(L, 2)) {
    4.33 +    lua_settop(L, 0);
    4.34 +    lua_pushnil(L);
    4.35 +    return 1;
    4.36 +  } else {
    4.37 +    return lua_gettop(L);
    4.38 +  }
    4.39 +}
    4.40 +
    4.41 +static int seqlua_ipairsaux_funcclosure(lua_State *L) {
    4.42 +  lua_Integer i = lua_tointeger(L, lua_upvalueindex(4)) + 1;
    4.43 +  lua_settop(L, 0);
    4.44 +  lua_pushinteger(L, i);
    4.45 +  lua_replace(L, lua_upvalueindex(4));
    4.46 +  lua_pushinteger(L, i);
    4.47 +  lua_pushvalue(L, lua_upvalueindex(1));
    4.48 +  lua_pushvalue(L, lua_upvalueindex(2));
    4.49 +  lua_pushvalue(L, lua_upvalueindex(3));
    4.50 +  lua_call(L, 2, LUA_MULTRET);
    4.51 +  if (lua_isnoneornil(L, 2)) {
    4.52 +    lua_settop(L, 0);
    4.53 +    lua_pushnil(L);
    4.54 +    return 1;
    4.55 +  } else {
    4.56 +    lua_pushvalue(L, 2);
    4.57 +    lua_replace(L, lua_upvalueindex(3));
    4.58 +    return lua_gettop(L);
    4.59 +  }
    4.60 +}
    4.61 +
    4.62 +static int seqlua_ipairs(lua_State *L) {
    4.63 +  if (luaL_getmetafield(L, 1, "__call")) {
    4.64 +    if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function");
    4.65 +    lua_replace(L, 1);
    4.66 +  }
    4.67 +  if (lua_type(L, 1) == LUA_TFUNCTION) {
    4.68 +    if (!lua_isnoneornil(L, 2) || !lua_isnoneornil(L, 3)) {
    4.69 +      lua_settop(L, 3);
    4.70 +      lua_pushinteger(L, 0);
    4.71 +      lua_pushcclosure(L, seqlua_ipairsaux_funcclosure, 4);
    4.72 +      return 1;
    4.73 +    }
    4.74 +    lua_pushcfunction(L, seqlua_ipairsaux_func);
    4.75 +  } else if (luaL_getmetafield(L, 1, "__index")) {
    4.76 +    lua_pushcfunction(L, seqlua_ipairsaux_meta);
    4.77 +  } else {
    4.78 +    luaL_checktype(L, 1, LUA_TTABLE);
    4.79 +    lua_pushcfunction(L, seqlua_ipairsaux_raw);
    4.80 +  }
    4.81 +  lua_pushvalue(L, 1);
    4.82 +  lua_pushinteger(L, 0);
    4.83 +  return 3;
    4.84 +}
    4.85 +
    4.86 +static int seqlua_iteratoraux(lua_State *L) {
    4.87 +  lua_settop(L, 0);
    4.88 +  lua_pushvalue(L, lua_upvalueindex(1));
    4.89 +  lua_pushvalue(L, lua_upvalueindex(2));
    4.90 +  lua_pushvalue(L, lua_upvalueindex(3));
    4.91 +  lua_call(L, 2, LUA_MULTRET);
    4.92 +  if (lua_isnoneornil(L, 1)) {
    4.93 +    lua_settop(L, 1);
    4.94 +    return 1;
    4.95 +  }
    4.96 +  lua_pushvalue(L, 1);
    4.97 +  lua_replace(L, lua_upvalueindex(3));
    4.98 +  return lua_gettop(L);
    4.99 +}
   4.100 +
   4.101 +static int seqlua_iterator(lua_State *L) {
   4.102 +  if (luaL_getmetafield(L, 1, "__call")) {
   4.103 +    if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function");
   4.104 +    lua_replace(L, 1);
   4.105 +  }
   4.106 +  if (lua_type(L, 1) == LUA_TFUNCTION) {
   4.107 +    if (lua_isnoneornil(L, 2) && lua_isnoneornil(L, 3)) {
   4.108 +      lua_settop(L, 1);
   4.109 +    } else {
   4.110 +      lua_settop(L, 3);
   4.111 +      lua_pushcclosure(L, seqlua_iteratoraux, 3);
   4.112 +    }
   4.113 +  } else {
   4.114 +    seqlua_iterclosure(L, 1);
   4.115 +    lua_settop(L, 1);
   4.116 +  }
   4.117 +  return 1;
   4.118 +}
   4.119 +
   4.120 +int luaopen_seqlua(lua_State *L) {
   4.121 +  lua_pushcfunction(L, seqlua_ipairs);
   4.122 +  lua_setglobal(L, "ipairs");
   4.123 +  lua_pushcfunction(L, seqlua_iterator);
   4.124 +  lua_setglobal(L, "iterator");
   4.125 +  return 1;
   4.126 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/seqlua_c_example.c	Wed Aug 20 00:39:10 2014 +0200
     5.3 @@ -0,0 +1,21 @@
     5.4 +#include <lua.h>
     5.5 +#include <lauxlib.h>
     5.6 +#include "seqlualib.h"
     5.7 +#include <stdio.h>
     5.8 +
     5.9 +static int seqlua_c_example_printcsv(lua_State *L) {
    5.10 +  seqlua_Iterator iter;
    5.11 +  seqlua_iterloop(L, &iter, 1) {
    5.12 +    if (seqlua_itercount(&iter) > 1) fputs(",", stdout);
    5.13 +    fputs(luaL_tolstring(L, -1, NULL), stdout);
    5.14 +    lua_pop(L, 1);
    5.15 +  }
    5.16 +  fputs("\n", stdout);
    5.17 +  return 0;
    5.18 +}
    5.19 +
    5.20 +int luaopen_seqlua_c_example(lua_State *L) {
    5.21 +  lua_pushcfunction(L, seqlua_c_example_printcsv);
    5.22 +  lua_setglobal(L, "printcsv");
    5.23 +  return 0;
    5.24 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/seqlua_c_example_test.lua	Wed Aug 20 00:39:10 2014 +0200
     6.3 @@ -0,0 +1,24 @@
     6.4 +require "seqlua_c_example"  -- defines function "printcsv"
     6.5 +
     6.6 +function alphabet()
     6.7 +  local letter = nil
     6.8 +  return function()
     6.9 +    if letter == nil then
    6.10 +      letter = "a"
    6.11 +    elseif letter == "z" then
    6.12 +      return nil
    6.13 +    else
    6.14 +      letter = string.char(string.byte(letter) + 1)
    6.15 +    end
    6.16 +    return letter
    6.17 +  end
    6.18 +end
    6.19 +
    6.20 +printcsv{"a", "b", "c"}
    6.21 +-- prints:
    6.22 +-- a,b,c
    6.23 +
    6.24 +printcsv(alphabet())
    6.25 +-- prints:
    6.26 +-- a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
    6.27 +
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/seqlualib.c	Wed Aug 20 00:39:10 2014 +0200
     7.3 @@ -0,0 +1,92 @@
     7.4 +#include <lua.h>
     7.5 +#include <lauxlib.h>
     7.6 +#include "seqlualib.h"
     7.7 +
     7.8 +#define SEQLUA_ITERTYPE_FUNC 1
     7.9 +#define SEQLUA_ITERTYPE_META 2
    7.10 +#define SEQLUA_ITERTYPE_RAW  3
    7.11 +
    7.12 +void seqlua_iterinit(lua_State *L, seqlua_Iterator *iter, int idx) {
    7.13 +  luaL_checkany(L, idx);  // provides better error message
    7.14 +  iter->L = L;
    7.15 +  if (luaL_getmetafield(L, idx, "__call")) {
    7.16 +    if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function");
    7.17 +    iter->itertype = SEQLUA_ITERTYPE_FUNC;
    7.18 +  } else if (lua_type(L, idx) == LUA_TFUNCTION) {
    7.19 +    lua_pushvalue(L, idx);
    7.20 +    iter->itertype = SEQLUA_ITERTYPE_FUNC;
    7.21 +  } else {
    7.22 +    if (luaL_getmetafield(L, idx, "__index")) {
    7.23 +      lua_pop(L, 1);
    7.24 +      iter->itertype = SEQLUA_ITERTYPE_META;
    7.25 +    } else {
    7.26 +      luaL_checktype(L, idx, LUA_TTABLE);
    7.27 +      iter->itertype = SEQLUA_ITERTYPE_RAW;
    7.28 +    }
    7.29 +    lua_pushvalue(L, idx);
    7.30 +  }
    7.31 +  iter->i = 0;
    7.32 +}
    7.33 +
    7.34 +int seqlua_iternext(seqlua_Iterator *iter) {
    7.35 +  lua_State *L = iter->L;
    7.36 +  lua_Integer i = ++iter->i;
    7.37 +  switch (iter->itertype) {
    7.38 +  case SEQLUA_ITERTYPE_FUNC:
    7.39 +    lua_pushvalue(L, -1);
    7.40 +    lua_call(L, 0, 1);
    7.41 +    break;
    7.42 +  case SEQLUA_ITERTYPE_META:
    7.43 +    lua_pushinteger(L, i);
    7.44 +    lua_gettable(L, -2);
    7.45 +    break;
    7.46 +  case SEQLUA_ITERTYPE_RAW:
    7.47 +    lua_rawgeti(L, -1, i);
    7.48 +  }
    7.49 +  if (lua_isnil(L, -1)) {
    7.50 +    lua_pop(L, 2);
    7.51 +    return 0;
    7.52 +  }
    7.53 +  return 1;
    7.54 +}
    7.55 +
    7.56 +static int seqlua_iterclosureaux_raw(lua_State *L) {
    7.57 +  lua_Integer i = lua_tointeger(L, lua_upvalueindex(2)) + 1;
    7.58 +  lua_rawgeti(L, lua_upvalueindex(1), i);
    7.59 +  if (lua_isnil(L, -1)) return 1;
    7.60 +  lua_pushinteger(L, i);
    7.61 +  lua_replace(L, lua_upvalueindex(2));
    7.62 +  return 1;
    7.63 +}
    7.64 +
    7.65 +static int seqlua_iterclosureaux_meta(lua_State *L) {
    7.66 +  lua_Integer i = lua_tointeger(L, lua_upvalueindex(2)) + 1;
    7.67 +  lua_pushinteger(L, i);
    7.68 +  lua_gettable(L, lua_upvalueindex(1));
    7.69 +  if (lua_isnil(L, -1)) return 1;
    7.70 +  lua_pushinteger(L, i);
    7.71 +  lua_replace(L, lua_upvalueindex(2));
    7.72 +  return 1;
    7.73 +}
    7.74 +
    7.75 +void seqlua_iterclosure(lua_State *L, int idx) {
    7.76 +  if (lua_type(L, idx) == LUA_TFUNCTION) {
    7.77 +    // do nothing
    7.78 +  } else if (luaL_getmetafield(L, idx, "__call")) {
    7.79 +    if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function");
    7.80 +    lua_replace(L, idx);
    7.81 +  } else if (luaL_getmetafield(L, idx, "__index")) {
    7.82 +    lua_pop(L, 1);
    7.83 +    lua_pushvalue(L, idx);
    7.84 +    lua_pushinteger(L, 0);
    7.85 +    lua_pushcclosure(L, seqlua_iterclosureaux_raw, 2);
    7.86 +    lua_replace(L, idx);
    7.87 +  } else {
    7.88 +    luaL_checktype(L, idx, LUA_TTABLE);
    7.89 +    lua_pushvalue(L, idx);
    7.90 +    lua_pushinteger(L, 0);
    7.91 +    lua_pushcclosure(L, seqlua_iterclosureaux_meta, 2);
    7.92 +    lua_replace(L, idx);
    7.93 +  }
    7.94 +}
    7.95 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/seqlualib.h	Wed Aug 20 00:39:10 2014 +0200
     8.3 @@ -0,0 +1,24 @@
     8.4 +#include <lua.h>
     8.5 +#include <lauxlib.h>
     8.6 +
     8.7 +typedef struct {
     8.8 +  lua_State *L;
     8.9 +  int itertype;
    8.10 +  lua_Integer i;
    8.11 +} seqlua_Iterator;
    8.12 +
    8.13 +extern void seqlua_iterinit(lua_State *L, seqlua_Iterator *iter, int idx);
    8.14 +
    8.15 +extern int seqlua_iternext(seqlua_Iterator *iter);
    8.16 +
    8.17 +#define seqlua_iterloop(L, iter, idx) \
    8.18 +  for ( \
    8.19 +    seqlua_iterinit((L), (iter), (idx)); \
    8.20 +    seqlua_iternext(iter); \
    8.21 +    lua_pop((L), 1) \
    8.22 +  )
    8.23 +
    8.24 +#define seqlua_itercount(iter) ((iter)->i)
    8.25 +
    8.26 +extern void seqlua_iterclosure(lua_State *L, int idx);
    8.27 +

Impressum / About Us