# HG changeset patch # User jbe # Date 1408649521 -7200 # Node ID 44880bcfc3237b1f88aad24dc67e8fcad53a6600 # Parent 28d472cc7a9b2d9b1d9d01e4cecda559d6cc15f0 Macro seqlua_iterloop doesn't automatically pop the value anymore (use seqlua_iterloopauto instead); New function string.concat(sep, seq) introduced diff -r 28d472cc7a9b -r 44880bcfc323 Makefile --- a/Makefile Thu Aug 21 20:20:20 2014 +0200 +++ b/Makefile Thu Aug 21 21:32:01 2014 +0200 @@ -8,8 +8,8 @@ seqlualib.o: seqlualib.c seqlualib.h cc -O2 -c -fpic -I $(LUA_INCLUDE) -o seqlualib.o seqlualib.c -seqlua.so: seqlua.o - ld -shared -o seqlua.so seqlua.o +seqlua.so: seqlua.o seqlualib.o + ld -shared -o seqlua.so seqlua.o seqlualib.o seqlua.o: seqlua.c seqlualib.h cc -O2 -c -fpic -I $(LUA_INCLUDE) -o seqlua.o seqlua.c diff -r 28d472cc7a9b -r 44880bcfc323 README --- a/README Thu Aug 21 20:20:20 2014 +0200 +++ b/README Thu Aug 21 21:32:01 2014 +0200 @@ -3,10 +3,18 @@ This is an experimental package to extend Lua in the following manner: -* allow ipairs(...) to accept tables as well as functions +* allow ``ipairs(seq)`` to accept tables as well as functions, +* 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 other words: +When calling ``ipairs(seq)`` or ``string.concat(separator, seq)``, +then ``seq`` may either be a (table) sequence or a (function) iterator. +Auxiliary C functions and macros are provided to simplify extending your own +C functions in the same manner. + This library completely ignores the ``__ipairs`` metamethod (as it is deprecated since Lua 5.3.0-alpha). It respects, however, any ``__index`` and ``__call`` metamethods (this may cause unexpected behavior when passing @@ -18,7 +26,8 @@ Lua part of the library ----------------------- -The new ``ipairs(...)`` function works as follows: +The modified ``ipairs(seq)`` function and the new ``string.concat`` function +work as demonstrated in the following examples: require "seqlua" @@ -32,6 +41,9 @@ -- 2 b -- 3 c + print(string.concat(",", t)) + -- prints: a,b,c + function alphabet() local letter = nil return function() @@ -57,6 +69,9 @@ -- 25 y -- 26 z + print(string.concat(",", alphabet())) + -- prints: 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 + function filter(f, seq) return coroutine.wrap(function() for i, v in ipairs(seq) do f(v) end @@ -85,6 +100,9 @@ -- true -- c + print((","):concat(filter(filterfunc, {"a", "b", 3, "c"}))) + -- prints: a,b,true,true,true,c + C part of the library --------------------- @@ -95,6 +113,14 @@ for ( \ seqlua_iterinit((L), (iter), (idx)); \ seqlua_iternext(iter); \ + ) + +and + + #define seqlua_iterloopauto(L, iter, idx) \ + for ( \ + seqlua_iterinit((L), (iter), (idx)); \ + seqlua_iternext(iter); \ lua_pop((L), 1) \ ) @@ -106,7 +132,9 @@ seqlua_iterloop(L, &iter, 1) { if (seqlua_itercount(&iter) > 1) fputs(",", stdout); fputs(luaL_tolstring(L, -1, NULL), stdout); - lua_pop(L, 1); // pops value that luaL_tolstring pushed onto stack + // two values need to be popped (the value pushed by + // seqlua_iternext and the value pushed by luaL_tolstring) + lua_pop(L, 2); } fputs("\n", stdout); return 0; diff -r 28d472cc7a9b -r 44880bcfc323 seqlua.c --- a/seqlua.c Thu Aug 21 20:20:20 2014 +0200 +++ b/seqlua.c Thu Aug 21 21:32:01 2014 +0200 @@ -1,5 +1,6 @@ #include #include +#include "seqlualib.h" static int seqlua_ipairsaux_raw(lua_State *L) { lua_Integer i; @@ -51,8 +52,30 @@ return 3; } +static int seqlua_concat(lua_State *L) { + const char *sep; + size_t seplen; + luaL_Buffer buf; + seqlua_Iterator iter; + sep = luaL_checklstring(L, 1, &seplen); + luaL_checkany(L, 2); + lua_settop(L, 3); + luaL_buffinit(L, &buf); + seqlua_iterloop(L, &iter, 2) { + lua_replace(L, 3); + if (seqlua_itercount(&iter) > 1) luaL_addlstring(&buf, sep, seplen); + luaL_tolstring(L, 3, NULL); + luaL_addvalue(&buf); + } + luaL_pushresult(&buf); + return 1; +} + int luaopen_seqlua(lua_State *L) { lua_pushcfunction(L, seqlua_ipairs); lua_setglobal(L, "ipairs"); - return 1; + lua_getglobal(L, "string"); + lua_pushcfunction(L, seqlua_concat); + lua_setfield(L, -2, "concat"); + return 0; } diff -r 28d472cc7a9b -r 44880bcfc323 seqlua_c_example.c --- a/seqlua_c_example.c Thu Aug 21 20:20:20 2014 +0200 +++ b/seqlua_c_example.c Thu Aug 21 21:32:01 2014 +0200 @@ -3,12 +3,14 @@ #include "seqlualib.h" #include -static int seqlua_c_example_printcsv(lua_State *L) { +int seqlua_c_example_printcsv(lua_State *L) { seqlua_Iterator iter; seqlua_iterloop(L, &iter, 1) { if (seqlua_itercount(&iter) > 1) fputs(",", stdout); fputs(luaL_tolstring(L, -1, NULL), stdout); - lua_pop(L, 1); // pop value that luaL_tolstring pushed onto stack + // two values need to be popped (the value pushed by + // seqlua_iternext and the value pushed by luaL_tolstring) + lua_pop(L, 2); } fputs("\n", stdout); return 0; diff -r 28d472cc7a9b -r 44880bcfc323 seqlualib.h --- a/seqlualib.h Thu Aug 21 20:20:20 2014 +0200 +++ b/seqlualib.h Thu Aug 21 21:32:01 2014 +0200 @@ -16,6 +16,12 @@ for ( \ seqlua_iterinit((L), (iter), (idx)); \ seqlua_iternext(iter); \ + ) + +#define seqlua_iterloopauto(L, iter, idx) \ + for ( \ + seqlua_iterinit((L), (iter), (idx)); \ + seqlua_iternext(iter); \ lua_pop((L), 1) \ )