github.com/joomcode/cue@v0.4.4-0.20221111115225-539fe3512047/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 switch d := v.BaseValue.(type) { 49 default: 50 return v 51 52 case *Disjunction: 53 var w *Vertex 54 55 switch d.NumDefaults { 56 case 0: 57 return v 58 case 1: 59 w = d.Values[0].Default() 60 default: 61 x := *v 62 x.state = nil 63 x.BaseValue = &Disjunction{ 64 Src: d.Src, 65 Values: d.Values[:d.NumDefaults], 66 NumDefaults: 0, 67 } 68 w = &x 69 w.Conjuncts = nil 70 } 71 72 if w.Conjuncts == nil { 73 for _, c := range v.Conjuncts { 74 // TODO: preserve field information. 75 expr, _ := stripNonDefaults(c.Elem()) 76 w.Conjuncts = append(w.Conjuncts, MakeRootConjunct(c.Env, expr)) 77 } 78 } 79 return w 80 81 case *ListMarker: 82 m := *d 83 m.IsOpen = false 84 85 w := *v 86 w.BaseValue = &m 87 w.state = nil 88 return &w 89 } 90 } 91 92 // TODO: this should go: record preexpanded disjunctions in Vertex. 93 func stripNonDefaults(elem Elem) (r Elem, stripped bool) { 94 expr, ok := elem.(Expr) 95 if !ok { 96 return elem, false 97 } 98 switch x := expr.(type) { 99 case *DisjunctionExpr: 100 if !x.HasDefaults { 101 return x, false 102 } 103 d := *x 104 d.Values = []Disjunct{} 105 for _, v := range x.Values { 106 if v.Default { 107 d.Values = append(d.Values, v) 108 } 109 } 110 if len(d.Values) == 1 { 111 return d.Values[0].Val, true 112 } 113 return &d, true 114 115 case *BinaryExpr: 116 if x.Op != AndOp { 117 return x, false 118 } 119 a, sa := stripNonDefaults(x.X) 120 b, sb := stripNonDefaults(x.Y) 121 if sa || sb { 122 bin := *x 123 bin.X = a.(Expr) 124 bin.Y = b.(Expr) 125 return &bin, true 126 } 127 return x, false 128 129 default: 130 return x, false 131 } 132 }