From 03a32dcc77b24f8f167b26c5905ea4844ed9c4b9 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Wed, 30 Apr 2014 16:31:44 -0700 Subject: [PATCH] feat(util): add macro for exposing the type list in Lua Signed-off-by: Leonardo de Moura --- src/util/list_lua.h | 50 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/util/list_lua.h b/src/util/list_lua.h index 001322fa1..3d1a02584 100644 --- a/src/util/list_lua.h +++ b/src/util/list_lua.h @@ -24,4 +24,54 @@ list table_to_list(lua_State * L, int idx, Proc const & to_value) { throw exception("invalid argument, lua table expected"); } } + +#define DEFINE_LUA_LIST(T, PushVal, ToVal) \ +typedef list list_ ## T; \ +DECL_UDATA(list_ ## T) \ +static int list_ ## T ## _cons(lua_State * L) { return push_list_ ## T(L, list(ToVal(L, 1), to_list_ ## T(L, 2))); } \ +static int list_ ## T ## _nil(lua_State * L) { return push_list_ ## T(L, list()); } \ +static int list_ ## T ## _mk(lua_State * L) { \ + int nargs = lua_gettop(L); \ + return (nargs == 0) ? list_ ## T ## _nil(L) : list_ ## T ## _cons(L); \ +} \ +static int list_ ## T ## _is_nil(lua_State * L) { return pushboolean(L, is_nil(to_list_ ## T(L, 1))); } \ +static int list_ ## T ## _car(lua_State * L) { \ + list & l = to_list_ ## T(L, 1); \ + if (is_nil(l)) throw exception("arg #1 must be a cons cell"); \ + return push_list_ ## T(L, car(l)); \ +} \ +static int list_ ## T ## _cdr(lua_State * L) { \ + list & l = to_list_ ## T(L, 1); \ + if (is_nil(l)) throw exception("arg #1 must be a cons cell"); \ + return push_list_ ## T(L, cdr(l)); \ +} \ +static int list_ ## T ## _eq(lua_State * L) { return pushboolean(L, to_list_ ## T(L, 1) == to_list_ ## T(L, 2)); } \ +static int list_ ## T ## _is_eqp(lua_State * L) { return pushboolean(L, is_eqp(to_list_ ## T(L, 1), to_list_ ## T(L, 2))); } \ +static const struct luaL_Reg list_ ## T ## _m[] = { \ + {"__gc", list_ ## T ## _gc}, \ + {"__eq", safe_function}, \ + {"is_nil", safe_function}, \ + {"empty", safe_function}, \ + {"car", safe_function}, \ + {"cdr", safe_function}, \ + {"head", safe_function}, \ + {"tail", safe_function}, \ + {"is_eqp", safe_function}, \ + {0, 0} \ +}; \ +list to_list_ ## T ## _ext(lua_State * L, int idx) { \ + if (is_list_ ## T(L, idx)) \ + return to_list_ ## T(L, idx); \ + else \ + return table_to_list(L, idx, ToVal); \ +} \ +static void open_list_ ## T(lua_State * L) { \ + luaL_newmetatable(L, list_ ## T ## _mt); \ + lua_pushvalue(L, -1); \ + lua_setfield(L, -2, "__index"); \ + setfuncs(L, list_ ## T ## _m, 0); \ + \ + set_global_function(L, "list_" #T); \ + set_global_function(L, "is_list_" #T); \ +} }