-- e.g. they're called after the right-hand-side has been visited in a
-- `Local node, but before in a `Localrec node.
--
+-- TODO: document scopes, relaxed cfg descriptions
+-- -----------------------------------------------
+--
+-- Examples of cfg structures:
+--
+-- { Id = f1, Local = f2 }
+-- f
+-- { up = f1, down = f2 }
+-- { scope = { up = f1, down = f2 }, up = f1, down = f2 }
+-- { stat = f1, expr = { up = f1 } }
+--
+--
--------------------------------------------------------------------------------
-{ extension "match" }
if #x%2 == 1 then BS(x[#x]) end
| `Call{...}|`Invoke{...}|`Return{...} -> EL(x)
| `Break | `Goto{ _ } | `Label{ _ } -> -- nothing
- | {...} if walk.tags.stat[x.tag]->
- printf("Warning: walk: malformed %s stat node: %s", x.tag, table.tostring(x,80))
- | {...} -> print("Warning: walk: unknown stat node: "..table.tostring(x,80))
- | _ -> print("Warning: walk: unexpected stat node of type "..type(x)
- ..": "..table.tostring(x,80))
+ | { tag=tag, ...} if walk.tags.stat[tag]->
+ walk.malformed (cfg, x, unpack (log))
+ | _ ->
+ walk.unknonw (cfg, x, unpack (log))
end
end
| v -> E(v)
end end
|`Nil|`Dots|`True|`False|`Number{_}|`String{_}|`Id{_} -> -- nothing
- | {...} if walk.tags.expr[x.tag]->
- printf("Warning: walk: malformed %s expr node: %s", x.tag, table.tostring(x,80))
- | {...} -> print("Warning: walk: unknown expr node: "..table.tostring(x,80))
- | _ -> print("Warning: walk: unexpected expr node of type "..type(x)
- ..": "..table.tostring(x,80))
+ | { tag=tag, ...} if walk.tags.expr[tag]->
+ walk.malformed (cfg, x, unpack (log))
+ | _ ->
+ walk.unknonw (cfg, x, unpack (log))
end
end
-- * if an entry is a table, look for 'up' and 'down' entries
-- * if it is a function, consider it as a `down' traverser.
----------------------------------------------------------------------
-local walker_builder = |cfg_field, traverse|
-function (cfg, x, ...)
- local sub_cfg = type (x)=='table' and x.tag and cfg[x.tag] or cfg[cfg_field] or cfg
+local walker_builder = |cfg_field, traverse| function (cfg, x, ...)
+ local sub_cfg = type (x)=='table' and x.tag and cfg[x.tag]
+ or cfg[cfg_field] or cfg
local broken, down, up = false
if type(sub_cfg)=='table' then
down, up = sub_cfg.down, sub_cfg.up
assert(not broken or broken=='break',
"Map functions must return 'break' or nil")
end
- if not broken then traverse (cfg, x, ...) end
+ if not broken and traverse then traverse (cfg, x, ...) end
if up then up (x, ...) end
end
----------------------------------------------------------------------
-- Declare [walk.stat], [walk.expr], [walk.block] and [walk.expr_list]
----------------------------------------------------------------------
-for w in values{ "stat", "expr", "block", "expr_list" } do
+for w in values{ "stat", "expr", "block", "expr_list",
+ "malformed", "unknown" } do
walk[w] = walker_builder (w, walk.traverse[w])
end