seqlua

view seqlua.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 03ed3361f332
line source
1 #include <lua.h>
2 #include <lauxlib.h>
4 static int seqlua_aux_call(lua_State *L) {
5 lua_pushvalue(L, lua_upvalueindex(1));
6 lua_pushvalue(L, lua_upvalueindex(2));
7 lua_call(L, 1, 1);
8 return 1;
9 }
11 static int seqlua_ipairsaux_raw(lua_State *L) {
12 lua_Integer i;
13 luaL_checktype(L, 1, LUA_TTABLE);
14 i = luaL_checkinteger(L, 2) + 1;
15 lua_pushinteger(L, i);
16 lua_rawgeti(L, 1, i); // TODO: Lua 5.3 returns type
17 return lua_isnil(L, -1) ? 1 : 2;
18 }
20 static int seqlua_ipairsaux_meta(lua_State *L) {
21 lua_Integer i;
22 i = luaL_checkinteger(L, 2) + 1;
23 lua_pushinteger(L, i);
24 lua_pushinteger(L, i);
25 lua_gettable(L, 1); // TODO: Lua 5.3 returns type
26 return lua_isnil(L, -1) ? 1 : 2;
27 }
29 static int seqlua_ipairsaux_func(lua_State *L) {
30 luaL_checktype(L, 1, LUA_TFUNCTION);
31 lua_pushinteger(L, luaL_checkinteger(L, 2) + 1);
32 lua_insert(L, 1);
33 lua_settop(L, 2);
34 lua_call(L, 0, LUA_MULTRET);
35 if (lua_isnoneornil(L, 2)) {
36 lua_settop(L, 0);
37 lua_pushnil(L);
38 return 1;
39 } else {
40 return lua_gettop(L);
41 }
42 }
44 static int seqlua_ipairsaux_triplet(lua_State *L) {
45 lua_Integer i = lua_tointeger(L, lua_upvalueindex(4)) + 1;
46 lua_settop(L, 0);
47 lua_pushinteger(L, i);
48 lua_replace(L, lua_upvalueindex(4));
49 lua_pushinteger(L, i);
50 lua_pushvalue(L, lua_upvalueindex(1));
51 lua_pushvalue(L, lua_upvalueindex(2));
52 lua_pushvalue(L, lua_upvalueindex(3));
53 lua_call(L, 2, LUA_MULTRET);
54 if (lua_isnoneornil(L, 2)) {
55 lua_settop(L, 0);
56 lua_pushnil(L);
57 return 1;
58 } else {
59 lua_pushvalue(L, 2);
60 lua_replace(L, lua_upvalueindex(3));
61 return lua_gettop(L);
62 }
63 }
65 static int seqlua_ipairs(lua_State *L) {
66 luaL_checkany(L, 1); // provides better error message
67 if (lua_type(L, 1) == LUA_TFUNCTION) {
68 seqlua_ipairs_function:
69 if (!lua_isnoneornil(L, 2) || !lua_isnoneornil(L, 3)) {
70 lua_settop(L, 3);
71 lua_pushinteger(L, 0);
72 lua_pushcclosure(L, seqlua_ipairsaux_triplet, 4);
73 return 1;
74 }
75 lua_pushcfunction(L, seqlua_ipairsaux_func);
76 } else if (luaL_getmetafield(L, 1, "__call")) {
77 if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function");
78 lua_pushvalue(L, 1);
79 lua_pushcclosure(L, seqlua_aux_call, 2);
80 lua_replace(L, 1);
81 goto seqlua_ipairs_function;
82 } else if (luaL_getmetafield(L, 1, "__index")) {
83 lua_pushcfunction(L, seqlua_ipairsaux_meta);
84 } else {
85 luaL_checktype(L, 1, LUA_TTABLE);
86 lua_pushcfunction(L, seqlua_ipairsaux_raw);
87 }
88 lua_pushvalue(L, 1);
89 lua_pushinteger(L, 0);
90 return 3;
91 }
93 static int seqlua_iteratoraux_raw(lua_State *L) {
94 lua_Integer i = lua_tointeger(L, lua_upvalueindex(2)) + 1;
95 lua_rawgeti(L, lua_upvalueindex(1), i);
96 if (lua_isnil(L, -1)) return 1;
97 lua_pushinteger(L, i);
98 lua_replace(L, lua_upvalueindex(2));
99 return 1;
100 }
102 static int seqlua_iteratoraux_meta(lua_State *L) {
103 lua_Integer i = lua_tointeger(L, lua_upvalueindex(2)) + 1;
104 lua_pushinteger(L, i);
105 lua_gettable(L, lua_upvalueindex(1));
106 if (lua_isnil(L, -1)) return 1;
107 lua_pushinteger(L, i);
108 lua_replace(L, lua_upvalueindex(2));
109 return 1;
110 }
112 static int seqlua_iteratoraux_triplet(lua_State *L) {
113 lua_settop(L, 0);
114 lua_pushvalue(L, lua_upvalueindex(1));
115 lua_pushvalue(L, lua_upvalueindex(2));
116 lua_pushvalue(L, lua_upvalueindex(3));
117 lua_call(L, 2, LUA_MULTRET);
118 if (lua_isnoneornil(L, 1)) {
119 lua_settop(L, 1);
120 return 1;
121 }
122 lua_pushvalue(L, 1);
123 lua_replace(L, lua_upvalueindex(3));
124 return lua_gettop(L);
125 }
127 int seqlua_iterator(lua_State *L) {
128 luaL_checkany(L, 1); // provides better error message
129 lua_settop(L, 3);
130 if (lua_type(L, 1) == LUA_TFUNCTION) {
131 seqlua_iterator_function:
132 if (lua_isnil(L, 2) && lua_isnil(L, 3)) {
133 lua_settop(L, 1);
134 } else {
135 lua_pushcclosure(L, seqlua_iteratoraux_triplet, 3);
136 }
137 } else if (luaL_getmetafield(L, 1, "__call")) {
138 if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function");
139 lua_pushvalue(L, 1);
140 lua_pushcclosure(L, seqlua_aux_call, 2);
141 lua_replace(L, 1);
142 goto seqlua_iterator_function;
143 } else if (luaL_getmetafield(L, 1, "__index")) {
144 lua_pushvalue(L, 1);
145 lua_pushinteger(L, 0);
146 lua_pushcclosure(L, seqlua_iteratoraux_raw, 2);
147 } else {
148 luaL_checktype(L, 1, LUA_TTABLE);
149 lua_pushvalue(L, 1);
150 lua_pushinteger(L, 0);
151 lua_pushcclosure(L, seqlua_iteratoraux_meta, 2);
152 }
153 return 1;
154 }
156 int luaopen_seqlua(lua_State *L) {
157 lua_pushcfunction(L, seqlua_ipairs);
158 lua_setglobal(L, "ipairs");
159 lua_pushcfunction(L, seqlua_iterator);
160 lua_setglobal(L, "iterator");
161 return 1;
162 }

Impressum / About Us