cuelang.org/go@v0.10.1/internal/core/adt/default.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 adt 16 17 // Default returns the default value or itself if there is no default. 18 func Default(v Value) Value { 19 switch x := v.(type) { 20 case *Vertex: 21 return x.Default() 22 case *Disjunction: 23 return x.Default() 24 default: 25 return v 26 } 27 } 28 29 func (d *Disjunction) Default() Value { 30 switch d.NumDefaults { 31 case 0: 32 return d 33 case 1: 34 return d.Values[0] 35 default: 36 return &Disjunction{ 37 Src: d.Src, 38 Values: d.Values[:d.NumDefaults], 39 NumDefaults: 0, 40 } 41 } 42 } 43 44 // Default returns the default value or itself if there is no default. 45 // 46 // It also closes a list, representing its default value. 47 func (v *Vertex) Default() *Vertex { 48 v = v.DerefValue() 49 switch d := v.BaseValue.(type) { 50 default: 51 return v 52 53 case *Disjunction: 54 var w *Vertex 55 56 switch d.NumDefaults { 57 case 0: 58 return v 59 case 1: 60 w = ToVertex(Default(d.Values[0])) 61 default: 62 x := *v 63 x.state = nil 64 x.BaseValue = &Disjunction{ 65 Src: d.Src, 66 Values: d.Values[:d.NumDefaults], 67 NumDefaults: 0, 68 } 69 w = &x 70 w.Conjuncts = nil 71 } 72 73 if w.Conjuncts == nil { 74 for _, c := range v.Conjuncts { 75 // TODO: preserve field information. 76 expr, _ := stripNonDefaults(c.Elem()) 77 w.Conjuncts = append(w.Conjuncts, MakeRootConjunct(c.Env, expr)) 78 } 79 } 80 return w 81 82 case *ListMarker: 83 m := *d 84 m.IsOpen = false 85 86 w := *v 87 w.BaseValue = &m 88 w.state = nil 89 return &w 90 } 91 } 92 93 // TODO: this should go: record preexpanded disjunctions in Vertex. 94 func stripNonDefaults(elem Elem) (r Elem, stripped bool) { 95 expr, ok := elem.(Expr) 96 if !ok { 97 return elem, false 98 } 99 switch x := expr.(type) { 100 case *DisjunctionExpr: 101 if !x.HasDefaults { 102 return x, false 103 } 104 d := *x 105 d.Values = []Disjunct{} 106 for _, v := range x.Values { 107 if v.Default { 108 d.Values = append(d.Values, v) 109 } 110 } 111 if len(d.Values) == 1 { 112 return d.Values[0].Val, true 113 } 114 return &d, true 115 116 case *BinaryExpr: 117 if x.Op != AndOp { 118 return x, false 119 } 120 a, sa := stripNonDefaults(x.X) 121 b, sb := stripNonDefaults(x.Y) 122 if sa || sb { 123 bin := *x 124 bin.X = a.(Expr) 125 bin.Y = b.(Expr) 126 return &bin, true 127 } 128 return x, false 129 130 case *ConjunctGroup: 131 // NOTE: this code requires allocations unconditional. This should be 132 // mitigated once we optimize conjunct groupings. 133 isNew := false 134 var a ConjunctGroup = make([]Conjunct, len(*x)) 135 for i, c := range *x { 136 a[i].x, ok = stripNonDefaults(c.Expr()) 137 if ok { 138 isNew = true 139 } 140 } 141 if isNew { 142 return &a, true 143 } 144 return x, false 145 146 default: 147 return x, false 148 } 149 }