cmd/cue/cmd: fix bug in resolving builtin package shorthands

Regression resulted in supporting only top-level
builtin packages.

Fixes #999

Change-Id: Ia22ed7435e59cf788e0664cff222eae1887c3b0d
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9902
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
diff --git a/cmd/cue/cmd/testdata/script/eval_e.txt b/cmd/cue/cmd/testdata/script/eval_e.txt
index 7d36f10..4723c7f 100644
--- a/cmd/cue/cmd/testdata/script/eval_e.txt
+++ b/cmd/cue/cmd/testdata/script/eval_e.txt
@@ -11,6 +11,10 @@
 ! cue eval foo.bar
 cmp stderr expect/foobar/stderr
 
+# Issue #999
+cue export --out text -e 'yaml.MarshalStream(X)' issue999/x.cue
+cmp stdout expect/issue999/stdout
+
 -- expect/nonExist/stdout --
 -- expect/nonExist/stderr --
 reference "nonExist" not found:
@@ -42,3 +46,18 @@
 Settings: {}
 blah: Settings.anyKey
 
+-- issue999/x.cue --
+X: [
+	{
+		a: 1
+	},
+	{
+		b: 2
+	},
+]
+
+-- expect/issue999/stdout --
+a: 1
+---
+b: 2
+
diff --git a/cue/context.go b/cue/context.go
index e3831a4..bf04091 100644
--- a/cue/context.go
+++ b/cue/context.go
@@ -100,10 +100,7 @@
 func InferBuiltins(elide bool) BuildOption {
 	return func(o *runtime.Config) {
 		o.Imports = func(x *ast.Ident) (pkgPath string) {
-			if !o.Runtime.IsBuiltinPackage(x.Name) {
-				return ""
-			}
-			return x.Name
+			return o.Runtime.BuiltinPackagePath(x.Name)
 		}
 	}
 }
diff --git a/internal/core/runtime/imports.go b/internal/core/runtime/imports.go
index 97f718d..694a0bb 100644
--- a/internal/core/runtime/imports.go
+++ b/internal/core/runtime/imports.go
@@ -30,16 +30,24 @@
 }
 
 func (x *index) RegisterBuiltin(importPath string, f PackageFunc) {
-	if x.builtins == nil {
-		x.builtins = map[string]PackageFunc{}
+	if x.builtinPaths == nil {
+		x.builtinPaths = map[string]PackageFunc{}
+		x.builtinShort = map[string]string{}
 	}
-	x.builtins[importPath] = f
+	x.builtinPaths[importPath] = f
+	base := path.Base(importPath)
+	if _, ok := x.builtinShort[base]; ok {
+		importPath = "" // Don't allow ambiguous base paths.
+	}
+	x.builtinShort[base] = importPath
 }
 
 var SharedRuntime = &Runtime{index: sharedIndex}
 
-func (x *Runtime) IsBuiltinPackage(path string) bool {
-	return x.index.isBuiltin(path)
+// BuiltinPackagePath converts a short-form builtin package identifier to its
+// full path or "" if this doesn't exist.
+func (x *Runtime) BuiltinPackagePath(path string) string {
+	return x.index.shortBuiltinToPath(path)
 }
 
 // sharedIndex is used for indexing builtins and any other labels common to
@@ -55,7 +63,8 @@
 	imports        map[*adt.Vertex]*build.Instance
 	importsByPath  map[string]*adt.Vertex
 	importsByBuild map[*build.Instance]*adt.Vertex
-	builtins       map[string]PackageFunc
+	builtinPaths   map[string]PackageFunc // Full path
+	builtinShort   map[string]string      // Commandline shorthand
 
 	// mutex     sync.Mutex
 	typeCache sync.Map // map[reflect.Type]evaluated
@@ -71,12 +80,11 @@
 	return i
 }
 
-func (x *index) isBuiltin(id string) bool {
-	if x == nil || x.builtins == nil {
-		return false
+func (x *index) shortBuiltinToPath(id string) string {
+	if x == nil || x.builtinPaths == nil {
+		return ""
 	}
-	_, ok := x.builtins[id]
-	return ok
+	return x.builtinShort[id]
 }
 
 func (r *Runtime) AddInst(path string, key *adt.Vertex, p *build.Instance) {
@@ -107,8 +115,8 @@
 		return key, nil
 	}
 
-	if x.builtins != nil {
-		if f := x.builtins[importPath]; f != nil {
+	if x.builtinPaths != nil {
+		if f := x.builtinPaths[importPath]; f != nil {
 			p, err := f(r)
 			if err != nil {
 				return adt.ToVertex(&adt.Bottom{Err: err}), nil
diff --git a/internal/core/runtime/resolve.go b/internal/core/runtime/resolve.go
index 8d3940b..59ab5f2 100644
--- a/internal/core/runtime/resolve.go
+++ b/internal/core/runtime/resolve.go
@@ -83,7 +83,7 @@
 		name := path.Base(id)
 		if imp := p.LookupImport(id); imp != nil {
 			name = imp.PkgName
-		} else if _, ok := idx.builtins[id]; !ok {
+		} else if _, ok := idx.builtinPaths[id]; !ok {
 			errs = errors.Append(errs,
 				nodeErrorf(spec, "package %q not found", id))
 			continue