diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2010-12-29 16:26:25 +0100 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2010-12-29 16:26:25 +0100 |
commit | d3148268857e01116d5d3c99ac0a43bc6a54b13c (patch) | |
tree | 6ae273025ef73942c0ac748e715a7f281a6af114 /src/unary.c | |
download | lspipat-master.tar.gz |
Diffstat (limited to 'src/unary.c')
-rw-r--r-- | src/unary.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/src/unary.c b/src/unary.c new file mode 100644 index 0000000..b3f40ef --- /dev/null +++ b/src/unary.c @@ -0,0 +1,182 @@ +/* + * LSPIPAT - LUA SPIPAT WRAPPER + * Copyright (C) 2010, Robin Haberkorn + * License: LGPL + * + * CORE: UNARY OPERATORS (ALSO USED AS PRIMITIVES) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdbool.h> +#include <string.h> + +#include "lspipat.h" + +static void +setcurFncHandler(unsigned pos, void *global __attribute__((unused)), void *local) +{ + struct simplefncRefs *simplefnc = local; + lua_State *L = simplefnc->cb.L; + + lua_rawgeti(L, LUA_REGISTRYINDEX, simplefnc->cb.function); + lua_pushinteger(L, pos); + lua_rawgeti(L, LUA_REGISTRYINDEX, simplefnc->cb.cookie); +#if 0 + lua_rawgeti(L, LUA_REGISTRYINDEX, *(int *)global); +#endif + + lua_call(L, 2, 0); +} + + /* + * if called as an operator, there will be a nil on top of the stack + */ +LUA_SIG(l_setcur) +{ + int top = lua_gettop(L); + + PATTERN_WRAPPER *new; + struct simplefncRefs *simplefnc; + + luaL_argcheck(L, top == 1 || top == 2, top, L_NUMBER); + luaL_argcheck(L, lua_isfunction(L, 1), 1, L_TYPE); + + if (!(new = lua_newuserdata(L, sizeof(PATTERN_WRAPPER)))) + L_ERROR(L_ALLOC); + memset(new, 0, sizeof(PATTERN_WRAPPER)); + + lua_insert(L, 1); /* move wrapper to bottom */ + if (top == 1) + lua_pushnil(L); /* cookie will be LUA_REFNIL */ + + new->type = PATTERN_SIMPLEFNC; + + simplefnc = &new->u.simplefnc; + simplefnc->cb.L = L; + simplefnc->cb.cookie = luaL_ref(L, LUA_REGISTRYINDEX); + simplefnc->cb.function = luaL_ref(L, LUA_REGISTRYINDEX); + /* wrapper at top again */ + + new->pattern = spipat_setcur_fnc(setcurFncHandler, simplefnc); + if (!new->pattern) + L_ERROR(L_ALLOC); + + luaL_getmetatable(L, PATTERN_MT); + lua_setmetatable(L, -2); + + return 1; +} + +static void +predFncHandler(void *global __attribute__((unused)), void *local, struct dynamic *ret) +{ + struct retfncRefs *retfnc = local; + lua_State *L = retfnc->cb.L; + + lua_rawgeti(L, LUA_REGISTRYINDEX, retfnc->cb.function); + lua_rawgeti(L, LUA_REGISTRYINDEX, retfnc->cb.cookie); +#if 0 + lua_rawgeti(L, LUA_REGISTRYINDEX, *(int *)global); +#endif + + lua_call(L, 1, 1); + + switch (lua_type(L, -1)) { + case LUA_TNUMBER: + case LUA_TSTRING: { + VString *str = &ret->val.str; + + ret->type = DY_VSTR; + + str->ptr = lua_tolstring(L, -1, (size_t *)&str->len); + str->release = retfncUnrefRet; + str->cookie = retfnc; + + /* + * Register value so Lua doesn't free it until spipat + * doesn't need it anymore (value has to be popped now) + */ + retfnc->ret = luaL_ref(L, LUA_REGISTRYINDEX); + return; + } + case LUA_TNIL: /* default behaviour: continue matching (Succeed) */ + ret->type = DY_BOOL; + + ret->val.pred = true; + + lua_pop(L, 1); + return; + + case LUA_TBOOLEAN: + ret->type = DY_BOOL; + + ret->val.pred = lua_toboolean(L, -1); + + lua_pop(L, 1); + return; + + case LUA_TUSERDATA: { /* FIXME: check whether it's really a Pattern */ + PATTERN_WRAPPER *wrapper = lua_touserdata(L, -1); + if (!wrapper->pattern) { + lua_pop(L, 1); + L_ERROR(L_RETURN); + } + + ret->type = DY_PAT; + + ret->val.pat.p = wrapper->pattern; + ret->val.pat.release = retfncUnrefRet; + ret->val.pat.cookie = retfnc; + + /* + * Register value so Lua doesn't free it until spipat + * doesn't need it anymore (value has to be popped now) + */ + retfnc->ret = luaL_ref(L, LUA_REGISTRYINDEX); + return; + } + default: + lua_pop(L, 1); + L_ERROR(L_RETURN); + } + + /* not reached */ +} + +LUA_SIG(l_pred) +{ + int top = lua_gettop(L); + + PATTERN_WRAPPER *new; + struct retfncRefs *retfnc; + + luaL_argcheck(L, top == 1 || top == 2, top, L_NUMBER); + luaL_argcheck(L, lua_isfunction(L, 1), 1, L_TYPE); + + if (!(new = lua_newuserdata(L, sizeof(PATTERN_WRAPPER)))) + L_ERROR(L_ALLOC); + memset(new, 0, sizeof(PATTERN_WRAPPER)); + + lua_insert(L, 1); /* move wrapper to bottom */ + if (top == 1) + lua_pushnil(L); /* cookie will be LUA_REFNIL */ + + new->type = PATTERN_RETFNC; + retfnc = &new->u.retfnc; + retfnc->cb.L = L; + retfnc->cb.cookie = luaL_ref(L, LUA_REGISTRYINDEX); + retfnc->cb.function = luaL_ref(L, LUA_REGISTRYINDEX); + /* wrapper at top again */ + + new->pattern = spipat_dynamic_fnc(predFncHandler, retfnc); + if (!new->pattern) + L_ERROR(L_ALLOC); + + luaL_getmetatable(L, PATTERN_MT); + lua_setmetatable(L, -2); + + return 1; +} |