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