cuelang.org/go@v0.13.0/internal/core/subsume/value.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 subsume 16 17 import ( 18 "bytes" 19 20 "cuelang.org/go/cue/errors" 21 "cuelang.org/go/internal/core/adt" 22 ) 23 24 func (s *subsumer) values(a, b adt.Value) (result bool) { 25 defer func() { 26 if !result && s.gt == nil && s.lt == nil { 27 s.gt = a 28 s.lt = b 29 } 30 }() 31 32 if a == b { 33 return true 34 } 35 36 if s.Defaults { 37 b = adt.Default(b) 38 } 39 40 switch b := b.(type) { 41 case *adt.Bottom: 42 // If the value is incomplete, the error is not final. So either check 43 // structural equivalence or return an error. 44 return !b.IsIncomplete() 45 46 case *adt.Vertex: 47 if a, ok := a.(*adt.Vertex); ok { 48 return s.vertices(a, b) 49 } 50 if v, ok := b.BaseValue.(adt.Value); ok { 51 // Safe to ignore arcs of w. 52 return s.values(a, v) 53 } 54 // Check based on first value. 55 56 case *adt.Conjunction: 57 if _, ok := a.(*adt.Conjunction); ok { 58 break 59 } 60 for _, y := range b.Values { 61 if s.values(a, y) { 62 return true 63 } 64 } 65 return false 66 67 case *adt.Disjunction: 68 if _, ok := a.(*adt.Disjunction); ok { 69 break 70 } 71 72 for _, y := range b.Values { 73 if !s.values(a, y) { 74 return false 75 } 76 } 77 return true 78 79 case *adt.NodeLink: 80 // Do not descend into NodeLinks to avoid processing cycles. 81 // TODO: this would work better if all equal nodes shared the same 82 // node link. 83 return deref(a) == deref(b) 84 } 85 86 switch x := a.(type) { 87 case *adt.Top: 88 return true 89 90 case *adt.Bottom: 91 // isBottom(b) was already tested above. 92 return false 93 94 case *adt.BasicType: 95 k := b.Kind() 96 return x.K&k == k 97 98 case *adt.BoundValue: 99 return s.bound(x, b) 100 101 case *adt.Builtin: 102 return x == b 103 104 case *adt.BuiltinValidator: 105 state := s.ctx.PushState(s.ctx.Env(0), b.Source()) 106 // TODO: is this always correct? 107 cx := adt.MakeRootConjunct(s.ctx.Env(0), x) 108 b1 := s.ctx.Validate(cx, b) 109 if b1 != nil { 110 s.errs = errors.Append(s.errs, b1.Err) 111 } 112 b2 := s.ctx.PopState(state) 113 if b2 != nil { 114 s.errs = errors.Append(s.errs, b2.Err) 115 } 116 return b1 == nil && b2 == nil 117 118 case *adt.Null: 119 return b.Kind() == adt.NullKind 120 121 case *adt.Bool: 122 y, ok := b.(*adt.Bool) 123 return ok && x.B == y.B 124 125 case *adt.Num: 126 y, ok := b.(*adt.Num) 127 return ok && x.K&y.K == y.K && test(s.ctx, x, adt.EqualOp, x, y) 128 129 case *adt.String: 130 y, ok := b.(*adt.String) 131 return ok && x.Str == y.Str 132 133 case *adt.Bytes: 134 y, ok := b.(*adt.Bytes) 135 return ok && bytes.Equal(x.B, y.B) 136 137 case *adt.Vertex: 138 y, ok := b.(*adt.Vertex) 139 if ok { 140 return s.vertices(x, y) 141 } 142 143 // TODO: Under what conditions can we cast to the value? 144 if v, _ := x.BaseValue.(adt.Value); v != nil { 145 return s.values(v, b) 146 } 147 return false 148 149 case *adt.Conjunction: 150 if y, ok := b.(*adt.Conjunction); ok { 151 // A Conjunction subsumes another Conjunction if for all values a in 152 // x there is a value b in y such that a subsumes b. 153 // 154 // This assumes overlapping ranges in disjunctions are merged.If 155 // this is not the case, subsumes will return a false negative, 156 // which is allowed. 157 outerC: 158 for _, a := range x.Values { 159 for _, b := range y.Values { 160 if s.values(a, b) { 161 continue outerC 162 } 163 } 164 // TODO: should this be marked as inexact? 165 return false 166 } 167 return true 168 } 169 subsumed := true 170 for _, a := range x.Values { 171 subsumed = subsumed && s.values(a, b) 172 } 173 return subsumed 174 175 case *adt.Disjunction: 176 177 if s.LeftDefault { 178 a = adt.Default(a) 179 var ok bool 180 x, ok = a.(*adt.Disjunction) 181 if !ok { 182 return s.values(a, b) 183 } 184 } 185 186 // A Disjunction subsumes another Disjunction if all values of y are 187 // subsumed by any of the values of x, and default values in y are 188 // subsumed by the default values of x. 189 // 190 // This assumes that overlapping ranges in x are merged. If this is not 191 // the case, subsumes will return a false negative, which is allowed. 192 if y, ok := b.(*adt.Disjunction); ok { 193 // at least one value in x should subsume each value in d. 194 outerD: 195 for i, b := range y.Values { 196 bDefault := i < y.NumDefaults 197 // v is subsumed if any value in x subsumes v. 198 for j, a := range x.Values { 199 aDefault := j < x.NumDefaults 200 if (aDefault || !bDefault) && s.values(a, b) { 201 continue outerD 202 } 203 } 204 return false 205 } 206 return true 207 } 208 // b is subsumed if any value in x subsumes b. 209 for _, a := range x.Values { 210 if s.values(a, b) { 211 return true 212 } 213 } 214 // TODO: should this be marked as inexact? 215 return false 216 217 case *adt.NodeLink: 218 return deref(x) == deref(b) 219 } 220 return false 221 } 222 223 func deref(v adt.Expr) *adt.Vertex { 224 switch x := v.(type) { 225 case *adt.Vertex: 226 return x 227 case *adt.NodeLink: 228 return x.Node 229 } 230 return nil 231 } 232 233 func (s *subsumer) bound(x *adt.BoundValue, v adt.Value) bool { 234 ctx := s.ctx 235 if isBottom(v) { 236 return true 237 } 238 239 switch y := v.(type) { 240 case *adt.BoundValue: 241 if !adt.IsConcrete(y.Value) { 242 return false 243 } 244 245 kx := x.Kind() 246 ky := y.Kind() 247 if (kx&ky)&^kx != 0 { 248 return false 249 } 250 // x subsumes y if 251 // x: >= a, y: >= b ==> a <= b 252 // x: >= a, y: > b ==> a <= b 253 // x: > a, y: > b ==> a <= b 254 // x: > a, y: >= b ==> a < b 255 // 256 // x: <= a, y: <= b ==> a >= b 257 // 258 // x: != a, y: != b ==> a != b 259 // 260 // false if types or op direction doesn't match 261 262 xv := x.Value 263 yv := y.Value 264 switch x.Op { 265 case adt.GreaterThanOp: 266 if y.Op == adt.GreaterEqualOp { 267 return test(ctx, x, adt.LessThanOp, xv, yv) 268 } 269 fallthrough 270 case adt.GreaterEqualOp: 271 if y.Op == adt.GreaterThanOp || y.Op == adt.GreaterEqualOp { 272 return test(ctx, x, adt.LessEqualOp, xv, yv) 273 } 274 case adt.LessThanOp: 275 if y.Op == adt.LessEqualOp { 276 return test(ctx, x, adt.GreaterThanOp, xv, yv) 277 } 278 fallthrough 279 case adt.LessEqualOp: 280 if y.Op == adt.LessThanOp || y.Op == adt.LessEqualOp { 281 return test(ctx, x, adt.GreaterEqualOp, xv, yv) 282 } 283 case adt.NotEqualOp: 284 switch y.Op { 285 case adt.NotEqualOp: 286 return test(ctx, x, adt.EqualOp, xv, yv) 287 case adt.GreaterEqualOp: 288 return test(ctx, x, adt.LessThanOp, xv, yv) 289 case adt.GreaterThanOp: 290 return test(ctx, x, adt.LessEqualOp, xv, yv) 291 case adt.LessThanOp: 292 return test(ctx, x, adt.GreaterEqualOp, xv, yv) 293 case adt.LessEqualOp: 294 return test(ctx, x, adt.GreaterThanOp, xv, yv) 295 } 296 297 case adt.MatchOp, adt.NotMatchOp: 298 // these are just approximations 299 if y.Op == x.Op { 300 return test(ctx, x, adt.EqualOp, xv, yv) 301 } 302 303 default: 304 // adt.NotEqualOp already handled above. 305 panic("cue: undefined bound mode") 306 } 307 308 case *adt.Num, *adt.String, *adt.Bool: 309 return test(ctx, x, x.Op, y, x.Value) 310 } 311 return false 312 } 313 314 func test(ctx *adt.OpContext, src adt.Node, op adt.Op, gt, lt adt.Value) bool { 315 x := adt.BinOp(ctx, op, gt, lt) 316 b, ok := x.(*adt.Bool) 317 return ok && b.B 318 }