seqlua

view seqlualib.c @ 15:a95fbd16473f

Removed unnecessary creation of closures for callable values (through __call)
author jbe
date Wed Aug 20 06:33:18 2014 +0200 (2014-08-20)
parents 144f0bddee2b
children 12a7a8f5a77d
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 iter->idx = idx;
13 if (lua_type(L, idx) == LUA_TFUNCTION) {
14 iter->itertype = SEQLUA_ITERTYPE_FUNC;
15 } else if (luaL_getmetafield(L, idx, "__call")) {
16 lua_pop(L, 1);
17 iter->itertype = SEQLUA_ITERTYPE_FUNC;
18 } else if (luaL_getmetafield(L, idx, "__index")) {
19 lua_pop(L, 1);
20 iter->itertype = SEQLUA_ITERTYPE_META;
21 } else {
22 luaL_checktype(L, idx, LUA_TTABLE);
23 iter->itertype = SEQLUA_ITERTYPE_RAW;
24 }
25 iter->i = 0;
26 }
28 int seqlua_iternext(seqlua_Iterator *iter) {
29 lua_State *L = iter->L;
30 lua_Integer i = ++iter->i;
31 switch (iter->itertype) {
32 case SEQLUA_ITERTYPE_FUNC:
33 lua_pushvalue(L, iter->idx);
34 lua_call(L, 0, 1);
35 break;
36 case SEQLUA_ITERTYPE_META:
37 lua_pushinteger(L, i);
38 lua_gettable(L, iter->idx);
39 break;
40 case SEQLUA_ITERTYPE_RAW:
41 lua_rawgeti(L, iter->idx, i);
42 break;
43 }
44 if (lua_isnil(L, -1)) {
45 lua_pop(L, 1);
46 return 0;
47 }
48 return 1;
49 }
51 static int seqlua_iterclosureaux_raw(lua_State *L) {
52 lua_Integer i = lua_tointeger(L, lua_upvalueindex(2)) + 1;
53 lua_rawgeti(L, lua_upvalueindex(1), i);
54 if (lua_isnil(L, -1)) return 1;
55 lua_pushinteger(L, i);
56 lua_replace(L, lua_upvalueindex(2));
57 return 1;
58 }
60 static int seqlua_iterclosureaux_meta(lua_State *L) {
61 lua_Integer i = lua_tointeger(L, lua_upvalueindex(2)) + 1;
62 lua_pushinteger(L, i);
63 lua_gettable(L, lua_upvalueindex(1));
64 if (lua_isnil(L, -1)) return 1;
65 lua_pushinteger(L, i);
66 lua_replace(L, lua_upvalueindex(2));
67 return 1;
68 }
70 void seqlua_iterclosure(lua_State *L, int idx) {
71 luaL_checkany(L, idx); // provides better error message
72 if (lua_type(L, idx) == LUA_TFUNCTION) {
73 // do nothing
74 } else if (luaL_getmetafield(L, idx, "__call")) {
75 lua_pop(L, 1);
76 } else if (luaL_getmetafield(L, idx, "__index")) {
77 lua_pop(L, 1);
78 lua_pushvalue(L, idx);
79 lua_pushinteger(L, 0);
80 lua_pushcclosure(L, seqlua_iterclosureaux_raw, 2);
81 lua_replace(L, idx);
82 } else {
83 luaL_checktype(L, idx, LUA_TTABLE);
84 lua_pushvalue(L, idx);
85 lua_pushinteger(L, 0);
86 lua_pushcclosure(L, seqlua_iterclosureaux_meta, 2);
87 lua_replace(L, idx);
88 }
89 }

Impressum / About Us