cue: implement embedded scalars

Mostly already implemented in evaluator.

Changes
- some adjustments in evaluator
- FieldSetDefined no longer necessary
  as result of adjustments.
- print definitions alongside scalars
  if requested in value mode.

Change-Id: Ie00dc2ef1dfe5a001c6133f0e7a27546687e2c9b
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7728
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/testdata/comprehensions/incomplete.txtar b/cue/testdata/comprehensions/incomplete.txtar
index 1d4b4cf..5381c49 100644
--- a/cue/testdata/comprehensions/incomplete.txtar
+++ b/cue/testdata/comprehensions/incomplete.txtar
@@ -1,19 +1,26 @@
 -- in.cue --
 cond: bool
-src: {}
+src:  {}
+top:  _
 a: [ if cond {} ]
 b: [ for x in src.foo {} ]
+c: { for x in top {} }
 -- out/eval --
 (struct){
   cond: (bool){ bool }
   src: (struct){
   }
+  top: (_){ _ }
   a: (_|_){
     // [incomplete] a: incomplete bool value 'bool'
   }
   b: (_|_){
     // [incomplete] b: undefined field foo:
-    //     ./in.cue:4:19
+    //     ./in.cue:5:19
+  }
+  c: (_|_){
+    // [incomplete] c: incomplete feed source value top (type _):
+    //     ./in.cue:6:15
   }
 }
 -- out/compile --
@@ -21,10 +28,14 @@
 {
   cond: bool
   src: {}
+  top: _
   a: [
     if 〈0;cond〉 {},
   ]
   b: [
     for _, x in 〈0;src〉.foo {},
   ]
+  c: {
+    for _, x in 〈1;top〉 {}
+  }
 }
