cue: implement fill in terms of Value.Fill

This is required to move both builtins out of package cue.

This required some streamlining of the Fill implementation.

Change-Id: I252fb70700a1eba7fddff5679a121a55d0ca6e4d
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6862
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/builtinutil.go b/cue/builtinutil.go
index e226cfa..2bfd8ad 100644
--- a/cue/builtinutil.go
+++ b/cue/builtinutil.go
@@ -14,11 +14,6 @@
 
 package cue
 
-import (
-	"cuelang.org/go/internal/core/adt"
-	"cuelang.org/go/internal/core/convert"
-)
-
 // TODO: this code could be generated, but currently isn't.
 
 type valueSorter struct {
@@ -38,11 +33,9 @@
 func (s *valueSorter) Len() int      { return len(s.a) }
 func (s *valueSorter) Swap(i, j int) { s.a[i], s.a[j] = s.a[j], s.a[i] }
 func (s *valueSorter) Less(i, j int) bool {
-	ctx := s.cmp.ctx()
-	x := fill(ctx, s.cmp.v, s.a[i], "x")
-	x = fill(ctx, x, s.a[j], "y")
-	ctx.opCtx.Unify(ctx.opCtx, x, adt.Finalized) // TODO: remove.
-	v := Value{s.cmp.idx, x}
+	v := s.cmp.Fill(s.a[i], "x")
+	v = v.Fill(s.a[j], "y")
+
 	isLess, err := v.Lookup("less").Bool()
 	if err != nil && s.err == nil {
 		s.err = err
@@ -50,25 +43,3 @@
 	}
 	return isLess
 }
-
-// fill creates a new value with the old value unified with the given value.
-// TODO: consider making this a method on Value.
-func fill(ctx *context, v *adt.Vertex, x interface{}, path ...string) *adt.Vertex {
-	for i := len(path) - 1; i >= 0; i-- {
-		x = map[string]interface{}{path[i]: x}
-	}
-	value := convertVal(ctx, v, false, x)
-
-	w := adt.ToVertex(value)
-	n := &adt.Vertex{Label: v.Label}
-	n.AddConjunct(adt.MakeConjunct(nil, v))
-	n.AddConjunct(adt.MakeConjunct(nil, w))
-
-	// n.Add(v)
-	// n.Add(w)
-	return n
-}
-
-func convertVal(ctx *context, src source, nullIsTop bool, x interface{}) adt.Value {
-	return convert.GoValueToValue(ctx.opCtx, x, nullIsTop)
-}
diff --git a/cue/types.go b/cue/types.go
index 3e5d0c2..ce9b720 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -1520,9 +1520,14 @@
 	for i := len(path) - 1; i >= 0; i-- {
 		x = map[string]interface{}{path[i]: x}
 	}
-	var value = convert.GoValueToExpr(ctx.opCtx, true, x)
-	n := &adt.Vertex{Parent: v.v.Parent}
-	n.AddConjunct(adt.MakeConjunct(nil, value))
+	var value = convert.GoValueToValue(ctx.opCtx, x, true)
+	n, _ := value.(*adt.Vertex)
+	if n == nil {
+		n = &adt.Vertex{Label: v.v.Label, Parent: v.v.Parent}
+		n.AddConjunct(adt.MakeConjunct(nil, value))
+	} else {
+		n.Label = v.v.Label
+	}
 	n.Finalize(ctx.opCtx)
 	w := makeValue(v.idx, n)
 	return v.Unify(w)
diff --git a/internal/core/adt/expr.go b/internal/core/adt/expr.go
index 8c980b6..d4ac293 100644
--- a/internal/core/adt/expr.go
+++ b/internal/core/adt/expr.go
@@ -890,7 +890,16 @@
 	args := []Value{}
 	for _, a := range x.Args {
 		expr := c.value(a)
-		args = append(args, expr)
+		if v, ok := expr.(*Vertex); ok {
+			// Remove the path of the origin for arguments. This results in
+			// more sensible error messages: an error should refer to the call
+			// site, not the original location of the argument.
+			w := *v
+			w.Parent = nil
+			args = append(args, &w)
+		} else {
+			args = append(args, expr)
+		}
 	}
 	if c.HasErr() {
 		return nil
diff --git a/internal/core/convert/go.go b/internal/core/convert/go.go
index 36cf236..aea75da 100644
--- a/internal/core/convert/go.go
+++ b/internal/core/convert/go.go
@@ -391,8 +391,9 @@
 
 		case reflect.Struct:
 			obj := &adt.StructLit{Src: src}
-			v := &adt.Vertex{Value: &adt.StructMarker{}}
+			v := &adt.Vertex{}
 			v.AddConjunct(adt.MakeConjunct(nil, obj))
+			v.SetValue(ctx, adt.Finalized, &adt.StructMarker{})
 
 			t := value.Type()
 			for i := 0; i < value.NumField(); i++ {
@@ -443,6 +444,7 @@
 			obj := &adt.StructLit{Src: src}
 			v := &adt.Vertex{Value: &adt.StructMarker{}}
 			v.AddConjunct(adt.MakeConjunct(nil, obj))
+			v.SetValue(ctx, adt.Finalized, &adt.StructMarker{})
 
 			t := value.Type()
 			switch key := t.Key(); key.Kind() {