-
Notifications
You must be signed in to change notification settings - Fork 0
Visitor API
Froley generates and updates two different "Visitor" base classes that can be used to analyze and/or rebuild an AST: Visitor and InspectionVisitor.
Both Visitor classes use a sophisticated multi-tiered double dispatch system that allows calls to be initiated on base class Cmd references while ensuring that the calls are dispatched to the appropriate extended-class overloads.
Base class Visitor is a "rebuilding" Visitor. By default it will visit each node in an AST, rebuilding the AST by reassigning each child to be the node resulting from visiting the child. The rebuilt AST will be the same unless you overload various node handlers to return different nodes - for example, you may define the on() for a general Access node to return a resolved GetVar node instead.
Here is the standard per-node call sequence for a standard Visitor. By default each handler invokes calls to the indented handlers underneath - for example, the default implementation of on() invokes on_visit_content() and then on_validate().
on(cmd:CmdType)->Cmd
on_visit_content(cmd:CmdType)
on_visit_children(cmd:CmdType)
on_validate(cmd:CmdType)->Cmd
Due to the double dispatch system, the visitor methods you call are not the same as the methods you overload to change behavior. The table below shows the mapping.
| Method Call | Overloadable Handler |
|---|---|
| visit(Cmd)->Cmd | on(CmdType)->Cmd |
| visit_content(Cmd)->Cmd | on_visit(CmdType) |
| visit_children(Cmd)->Cmd | on_visit_children(CmdType) |
| validate(Cmd)->Cmd | on_validate(CmdType) |
Note that all the visit methods return values while only the first and last of the on handlers return a value. visit() returns the result of on(), which returns the result of on_validate(), while the other visit methods return their argument, unmodified, for chaining purposes.
Here is a table describing the overloadable handlers in more detail.
| Visit Callback | Description |
|---|---|
| on(CmdType)->Cmd | Overload this to return a different Cmd node to replace the given subtree and/or to have total control over how the given node is visited. |
| on_visit(CmdType) | Overload this to handle visiting the node without needing a return value. By default it simply invokes on_visit_children(). |
| on_visit_children(CmdType) | Overload/overide this to define how child nodes are visited for a given node type. |
| on_validate(CmdType)->Cmd | Overload/overide this to convert a node to another type after all the standard calls have been made. |
In extended Visitor classes you only need to overload the node types you want to add custom logic to.
Base class InspectionVisitor<<$ReturnType>> is designed to analyze an AST without necessarily modifying the structure. It allows custom data to be passed back from visit() calls and it allows the AST traversal to terminate early with a call to halt().
The API is simpler than that of Visitor. Traversal logic is fully contained in the default on() handlers, with each default on(CmdType) calling on_enter(CmdType) as that node is visited.
on(cmd:CmdType)->$ReturnType
on_enter(cmd:CmdType)
Due to the double dispatch system, the visitor methods you call are not the same as the methods you overload to change behavior. The table below shows the mapping.
| Method Call | Overloadable Handler |
|---|---|
| visit(Cmd)->$ReturnType | on(CmdType)->$ReturnType |
| enter(Cmd) | on_enter(CmdType) |