[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: cons cells
- From: RLake@...
- Date: Thu, 25 Mar 2004 14:14:49 -0500
How about this one, which creates record types with
named fields?
(I guess it is my competitive spirit :) )
And dangerously close to implementing ADTs; only lacking
pattern matching. hmmm....
#include <lua.h>
#include <lauxlib.h>
/* constructor = record(typename, field...)
rec = constructor(val...)
val = rec(field)
val... = rec(field...)
allvals = rec()
typename = rec(nil)
*/
static int aux_record(lua_State *L) {
int m = lua_gettop(L);
int n = lua_pushupvalues(L);
if (m == 0) {
return n - 1; /* return all the
values */
} else {
int i = 1;
++m;
for (; i < m; ++i) {
int field;
if (lua_isnil(L, i)) { /*
get the typename */
lua_pushvalue(L, m);
lua_gettable(L, m);
} else {
lua_pushvalue(L, i);
lua_gettable(L, m);
if (!lua_isnil(L, -1))
{
field = (int)lua_tonumber(L,
-1);
lua_pop(L, 1);
lua_pushvalue(L,
m + field);
}
}
lua_replace(L, i);
}
--m;
lua_settop(L, m);
return m;
}
}
static int aux_factory(lua_State *L) {
int nfields = (int)lua_tonumber(L, lua_upvalueindex(2));
lua_settop(L, nfields - 1); /* cavalierly
discard extra values */
lua_pushvalue(L, lua_upvalueindex(1));
lua_insert(L, 1);
lua_pushcclosure(L, aux_record, nfields);
return 1;
}
/* create a record type by generating its constructor
from a list of field names;
the first argument is the name of the
record type itself
*/
static int l_recordFactory(lua_State *L) {
int n = lua_gettop(L);
int i;
luaL_checkstring(L, 1);
luaL_argcheck(L, n <= LUA_MINSTACK, n, "too
many fields");
/* Actually, the
limit could be quite a bit bigger) */
luaL_argcheck(L, n > 1, n, "need at
least one field");
luaL_checkstack(L, 3, "This should never
happen");
lua_newtable(L);
lua_pushvalue(L, -1); /* The table itself is
the key for the typename */
lua_pushvalue(L, 1);
lua_settable(L, -3);
lua_replace(L, 1);
for (i = n; i > 1; ) {
luaL_checkstring(L, -1); /* strictly
optional, why shouldn't they be arbitrary types */
lua_pushnumber(L, (lua_Number)--i);
lua_settable(L, 1);
}
lua_pushnumber(L, (lua_Number)n);
lua_pushcclosure(L, aux_factory, 2);
return 1;
}
int luaopen_record(lua_State *L) {
lua_pushliteral(L, "record");
lua_pushcclosure(L, l_recordFactory, 0);
lua_settable(L, LUA_GLOBALSINDEX);
return 0;
}
-------------------
Lua 5.0.2-rici Copyright (C) 1994-2003 Tecgraf,
PUC-Rio
> cons = record("cons", "cdr",
"car")
> null = cons()
> =null()
nil nil
> a = cons(null, 24)
> b = cons(a, 37)
> =b()
function: 0x6049b0 37
> =b(nil)
cons
> =a()
function: 0x604910 24
> =a 'car'
24
> =a(nil)
list
> =a("car", "cdr")
24 function: 0x604910