cue: change emit value semantics
- top-level emit structs are now embedded
as with other structs
- for non-structs, regular and optional
top-level fields are disallowed.
Change-Id: Id7d62b956209b6657833920d24e6f3c7b127cb39
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/3682
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/cue/builtin_test.go b/cue/builtin_test.go
index 57ad4a5..41f8861 100644
--- a/cue/builtin_test.go
+++ b/cue/builtin_test.go
@@ -379,7 +379,7 @@
`"foo"`,
}, {
testExpr(`and([])`),
- `_`,
+ `{}`, // _ & top scope
}, {
testExpr(`or([1, 2, 3]) & 2`),
`2`,
diff --git a/cue/instance.go b/cue/instance.go
index 8493ae0..9b7955e 100644
--- a/cue/instance.go
+++ b/cue/instance.go
@@ -20,6 +20,7 @@
"cuelang.org/go/cue/ast"
"cuelang.org/go/cue/build"
"cuelang.org/go/cue/errors"
+ "cuelang.org/go/cue/token"
"cuelang.org/go/internal"
)
@@ -100,7 +101,25 @@
// TODO: remove manifest here?
v := ctx.manifest(inst.rootValue)
if s, ok := v.(*structLit); ok && s.emit != nil {
- return s.emit.evalPartial(ctx)
+ e := s.emit.evalPartial(ctx)
+ src := binSrc(token.NoPos, opUnify, v, e)
+ outer:
+ switch e.(type) {
+ case *structLit, *top:
+ v = binOp(ctx, src, opUnifyUnchecked, v, e)
+ if s, ok := v.(*structLit); ok {
+ s.emit = nil
+ }
+
+ default:
+ for _, a := range s.arcs {
+ if !a.definition {
+ v = binOp(ctx, src, opUnify, v, e)
+ break outer
+ }
+ }
+ return e
+ }
}
return v
}
diff --git a/doc/ref/spec.md b/doc/ref/spec.md
index 4efc3a7..4e58c18 100644
--- a/doc/ref/spec.md
+++ b/doc/ref/spec.md
@@ -1289,6 +1289,11 @@
A struct resulting from such a unification is closed if either of the involved
structs were closed.
+At the top level, an embedded value may be any type.
+In this case, a CUE program will evaluate to the embedded value
+and the CUE program may not have top-level regular or optional
+fields (definitions and aliases are allowed).
+
Syntactically, embeddings may be any expression, except that `<`
is eagerly interpreted as a bind label.