pkg/encoding/yaml: request concrete data for syntax

Also fixes export to not  show
comprehensions in concrete mode.

Change-Id: Id803716f54e0c268421a9a6c48be97569c53277f
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/5253
Reviewed-by: roger peppe <rogpeppe@gmail.com>
diff --git a/cmd/cue/cmd/testdata/script/export_yaml.txt b/cmd/cue/cmd/testdata/script/export_yaml.txt
index 1fe971d..5677c7b 100644
--- a/cmd/cue/cmd/testdata/script/export_yaml.txt
+++ b/cmd/cue/cmd/testdata/script/export_yaml.txt
@@ -2,6 +2,7 @@
 cmp stdout expect-stdout
 -- expect-stdout --
 message: Hello World!
+test: {}
 -- hello/data.cue --
 package hello
 
@@ -10,4 +11,11 @@
 package hello
 
 message: "Hello \(who)!" // who declared in data.cue
+
+test: {
+	_foo: string // technically in error, but test anyway.
+	if len(_foo) > 0 {
+		command: ["foo", "bar"]
+	}
+}
 -- hello/cue.mod --
diff --git a/cue/builtins.go b/cue/builtins.go
index d350402..ffb39e6 100644
--- a/cue/builtins.go
+++ b/cue/builtins.go
@@ -643,7 +643,7 @@
 							}
 							return "", internal.ErrIncomplete
 						}
-						n := v.Syntax(Final())
+						n := v.Syntax(Final(), Concrete(true))
 						b, err := cueyaml.Encode(n)
 						return string(b), err
 					}()
@@ -674,7 +674,7 @@
 								}
 								return "", internal.ErrIncomplete
 							}
-							n := v.Syntax(Final())
+							n := v.Syntax(Final(), Concrete(true))
 							b, err := cueyaml.Encode(n)
 							if err != nil {
 								return "", err
diff --git a/cue/export.go b/cue/export.go
index 9ea215b..3279d2a 100644
--- a/cue/export.go
+++ b/cue/export.go
@@ -901,42 +901,44 @@
 		obj.Elts = append(obj.Elts, f)
 	}
 
-	for _, v := range x.comprehensions {
-		switch c := v.comp.(type) {
-		case *fieldComprehension:
-			l := p.expr(c.key)
-			label, _ := l.(ast.Label)
-			opt := token.NoPos
-			if c.opt {
-				opt = token.NoSpace.Pos() // anything but token.NoPos
-			}
-			tok := token.COLON
-			if c.def {
-				tok = token.ISA
-			}
-			f := &ast.Field{
-				Label:    label,
-				Optional: opt,
-				Token:    tok,
-				Value:    p.expr(c.val),
-			}
-			obj.Elts = append(obj.Elts, f)
-
-		case *structComprehension:
-			var clauses []ast.Clause
-			next := c.clauses
-			for {
-				if yield, ok := next.(*yield); ok {
-					obj.Elts = append(obj.Elts, &ast.Comprehension{
-						Clauses: clauses,
-						Value:   p.expr(yield.value),
-					})
-					break
+	if !p.mode.concrete {
+		for _, v := range x.comprehensions {
+			switch c := v.comp.(type) {
+			case *fieldComprehension:
+				l := p.expr(c.key)
+				label, _ := l.(ast.Label)
+				opt := token.NoPos
+				if c.opt {
+					opt = token.NoSpace.Pos() // anything but token.NoPos
 				}
+				tok := token.COLON
+				if c.def {
+					tok = token.ISA
+				}
+				f := &ast.Field{
+					Label:    label,
+					Optional: opt,
+					Token:    tok,
+					Value:    p.expr(c.val),
+				}
+				obj.Elts = append(obj.Elts, f)
 
-				var y ast.Clause
-				y, next = p.clause(next)
-				clauses = append(clauses, y)
+			case *structComprehension:
+				var clauses []ast.Clause
+				next := c.clauses
+				for {
+					if yield, ok := next.(*yield); ok {
+						obj.Elts = append(obj.Elts, &ast.Comprehension{
+							Clauses: clauses,
+							Value:   p.expr(yield.value),
+						})
+						break
+					}
+
+					var y ast.Clause
+					y, next = p.clause(next)
+					clauses = append(clauses, y)
+				}
 			}
 		}
 	}
diff --git a/cue/export_test.go b/cue/export_test.go
index e1d5eca..af303e0 100644
--- a/cue/export_test.go
+++ b/cue/export_test.go
@@ -1064,6 +1064,31 @@
 			a:  int
 			b?: string
 		}`),
+	}, {
+		// Drop comprehensions in final mode.
+		eval: true,
+		opts: []Option{Final(), Concrete(true)},
+		in: `
+		foo: _
+		a: {
+			if len(foo.bar) > 0 {
+				command: ["envoy-lifecycle", string]
+			}
+		}
+		`,
+		out: unindent(`
+		{
+			foo: _
+			a: {}
+		}`),
+	}, {
+		// Don't output hidden fields in concrete and final mode.
+		eval: true,
+		opts: []Option{Final(), Concrete(true)},
+		in: `
+			_foo: _
+			`,
+		out: `{}`,
 	}}
 	for _, tc := range testCases {
 		t.Run("", func(t *testing.T) {
diff --git a/pkg/encoding/yaml/manual.go b/pkg/encoding/yaml/manual.go
index 4697982..e35a060 100644
--- a/pkg/encoding/yaml/manual.go
+++ b/pkg/encoding/yaml/manual.go
@@ -33,7 +33,7 @@
 		}
 		return "", internal.ErrIncomplete
 	}
-	n := v.Syntax(cue.Final())
+	n := v.Syntax(cue.Final(), cue.Concrete(true))
 	b, err := cueyaml.Encode(n)
 	return string(b), err
 }
@@ -57,7 +57,7 @@
 			}
 			return "", internal.ErrIncomplete
 		}
-		n := v.Syntax(cue.Final())
+		n := v.Syntax(cue.Final(), cue.Concrete(true))
 		b, err := cueyaml.Encode(n)
 		if err != nil {
 			return "", err