diff --git a/cue/testdata/scalars/embed.txtar b/cue/testdata/scalars/embed.txtar
new file mode 100644
index 0000000..e3c9e28
--- /dev/null
+++ b/cue/testdata/scalars/embed.txtar
@@ -0,0 +1,125 @@
+-- in.cue --
+import "strings"
+
+a1: {
+    2
+}
+a2: {
+    v: {
+        3
+        #foo: a2.v + 1
+    }
+    w: v
+    x: v.#foo
+}
+a3: a1 + a2.v
+
+b3: {
+    [1, 2]
+    #foo: 1
+}
+b4: b3 + b3
+b5: b3[1]
+b6: b3[5]
+b7: b4[a1] // 1
+
+s1: {
+    "foo"
+    #bar: "bar"
+}
+s2: [ s1, { s1.#bar, #baz: 4 } ]
+s3: strings.Join(s2, "--")
+
+-- out/eval --
+Errors:
+b6: invalid list index 5 (out of bounds):
+    ./in.cue:22:8
+
+Result:
+(_|_){
+  // [eval]
+  a1: (int){ 2 }
+  a2: (struct){
+    v: (int){
+      3
+      #foo: (int){ 4 }
+    }
+    w: (int){
+      3
+      #foo: (int){ 4 }
+    }
+    x: (int){ 4 }
+  }
+  a3: (int){ 5 }
+  b3: (#list){
+    #foo: (int){ 1 }
+    0: (int){ 1 }
+    1: (int){ 2 }
+  }
+  b4: (#list){
+    0: (int){ 1 }
+    1: (int){ 2 }
+    2: (int){ 1 }
+    3: (int){ 2 }
+  }
+  b5: (int){ 2 }
+  b6: (_|_){
+    // [eval] b6: invalid list index 5 (out of bounds):
+    //     ./in.cue:22:8
+  }
+  b7: (int){ 1 }
+  s1: (string){
+    "foo"
+    #bar: (string){ "bar" }
+  }
+  s2: (#list){
+    0: (string){
+      "foo"
+      #bar: (string){ "bar" }
+    }
+    1: (string){
+      "bar"
+      #baz: (int){ 4 }
+    }
+  }
+  s3: (string){ "foo--bar" }
+}
+-- out/compile --
+--- in.cue
+{
+  a1: {
+    2
+  }
+  a2: {
+    v: {
+      3
+      #foo: (〈2;a2〉.v + 1)
+    }
+    w: 〈0;v〉
+    x: 〈0;v〉.#foo
+  }
+  a3: (〈0;a1〉 + 〈0;a2〉.v)
+  b3: {
+    [
+      1,
+      2,
+    ]
+    #foo: 1
+  }
+  b4: (〈0;b3〉 + 〈0;b3〉)
+  b5: 〈0;b3〉[1]
+  b6: 〈0;b3〉[5]
+  b7: 〈0;b4〉[〈0;a1〉]
+  s1: {
+    "foo"
+    #bar: "bar"
+  }
+  s2: [
+    〈0;s1〉,
+    {
+      〈1;s1〉.#bar
+      #baz: 4
+    },
+  ]
+  s3: 〈import;strings〉.Join(〈0;s2〉, "--")
+}
diff --git a/internal/core/adt/composite.go b/internal/core/adt/composite.go
index 2e8806c..e5aeba4 100644
--- a/internal/core/adt/composite.go
+++ b/internal/core/adt/composite.go
@@ -228,10 +228,6 @@
 	// nodeContext to allow reusing the computations done so far.
 	Partial
 
-	// FieldSetDefined indicates that the value and conjuncts of all fields have
-	// been completed, but that the individual arcs are not yet evaluated.
-	FieldSetDefined
-
 	// EvaluatingArcs indicates that the arcs of the Vertex are currently being
 	// evaluated. If this is encountered it indicates a structural cycle.
 	// Value does not have to be nil
diff --git a/internal/core/adt/context.go b/internal/core/adt/context.go
index 5b52a18..3ae8892 100644
--- a/internal/core/adt/context.go
+++ b/internal/core/adt/context.go
@@ -387,7 +387,7 @@
 
 	v, complete := c.Evaluate(env, x)
 
-	v, ok := c.getDefault(v)
+	v, ok := c.getDefault(v, true)
 	if !ok {
 		return v, false
 	}
@@ -406,13 +406,14 @@
 	return v, true
 }
 
-func (c *OpContext) getDefault(v Value) (result Value, ok bool) {
+func (c *OpContext) getDefault(v Value, scalar bool) (result Value, ok bool) {
 	var d *Disjunction
 	switch x := v.(type) {
 	default:
 		return v, true
 
 	case *Vertex:
+		// TODO: return vertex if not disjunction.
 		switch t := x.Value.(type) {
 		case *Disjunction:
 			d = t
@@ -420,7 +421,13 @@
 		case *StructMarker, *ListMarker:
 			return v, true
 
+		case *Vertex:
+			return c.getDefault(t, scalar)
+
 		default:
+			if !scalar {
+				return v, true
+			}
 			return t, true
 		}
 
@@ -433,7 +440,7 @@
 			"unresolved disjunction %s (type %s)", c.Str(d), d.Kind())
 		return nil, false
 	}
-	return c.getDefault(d.Values[0])
+	return c.getDefault(d.Values[0], scalar)
 }
 
 // Evaluate evaluates an expression within the given environment and indicates
@@ -473,12 +480,14 @@
 func (c *OpContext) value(x Expr) (result Value) {
 	v := c.evalState(x, Partial)
 
-	v, _ = c.getDefault(v)
+	v, _ = c.getDefault(v, true)
 	return v
 }
 
-func (c *OpContext) eval(v Expr) (result Value) {
-	return c.evalState(v, Partial)
+func (c *OpContext) eval(x Expr) (result Value) {
+	v := c.evalState(x, Partial)
+	return v
+
 }
 
 func (c *OpContext) evalState(v Expr, state VertexStatus) (result Value) {
@@ -626,36 +635,43 @@
 	return x.Source().Pos()
 }
 
-func (c *OpContext) node(x Expr, state VertexStatus) *Vertex {
-	v := c.evalState(x, state)
+func (c *OpContext) node(x Expr, scalar bool) *Vertex {
+	v := c.evalState(x, EvaluatingArcs)
 
-	v, ok := c.getDefault(v)
+	v, ok := c.getDefault(v, scalar)
 	if !ok {
 		// Error already generated by getDefault.
 		return emptyNode
 	}
 
 	node, ok := v.(*Vertex)
-	if !ok {
-		if isError(v) {
-			if v == nil {
-				c.addErrf(IncompleteError, pos(x), "incomplete value %s", c.Str(x))
-				return emptyNode
-			}
-		}
+	if ok {
+		v = node.Value
+	}
+	switch nv := v.(type) {
+	case nil:
+		c.addErrf(IncompleteError, pos(x), "incomplete value %s", c.Str(x))
+		return emptyNode
+
+	case *Bottom:
+		c.AddBottom(nv)
+		return emptyNode
+
+	case *StructMarker, *ListMarker:
+
+	default:
 		if v.Kind()&StructKind != 0 {
 			c.addErrf(IncompleteError, pos(x),
 				"incomplete feed source value %s (type %s)",
 				x.Source(), v.Kind())
-		} else if b, ok := v.(*Bottom); ok {
-			c.AddBottom(b)
-		} else {
+			return emptyNode
+
+		} else if !ok {
 			c.addErrf(0, pos(x), // TODO(error): better message.
 				"invalid operand %s (found %s, want list or struct)",
 				x.Source(), v.Kind())
-
+			return emptyNode
 		}
-		return emptyNode
 	}
 	return node.Default()
 }
diff --git a/internal/core/adt/expr.go b/internal/core/adt/expr.go
index e0f7819..a2dd75f 100644
--- a/internal/core/adt/expr.go
+++ b/internal/core/adt/expr.go
@@ -585,7 +585,7 @@
 }
 
 func (x *SelectorExpr) resolve(c *OpContext) *Vertex {
-	n := c.node(x.X, FieldSetDefined)
+	n := c.node(x.X, x.Sel.IsRegular())
 	return c.lookup(n, x.Src.Sel.Pos(), x.Sel)
 }
 
@@ -608,7 +608,7 @@
 
 func (x *IndexExpr) resolve(ctx *OpContext) *Vertex {
 	// TODO: support byte index.
-	n := ctx.node(x.X, EvaluatingArcs)
+	n := ctx.node(x.X, true)
 	i := ctx.value(x.Index)
 	f := ctx.Label(i)
 	return ctx.lookup(n, x.Src.Index.Pos(), f)
@@ -1174,7 +1174,7 @@
 }
 
 func (x *ForClause) yield(c *OpContext, f YieldFunc) {
-	n := c.node(x.Src, EvaluatingArcs)
+	n := c.node(x.Src, true)
 	for _, a := range n.Arcs {
 		c.Unify(c, a, Partial)
 
diff --git a/internal/core/eval/eval.go b/internal/core/eval/eval.go
index 885a719..d323938 100644
--- a/internal/core/eval/eval.go
+++ b/internal/core/eval/eval.go
@@ -145,6 +145,7 @@
 // can be the only value in a valid configuration. This means that an error
 // may go undetected at this point, as long as it is caught later.
 //
+// TODO: return *adt.Vertex
 func (e *Evaluator) Evaluate(c *adt.OpContext, v *adt.Vertex) adt.Value {
 	var resultValue adt.Value
 
@@ -235,17 +236,14 @@
 		// TODO: Store if concrete and fully resolved.
 	}
 
-	switch v.Value.(type) {
-	case nil:
-		// Error saved in result.
-		return resultValue // incomplete
-
-	case *adt.ListMarker, *adt.StructMarker:
-		return v
-
-	default:
-		return v.Value
+	// TODO: Use this and ensure that each use of Evaluate handles
+	// struct numbers correctly. E.g. by using a function that
+	// gets the concrete value.
+	//
+	if v.Value == nil {
+		return resultValue
 	}
+	return v
 }
 
 // Unify implements adt.Unifier.
diff --git a/internal/core/export/export.go b/internal/core/export/export.go
index 5902187..880f49f 100644
--- a/internal/core/export/export.go
+++ b/internal/core/export/export.go
@@ -385,6 +385,11 @@
 	frame.fields[label] = entry
 }
 
+func (e *exporter) addEmbed(x ast.Expr) {
+	frame := e.top()
+	frame.scope.Elts = append(frame.scope.Elts, x)
+}
+
 func (e *exporter) pushFrame(conjuncts []adt.Conjunct) (s *ast.StructLit, saved []frame) {
 	saved = e.stack
 	s = &ast.StructLit{}
diff --git a/internal/core/export/testdata/embedscalar.txtar b/internal/core/export/testdata/embedscalar.txtar
new file mode 100644
index 0000000..4302de6
--- /dev/null
+++ b/internal/core/export/testdata/embedscalar.txtar
@@ -0,0 +1,87 @@
+-- in.cue --
+#top: 4
+sub: {
+    #sub: 5
+    a: {
+        3
+        #foo: 4
+    }
+    b: {
+        [1, 2]
+        #bar: 5
+        #baz: "foo"
+    }
+}
+-- out/definition --
+#top: 4
+sub: {
+	#sub: 5
+	a: {
+		3
+		#foo: 4
+	}
+	b: {
+		[1, 2]
+		#bar: 5
+		#baz: "foo"
+	}
+}
+-- out/doc --
+[]
+[#top]
+[sub]
+[sub #sub]
+[sub a]
+[sub a #foo]
+[sub b]
+[sub b #bar]
+[sub b #baz]
+[sub b 0]
+[sub b 1]
+-- out/value --
+== Simplified
+{
+	sub: {
+		a: 3
+		b: [1, 2]
+	}
+}
+== Raw
+{
+	#top: 4
+	sub: {
+		#sub: 5
+		a: {
+			3
+			#foo: 4
+		}
+		b: {
+			#bar: 5
+			#baz: "foo"
+			[1, 2]
+		}
+	}
+}
+== Final
+{
+	sub: {
+		a: 3
+		b: [1, 2]
+	}
+}
+== All
+{
+	#top: 4
+	sub: {
+		#sub: 5
+		a: {
+			3
+			#foo: 4
+		}
+		b: {
+			#bar: 5
+			#baz: "foo"
+			[1, 2]
+		}
+	}
+}
diff --git a/internal/core/export/value.go b/internal/core/export/value.go
index 7bf8f11..7b5e99f 100644
--- a/internal/core/export/value.go
+++ b/internal/core/export/value.go
@@ -48,7 +48,11 @@
 		result = e.structComposite(n)
 
 	case *adt.ListMarker:
-		result = e.listComposite(n)
+		if e.showArcs(n) {
+			result = e.structComposite(n)
+		} else {
+			result = e.listComposite(n)
+		}
 
 	case *adt.Bottom:
 		if !x.IsIncomplete() || len(n.Conjuncts) == 0 {
@@ -64,7 +68,11 @@
 		result = ast.NewBinExpr(token.AND, a...)
 
 	default:
-		result = e.value(n.Value, n.Conjuncts...)
+		if e.showArcs(n) {
+			result = e.structComposite(n)
+		} else {
+			result = e.value(n.Value, n.Conjuncts...)
+		}
 	}
 	return result
 }
@@ -297,6 +305,22 @@
 	return l
 }
 
+func (e exporter) showArcs(v *adt.Vertex) bool {
+	p := e.cfg
+	if !p.ShowHidden && !p.ShowDefinitions {
+		return false
+	}
+	for _, a := range v.Arcs {
+		switch {
+		case a.Label.IsDef() && p.ShowDefinitions:
+			return true
+		case a.Label.IsHidden() && p.ShowHidden:
+			return true
+		}
+	}
+	return false
+}
+
 func (e *exporter) structComposite(v *adt.Vertex) ast.Expr {
 	s, saved := e.pushFrame(v.Conjuncts)
 	e.top().upCount++
@@ -305,18 +329,32 @@
 		e.popFrame(saved)
 	}()
 
+	showRegular := false
+	switch x := v.Value.(type) {
+	case *adt.StructMarker:
+		showRegular = true
+	case *adt.ListMarker:
+		// As lists may be long, put them at the end.
+		defer e.addEmbed(e.listComposite(v))
+	default:
+		e.addEmbed(e.value(x))
+	}
+
 	p := e.cfg
 	for _, label := range VertexFeatures(v) {
-		if label.IsDef() && !p.ShowDefinitions {
+		show := false
+		switch label.Typ() {
+		case adt.StringLabel:
+			show = showRegular
+		case adt.IntLabel:
 			continue
+		case adt.DefinitionLabel:
+			show = p.ShowDefinitions
+		case adt.HiddenLabel, adt.HiddenDefinitionLabel:
+			show = p.ShowHidden && label.PkgID(e.ctx) == e.pkgID
 		}
-		if label.IsHidden() {
-			if !p.ShowHidden {
-				continue
-			}
-			if label.PkgID(e.ctx) != e.pkgID {
-				continue
-			}
+		if !show {
+			continue
 		}
 
 		f := &ast.Field{Label: e.stringLabel(label)}