cmd/cue/cmd: use unify semantics merging across packages

This includes two changes:
1) Use Unify instead of Fill to merge values
2) Change instance iteration to value iteration.

Instead of merging all files into a single file using the
semantics of embedding, we should use that of
unification if files are anonymous or originate from
different packages.

This is easier to do when all values in play are cue.Value.
The goal is to ultimately move away from cue.Instance
anwyay, so this is a first step in this simplification.

Fixes #743
Fixes #752

Change-Id: Ia0b3f367527eb97d32e665ba000d7bbbc14965ca
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/8763
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
diff --git a/cmd/cue/cmd/common.go b/cmd/cue/cmd/common.go
index e8effa6..cbe713e 100644
--- a/cmd/cue/cmd/common.go
+++ b/cmd/cue/cmd/common.go
@@ -16,7 +16,6 @@
 
 import (
 	"bytes"
-	"fmt"
 	"io"
 	"os"
 	"path/filepath"
@@ -169,7 +168,7 @@
 
 type iterator interface {
 	scan() bool
-	instance() *cue.Instance
+	value() cue.Value
 	file() *ast.File // may return nil
 	err() error
 	close()
@@ -187,11 +186,11 @@
 	return i.i < len(i.a) && i.e == nil
 }
 
-func (i *instanceIterator) close()                  {}
-func (i *instanceIterator) err() error              { return i.e }
-func (i *instanceIterator) instance() *cue.Instance { return i.a[i.i] }
-func (i *instanceIterator) file() *ast.File         { return nil }
-func (i *instanceIterator) id() string              { return i.a[i.i].Dir }
+func (i *instanceIterator) close()           {}
+func (i *instanceIterator) err() error       { return i.e }
+func (i *instanceIterator) value() cue.Value { return i.a[i.i].Value() }
+func (i *instanceIterator) file() *ast.File  { return nil }
+func (i *instanceIterator) id() string       { return i.a[i.i].Dir }
 
 type streamingIterator struct {
 	r    *cue.Runtime
@@ -201,7 +200,7 @@
 	cfg  *encoding.Config
 	a    []*build.File
 	dec  *encoding.Decoder
-	i    *cue.Instance
+	v    cue.Value
 	f    *ast.File
 	e    error
 }
@@ -240,8 +239,8 @@
 	return i
 }
 
