# HG changeset patch # User Matthew Wild # Date 1600867520 -3600 # Node ID 9bd292b35f2340536f499639bfedabac68ae64d2 # Parent e3e3cbe544ec69a8d99e0aa7c936d7cc51c0f053 Add dump.lua to write state graphs to file diff -r e3e3cbe544ec -r 9bd292b35f23 dump.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dump.lua Wed Sep 23 14:25:20 2020 +0100 @@ -0,0 +1,72 @@ +local statewalk = require("luatraverse"); +local format = string.format; +local type = type; +local tostring = tostring; +local io, os = io, os; + +local getsize; +do + local ok, ret = pcall(require, "getsize"); + if ok then + --luacheck: ignore 143/debug + if type(ret) == "function" then + getsize = ret; + elseif debug.getsize then + getsize = debug.getsize; + end + end +end + +local function dump_state(f, config) + if io.type(f) ~= "file" then + local err; + f, err = io.open(f, "w+"); + if not f then return false, err; end + end + + local metadata = config and config.metadata; + local start_time = os.time(); + + f:write("# Lua state graph", "\n"); + f:write("# Generated by dump.lua v2.1", "\n"); + f:write("# at ", os.date("!%F %R UTC", start_time), "\n"); + if metadata then + local keys = {}; + for k in pairs(metadata) do + table.insert(keys, k); + end + table.sort(keys); + if #keys > 0 then + for _, k in ipairs(keys) do + f:write("## ", k, ": ", metadata[k], "\n"); + end + end + end + + local seenobjects, id = {}, 0; + local function edge(from, to, how, value) + if from and (not seenobjects[from] or seenobjects[from] == true) then + id = id + 1; + seenobjects[from] = id; + f:write("V:", id, ":", type(from), ":", (getsize and getsize(from)) or "?", "\n"); + end + if not seenobjects[to] or seenobjects[to] == true then + id = id + 1; + seenobjects[to] = id; + f:write("V:", id, ":", type(to), ":", (getsize and getsize(to)) or "?", "\n"); + end + if seenobjects[from] == true or seenobjects[to] == true then + return; + end + local value_rep = (value and format("%q", tostring(value))) or "?"; + f:write("E:", seenobjects[from] or "?", ":", seenobjects[to], ":", tostring(how or "?"), ":", value_rep, "\n"); + end + local ignore = {f, dump_state, statewalk, seenobjects, edge}; + statewalk.traverse({edge=edge}, ignore, seenobjects); + f:write("# Completed in ", tostring(os.time() - start_time), "s", "\n"); + f:close(); +end + +return { + dump_state = dump_state; +};