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.