seqlua

view seqlualib.c @ 12:91b0d0d4c4dd

Added coroutine example to README
author jbe
date Wed Aug 20 05:18:16 2014 +0200 (2014-08-20)
parents 144f0bddee2b
children a95fbd16473f
line source
1 #include <lua.h>
2 #include <lauxlib.h>
3 #include "seqlualib.h"
5 #define SEQLUA_ITERTYPE_CALL 1
6 #define SEQLUA_ITERTYPE_FUNC 2
7 #define SEQLUA_ITERTYPE_META 3
8 #define SEQLUA_ITERTYPE_RAW 4
10 void seqlua_iterinit(lua_State *L, seqlua_Iterator *iter, int idx) {
11 luaL_checkany(L, idx); // provides better error message
12 iter->L = L;
13 if (luaL_getmetafield(L, idx, "__call")) {
14 if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function");
15 iter->idx = lua_gettop(L);
16 iter->callargidx = idx;
17 iter->itertype = SEQLUA_ITERTYPE_CALL;
18 } else if (lua_type(L, idx) == LUA_TFUNCTION) {
19 lua_pushnil(L); // dummy value
20 iter->idx = idx;
21 iter->itertype = SEQLUA_ITERTYPE_FUNC;
22 } else {
23 iter->idx = idx;
24 if (luaL_getmetafield(L, idx, "__index")) {
25 iter->itertype = SEQLUA_ITERTYPE_META;
26 // leave __index as dummy value
27 } else {
28 lua_pushnil(L); // dummy value
29 luaL_checktype(L, idx, LUA_TTABLE);
30 iter->itertype = SEQLUA_ITERTYPE_RAW;
31 }
32 }
33 iter->i = 0;
34 }
36 int seqlua_iternext(seqlua_Iterator *iter) {
37 lua_State *L = iter->L;
38 lua_Integer i = ++iter->i;
39 switch (iter->itertype) {
40 case SEQLUA_ITERTYPE_CALL:
41 lua_pushvalue(L, iter->idx);
42 lua_pushvalue(L, iter->callargidx);
43 lua_call(L, 1, 1);
44 break;
45 case SEQLUA_ITERTYPE_FUNC:
46 lua_pushvalue(L, iter->idx);
47 lua_call(L, 0, 1);
48 break;
49 case SEQLUA_ITERTYPE_META:
50 lua_pushinteger(L, i);
51 lua_gettable(L, iter->idx);
52 break;
53 case SEQLUA_ITERTYPE_RAW:
54 lua_rawgeti(L, iter->idx, i);
55 break;
56 }
57 if (lua_isnil(L, -1)) {
58 lua_pop(L, 2); // remove nil and dummy value
59 return 0;
60 }
61 return 1;
62 }
64 static int seqlua_iterclosureaux_raw(lua_State *L) {
65 lua_Integer i = lua_tointeger(L, lua_upvalueindex(2)) + 1;
66 lua_rawgeti(L, lua_upvalueindex(1), i);
67 if (lua_isnil(L, -1)) return 1;
68 lua_pushinteger(L, i);
69 lua_replace(L, lua_upvalueindex(2));
70 return 1;
71 }
73 static int seqlua_iterclosureaux_meta(lua_State *L) {
74 lua_Integer i = lua_tointeger(L, lua_upvalueindex(2)) + 1;
75 lua_pushinteger(L, i);
76 lua_gettable(L, lua_upvalueindex(1));
77 if (lua_isnil(L, -1)) return 1;
78 lua_pushinteger(L, i);
79 lua_replace(L, lua_upvalueindex(2));
80 return 1;
81 }
83 static int seqlua_iterclosureaux_call(lua_State *L) {
84 lua_pushvalue(L, lua_upvalueindex(1));
85 lua_pushvalue(L, lua_upvalueindex(2));
86 lua_call(L, 1, 1);
87 return 1;
88 }
90 void seqlua_iterclosure(lua_State *L, int idx) {
91 luaL_checkany(L, idx); // provides better error message
92 if (lua_type(L, idx) == LUA_TFUNCTION) {
93 // do nothing
94 } else if (luaL_getmetafield(L, idx, "__call")) {
95 if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function");
96 lua_pushvalue(L, idx);
97 lua_pushcclosure(L, seqlua_iterclosureaux_call, 2);
98 lua_replace(L, idx);
99 } else if (luaL_getmetafield(L, idx, "__index")) {
100 lua_pop(L, 1);
101 lua_pushvalue(L, idx);
102 lua_pushinteger(L, 0);
103 lua_pushcclosure(L, seqlua_iterclosureaux_raw, 2);
104 lua_replace(L, idx);
105 } else {
106 luaL_checktype(L, idx, LUA_TTABLE);
107 lua_pushvalue(L, idx);
108 lua_pushinteger(L, 0);
109 lua_pushcclosure(L, seqlua_iterclosureaux_meta, 2);
110 lua_replace(L, idx);
111 }
112 }

Impressum / About Us