internal/core/export: fix quoting of definitions

IsValidIdent passes for definitions and hidden fields,
so this should be handled separately.

Also added some tests in compile, although this is not necessary.

Fixes #746

Change-Id: I38024a9391e985bc2f87c401c5682ed5f64d6421
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/8705
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/testdata/compile/fields.txtar b/cue/testdata/compile/fields.txtar
new file mode 100644
index 0000000..c94bc29
--- /dev/null
+++ b/cue/testdata/compile/fields.txtar
@@ -0,0 +1,20 @@
+-- in.cue --
+#dev:   int
+"#dev": int
+_dev:   int
+_#dev:  int
+-- out/compile --
+--- in.cue
+{
+  #dev: int
+  "#dev": int
+  _dev: int
+  _#dev: int
+}
+-- out/eval --
+(struct){
+  #dev: (int){ int }
+  "#dev": (int){ int }
+  _dev: (int){ int }
+  _#dev: (int){ int }
+}
diff --git a/internal/core/export/label.go b/internal/core/export/label.go
index d5128f6..4e62d9e 100644
--- a/internal/core/export/label.go
+++ b/internal/core/export/label.go
@@ -16,6 +16,7 @@
 
 import (
 	"strconv"
+	"strings"
 
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/literal"
@@ -35,7 +36,8 @@
 
 	case adt.StringLabel:
 		s := e.ctx.IndexToString(int64(x))
-		if f == 0 || !ast.IsValidIdent(s) {
+		if f == 0 || !ast.IsValidIdent(s) ||
+			strings.HasPrefix(s, "#") || strings.HasPrefix(s, "_") {
 			return ast.NewLit(token.STRING, literal.Label.Quote(s))
 		}
 		fallthrough
diff --git a/internal/core/export/testdata/labels.txtar b/internal/core/export/testdata/labels.txtar
new file mode 100644
index 0000000..c030163
--- /dev/null
+++ b/internal/core/export/testdata/labels.txtar
@@ -0,0 +1,89 @@
+-- in.cue --
+package foo
+
+#def:   int
+"#def": int
+_def:   int
+_#def:  int
+
+a: {
+    #def:   int
+    "#def": int
+    _def:   int
+    _#def:  int
+}
+
+-- out/definition --
+package foo
+
+#def:   int
+"#def": int
+_def:   int
+_#def:  int
+a: {
+	#def:   int
+	"#def": int
+	_def:   int
+	_#def:  int
+}
+-- out/doc --
+[]
+[#def]
+["#def"]
+[_def]
+[_#def]
+[a]
+[a #def]
+[a "#def"]
+[a _def]
+[a _#def]
+-- out/value --
+== Simplified
+{
+	"#def": int
+	a: {
+		"#def": int
+	}
+}
+== Raw
+{
+	#def:   int
+	"#def": int
+	_def:   int
+	_#def:  int
+	a: {
+		#def:   int
+		"#def": int
+		_def:   int
+		_#def:  int
+	}
+}
+== Final
+{
+	"#def": int
+	a: {
+		"#def": int
+	}
+}
+== All
+{
+	#def:   int
+	"#def": int
+	_def:   int
+	_#def:  int
+	a: {
+		#def:   int
+		"#def": int
+		_def:   int
+		_#def:  int
+	}
+}
+== Eval
+{
+	#def:   int
+	"#def": int
+	a: {
+		#def:   int
+		"#def": int
+	}
+}