cue: implement "front-style" list comprehensions

This now also allows any of the non-JSON keywords
to be used as references. Previously, these were already
supported as field names.

Issue #339
Issue #165

Change-Id: I721d054c8220ba3536f680fe2e3e502a62f99b6b
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/5683
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/doc/tutorial/kubernetes/manual/services/cloud.cue b/doc/tutorial/kubernetes/manual/services/cloud.cue
index bf86197..e16bbff 100644
--- a/doc/tutorial/kubernetes/manual/services/cloud.cue
+++ b/doc/tutorial/kubernetes/manual/services/cloud.cue
@@ -26,7 +26,7 @@
 	port: [string]: int
 
 	arg: [string]: string
-	args: [ "-\(k)=\(v)" for k, v in arg ] | [...string]
+	args: [ for k, v in arg { "-\(k)=\(v)" } ] | [...string]
 
 	// Environment variables
 	env: [string]: string
diff --git a/doc/tutorial/kubernetes/manual/services/k8s.cue b/doc/tutorial/kubernetes/manual/services/k8s.cue
index cefab64..381e483 100644
--- a/doc/tutorial/kubernetes/manual/services/k8s.cue
+++ b/doc/tutorial/kubernetes/manual/services/k8s.cue
@@ -84,13 +84,13 @@
 			image: X.image
 			args:  X.args
 			if len(X.envSpec) > 0 {
-				env: [ {name: k} & v for k, v in X.envSpec ]
+				env: [ for k, v in X.envSpec {v, name: k} ]
 			}
 
-			ports: [ {
+			ports: [ for k, p in X.expose.port & X.port {
 				name:          k
 				containerPort: p
-			} for k, p in X.expose.port & X.port ]
+			} ]
 		}]
 	}
 
@@ -98,7 +98,11 @@
 	spec: template: spec: {
 		if len(X.volume) > 0 {
 			volumes: [
-					v.kubernetes & {name: v.name} for v in X.volume
+				for v in X.volume {
+					v.kubernetes
+
+					name: v.name
+				}
 			]
 		}
 
@@ -106,16 +110,17 @@
 			// TODO: using conversions this would look like:
 			// volumeMounts: [ k8s.VolumeMount(v) for v in d.volume ]
 			if len(X.volume) > 0 {
-				volumeMounts: [ {
-					name:      v.name
-					mountPath: v.mountPath
-					if v.subPath != null | true {
-						subPath: v.subPath
+				volumeMounts: [
+					for v in X.volume {
+						name:      v.name
+						mountPath: v.mountPath
+						if v.subPath != null | true {
+							subPath: v.subPath
+						}
+						if v.readOnly {
+							readOnly: v.readOnly
+						}
 					}
-					if v.readOnly {
-						readOnly: v.readOnly
-					}
-				} for v in X.volume
 				]
 			}
 		}]
diff --git a/doc/tutorial/kubernetes/manual/services/kube_tool.cue b/doc/tutorial/kubernetes/manual/services/kube_tool.cue
index b41cea0..0ca9d0f 100644
--- a/doc/tutorial/kubernetes/manual/services/kube_tool.cue
+++ b/doc/tutorial/kubernetes/manual/services/kube_tool.cue
@@ -1,6 +1,6 @@
 package kube
 
-objects: [ x for v in objectSets for x in v ]
+objects: [ for v in objectSets for x in v { x } ]
 
 objectSets: [
 	kubernetes.services,
diff --git a/doc/tutorial/kubernetes/manual/services/ls_tool.cue b/doc/tutorial/kubernetes/manual/services/ls_tool.cue
index d82e2af..d5739ba 100644
--- a/doc/tutorial/kubernetes/manual/services/ls_tool.cue
+++ b/doc/tutorial/kubernetes/manual/services/ls_tool.cue
@@ -6,8 +6,10 @@
 	task: print: {
 		kind: "print"
 		Lines = [
-			"\(x.kind)  \t\(x.metadata.labels.component)   \t\(x.metadata.name)"
-			for x in objects ]
+			for x in objects {
+				"\(x.kind)  \t\(x.metadata.labels.component)   \t\(x.metadata.name)"
+			}
+		]
 		text: strings.Join(Lines, "\n")
 	}
 }