internal/core/eval: nested comprehension fix

While iterating over comprehension to execute, new
ones may be added.

The iterator terminated at the end of the start of the
iteration, however, and the added elements were
promptly deleted.

Change-Id: I22b420e5d9fbb0a7c8b783ae1620aee3775f0bca
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6761
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/testdata/comprehensions/nested2.txtar b/cue/testdata/comprehensions/nested2.txtar
new file mode 100644
index 0000000..df3fc90
--- /dev/null
+++ b/cue/testdata/comprehensions/nested2.txtar
@@ -0,0 +1,92 @@
+-- in.cue --
+given: {
+	INC: USD: 2.0
+	USD: GBP: 3.0
+}
+hydrated: {
+	for k,v in given {
+		for k1,r in v {
+			"\(k)": "\(k)":  1.0
+			"\(k1)": "\(k1)": 1.0
+			"\(k)": "\(k1)": r
+			"\(k1)": "\(k)": number
+		}
+	}
+}
+
+foo: {
+    a: 10
+    if a < 20 {
+        if a < 50 {
+            b: 20
+        }
+    }
+}
+-- out/eval --
+(struct){
+  given: (struct){
+    INC: (struct){
+      USD: (float){ 2.0 }
+    }
+    USD: (struct){
+      GBP: (float){ 3.0 }
+    }
+  }
+  hydrated: (struct){
+    INC: (struct){
+      INC: (float){ 1.0 }
+      USD: (float){ 2.0 }
+    }
+    USD: (struct){
+      USD: (float){ 1.0 }
+      INC: (number){ number }
+      GBP: (float){ 3.0 }
+    }
+    GBP: (struct){
+      GBP: (float){ 1.0 }
+      USD: (number){ number }
+    }
+  }
+  foo: (struct){
+    a: (int){ 10 }
+    b: (int){ 20 }
+  }
+}
+-- out/compile --
+--- in.cue
+{
+  given: {
+    INC: {
+      USD: 2.0
+    }
+    USD: {
+      GBP: 3.0
+    }
+  }
+  hydrated: {
+    for k, v in 〈1;given〉 {
+      for k1, r in 〈1;v〉 {
+        "\(〈3;k〉)": {
+          "\(〈4;k〉)": 1.0
+        }
+        "\(〈1;k1〉)": {
+          "\(〈2;k1〉)": 1.0
+        }
+        "\(〈3;k〉)": {
+          "\(〈2;k1〉)": 〈2;r〉
+        }
+        "\(〈1;k1〉)": {
+          "\(〈4;k〉)": number
+        }
+      }
+    }
+  }
+  foo: {
+    a: 10
+    if (〈0;a〉 < 20) {
+      if (〈1;a〉 < 50) {
+        b: 20
+      }
+    }
+  }
+}
diff --git a/internal/core/eval/eval.go b/internal/core/eval/eval.go
index 8b58c7e..3298f7d 100644
--- a/internal/core/eval/eval.go
+++ b/internal/core/eval/eval.go
@@ -1482,11 +1482,11 @@
 		return true
 	}
 
-	if n.ifClauses, progress = n.injectEmbedded(n.ifClauses); progress {
+	if progress = n.injectEmbedded(&(n.ifClauses)); progress {
 		return true
 	}
 
-	if n.forClauses, progress = n.injectEmbedded(n.forClauses); progress {
+	if progress = n.injectEmbedded(&(n.forClauses)); progress {
 		return true
 	}
 
@@ -1542,7 +1542,7 @@
 // injectEmbedded evaluates and inserts embeddings. It first evaluates all
 // embeddings before inserting the results to ensure that the order of
 // evaluation does not matter.
-func (n *nodeContext) injectEmbedded(all []envYield) (a []envYield, progress bool) {
+func (n *nodeContext) injectEmbedded(all *[]envYield) (progress bool) {
 	ctx := n.ctx
 	type envStruct struct {
 		env *adt.Environment
@@ -1554,12 +1554,13 @@
 	}
 
 	k := 0
-	for _, d := range all {
+	for i := 0; i < len(*all); i++ {
+		d := (*all)[i]
 		sa = sa[:0]
 
 		if err := ctx.Yield(d.env, d.yield, f); err != nil {
 			if err.IsIncomplete() {
-				all[k] = d
+				(*all)[k] = d
 				k++
 			} else {
 				// continue to collect other errors.
@@ -1573,7 +1574,8 @@
 		}
 	}
 
-	return all[:k], k < len(all)
+	*all = (*all)[:k]
+	return k < len(*all)
 }
 
 // addLists