-func (i *streamingIterator) file() *ast.File         { return i.f }
-func (i *streamingIterator) instance() *cue.Instance { return i.i }
+func (i *streamingIterator) file() *ast.File  { return i.f }
+func (i *streamingIterator) value() cue.Value { return i.v }
 
 func (i *streamingIterator) id() string {
 	if i.inst != nil {
@@ -284,15 +283,12 @@
 		i.e = err
 		return false
 	}
-	i.i = inst
+	i.v = inst.Value()
 	if i.base.Exists() {
 		i.e = i.base.Err()
 		if i.e == nil {
-			i.i, i.e = i.i.Fill(i.base)
-			i.i.DisplayName = internal.DebugStr(i.b.schema)
-			if inst.DisplayName != "" {
-				i.i.DisplayName = fmt.Sprintf("%s|%s", inst.DisplayName, i.i.DisplayName)
-			}
+			i.v = i.v.Unify(i.base)
+			i.e = i.v.Err()
 		}
 		i.f = nil
 	}
@@ -339,15 +335,11 @@
 
 func (i *expressionIter) file() *ast.File { return nil }
 
-func (i *expressionIter) instance() *cue.Instance {
+func (i *expressionIter) value() cue.Value {
 	if len(i.expr) == 0 {
-		return i.iter.instance()
+		return i.iter.value()
 	}
-	inst := i.iter.instance()
-	v := i.iter.instance().Eval(i.expr[i.i])
-	ni := internal.MakeInstance(v).(*cue.Instance)
-	ni.DisplayName = fmt.Sprintf("%s|%s", inst.DisplayName, i.expr[i.i])
-	return ni
+	return internal.EvalExpr(i.iter.value(), i.expr[i.i]).(cue.Value)
 }
 
 type config struct {
diff --git a/cmd/cue/cmd/def.go b/cmd/cue/cmd/def.go
index bb21e4a..edba0e6 100644
--- a/cmd/cue/cmd/def.go
+++ b/cmd/cue/cmd/def.go
@@ -64,7 +64,7 @@
 			err := e.EncodeFile(f)
 			exitOnErr(cmd, err, true)
 		} else {
-			err := e.Encode(iter.instance())
+			err := e.Encode(iter.value())
 			exitOnErr(cmd, err, true)
 		}
 	}
diff --git a/cmd/cue/cmd/eval.go b/cmd/cue/cmd/eval.go
index 0d90deb..8cb676a 100644
--- a/cmd/cue/cmd/eval.go
+++ b/cmd/cue/cmd/eval.go
@@ -117,7 +117,7 @@
 		if len(b.insts) > 1 {
 			id = iter.id()
 		}
-		v := iter.instance().Value()
+		v := iter.value()
 
 		if flagConcrete.Bool(cmd) {
 			syn = append(syn, cue.Concrete(true))
diff --git a/cmd/cue/cmd/export.go b/cmd/cue/cmd/export.go
index 0f7669b..9a5e302 100644
--- a/cmd/cue/cmd/export.go
+++ b/cmd/cue/cmd/export.go
@@ -114,8 +114,8 @@
 	iter := b.instances()
 	defer iter.close()
 	for iter.scan() {
-		inst := iter.instance()
-		err = enc.Encode(inst)
+		v := iter.value()
+		err = enc.Encode(v)
 		exitOnErr(cmd, err, true)
 	}
 	exitOnErr(cmd, iter.err(), true)
diff --git a/cmd/cue/cmd/testdata/script/vet_embed.txt b/cmd/cue/cmd/testdata/script/vet_embed.txt
new file mode 100644
index 0000000..2ce8030
--- /dev/null
+++ b/cmd/cue/cmd/testdata/script/vet_embed.txt
@@ -0,0 +1,36 @@
+# Embedding at the file level should still close the package and validate
+# correctly against files from other packages without first merging these
+# files, thereby effectively embedding them and averting the closed check.
+
+# Issue #743
+
+! cue vet schema.cue foo.yaml
+cmp stderr expect-foo
+
+! cue vet schema.cue stream.yaml
+cmp stderr expect-stream
+
+-- schema.cue --
+package schema
+
+#Foo: {
+    a: int
+    b?: int
+}
+#Foo
+
+-- foo.yaml --
+a: 1
+c: 2
+
+-- stream.yaml --
+a: 1
+d: 2
+---
+a: 1
+e: 2
+
+-- expect-foo --
+field `c` not allowed
+-- expect-stream --
+field `d` not allowed
diff --git a/cmd/cue/cmd/vet.go b/cmd/cue/cmd/vet.go
index deb623d..b20a143 100644
--- a/cmd/cue/cmd/vet.go
+++ b/cmd/cue/cmd/vet.go
@@ -107,7 +107,7 @@
 	iter := b.instances()
 	defer iter.close()
 	for iter.scan() {
-		inst := iter.instance()
+		v := iter.value()
 		// TODO: use ImportPath or some other sanitized path.
 
 		concrete := true
@@ -124,9 +124,9 @@
 			cue.Hidden(true),
 		}
 		w := cmd.Stderr()
-		err := inst.Value().Validate(append(opt, cue.Concrete(concrete))...)
+		err := v.Validate(append(opt, cue.Concrete(concrete))...)
 		if err != nil && !hasFlag {
-			err = inst.Value().Validate(append(opt, cue.Concrete(false))...)
+			err = v.Validate(append(opt, cue.Concrete(false))...)
 			if !shown && err == nil {
 				shown = true
 				p := message.NewPrinter(getLang())
@@ -150,7 +150,7 @@
 	iter := b.instances()
 	defer iter.close()
 	for iter.scan() {
-		v := iter.instance().Value()
+		v := iter.value()
 
 		// Always concrete when checking against concrete files.
 		err := v.Validate(cue.Concrete(true))
diff --git a/internal/encoding/encoder.go b/internal/encoding/encoder.go
index f803d95..764d482 100644
--- a/internal/encoding/encoder.go
+++ b/internal/encoding/encoder.go
@@ -40,7 +40,7 @@
 type Encoder struct {
 	cfg          *Config
 	close        func() error
-	interpret    func(*cue.Instance) (*ast.File, error)
+	interpret    func(cue.Value) (*ast.File, error)
 	encFile      func(*ast.File) error
 	encValue     func(cue.Value) error
 	autoSimplify bool
@@ -79,7 +79,8 @@
 	case build.OpenAPI:
 		// TODO: get encoding options
 		cfg := &openapi.Config{}
-		e.interpret = func(i *cue.Instance) (*ast.File, error) {
+		e.interpret = func(v cue.Value) (*ast.File, error) {
+			i := internal.MakeInstance(v).(*cue.Instance)
 			return openapi.Generate(i, cfg)
 		}
 	// case build.JSONSchema:
@@ -204,26 +205,25 @@
 	return e.encodeFile(f, e.interpret)
 }
 
-func (e *Encoder) Encode(inst *cue.Instance) error {
+func (e *Encoder) Encode(v cue.Value) error {
 	e.autoSimplify = true
 	if e.interpret != nil {
-		f, err := e.interpret(inst)
+		f, err := e.interpret(v)
 		if err != nil {
 			return err
 		}
 		return e.encodeFile(f, nil)
 	}
-	v := inst.Value()
 	if err := v.Validate(cue.Concrete(e.concrete)); err != nil {
 		return err
 	}
 	if e.encValue != nil {
-		return e.encValue(inst.Value())
+		return e.encValue(v)
 	}
-	return e.encFile(valueToFile(inst.Value()))
+	return e.encFile(valueToFile(v))
 }
 
-func (e *Encoder) encodeFile(f *ast.File, interpret func(*cue.Instance) (*ast.File, error)) error {
+func (e *Encoder) encodeFile(f *ast.File, interpret func(cue.Value) (*ast.File, error)) error {
 	if interpret == nil && e.encFile != nil {
 		return e.encFile(f)
 	}
@@ -234,13 +234,13 @@
 		return err
 	}
 	if interpret != nil {
-		return e.Encode(inst)
+		return e.Encode(inst.Value())
 	}
 	v := inst.Value()
 	if err := v.Validate(cue.Concrete(e.concrete)); err != nil {
 		return err
 	}
-	return e.encValue(inst.Value())
+	return e.encValue(v)
 }
 
 func writer(f *build.File, cfg *Config) (_ io.Writer, close func() error, err error) {