seqlua

annotate seqlua.c @ 14:03ed3361f332

Added TODO: avoid closure creation with seqlua_aux_call in seqlua.c
author jbe
date Wed Aug 20 06:08:03 2014 +0200 (2014-08-20)
parents 144f0bddee2b
children a95fbd16473f
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 }

Impressum / About Us