[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Hmmm... A different question I presume?
- From: Peter Shook <pshook@...>
- Date: Sat, 09 Aug 2003 14:30:18 -0400
Ando Sonenblick wrote:
I have a table (obviously a metatable that implements simple inheritance):
{
__index = function(table, key)
return rawget(XMethods, key) or
rawget(YMethods, key) or
rawget(ZMethods, key) end
}
Now, is there a way (from C code) to traverse the table to extract out the
strings "XMethods", "YMethods" and "ZMethods" (without having to resort to
parsing the Lua source code)?
I'm hoping to implement an object inspector that will take and object and
digest it's metatable and display in a UI the contents of the "inherited"
tables, etc...
Hi Ando,
You could make your index event a C function with an upvalue that is a
list of tables to search. Then from C, you could retrieve the upvalue
and find the names of the list elements in the table of globals.
This should give you some ideas:
print'hello'
one = { a=1,b=2,c=3 }
two = { d=99 }
three = function(t,i) print('did not find',i) return false end
print('one', one)
print('two', two)
print('three', three)
x = setmetatable({}, {__index = search{ one, two, three } })
print(x.a, x.b, x.c, x.d, x.it)
function name(value)
for n,v in _G do
if value == v then return n end
end
end
for i,e in ipairs(searchlist(x)) do print(name(e), e) end
The output from this script is:
hello
one table: 0xa045d20
two table: 0xa0464a8
three function: 0xa045e78
did not find it
1 2 3 99 false
one table: 0xa045d20
two table: 0xa0464a8
three function: 0xa045e78
where the search and searchlist functions are written in C like so:
#include "lua.h"
#include "lauxlib.h"
static int searcher (lua_State *L) {
int i=1;
do {
lua_settop(L, 2);
lua_rawgeti(L, lua_upvalueindex(1), i++);
if (lua_isnil(L, -1)) return 0; /* end of search list */
if (lua_isfunction(L, -1)) {
lua_pushvalue(L, 1); /* table */
lua_pushvalue(L, 2); /* index */
lua_call(L, 2, 1);
} else if (lua_istable(L, -1) || lua_isuserdata(L, -1)) {
if (lua_rawequal(L, 1, -1)) continue; /* ignore recursive tables */
lua_pushvalue(L, 2); /* index */
lua_gettable(L, -2);
} else {
luaL_error(L, "search list item must be a function, table or
userdata");
}
} while (lua_isnil(L, -1));
return 1;
}
static int search (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1);
lua_pushcclosure(L, searcher, 1);
return 1;
}
static int searchlist (lua_State *L) {
if (!lua_getmetatable(L, 1)) return 0; /* no metatable */
lua_pushliteral(L, "__index");
lua_gettable(L, -2);
if (lua_isnil(L, -1)) return 0; /* no __index event */
if (!lua_iscfunction(L, -1)) return 0; /* not a searcher function */
if (!lua_getupvalue(L, -1, 1)) return 0; /* no upvalue */
if (!lua_istable(L, -1)) return 0; /* upvalue not a table */
return 1;
}
int search_register (lua_State *L) {
lua_register(L,"search", search);
lua_register(L,"searchlist", searchlist);
return 0;
}
- Peter