dump.lua

1
local statewalk = require("luatraverse");
2
local format = string.format;
3
local type = type;
4
local tostring = tostring;
5
local io, os = io, os;
6
 
7
local getsize;
8
do
9
	local ok, ret = pcall(require, "getsize");
10
	if ok then
11
		--luacheck: ignore 143/debug
12
		if type(ret) == "function" then
13
			getsize = ret;
14
		elseif debug.getsize then
15
			getsize = debug.getsize;
16
		end
17
	end
18
end
19
 
20
local function dump_state(f, config)
21
	if io.type(f) ~= "file" then
22
		local err;
23
		f, err = io.open(f, "w+");
24
		if not f then return false, err; end
25
	end
26
 
27
	local metadata = config and config.metadata;
28
	local start_time = os.time();
29
 
30
	f:write("# Lua state graph", "\n");
31
	f:write("# Generated by dump.lua v2.1", "\n");
32
	f:write("# at ", os.date("!%F %R UTC", start_time), "\n");
33
	if metadata then
34
		local keys = {};
35
		for k in pairs(metadata) do
36
			table.insert(keys, k);
37
		end
38
		table.sort(keys);
39
		if #keys > 0 then
40
			for _, k in ipairs(keys) do
41
				f:write("## ", k, ": ", metadata[k], "\n");
42
			end
43
		end
44
	end
45
 
46
	local seenobjects, id = {}, 0;
47
	local function edge(from, to, how, value)
48
		if from and (not seenobjects[from] or seenobjects[from] == true) then
49
			id = id + 1;
50
			seenobjects[from] = id;
51
			f:write("V:", id, ":", type(from), ":", (getsize and getsize(from)) or "?", "\n");
52
		end
53
		if not seenobjects[to] or seenobjects[to] == true then
54
			id = id + 1;
55
			seenobjects[to] = id;
56
			f:write("V:", id, ":", type(to), ":", (getsize and getsize(to)) or "?", "\n");
57
		end
58
		if seenobjects[from] == true or seenobjects[to] == true then
59
			return;
60
		end
61
		local value_rep = (value and format("%q", tostring(value))) or "?";
62
		f:write("E:", seenobjects[from] or "?", ":", seenobjects[to], ":", tostring(how or "?"), ":", value_rep, "\n");
63
	end
64
	local ignore = {f, dump_state, statewalk, seenobjects, edge};
65
	statewalk.traverse({edge=edge}, ignore, seenobjects);
66
	f:write("# Completed in ", tostring(os.time() - start_time), "s", "\n");
67
	f:close();
68
end
69
 
70
return {
71
	dump_state = dump_state;
72
};