-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
walk.go
66 lines (58 loc) · 1.1 KB
/
walk.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// Copyright 2018 The OPA Authors. All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.
package ir
// Visitor defines the interface for visiting IR nodes.
type Visitor interface {
Before(x interface{})
Visit(x interface{}) (Visitor, error)
After(x interface{})
}
// Walk invokes the visitor for nodes under x.
func Walk(vis Visitor, x interface{}) error {
impl := walkerImpl{
vis: vis,
}
impl.walk(x)
return impl.err
}
type walkerImpl struct {
vis Visitor
err error
}
func (w *walkerImpl) walk(x interface{}) {
if x == nil {
return
}
prev := w.vis
w.vis.Before(x)
defer w.vis.After(x)
w.vis, w.err = w.vis.Visit(x)
if w.err != nil {
return
} else if w.vis == nil {
w.vis = prev
return
}
switch x := x.(type) {
case *Policy:
w.walk(x.Static)
w.walk(x.Plan)
case Static:
for _, s := range x.Strings {
w.walk(s)
}
case Plan:
for _, b := range x.Blocks {
w.walk(b)
}
case Block:
for _, s := range x.Stmts {
w.walk(s)
}
case ScanStmt:
w.walk(x.Block)
case NotStmt:
w.walk(x.Block)
}
}