monotonically accumulate versions of definitions
One old drawback now has a new look. Before, we loaded definitions in order, so global definitions had to exist before other global definitions that used them. See window and grid in life.tlv. Now we load definitions in reverse order, so initialization needs to change. Worse, if we update window, we need to edit grid just to fix the order. This implies that we can't yet optimize away bindings where there are no new changes.
This commit is contained in:
parent
b40ad26544
commit
5a63a5ca40
37
chesstv.tlv
37
chesstv.tlv
|
@ -1,10 +1,16 @@
|
|||
teliva_program = {
|
||||
{
|
||||
window = [==[
|
||||
window = curses.stdscr()
|
||||
-- animation-based app
|
||||
window:nodelay(true)
|
||||
lines, cols = window:getmaxyx()]==],
|
||||
current_game = [==[current_game = {}]==],
|
||||
},
|
||||
{
|
||||
current_game = [==[
|
||||
current_game = {}]==],
|
||||
},
|
||||
{
|
||||
piece_glyph = [==[
|
||||
piece_glyph = {
|
||||
-- for legibility, white pieces also use unicode glyphs for black pieces
|
||||
|
@ -22,6 +28,8 @@ piece_glyph = {
|
|||
n = 0x265e,
|
||||
p = 0x265f,
|
||||
}]==],
|
||||
},
|
||||
{
|
||||
top_player = [==[
|
||||
function top_player(current_game)
|
||||
if current_game.players[1].color == "black" then
|
||||
|
@ -29,6 +37,8 @@ function top_player(current_game)
|
|||
end
|
||||
return current_game.players[2]
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
bottom_player = [==[
|
||||
function bottom_player(current_game)
|
||||
if current_game.players[1].color == "white" then
|
||||
|
@ -36,12 +46,16 @@ function bottom_player(current_game)
|
|||
end
|
||||
return current_game.players[2]
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
render_player = [==[
|
||||
function render_player(y, x, player)
|
||||
curses.mvaddstr(y, x, player.user.name)
|
||||
curses.addstr(" · ")
|
||||
curses.addstr(tostring(player.rating))
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
render_square = [==[
|
||||
function render_square(current_game, rank, file, highlighted_squares)
|
||||
-- decide whether to highlight
|
||||
|
@ -62,6 +76,8 @@ function render_square(current_game, rank, file, highlighted_squares)
|
|||
curses.mvaddstr((8 - rank + 1)*3+2, file*5, " ")
|
||||
curses.attrset(curses.A_NORMAL)
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
render_fen_rank = [==[
|
||||
function render_fen_rank(rank, fen_rank, highlighted_squares)
|
||||
local file = 1
|
||||
|
@ -98,12 +114,16 @@ function render_fen_rank(rank, fen_rank, highlighted_squares)
|
|||
end
|
||||
end
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
render_time = [==[
|
||||
function render_time(y, x, seconds)
|
||||
if seconds == nil then return end
|
||||
curses.mvaddstr(y, x, tostring(math.floor(seconds/60)))
|
||||
curses.addstr(string.format(":%02d", seconds%60))
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
render_board = [==[
|
||||
function render_board(current_game)
|
||||
--? curses.mvaddstr(1, 50, dump(current_game.fen))
|
||||
|
@ -119,6 +139,8 @@ function render_board(current_game)
|
|||
render_player(27, 5, bottom_player(current_game))
|
||||
render_time(27, 35, current_game.wc)
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
parse_lm = [==[
|
||||
function parse_lm(move)
|
||||
--? curses.mvaddstr(4, 50, move)
|
||||
|
@ -129,6 +151,8 @@ function parse_lm(move)
|
|||
--? curses.mvaddstr(5, 50, dump({{rank1, file1}, {rank2, file2}}))
|
||||
return {from={rank=rank1, file=file1}, to={rank=rank2, file=file2}}
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
render = [==[
|
||||
function render(chunk)
|
||||
local o = json.decode(chunk)
|
||||
|
@ -149,6 +173,8 @@ function render(chunk)
|
|||
render_board(current_game)
|
||||
curses.refresh()
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
init_colors = [==[
|
||||
function init_colors()
|
||||
-- colors
|
||||
|
@ -168,6 +194,8 @@ function init_colors()
|
|||
curses.init_pair(7, light_piece, dark_last_moved_square)
|
||||
curses.init_pair(8, dark_piece, dark_last_moved_square)
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
main = [==[
|
||||
function main()
|
||||
init_colors()
|
||||
|
@ -184,6 +212,8 @@ function main()
|
|||
}
|
||||
http.request(request)
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
utf8 = [==[
|
||||
-- https://stackoverflow.com/questions/7983574/how-to-write-a-unicode-symbol-in-lua
|
||||
function utf8(decimal)
|
||||
|
@ -203,6 +233,8 @@ function utf8(decimal)
|
|||
end
|
||||
return table.concat(charbytes)
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
split = [==[
|
||||
function split(s, pat)
|
||||
result = {}
|
||||
|
@ -211,6 +243,8 @@ function split(s, pat)
|
|||
end
|
||||
return result
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
dump = [==[
|
||||
-- https://stackoverflow.com/questions/9168058/how-to-dump-a-table-to-console
|
||||
function dump(o)
|
||||
|
@ -225,4 +259,5 @@ function dump(o)
|
|||
return tostring(o)
|
||||
end
|
||||
end]==],
|
||||
},
|
||||
}
|
||||
|
|
27
counter.tlv
27
counter.tlv
|
@ -1,7 +1,14 @@
|
|||
teliva_program = {
|
||||
window = [==[window = curses.stdscr()]==],
|
||||
n = [==[n = 0]==],
|
||||
render = [==[
|
||||
{
|
||||
window = [==[
|
||||
window = curses.stdscr()]==],
|
||||
},
|
||||
{
|
||||
n = [==[
|
||||
n = 0]==],
|
||||
},
|
||||
{
|
||||
render = [==[
|
||||
function render(window)
|
||||
window:clear()
|
||||
window:attron(curses.A_BOLD)
|
||||
|
@ -12,15 +19,22 @@ function render(window)
|
|||
window:attroff(curses.A_BOLD)
|
||||
curses.refresh()
|
||||
end]==],
|
||||
menu = [==[menu = {Enter="increment"}]==],
|
||||
update = [==[
|
||||
},
|
||||
{
|
||||
menu = [==[
|
||||
menu = {Enter="increment"}]==],
|
||||
},
|
||||
{
|
||||
update = [==[
|
||||
function update(window)
|
||||
local key = curses.getch()
|
||||
if key == 10 then
|
||||
n = n+1
|
||||
end
|
||||
end]==],
|
||||
main = [==[
|
||||
},
|
||||
{
|
||||
main = [==[
|
||||
function main()
|
||||
for i=1,7 do
|
||||
curses.init_pair(i, 0, i)
|
||||
|
@ -31,4 +45,5 @@ function main()
|
|||
update(window)
|
||||
end
|
||||
end]==],
|
||||
},
|
||||
}
|
||||
|
|
30
hanoi.tlv
30
hanoi.tlv
|
@ -1,4 +1,5 @@
|
|||
teliva_program = {
|
||||
{
|
||||
render = [==[
|
||||
function render(window)
|
||||
window:clear()
|
||||
|
@ -10,16 +11,25 @@ function render(window)
|
|||
end
|
||||
curses.refresh()
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
lines = [==[
|
||||
function lines(window)
|
||||
local lines, cols = window:getmaxyx()
|
||||
return lines
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
pop = [==[
|
||||
function pop(array)
|
||||
return table.remove(array)
|
||||
end]==],
|
||||
window = [==[window = curses.stdscr()]==],
|
||||
},
|
||||
{
|
||||
window = [==[
|
||||
window = curses.stdscr()]==],
|
||||
},
|
||||
{
|
||||
render_tower = [==[
|
||||
function render_tower(window, line, col, tower_index, tower)
|
||||
window:attron(curses.A_BOLD)
|
||||
|
@ -39,7 +49,12 @@ function render_tower(window, line, col, tower_index, tower)
|
|||
line = line - 1
|
||||
end
|
||||
end]==],
|
||||
tower = [==[tower = {{6, 5, 4, 3, 2}, {}, {}}]==],
|
||||
},
|
||||
{
|
||||
tower = [==[
|
||||
tower = {{6, 5, 4, 3, 2}, {}, {}}]==],
|
||||
},
|
||||
{
|
||||
render_disk = [==[
|
||||
function render_disk(window, line, col, size)
|
||||
col = col-size+1
|
||||
|
@ -50,6 +65,8 @@ function render_disk(window, line, col, size)
|
|||
col = col+2
|
||||
end
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
main = [==[
|
||||
function main()
|
||||
for i=1,7 do
|
||||
|
@ -62,6 +79,8 @@ function main()
|
|||
end
|
||||
end
|
||||
]==],
|
||||
},
|
||||
{
|
||||
len = [==[
|
||||
function len(array)
|
||||
local result = 0
|
||||
|
@ -70,6 +89,8 @@ function len(array)
|
|||
end
|
||||
return result
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
update = [==[
|
||||
function update(window)
|
||||
window:mvaddstr(lines(window)-2, 5, "tower to remove top disk from? ")
|
||||
|
@ -78,14 +99,19 @@ function update(window)
|
|||
local to = curses.getch() - 96
|
||||
make_move(from, to)
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
make_move = [==[
|
||||
function make_move(from, to)
|
||||
local disk = pop(tower[from])
|
||||
table.insert(tower[to], disk)
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
cols = [==[
|
||||
function cols(window)
|
||||
local lines, cols = window:getmaxyx()
|
||||
return cols
|
||||
end]==],
|
||||
},
|
||||
}
|
||||
|
|
42
life.tlv
42
life.tlv
|
@ -1,9 +1,5 @@
|
|||
teliva_program = {
|
||||
window = [==[
|
||||
window = curses.stdscr()
|
||||
-- animation-based app
|
||||
window:nodelay(true)
|
||||
lines, cols = window:getmaxyx()]==],
|
||||
{
|
||||
grid = [==[
|
||||
-- main data structure
|
||||
grid = {}
|
||||
|
@ -14,6 +10,15 @@ for i=1,lines*4 do
|
|||
end
|
||||
end
|
||||
]==],
|
||||
},
|
||||
{
|
||||
window = [==[
|
||||
window = curses.stdscr()
|
||||
-- animation-based app
|
||||
window:nodelay(true)
|
||||
lines, cols = window:getmaxyx()]==],
|
||||
},
|
||||
{
|
||||
grid_char = [==[
|
||||
-- grab a 4x2 chunk of grid
|
||||
function grid_char(line, col)
|
||||
|
@ -23,6 +28,8 @@ function grid_char(line, col)
|
|||
end
|
||||
return result
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
print_grid_char = [==[
|
||||
function print_grid_char(window, x)
|
||||
result = {}
|
||||
|
@ -33,6 +40,8 @@ function print_grid_char(window, x)
|
|||
end
|
||||
return result
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
glyph = [==[
|
||||
-- look up the braille pattern corresponding to a 4x2 chunk of grid
|
||||
-- https://en.wikipedia.org/wiki/Braille_Patterns
|
||||
|
@ -56,6 +65,8 @@ glyph = {
|
|||
0x28b0, 0x28b1, 0x28b2, 0x28b3, 0x28b4, 0x28b5, 0x28b6, 0x28b7, 0x28f0, 0x28f1, 0x28f2, 0x28f3, 0x28f4, 0x28f5, 0x28f6, 0x28f7,
|
||||
0x28b8, 0x28b9, 0x28ba, 0x28bb, 0x28bc, 0x28bd, 0x28be, 0x28bf, 0x28f8, 0x28f9, 0x28fa, 0x28fb, 0x28fc, 0x28fd, 0x28fe, 0x28ff,
|
||||
}]==],
|
||||
},
|
||||
{
|
||||
utf8 = [==[
|
||||
-- https://stackoverflow.com/questions/7983574/how-to-write-a-unicode-symbol-in-lua
|
||||
function utf8(decimal)
|
||||
|
@ -75,6 +86,8 @@ function utf8(decimal)
|
|||
end
|
||||
return table.concat(charbytes)
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
grid_char_to_glyph_index = [==[
|
||||
-- convert a chunk of grid into a number
|
||||
function grid_char_to_glyph_index(g)
|
||||
|
@ -82,6 +95,8 @@ function grid_char_to_glyph_index(g)
|
|||
g[1][2]*16 + g[2][2]*32 + g[3][2]*64 + g[4][2]*128 +
|
||||
1 -- 1-indexing
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
render = [==[
|
||||
function render(window)
|
||||
window:clear()
|
||||
|
@ -93,6 +108,8 @@ function render(window)
|
|||
curses.refresh()
|
||||
end
|
||||
]==],
|
||||
},
|
||||
{
|
||||
state = [==[
|
||||
function state(line, col)
|
||||
if line < 1 or line > table.getn(grid) or col < 1 or col > table.getn(grid[1]) then
|
||||
|
@ -100,12 +117,16 @@ function state(line, col)
|
|||
end
|
||||
return grid[line][col]
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
num_live_neighbors = [==[
|
||||
function num_live_neighbors(line, col)
|
||||
return state(line-1, col-1) + state(line-1, col) + state(line-1, col+1) +
|
||||
state(line, col-1) + state(line, col+1) +
|
||||
state(line+1, col-1) + state(line+1, col) + state(line+1, col+1)
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
step = [==[
|
||||
function step()
|
||||
local new_grid = {}
|
||||
|
@ -124,12 +145,16 @@ function step()
|
|||
end
|
||||
grid = new_grid
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
sleep = [==[
|
||||
function sleep(a)
|
||||
local sec = tonumber(os.clock() + a);
|
||||
while (os.clock() < sec) do
|
||||
end
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
file_exists = [==[
|
||||
function file_exists(filename)
|
||||
local f = io.open(filename, "r")
|
||||
|
@ -140,6 +165,8 @@ function file_exists(filename)
|
|||
return false
|
||||
end
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
load_file = [==[
|
||||
function load_file(window, filename)
|
||||
io.input(filename)
|
||||
|
@ -160,6 +187,8 @@ function load_file(window, filename)
|
|||
end
|
||||
end
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
update = [==[
|
||||
menu = {arrow="pan"}
|
||||
|
||||
|
@ -198,6 +227,8 @@ function update(window, c)
|
|||
end
|
||||
end
|
||||
end]==],
|
||||
},
|
||||
{
|
||||
main = [==[
|
||||
function main()
|
||||
for i=1,7 do
|
||||
|
@ -274,4 +305,5 @@ function main()
|
|||
step()
|
||||
end
|
||||
end]==],
|
||||
},
|
||||
}
|
||||
|
|
212
src/lua.c
212
src/lua.c
|
@ -280,27 +280,64 @@ void stack_dump (lua_State *L) {
|
|||
}
|
||||
|
||||
|
||||
static int binding_exists (lua_State *L, const char *name) {
|
||||
int result = 0;
|
||||
lua_getglobal(L, name);
|
||||
result = !lua_isnil(L, -1);
|
||||
lua_pop(L, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static const char *look_up_definition (lua_State *L, const char *name) {
|
||||
lua_getglobal(L, "teliva_program");
|
||||
int history_array = lua_gettop(L);
|
||||
/* iterate over mutations in teliva_program history in reverse order */
|
||||
int history_array_size = luaL_getn(L, history_array);
|
||||
for (int i = history_array_size; i > 0; --i) {
|
||||
lua_rawgeti(L, history_array, i);
|
||||
int table = lua_gettop(L);
|
||||
/* iterate over bindings */
|
||||
/* really we expect only one */
|
||||
for (lua_pushnil(L); lua_next(L, table) != 0; lua_pop(L, 1)) {
|
||||
const char* key = lua_tostring(L, -2);
|
||||
if (strcmp(key, name) == 0)
|
||||
return lua_tostring(L, -1);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *Image_name = NULL;
|
||||
static int handle_image (lua_State *L, char **argv, int n) {
|
||||
int status;
|
||||
int narg = getargs(L, argv, n); /* collect arguments */
|
||||
lua_setglobal(L, "arg");
|
||||
/* parse and load file contents (teliva_program table) */
|
||||
/* parse and load file contents (teliva_program array) */
|
||||
Image_name = argv[n];
|
||||
status = luaL_loadfile(L, Image_name);
|
||||
lua_insert(L, -(narg+1));
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
if (status != 0) return status;
|
||||
status = docall(L, narg, 0);
|
||||
lua_getglobal(L, "teliva_program");
|
||||
int table = lua_gettop(L);
|
||||
/* parse and load each binding in teliva_program */
|
||||
for (lua_pushnil(L); lua_next(L, table) != 0; lua_pop(L, 1)) {
|
||||
const char* key = lua_tostring(L, -2);
|
||||
const char* value = lua_tostring(L, -1);
|
||||
status = dostring(L, value, key);
|
||||
if (status != 0) return report(L, status);
|
||||
int history_array = lua_gettop(L);
|
||||
/* iterate over mutations in teliva_program history in reverse order */
|
||||
int history_array_size = luaL_getn(L, history_array);
|
||||
for (int i = history_array_size; i > 0; --i) {
|
||||
lua_rawgeti(L, history_array, i);
|
||||
int table = lua_gettop(L);
|
||||
/* iterate over bindings */
|
||||
/* really we expect only one */
|
||||
for (lua_pushnil(L); lua_next(L, table) != 0; lua_pop(L, 1)) {
|
||||
const char* key = lua_tostring(L, -2);
|
||||
if (binding_exists(L, key))
|
||||
continue; // most recent binding trumps older ones
|
||||
const char* value = lua_tostring(L, -1);
|
||||
status = dostring(L, value, key);
|
||||
if (status != 0) return report(L, status);
|
||||
}
|
||||
}
|
||||
/* call main() */
|
||||
lua_getglobal(L, "main");
|
||||
|
@ -314,10 +351,7 @@ static int handle_image (lua_State *L, char **argv, int n) {
|
|||
char Current_definition[CURRENT_DEFINITION_LEN+1] = {0};
|
||||
void save_to_current_definition_and_editor_buffer (lua_State *L, const char *definition) {
|
||||
strncpy(Current_definition, definition, CURRENT_DEFINITION_LEN);
|
||||
lua_getglobal(L, "teliva_program");
|
||||
lua_getfield(L, -1, Current_definition);
|
||||
const char *contents = lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
const char *contents = look_up_definition(L, Current_definition);
|
||||
FILE *out = fopen("teliva_editbuffer", "w");
|
||||
if (contents != NULL)
|
||||
fprintf(out, "%s", contents);
|
||||
|
@ -333,27 +367,42 @@ static void read_editor_buffer (char *out) {
|
|||
}
|
||||
|
||||
|
||||
/* table to update is at top of stack */
|
||||
static void update_definition (lua_State *L, const char *name, char *out) {
|
||||
static void update_definition (lua_State *L, const char *name, char *new_contents) {
|
||||
assert(lua_gettop(L) == 0);
|
||||
lua_getglobal(L, "teliva_program");
|
||||
lua_pushstring(L, out);
|
||||
int history_array = 1;
|
||||
/* create a new table containing a single binding */
|
||||
lua_createtable(L, /*number of fields per mutation*/2, 0);
|
||||
lua_pushstring(L, new_contents);
|
||||
assert(strlen(name) > 0);
|
||||
lua_setfield(L, -2, name);
|
||||
/* append the new table to the history of mutations */
|
||||
int history_array_size = luaL_getn(L, history_array);
|
||||
++history_array_size;
|
||||
lua_rawseti(L, history_array, history_array_size);
|
||||
lua_settop(L, 0);
|
||||
}
|
||||
|
||||
|
||||
static void save_image (lua_State *L) {
|
||||
lua_getglobal(L, "teliva_program");
|
||||
int table = lua_gettop(L);
|
||||
FILE *out = fopen(Image_name, "w");
|
||||
int history_array = lua_gettop(L);
|
||||
int history_array_size = luaL_getn(L, history_array);
|
||||
FILE* out = fopen(Image_name, "w");
|
||||
fprintf(out, "teliva_program = {\n");
|
||||
for (lua_pushnil(L); lua_next(L, table) != 0; lua_pop(L, 1)) {
|
||||
const char *key = lua_tostring(L, -2);
|
||||
const char *value = lua_tostring(L, -1);
|
||||
fprintf(out, " %s = [==[", key);
|
||||
fprintf(out, "%s", value);
|
||||
fprintf(out, "]==],\n");
|
||||
for (int i = 1; i <= history_array_size; ++i) {
|
||||
lua_rawgeti(L, history_array, i);
|
||||
int table = lua_gettop(L);
|
||||
fprintf(out, " {\n");
|
||||
for (lua_pushnil(L); lua_next(L, table) != 0; lua_pop(L, 1)) {
|
||||
const char* key = lua_tostring(L, -2);
|
||||
const char* value = lua_tostring(L, -1);
|
||||
fprintf(out, " %s = [==[\n", key);
|
||||
fprintf(out, "%s", value);
|
||||
fprintf(out, "]==],\n");
|
||||
}
|
||||
fprintf(out, " },\n");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
fprintf(out, "}\n");
|
||||
fclose(out);
|
||||
|
@ -434,46 +483,55 @@ int browse_image (lua_State *L) {
|
|||
clear();
|
||||
luaL_newmetatable(L, "__teliva_call_graph_depth");
|
||||
int cgt = lua_gettop(L);
|
||||
// special-case: we don't instrument the call to main, but it's always 1
|
||||
// special-case: we don't instrument the call to main, but it's always at depth 1
|
||||
lua_pushinteger(L, 1);
|
||||
lua_setfield(L, cgt, "main");
|
||||
// segment definitions by depth
|
||||
lua_getglobal(L, "teliva_program");
|
||||
int t = lua_gettop(L);
|
||||
int history_array = lua_gettop(L);
|
||||
int history_array_size = luaL_getn(L, history_array);
|
||||
|
||||
int y = 2;
|
||||
mvaddstr(y, 0, "data: ");
|
||||
// first: data (non-functions) that's not the Teliva menu or curses variables
|
||||
for (lua_pushnil(L); lua_next(L, t) != 0;) {
|
||||
const char *definition_name = lua_tostring(L, -2);
|
||||
lua_getglobal(L, definition_name);
|
||||
int is_userdata = lua_isuserdata(L, -1);
|
||||
int is_function = lua_isfunction(L, -1);
|
||||
lua_pop(L, 1);
|
||||
if (strcmp(definition_name, "menu") != 0 // required by all Teliva programs
|
||||
&& !is_function // functions are not data
|
||||
&& !is_userdata // including curses window objects
|
||||
// (unlikely to have an interesting definition)
|
||||
) {
|
||||
browse_definition(definition_name);
|
||||
for (int i = history_array_size; i > 0; --i) {
|
||||
lua_rawgeti(L, history_array, i);
|
||||
int t = lua_gettop(L);
|
||||
for (lua_pushnil(L); lua_next(L, t) != 0;) {
|
||||
const char *definition_name = lua_tostring(L, -2);
|
||||
lua_getglobal(L, definition_name);
|
||||
int is_userdata = lua_isuserdata(L, -1);
|
||||
int is_function = lua_isfunction(L, -1);
|
||||
lua_pop(L, 1);
|
||||
if (strcmp(definition_name, "menu") != 0 // required by all Teliva programs
|
||||
&& !is_function // functions are not data
|
||||
&& !is_userdata // including curses window objects
|
||||
// (unlikely to have an interesting definition)
|
||||
) {
|
||||
browse_definition(definition_name);
|
||||
}
|
||||
lua_pop(L, 1); // value
|
||||
// leave key on stack for next iteration
|
||||
}
|
||||
lua_pop(L, 1); // value
|
||||
// leave key on stack for next iteration
|
||||
}
|
||||
|
||||
// second: menu and other userdata
|
||||
for (lua_pushnil(L); lua_next(L, t) != 0;) {
|
||||
const char* definition_name = lua_tostring(L, -2);
|
||||
lua_getglobal(L, definition_name);
|
||||
int is_userdata = lua_isuserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
if (strcmp(definition_name, "menu") == 0
|
||||
|| is_userdata // including curses window objects
|
||||
) {
|
||||
browse_definition(definition_name);
|
||||
for (int i = history_array_size; i > 0; --i) {
|
||||
lua_rawgeti(L, history_array, i);
|
||||
int t = lua_gettop(L);
|
||||
for (lua_pushnil(L); lua_next(L, t) != 0;) {
|
||||
const char* definition_name = lua_tostring(L, -2);
|
||||
lua_getglobal(L, definition_name);
|
||||
int is_userdata = lua_isuserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
if (strcmp(definition_name, "menu") == 0
|
||||
|| is_userdata // including curses window objects
|
||||
) {
|
||||
browse_definition(definition_name);
|
||||
}
|
||||
lua_pop(L, 1); // value
|
||||
// leave key on stack for next iteration
|
||||
}
|
||||
lua_pop(L, 1); // value
|
||||
// leave key on stack for next iteration
|
||||
}
|
||||
|
||||
// functions by level
|
||||
|
@ -482,32 +540,40 @@ int browse_image (lua_State *L) {
|
|||
y++;
|
||||
for (int level = 1; level < 5; ++level) {
|
||||
mvaddstr(y, 0, " ");
|
||||
for (lua_pushnil(L); lua_next(L, t) != 0;) {
|
||||
const char* definition_name = lua_tostring(L, -2);
|
||||
lua_getfield(L, cgt, definition_name);
|
||||
int depth = lua_tointeger(L, -1);
|
||||
if (depth == level)
|
||||
browse_definition(definition_name);
|
||||
lua_pop(L, 1); // depth of value
|
||||
lua_pop(L, 1); // value
|
||||
// leave key on stack for next iteration
|
||||
for (int i = history_array_size; i > 0; --i) {
|
||||
lua_rawgeti(L, history_array, i);
|
||||
int t = lua_gettop(L);
|
||||
for (lua_pushnil(L); lua_next(L, t) != 0;) {
|
||||
const char* definition_name = lua_tostring(L, -2);
|
||||
lua_getfield(L, cgt, definition_name);
|
||||
int depth = lua_tointeger(L, -1);
|
||||
if (depth == level)
|
||||
browse_definition(definition_name);
|
||||
lua_pop(L, 1); // depth of value
|
||||
lua_pop(L, 1); // value
|
||||
// leave key on stack for next iteration
|
||||
}
|
||||
}
|
||||
y += 2;
|
||||
}
|
||||
|
||||
// unused functions
|
||||
mvaddstr(y, 0, " ");
|
||||
for (lua_pushnil(L); lua_next(L, t) != 0;) {
|
||||
const char* definition_name = lua_tostring(L, -2);
|
||||
lua_getglobal(L, definition_name);
|
||||
int is_function = lua_isfunction(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, cgt, definition_name);
|
||||
if (is_function && lua_isnoneornil(L, -1))
|
||||
browse_definition(definition_name);
|
||||
lua_pop(L, 1); // depth of value
|
||||
lua_pop(L, 1); // value
|
||||
// leave key on stack for next iteration
|
||||
for (int i = history_array_size; i > 0; --i) {
|
||||
lua_rawgeti(L, history_array, i);
|
||||
int t = lua_gettop(L);
|
||||
for (lua_pushnil(L); lua_next(L, t) != 0;) {
|
||||
const char* definition_name = lua_tostring(L, -2);
|
||||
lua_getglobal(L, definition_name);
|
||||
int is_function = lua_isfunction(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, cgt, definition_name);
|
||||
if (is_function && lua_isnoneornil(L, -1))
|
||||
browse_definition(definition_name);
|
||||
lua_pop(L, 1); // depth of value
|
||||
lua_pop(L, 1); // value
|
||||
// leave key on stack for next iteration
|
||||
}
|
||||
}
|
||||
|
||||
lua_settop(L, 0);
|
||||
|
|
Loading…
Reference in New Issue