cue: fix compiler bug and improve debug print

empty labels were dropped by compiler

non-identifier keys are printed as strings

Change-Id: I1523114046301d87b8186d68b6865f1dbb144a79
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/4944
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/ast.go b/cue/ast.go
index 0e43a64..17996da 100644
--- a/cue/ast.go
+++ b/cue/ast.go
@@ -449,11 +449,9 @@
 			if !ok {
 				return v.errf(lab, "invalid field name: %v", lab)
 			}
-			if f != 0 {
-				val := v.walk(n.Value)
-				v.object.insertValue(v.ctx(), f, opt, isDef, val, attrs, v.doc)
-				v.doc = leftOverDoc
-			}
+			val := v.walk(n.Value)
+			v.object.insertValue(v.ctx(), f, opt, isDef, val, attrs, v.doc)
+			v.doc = leftOverDoc
 
 		default:
 			panic("cue: unknown label type")
diff --git a/cue/ast_test.go b/cue/ast_test.go
index 240105f..0aed17f 100644
--- a/cue/ast_test.go
+++ b/cue/ast_test.go
@@ -48,8 +48,9 @@
 		c: 4_5
 		d: "abc"
 		e: 3e2 // 3h1m2ss
+		"": 8
 		`,
-		out: "<0>{a: true, b: 2000, c: 45, d: \"abc\", e: 3e+2}",
+		out: `<0>{"": 8, a: true, b: 2000, c: 45, d: "abc", e: 3e+2}`,
 	}, {
 		in: `
 		a: null
@@ -99,10 +100,9 @@
 		b: int
 		c: float
 		d: bool
-		e: duration
-		f: string
+		e: string
 		`,
-		out: "<0>{a: _, b: int, c: float, d: bool, e: duration, f: string}",
+		out: "<0>{a: _, b: int, c: float, d: bool, e: string}",
 	}, {
 		in: `
 		a: null
@@ -225,7 +225,7 @@
 			C="\(a)": 5
 			c: C
 			`,
-		out: `<0>{[]: <1>(ID: string)-><2>{name: <1>.ID}, foo=bar: 3, a: <0>.foo=bar, bb: 4, b1: (<0>.bb & <0>.bb), c: <0>[""+<0>.a+""]""+<0>.a+"": 5}`,
+		out: `<0>{[]: <1>(ID: string)-><2>{name: <1>.ID}, "foo=bar": 3, a: <0>.foo=bar, bb: 4, b1: (<0>.bb & <0>.bb), c: <0>[""+<0>.a+""]""+<0>.a+"": 5}`,
 	}, {
 		// optional fields with key filters
 		in: `
diff --git a/cue/debug.go b/cue/debug.go
index e525c17..c4b0cfc 100644
--- a/cue/debug.go
+++ b/cue/debug.go
@@ -16,6 +16,7 @@
 
 import (
 	"bytes"
+	"cuelang.org/go/cue/ast"
 	"fmt"
 	"strconv"
 	"strings"
@@ -367,10 +368,9 @@
 
 	case arc:
 		n := x.v
-		orig := p.label(x.feature)
-		str := strconv.Quote(orig)
-		if len(orig)+2 == len(str) {
-			str = str[1 : len(str)-1]
+		str := p.label(x.feature)
+		if !ast.IsValidIdent(str) {
+			str = strconv.Quote(str)
 		}
 		p.writef(str)
 		if x.optional {
diff --git a/cue/go_test.go b/cue/go_test.go
index d83d847..1a554cf 100644
--- a/cue/go_test.go
+++ b/cue/go_test.go
@@ -106,7 +106,7 @@
 	}, {
 		map[struct{}]int{struct{}{}: 2}, "_|_(unsupported Go type for map key (struct {}))",
 	}, {
-		map[int]int{1: 2}, "<0>{1: 2}",
+		map[int]int{1: 2}, `<0>{"1": 2}`,
 	}, {
 		struct {
 			a int
diff --git a/cue/resolve_test.go b/cue/resolve_test.go
index c4871fc..548bd2e 100644
--- a/cue/resolve_test.go
+++ b/cue/resolve_test.go
@@ -577,7 +577,7 @@
 		out: "<0>{a: 3, b: <1>{c: <2>{d: 3}}, c: <3>{c: 2}, d: <4>{d: 2}}",
 	}, {
 		in:  "`foo-bar`: 3\n x: `foo-bar`,",
-		out: `<0>{x: 3, foo-bar: 3}`,
+		out: `<0>{x: 3, "foo-bar": 3}`,
 	}, {
 		desc: "resolution of quoted identifiers",
 		in: `
@@ -591,7 +591,7 @@
 	` + "`qux-quux`" + `: qux
 	"qaz":      ` + "`qux-quux`" + `
 }`,
-		out: "<0>{foo-bar: 2, baz: 2, a: <1>{qux: 3, qux-quux: 3, qaz: 3}}",
+		out: `<0>{"foo-bar": 2, baz: 2, a: <1>{qux: 3, "qux-quux": 3, qaz: 3}}`,
 	}, {
 		in: `
 			a: _
@@ -2288,7 +2288,7 @@
 		in: `
 			a: { for _, b in ["c"] { "\(b + ".")": "a" } }
 			`,
-		out: `<0>{a: <1>{c.: "a"}}`,
+		out: `<0>{a: <1>{"c.": "a"}}`,
 	}, {
 		desc: "recursive evaluation within list",
 		in: `
@@ -2630,7 +2630,7 @@
 		`,
 		out: `<0>{` +
 			`p: <1>{[]: <2>(ID: string)-><3>{name: <2>.ID}, }, ` +
-			`foo=bar: "str", ` +
+			`"foo=bar": "str", ` +
 			`a: "str", ` +
 			`bb: 4, ` +
 			`b1: 4, ` +
@@ -2833,7 +2833,7 @@
 			}
 		}
 		`,
-		out: `<0>{x: <1>{v: <2>{1: 2}, _p: 3}}`,
+		out: `<0>{x: <1>{v: <2>{"1": 2}, _p: 3}}`,
 	}, {
 		desc: "non-structural direct cycles",
 		in: `