internal/core/export: handle scalar values in adt.Vertex

Fixes #523

Change-Id: I9662bb76cebb326e012575fbfc8c6ca497d2c278
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7141
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
diff --git a/internal/core/export/export_test.go b/internal/core/export/export_test.go
index 69a44db..2803c01 100644
--- a/internal/core/export/export_test.go
+++ b/internal/core/export/export_test.go
@@ -22,6 +22,7 @@
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/format"
+	"cuelang.org/go/cue/parser"
 	"cuelang.org/go/internal"
 	"cuelang.org/go/internal/core/adt"
 	"cuelang.org/go/internal/core/compile"
@@ -76,23 +77,62 @@
 // different from parsed or evaluated CUE, such as having Vertex values.
 func TestGenerated(t *testing.T) {
 	testCases := []struct {
-		in    interface{}
-		value string
-		typ   string
+		in  func(ctx *adt.OpContext) (adt.Expr, error)
+		out string
 	}{{
-		in: &C{
-			Terminals: []*A{
-				{Name: "Name", Description: "Desc"},
-			},
+		in: func(ctx *adt.OpContext) (adt.Expr, error) {
+			in := &C{
+				Terminals: []*A{{Name: "Name", Description: "Desc"}},
+			}
+			return convert.GoValueToValue(ctx, in, false), nil
 		},
-		value: `{Terminals: [{Description: "Desc", Name: "Name"}]}`,
-		typ:   `*null|{Terminals?: *null|[...*null|{Name: string, Description: string}]}`,
+		out: `{Terminals: [{Description: "Desc", Name: "Name"}]}`,
 	}, {
-		in: []*A{
-			{Name: "Name", Description: "Desc"},
+		in: func(ctx *adt.OpContext) (adt.Expr, error) {
+			in := &C{
+				Terminals: []*A{{Name: "Name", Description: "Desc"}},
+			}
+			return convert.GoTypeToExpr(ctx, in)
 		},
-		value: `[{Name: "Name", Description: "Desc"}]`,
-		typ:   `*null|[...*null|{Name: string, Description: string}]`,
+		out: `*null|{Terminals?: *null|[...*null|{Name: string, Description: string}]}`,
+	}, {
+		in: func(ctx *adt.OpContext) (adt.Expr, error) {
+			in := []*A{{Name: "Name", Description: "Desc"}}
+			return convert.GoValueToValue(ctx, in, false), nil
+		},
+		out: `[{Name: "Name", Description: "Desc"}]`,
+	}, {
+		in: func(ctx *adt.OpContext) (adt.Expr, error) {
+			in := []*A{{Name: "Name", Description: "Desc"}}
+			return convert.GoTypeToExpr(ctx, in)
+		},
+		out: `*null|[...*null|{Name: string, Description: string}]`,
+	}, {
+		in: func(ctx *adt.OpContext) (adt.Expr, error) {
+			expr, err := parser.ParseExpr("test", `{
+				x: Guide.#Terminal
+				Guide: {}
+			}`)
+			if err != nil {
+				return nil, err
+			}
+			c, err := compile.Expr(nil, ctx, expr)
+			if err != nil {
+				return nil, err
+			}
+			root := &adt.Vertex{}
+			root.AddConjunct(c)
+			root.Finalize(ctx)
+
+			// Simulate Value.Unify of Lookup("x") and Lookup("Guide").
+			n := &adt.Vertex{}
+			n.AddConjunct(adt.MakeRootConjunct(nil, root.Arcs[0]))
+			n.AddConjunct(adt.MakeRootConjunct(nil, root.Arcs[1]))
+			n.Finalize(ctx)
+
+			return n, nil
+		},
+		out: `<[l2// x: undefined field #Terminal] _|_>`,
 	}}
 	for _, tc := range testCases {
 		t.Run("", func(t *testing.T) {
@@ -100,30 +140,18 @@
 			e := eval.New(r)
 			ctx := adt.NewContext(r, e, &adt.Vertex{})
 
-			v := convert.GoValueToValue(ctx, tc.in, false)
-
+			v, err := tc.in(ctx)
+			if err != nil {
+				t.Fatal("failed test case: ", err)
+			}
 			expr, err := export.Expr(ctx, v)
 			if err != nil {
-				t.Fatal(err)
+				t.Fatal("failed export: ", err)
 			}
 			got := internal.DebugStr(expr)
-			if got != tc.value {
-				t.Errorf("value: got:  %s\nwant: %s", got, tc.value)
+			if got != tc.out {
+				t.Errorf("got:  %s\nwant: %s", got, tc.out)
 			}
-
-			x, err := convert.GoTypeToExpr(ctx, tc.in)
-			if err != nil {
-				t.Fatal(err)
-			}
-			expr, err = export.Expr(ctx, x)
-			if err != nil {
-				t.Fatal(err)
-			}
-			got = internal.DebugStr(expr)
-			if got != tc.typ {
-				t.Errorf("type: got:  %s\nwant: %s", got, tc.typ)
-			}
-
 		})
 	}
 }
diff --git a/internal/core/export/value.go b/internal/core/export/value.go
index da0d853..375c11e 100644
--- a/internal/core/export/value.go
+++ b/internal/core/export/value.go
@@ -50,12 +50,17 @@
 		result = e.listComposite(n)
 
 	case *adt.Bottom:
-		if x.IsIncomplete() {
-			// fall back to expression mode
-			result = stripRefs(e.expr(n))
+		if !x.IsIncomplete() || len(n.Conjuncts) == 0 {
+			result = e.bottom(x)
 			break
 		}
-		result = e.bottom(x)
+
+		// fall back to expression mode
+		a := []ast.Expr{}
+		for _, c := range n.Conjuncts {
+			a = append(a, e.expr(c.Expr()))
+		}
+		result = ast.NewBinExpr(token.AND, a...)
 
 	default:
 		result = e.value(n.Value, n.Conjuncts...)