cue: fix bug in normalization
final normalization was not triggered if the individual values
did not change during evaluation.
Change-Id: Ib5d70c23ee872def328cea300b5b20c38a9f42e6
diff --git a/cue/eval.go b/cue/eval.go
index fa204a8..93efbd3 100644
--- a/cue/eval.go
+++ b/cue/eval.go
@@ -324,9 +324,8 @@
dn.add(ctx, n, v.marked)
}
}
- // TODO: move to evaluator
if !changed {
- return x
+ dn = x
}
return dn.normalize(ctx, x).val
}
@@ -342,6 +341,7 @@
switch {
case d.marked:
if marked != nil {
+ // TODO: allow disjunctions to be returned as is.
return ctx.mkErr(x, "more than one default remaining (%v and %v)", debugStr(ctx, marked), debugStr(ctx, d.val))
}
marked = d.val.(evaluated)
diff --git a/cue/resolve_test.go b/cue/resolve_test.go
index 47cd3fc..c3d50a4 100644
--- a/cue/resolve_test.go
+++ b/cue/resolve_test.go
@@ -794,11 +794,11 @@
in: `
obj foo a: "bar"
obj <Name>: {
- a: "dummy" | string
+ a: *"dummy" | string
sub as: a if true
}
`,
- out: `<0>{obj: <1>{<>: <2>(Name: string)-><3>{a: ("dummy" | string) if true yield ("sub"): <4>{as: <3>.a}}, ` +
+ out: `<0>{obj: <1>{<>: <2>(Name: string)-><3>{a: (*"dummy" | string) if true yield ("sub"): <4>{as: <3>.a}}, ` +
`foo: <5>{a: "bar", sub: <6>{as: "bar"}}}}`,
}, {
desc: "self-reference cycles conflicts with strings",
@@ -959,7 +959,6 @@
name: A
kind: B
} if num < 5
-
}
a b c d: "bar"
`,
@@ -977,6 +976,25 @@
`,
out: `<0>{l: [int,int], l1: ["a","b"], l2: ["c","d"]}`,
}, {
+ desc: "normalization",
+ in: `
+ a: string | string
+ b: *1 | *int // 1 == int(1) | float(1)
+ c: *1.0 | *float
+ `,
+ out: `<0>{a: string, b: _|_((*1 | *int):more than one default remaining (1 and int)), c: float}`,
+ }, {
+ desc: "default disambiguation",
+ in: `
+ a: *1 | int
+ b: *3 | int
+ c: a & b
+ d: b & a
+
+ e: *1 | *1
+ `,
+ out: `<0>{a: 1, b: 3, c: _|_((*1 | *3 | int):more than one default remaining (1 and 3)), d: _|_((*3 | *1 | int):more than one default remaining (3 and 1)), e: 1}`,
+ }, {
desc: "list comprehension",
in: `
// a: [ k for k: v in b if k < "d" if v > b.a ] // TODO test error using common iso colon
diff --git a/cue/subsume_test.go b/cue/subsume_test.go
index b0d9382..2781be5 100644
--- a/cue/subsume_test.go
+++ b/cue/subsume_test.go
@@ -23,7 +23,7 @@
func TestSubsume(t *testing.T) {
testCases := []struct {
- // the result of a ⊑ b, where a and b are defined in "in"
+ // the result of b ⊑ a, where a and b are defined in "in"
subsumes bool
in string
mode subsumeMode
@@ -156,10 +156,7 @@
87: {subsumes: true, in: `a: number, b: 2 | 1`},
88: {subsumes: false, in: `a: int, b: 1 | 2 | 3.1`},
- // Disjunction TODO: for now these two are false: unifying may result in
- // an ambiguity that we are currently not handling, so safer to not
- // unify.
- 89: {subsumes: false, in: `a: float | number, b: 1 | 2 | 3.1`},
+ 89: {subsumes: true, in: `a: float | number, b: 1 | 2 | 3.1`},
90: {subsumes: false, in: `a: int, b: 1 | 2 | 3.1`},
91: {subsumes: true, in: `a: 1 | 2, b: 1`},
diff --git a/cue/value.go b/cue/value.go
index b458284..945fe30 100644
--- a/cue/value.go
+++ b/cue/value.go
@@ -997,7 +997,7 @@
// normalize removes redundant element from unification.
// x must already have been evaluated.
func (x *disjunction) normalize(ctx *context, src source) mVal {
- less := func(ctx *context, lt, gt dValue) bool {
+ leq := func(ctx *context, lt, gt dValue) bool {
if isBottom(lt.val) {
return true
}
@@ -1018,7 +1018,7 @@
if i == j {
continue
}
- if less(ctx, v, w) && (!less(ctx, w, v) || j < i) {
+ if leq(ctx, v, w) && (!leq(ctx, w, v) || j < i) {
// strictly subsumed, or equal and and the equal element was
// processed earlier.
continue outer
@@ -1027,7 +1027,7 @@
// If there was a three-way equality, an element w, where w == v could
// already have been added.
for j := 0; j < k; j++ {
- if less(ctx, v, x.values[j]) {
+ if leq(ctx, v, x.values[j]) {
continue outer
}
}