seqlua

annotate seqlualib.c @ 8:144f0bddee2b

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

Impressum / About Us