github.com/solo-io/cue@v0.4.7/internal/core/dep/mixed.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 package dep 16 17 import ( 18 "fmt" 19 20 "github.com/solo-io/cue/internal/core/adt" 21 ) 22 23 // dynamic visits conjuncts of structs that are defined by the root for all 24 // of its fields, recursively. 25 // 26 // The current algorithm visits all known conjuncts and descends into the 27 // evaluated Vertex. A more correct and more performant algorithm would be to 28 // descend into the conjuncts and evaluate the necessary values, like fields 29 // and comprehension sources. 30 func dynamic(c *adt.OpContext, n *adt.Vertex, f VisitFunc, m marked, top bool) { 31 found := false 32 for _, c := range n.Conjuncts { 33 if m[c.Expr()] { 34 found = true 35 break 36 } 37 } 38 39 if !found { 40 return 41 } 42 43 if visit(c, n, f, false, top) != nil { 44 return 45 } 46 47 for _, a := range n.Arcs { 48 dynamic(c, a, f, m, false) 49 } 50 } 51 52 type marked map[adt.Expr]bool 53 54 // TODO: factor out the below logic as either a low-level dependency analyzer or 55 // some walk functionality. 56 57 // markExpr visits all nodes in an expression to mark dependencies. 58 func (m marked) markExpr(x adt.Expr) { 59 m[x] = true 60 61 switch x := x.(type) { 62 default: 63 64 case nil: 65 case *adt.Vertex: 66 for _, c := range x.Conjuncts { 67 m.markExpr(c.Expr()) 68 } 69 70 case *adt.BinaryExpr: 71 if x.Op == adt.AndOp { 72 m.markExpr(x.X) 73 m.markExpr(x.Y) 74 } 75 76 case *adt.StructLit: 77 for _, e := range x.Decls { 78 switch x := e.(type) { 79 case *adt.Field: 80 m.markExpr(x.Value) 81 82 case *adt.OptionalField: 83 m.markExpr(x.Value) 84 85 case *adt.BulkOptionalField: 86 m.markExpr(x.Value) 87 88 case *adt.DynamicField: 89 m.markExpr(x.Value) 90 91 case *adt.Ellipsis: 92 m.markExpr(x.Value) 93 94 case adt.Expr: 95 m.markExpr(x) 96 97 case adt.Yielder: 98 m.markYielder(x) 99 100 default: 101 panic(fmt.Sprintf("unreachable %T", x)) 102 } 103 } 104 105 case *adt.ListLit: 106 for _, e := range x.Elems { 107 switch x := e.(type) { 108 case adt.Expr: 109 m.markExpr(x) 110 111 case adt.Yielder: 112 m.markYielder(x) 113 114 case *adt.Ellipsis: 115 m.markExpr(x.Value) 116 117 default: 118 panic(fmt.Sprintf("unreachable %T", x)) 119 } 120 } 121 122 case *adt.DisjunctionExpr: 123 for _, d := range x.Values { 124 m.markExpr(d.Val) 125 } 126 127 case adt.Yielder: 128 m.markYielder(x) 129 } 130 } 131 132 func (m marked) markYielder(y adt.Yielder) { 133 switch x := y.(type) { 134 case *adt.ForClause: 135 m.markYielder(x.Dst) 136 137 case *adt.IfClause: 138 m.markYielder(x.Dst) 139 140 case *adt.LetClause: 141 m.markYielder(x.Dst) 142 143 case *adt.ValueClause: 144 m.markExpr(x.StructLit) 145 } 146 }