|
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 }; |