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  }