cue: add IsClosed method

Change-Id: I2303819226b0fe2ee692e2e1abccf938a5de955a
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/5400
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/types.go b/cue/types.go
index b37631f..6ef9b5c 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -984,6 +984,24 @@
 
 // TODO: IsFinal: this value can never be changed.
 
+// IsClosed reports whether a list of struct is closed. It reports false when
+// when the value is not a list or struct.
+func (v Value) IsClosed() bool {
+	switch v.Kind() {
+	case StructKind:
+		if st, ok := v.path.val().(*structLit); ok {
+			return st.closeStatus.shouldClose()
+		}
+	case ListKind:
+		if l, ok := v.path.val().(*list); ok {
+			if n, ok := l.len.(*numLit); ok {
+				return n.intValue(v.ctx()) == len(l.elem.arcs)
+			}
+		}
+	}
+	return false
+}
+
 // IsConcrete reports whether the current value is a concrete scalar value
 // (not relying on default values), a terminal error, a list, or a struct.
 // It does not verify that values of lists or structs are concrete themselves.
diff --git a/cue/types_test.go b/cue/types_test.go
index 4a9611e..aa4da04 100644
--- a/cue/types_test.go
+++ b/cue/types_test.go
@@ -50,6 +50,7 @@
 		json           string
 		valid          bool
 		concrete       bool
+		closed         bool
 		// pos            token.Pos
 	}{{ // Not a concrete value.
 		value:          `v: _`,
@@ -152,10 +153,17 @@
 		incompleteKind: StructKind,
 		concrete:       true,
 	}, {
+		value:          `v: close({})`,
+		kind:           StructKind,
+		incompleteKind: StructKind,
+		concrete:       true,
+		closed:         true,
+	}, {
 		value:          `v: []`,
 		kind:           ListKind,
 		incompleteKind: ListKind,
 		concrete:       true,
+		closed:         true,
 	}, {
 		value:    `v: {a: int, b: [1][a]}.b`,
 		kind:     BottomKind,
@@ -199,6 +207,9 @@
 			if got := v.IsConcrete(); got != tc.concrete {
 				t.Errorf("IsConcrete: got %v; want %v", got, tc.concrete)
 			}
+			if got := v.IsClosed(); got != tc.closed {
+				t.Errorf("IsClosed: got %v; want %v", got, tc.closed)
+			}
 		})
 	}
 }
diff --git a/cue/value.go b/cue/value.go
index 3ba7d65..52abfd1 100644
--- a/cue/value.go
+++ b/cue/value.go
@@ -397,7 +397,6 @@
 func (x *numLit) intValue(ctx *context) int {
 	v, err := x.v.Int64()
 	if err != nil {
-		ctx.mkErr(x, "intValue: %v", err)
 		return 0
 	}
 	return int(v)