[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Lua 5.4 Tuples FTW!
- From: Duane Leslie <parakleta@...>
- Date: Fri, 16 Mar 2018 10:37:39 +1100
Hi,
A quick and dirty tuple implementation using the new multi-uservalue
userdata implementation.
Compile with `cc -shared -fPIC -o tuple.so ltuple.c`.
Use as follows:
Lua 5.4.0 (work1) Copyright (C) 1994-2018 Lua.org, PUC-Rio
> tuple = require"tuple"
> function test(...) return tuple(...) end
> t = test(1,2,nil,4,nil)
> #t
5
> t[2], t[3], t[4]
2 nil 4
> for i,v in pairs(t) do print(i,v) end
1 1
2 2
3 nil
4 4
5 nil
>
Enjoy.
Regards,
Duane.
#include "lua.h"
#include "lauxlib.h"
int luaopen_tuple(lua_State *L);
static int
constructor(lua_State *L)
{
unsigned short n = lua_gettop(L);
unsigned short *nptr = lua_newuserdatauv(L, sizeof(n), n);
*nptr = n;
if (n) {
lua_insert(L, 1);
do {
lua_setiuservalue(L, 1, n);
} while (--n);
}
lua_pushvalue(L, lua_upvalueindex(1));
lua_setmetatable(L, 1);
return 1;
}
static int
tuple__len(lua_State *L)
{
unsigned short *nptr = lua_touserdata(L, 1);
lua_pushinteger(L, *nptr);
return 1;
}
static int
tuple__index(lua_State *L)
{
unsigned short *nptr = lua_touserdata(L, 1);
lua_Integer idx = luaL_checkinteger(L, 2);
luaL_argcheck(L, 0 < idx && idx <= *nptr, 2, "Index out of bounds");
lua_getiuservalue(L, 1, idx);
return 1;
}
static int
tuple__next(lua_State *L)
{
lua_Integer idx;
lua_settop(L, 2);
if (lua_isnil(L, 2)) {
idx = 1;
} else {
idx = luaL_checkinteger(L, 2)+1;
}
lua_pushinteger(L, idx);
return (LUA_TNONE == lua_getiuservalue(L, 1, idx)) ? 1 : 2;
}
static int
tuple__pairs(lua_State *L)
{
lua_pushcfunction(L, tuple__next);
lua_pushvalue(L, 1);
lua_pushinteger(L, 0);
return 3;
}
static struct luaL_Reg tuple_m[] = {
//{ "__add", NULL}, /* Append */
//{ "__div", NULL}, /* Remove */
//{ "__concat", NULL}, /* Join */
//{ "__bor", NULL}, /* Split */
{ "__len", tuple__len },
//{ "__eq", NULL},
//{ "__lt", NULL},
//{ "__le", NULL},
{ "__index", tuple__index },
//{ "__name", NULL }, /* Requires `setfuncs` placeholder patch */
{ "__pairs", tuple__pairs },
{ NULL, NULL }
};
LUA_API int
luaopen_tuple(lua_State *L)
{
luaL_newlib(L, tuple_m);
lua_pushstring(L, "tuple");
lua_setfield(L, -2, "__name");
lua_pushcclosure(L, constructor, 1);
return 1;
}