internal/legacy/cue: use UnifyAccept and some other changes
Change-Id: Icc27f993a2039581e83e6c46e9137eeb75534f03
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6649
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/internal/legacy/cue/types.go b/internal/legacy/cue/types.go
index c3665c7..37f5f62 100644
--- a/internal/legacy/cue/types.go
+++ b/internal/legacy/cue/types.go
@@ -618,6 +618,11 @@
}
func remakeValue(base Value, env *adt.Environment, v value) Value {
+ // TODO: right now this is necessary because disjunctions do not have
+ // populated conjuncts.
+ if v, ok := v.(*adt.Vertex); ok && v.Status() >= adt.Partial {
+ return Value{base.idx, v}
+ }
n := &adt.Vertex{Parent: base.v.Parent, Label: base.v.Label}
n.AddConjunct(adt.MakeConjunct(env, v))
n = base.ctx().manifest(n)
@@ -1533,7 +1538,12 @@
// given its name.
func (v Value) Template() func(label string) Value {
// TODO: rename to optional.
- if v.v == nil || v.v.Closed == nil {
+ if v.v == nil {
+ return nil
+ }
+
+ types := v.v.OptionalTypes()
+ if types&(adt.HasAdditional|adt.HasPattern) == 0 {
return nil
}
@@ -1543,6 +1553,9 @@
f := ctx.StringLabel(label)
arc := &adt.Vertex{Parent: parent, Label: f}
v.v.MatchAndInsert(ctx, arc)
+ if len(arc.Conjuncts) == 0 {
+ return Value{}
+ }
arc.Finalize(ctx)
return makeValue(v.idx, arc)
}
@@ -1613,6 +1626,33 @@
return makeValue(v.idx, n)
}
+// UnifyAccept is as v.Unify(w), but will disregard any field that is allowed
+// in the Value accept.
+func (v Value) UnifyAccept(w Value, accept Value) Value {
+ if v.v == nil {
+ return w
+ }
+ if w.v == nil {
+ return v
+ }
+ if accept.v == nil {
+ panic("accept must exist")
+ }
+
+ n := &adt.Vertex{Parent: v.v.Parent, Label: v.v.Label}
+ n.AddConjunct(adt.MakeConjunct(nil, v.v))
+ n.AddConjunct(adt.MakeConjunct(nil, w.v))
+
+ e := eval.New(v.idx.Runtime)
+ ctx := e.NewContext(n)
+ e.UnifyAccept(ctx, n, adt.Finalized, accept.v.Closed)
+
+ // ctx := v.idx.newContext()
+ n.Closed = accept.v.Closed
+ n.Finalize(ctx)
+ return makeValue(v.idx, n)
+}
+
// Equals reports whether two values are equal, ignoring optional fields.
// The result is undefined for incomplete values.
func (v Value) Equals(other Value) bool {
@@ -2005,19 +2045,20 @@
if v.v.Value == nil {
return NoOp, []Value{makeValue(v.idx, v.v)}
}
- expr = v.v.Value
+ switch x := v.v.Value.(type) {
+ case *adt.ListMarker, *adt.StructMarker:
+ expr = v.v
+ default:
+ expr = x
+ }
case 1:
// the default case, processed below.
c := v.v.Conjuncts[0]
env = c.Env
expr = c.Expr()
- if v, ok := expr.(*adt.Vertex); ok {
- switch x := v.Value.(type) {
- case *adt.ListMarker, *adt.StructMarker:
- default:
- expr = x
- }
+ if w, ok := expr.(*adt.Vertex); ok {
+ return Value{v.idx, w}.Expr()
}
default:
@@ -2060,30 +2101,55 @@
}
op = AndOp
case *adt.Disjunction:
- for _, disjunct := range x.Values {
- a = append(a, makeValue(v.idx, disjunct))
+ count := 0
+ outer:
+ for i, disjunct := range x.Values {
+ if i < x.NumDefaults {
+ for _, n := range x.Values[x.NumDefaults:] {
+ if subsume.Value(v.ctx().opCtx, n, disjunct) == nil {
+ continue outer
+ }
+ }
+ }
+ count++
+ a = append(a, remakeValue(v, env, disjunct))
}
- op = OrOp
+ if count > 1 {
+ op = OrOp
+ }
case *adt.DisjunctionExpr:
// Filter defaults that are subsumed by another value.
count := 0
- // outer:
+ outerExpr:
for _, disjunct := range x.Values {
- // if disjunct.marked {
- // for _, n := range x.Values {
- // s := subsumer{ctx: v.ctx()}
- // if !n.marked && s.subsumes(n.val, disjunct.val) {
- // continue outer
- // }
- // }
- // }
+ if disjunct.Default {
+ for _, n := range x.Values {
+ a := adt.Vertex{
+ Parent: v.v.Parent,
+ Label: v.v.Label,
+ Closed: v.v.Closed,
+ }
+ b := a
+ a.AddConjunct(adt.MakeConjunct(env, n.Val))
+ b.AddConjunct(adt.MakeConjunct(env, disjunct.Val))
+
+ e := eval.New(v.idx.Runtime)
+ ctx := e.NewContext(nil)
+ e.UnifyAccept(ctx, &a, adt.Finalized, v.v.Closed)
+ e.UnifyAccept(ctx, &b, adt.Finalized, v.v.Closed)
+ if !n.Default && subsume.Value(ctx, &a, &b) == nil {
+ continue outerExpr
+ }
+ }
+ }
count++
a = append(a, remakeValue(v, env, disjunct.Val))
}
if count > 1 {
op = adt.OrOp
}
+
case *interpolation:
for _, p := range x.Parts {
a = append(a, remakeValue(v, env, p))
diff --git a/internal/legacy/cue/types_test.go b/internal/legacy/cue/types_test.go
index 5ba255b..b36c6c5 100644
--- a/internal/legacy/cue/types_test.go
+++ b/internal/legacy/cue/types_test.go
@@ -2915,7 +2915,7 @@
want: `&({c:a} {b:a})`,
}, {
input: `v: [...number] | *[1, 2, 3]`,
- want: `|([...number] [1,2,3])`,
+ want: `([...number]|*[1,2,3])`,
}}
for _, tc := range testCases {
t.Run(tc.input, func(t *testing.T) {