cuelang.org/go@v0.10.1/internal/core/walk/walk.go (about) 1 // Copyright 2020 CUE Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // walk provides functions for visiting the nodes of an ADT tree. 16 package walk 17 18 import ( 19 "fmt" 20 21 "cuelang.org/go/internal/core/adt" 22 ) 23 24 // Features calls f for all features used in x and indicates whether the 25 // feature is used as a reference or not. 26 func Features(x adt.Expr, f func(label adt.Feature, src adt.Node)) { 27 w := Visitor{ 28 Feature: f, 29 } 30 w.Elem(x) 31 } 32 33 // A Visitor walks over all elements in an ADT, recursively. 34 type Visitor struct { 35 // Feature is invoked for all field names. 36 Feature func(f adt.Feature, src adt.Node) 37 38 // Before is invoked for all nodes in pre-order traversal. 39 // Returning false prevents the visitor from visiting the node's 40 // children. 41 Before func(adt.Node) bool 42 } 43 44 func (w *Visitor) Elem(x adt.Elem) { 45 w.node(x) 46 } 47 48 func (w *Visitor) feature(x adt.Feature, src adt.Node) { 49 if w.Feature != nil { 50 w.Feature(x, src) 51 } 52 } 53 54 func (w *Visitor) node(n adt.Node) { 55 if w.Before != nil && !w.Before(n) { 56 return 57 } 58 59 switch x := n.(type) { 60 case nil: 61 62 // TODO: special-case Vertex? 63 case adt.Value: 64 65 case *adt.ConjunctGroup: 66 for _, x := range *x { 67 w.Elem(x.Elem()) 68 } 69 70 case *adt.ListLit: 71 for _, x := range x.Elems { 72 w.node(x) 73 } 74 75 case *adt.StructLit: 76 for _, x := range x.Decls { 77 w.node(x) 78 } 79 80 case *adt.FieldReference: 81 w.feature(x.Label, x) 82 83 case *adt.ValueReference: 84 w.feature(x.Label, x) 85 86 case *adt.LabelReference: 87 88 case *adt.DynamicReference: 89 90 case *adt.ImportReference: 91 w.feature(x.ImportPath, x) 92 w.feature(x.Label, x) 93 94 case *adt.LetReference: 95 w.feature(x.Label, x) 96 97 case *adt.SelectorExpr: 98 w.node(x.X) 99 w.feature(x.Sel, x) 100 101 case *adt.IndexExpr: 102 w.node(x.X) 103 w.node(x.Index) 104 105 case *adt.SliceExpr: 106 w.node(x.X) 107 w.node(x.Lo) 108 w.node(x.Hi) 109 w.node(x.Stride) 110 111 case *adt.Interpolation: 112 for _, x := range x.Parts { 113 w.node(x) 114 } 115 116 case *adt.BoundExpr: 117 w.node(x.Expr) 118 119 case *adt.UnaryExpr: 120 w.node(x.X) 121 122 case *adt.BinaryExpr: 123 w.node(x.X) 124 w.node(x.Y) 125 126 case *adt.CallExpr: 127 w.node(x.Fun) 128 for _, arg := range x.Args { 129 w.node(arg) 130 } 131 132 case *adt.DisjunctionExpr: 133 for _, d := range x.Values { 134 w.node(d.Val) 135 } 136 137 // Fields 138 139 case *adt.Ellipsis: 140 if x.Value != nil { 141 w.node(x.Value) 142 } 143 144 case *adt.Field: 145 w.feature(x.Label, x) 146 w.node(x.Value) 147 148 case *adt.LetField: 149 w.feature(x.Label, x) 150 w.node(x.Value) 151 152 case *adt.BulkOptionalField: 153 w.node(x.Filter) 154 w.node(x.Value) 155 156 case *adt.DynamicField: 157 w.node(x.Key) 158 w.node(x.Value) 159 160 // Yielders 161 162 case *adt.Comprehension: 163 for _, c := range x.Clauses { 164 w.node(c) 165 } 166 w.node(adt.ToExpr(x.Value)) 167 168 case *adt.ForClause: 169 w.feature(x.Key, x) 170 w.feature(x.Value, x) 171 172 case *adt.IfClause: 173 w.node(x.Condition) 174 175 case *adt.LetClause: 176 w.feature(x.Label, x) 177 w.node(x.Expr) 178 179 case *adt.ValueClause: 180 181 default: 182 panic(fmt.Sprintf("unknown field %T", x)) 183 } 184 }