encoding/yaml: eliminate use of ghodss yaml pkg

This implementation translates a CUE AST to yaml.Node
for the yaml.v3 package.

The new builtins now also verify the concreteness of
the value.  Closes #288.

Also, the extra roundtrip by ghodss translates CUE to
a map, which then causes the fields to be ordered
lexically, which is undesirable.
The new encoder leaves fields in CUE ordering
which is closer to the original ordering of the
fields. This causes large (desirable) changes in the
Kubernetes' demo validation data.

Change-Id: Iedd32c46b9738d9c367628087c918c4c70310e1d
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/5087
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/encoding/yaml/yaml.go b/encoding/yaml/yaml.go
index f972bd2..80c19b9 100644
--- a/encoding/yaml/yaml.go
+++ b/encoding/yaml/yaml.go
@@ -20,19 +20,13 @@
 	"bytes"
 	"io"
 
-	goyaml "github.com/ghodss/yaml"
-
 	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
+	cueyaml "cuelang.org/go/internal/encoding/yaml"
 	"cuelang.org/go/internal/third_party/yaml"
 	pkgyaml "cuelang.org/go/pkg/encoding/yaml"
 )
 
-// TODO: replace the ghodss YAML encoder. It has a few major issues:
-//   - it does not expose the underlying error, which means we lose valuable
-//     information.
-//   - comments and other meta data are lost.
-
 // Extract parses the YAML to a CUE expression. Streams are returned as a list
 // of the streamed values.
 func Extract(filename string, src interface{}) (*ast.File, error) {
@@ -79,7 +73,8 @@
 
 // Encode returns the YAML encoding of v.
 func Encode(v cue.Value) ([]byte, error) {
-	b, err := goyaml.Marshal(v)
+	n := v.Syntax(cue.Final())
+	b, err := cueyaml.Encode(n)
 	return b, err
 }
 
@@ -92,7 +87,8 @@
 		if i > 0 {
 			buf.WriteString("---\n")
 		}
-		b, err := goyaml.Marshal(iter.Value())
+		n := iter.Value().Syntax(cue.Final())
+		b, err := cueyaml.Encode(n)
 		if err != nil {
 			return nil, err
 		}