forked from open-policy-agent/opa
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwalk.go
93 lines (86 loc) · 1.55 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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// 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 w.err != nil { // abort on error
return
}
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.Plans)
w.walk(x.Funcs)
case *Static:
for _, s := range x.Strings {
w.walk(s)
}
for _, f := range x.BuiltinFuncs {
w.walk(f)
}
for _, f := range x.Files {
w.walk(f)
}
case *Plans:
for _, pl := range x.Plans {
w.walk(pl)
}
case *Funcs:
for _, fn := range x.Funcs {
w.walk(fn)
}
case *Func:
for _, b := range x.Blocks {
w.walk(b)
}
case *Plan:
for _, b := range x.Blocks {
w.walk(b)
}
case *Block:
for _, s := range x.Stmts {
w.walk(s)
}
case *BlockStmt:
for _, b := range x.Blocks {
w.walk(b)
}
case *ScanStmt:
w.walk(x.Block)
case *NotStmt:
w.walk(x.Block)
case *WithStmt:
w.walk(x.Block)
}
}