local stage = {}
|
|
local function get_index_name(base_name, key_node)
|
if key_node.tag == "String" then
|
return base_name .. "." .. key_node[1]
|
end
|
end
|
|
local function get_full_field_name(node)
|
if node.tag == "Id" then
|
return node[1]
|
elseif node.tag == "Index" then
|
local base_name = get_full_field_name(node[1])
|
return base_name and get_index_name(base_name, node[2])
|
end
|
end
|
|
local handle_node
|
|
local function handle_nodes(nodes)
|
for _, node in ipairs(nodes) do
|
if type(node) == "table" then
|
handle_node(node)
|
end
|
end
|
end
|
|
function handle_node(node, name)
|
if node.tag == "Function" then
|
node.name = name
|
handle_nodes(node[2])
|
elseif node.tag == "Set" or node.tag == "Local" or node.tag == "Localrec" then
|
local lhs = node[1]
|
local rhs = node[2]
|
|
-- No need to handle LHS if there is no RHS, it's always just a list of locals in that case.
|
if rhs then
|
handle_nodes(lhs)
|
|
for index, rhs_node in ipairs(rhs) do
|
local lhs_node = lhs[index]
|
local field_name = lhs_node and get_full_field_name(lhs_node)
|
handle_node(rhs_node, field_name)
|
end
|
end
|
elseif node.tag == "Table" and name then
|
for _, pair_node in ipairs(node) do
|
if pair_node.tag == "Pair" then
|
local key_node = pair_node[1]
|
local value_node = pair_node[2]
|
handle_node(key_node)
|
handle_node(value_node, get_index_name(name, key_node))
|
else
|
handle_node(pair_node)
|
end
|
end
|
else
|
handle_nodes(node)
|
end
|
end
|
|
-- Adds `name` field to `Function` ast nodes when possible:
|
-- * Function assigned to a variable (doesn't matter if local or global): "foo".
|
-- * Function assigned to a field: "foo.bar.baz".
|
-- Function can be in a table assigned to a variable or a field, e.g. `foo.bar = {baz = function() ... end}`.
|
-- * Otherwise: `nil`.
|
function stage.run(chstate)
|
handle_nodes(chstate.ast)
|
end
|
|
return stage
|