v2 / vlib / v / ast / walker / walker.v
43 lines · 35 sloc · 1.05 KB · 791d0d30ea54bf564573fbb801def32b6214ee38
Raw
1module walker
2
3import v.ast
4
5// Visitor defines a visit method which is invoked by the walker in each node it encounters.
6pub interface Visitor {
7mut:
8 visit(node &ast.Node) !
9}
10
11pub type InspectorFn = fn (node &ast.Node, data voidptr) bool
12
13fn empty_callback(node &ast.Node, data voidptr) bool {
14 panic('empty ast.walker, node: ${voidptr(node)}, data: ${voidptr(data)}')
15}
16
17struct Inspector {
18 inspector_callback InspectorFn = empty_callback
19mut:
20 data voidptr
21}
22
23pub fn (i &Inspector) visit(node &ast.Node) ! {
24 if i.inspector_callback(node, i.data) {
25 return
26 }
27 return error('')
28}
29
30// inspect traverses and checks the AST node on a depth-first order and based on the data given
31pub fn inspect(node &ast.Node, data voidptr, inspector_callback InspectorFn) {
32 mut inspector := Inspector{inspector_callback, data}
33 walk(mut inspector, node)
34}
35
36// walk traverses the AST using the given visitor
37pub fn walk(mut visitor Visitor, node &ast.Node) {
38 visitor.visit(node) or { return }
39 children := node.children()
40 for child_node in children {
41 walk(mut visitor, &child_node)
42 }
43}
44