Created
September 27, 2014 08:18
-
-
Save mpeterv/d1741738876e9923e77c to your computer and use it in GitHub Desktop.
Program flow graph printer using luacheck.flow
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Requires luacheck scm-6 | |
-- Reads a Lua program from stdin, prints program flow graph for top level closure. | |
-- Format: node id: (ids of previous nodes) -> ast node tag:line:column -> (ids of next nodes) | |
-- Crashes on `break` or `goto` or labels. | |
local flow = require "luacheck.flow" | |
local parser = require "metalua.compiler".new() | |
local src = assert(io.stdin:read("*a")) | |
local ast = assert(parser:src_to_ast(src)) | |
local intel = {closures = {{stmts = ast}}, gotos = {}} | |
flow(intel) | |
local node_to_i = {} | |
for i=1, #intel.flow_nodes do | |
local node = intel.flow_nodes[i] | |
node_to_i[node] = i | |
if node.ast_node then | |
node.ast_node = ("%s:%d:%d"):format(node.ast_node.tag or "Block", | |
node.ast_node.lineinfo.first.line, | |
node.ast_node.lineinfo.first.column) | |
end | |
end | |
local function pad(s, l) | |
return s .. (" "):rep(math.max(l-#s, 0)) | |
end | |
local function tuple(t) | |
return "("..table.concat(t, ",")..")" | |
end | |
for i, node in ipairs(intel.flow_nodes) do | |
local prevs = {} | |
for _, prev in ipairs(node.prevs) do | |
table.insert(prevs, tostring(node_to_i[prev])) | |
end | |
local nexts = {} | |
for _, next_ in ipairs(node.nexts) do | |
table.insert(nexts, tostring(node_to_i[next_])) | |
end | |
print(("%s %s -> %s -> %s"):format( | |
pad(i..":", 4), | |
pad(tuple(prevs), 10), | |
pad(node.ast_node or "Virtual", 15), | |
pad(tuple(nexts), 10) | |
)) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment