seqlua

view seqlualib.c @ 6:7b05ca6ef925

Allow seqlua_iterinit to modify the value on stack instead of storing an extra element on stack
author jbe
date Wed Aug 20 01:52:35 2014 +0200 (2014-08-20)
parents 47f9b323d68c
children 2cb22d01fdd0
line source
1 #include <lua.h>
2 #include <lauxlib.h>
3 #include "seqlualib.h"
5 #define SEQLUA_ITERTYPE_FUNC 1
6 #define SEQLUA_ITERTYPE_META 2
7 #define SEQLUA_ITERTYPE_RAW 3
9 void seqlua_iterinit(lua_State *L, seqlua_Iterator *iter, int idx) {
10 luaL_checkany(L, idx); // provides better error message
11 iter->L = L;
12 if (luaL_getmetafield(L, idx, "__call")) {
13 if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function");
14 lua_replace(L, idx);
15 iter->itertype = SEQLUA_ITERTYPE_FUNC;
16 } else if (lua_type(L, idx) == LUA_TFUNCTION) {
17 iter->itertype = SEQLUA_ITERTYPE_FUNC;
18 } else {
19 if (luaL_getmetafield(L, idx, "__index")) {
20 lua_pop(L, 1);
21 iter->itertype = SEQLUA_ITERTYPE_META;
22 } else {
23 luaL_checktype(L, idx, LUA_TTABLE);
24 iter->itertype = SEQLUA_ITERTYPE_RAW;
25 }
26 }
27 iter->i = 0;
28 }
30 int seqlua_iternext(seqlua_Iterator *iter) {
31 lua_State *L = iter->L;
32 lua_Integer i = ++iter->i;
33 switch (iter->itertype) {
34 case SEQLUA_ITERTYPE_FUNC:
35 lua_pushvalue(L, -1);
36 lua_call(L, 0, 1);
37 break;
38 case SEQLUA_ITERTYPE_META:
39 lua_pushinteger(L, i);
40 lua_gettable(L, -2);
41 break;
42 case SEQLUA_ITERTYPE_RAW:
43 lua_rawgeti(L, -1, i);
44 }
45 if (lua_isnil(L, -1)) {
46 lua_pop(L, 1);
47 return 0;
48 }
49 return 1;
50 }
52 static int seqlua_iterclosureaux_raw(lua_State *L) {
53 lua_Integer i = lua_tointeger(L, lua_upvalueindex(2)) + 1;
54 lua_rawgeti(L, lua_upvalueindex(1), i);
55 if (lua_isnil(L, -1)) return 1;
56 lua_pushinteger(L, i);
57 lua_replace(L, lua_upvalueindex(2));
58 return 1;
59 }
61 static int seqlua_iterclosureaux_meta(lua_State *L) {
62 lua_Integer i = lua_tointeger(L, lua_upvalueindex(2)) + 1;
63 lua_pushinteger(L, i);
64 lua_gettable(L, lua_upvalueindex(1));
65 if (lua_isnil(L, -1)) return 1;
66 lua_pushinteger(L, i);
67 lua_replace(L, lua_upvalueindex(2));
68 return 1;
69 }
71 void seqlua_iterclosure(lua_State *L, int idx) {
72 if (lua_type(L, idx) == LUA_TFUNCTION) {
73 // do nothing
74 } else if (luaL_getmetafield(L, idx, "__call")) {
75 if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function");
76 lua_replace(L, idx);
77 } else if (luaL_getmetafield(L, idx, "__index")) {
78 lua_pop(L, 1);
79 lua_pushvalue(L, idx);
80 lua_pushinteger(L, 0);
81 lua_pushcclosure(L, seqlua_iterclosureaux_raw, 2);
82 lua_replace(L, idx);
83 } else {
84 luaL_checktype(L, idx, LUA_TTABLE);
85 lua_pushvalue(L, idx);
86 lua_pushinteger(L, 0);
87 lua_pushcclosure(L, seqlua_iterclosureaux_meta, 2);
88 lua_replace(L, idx);
89 }
90 }

Impressum / About Us