Skip to content

Commit

Permalink
internal/core/eval: nested comprehension fix
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
mpvl committed Jul 30, 2020
1 parent 845df05 commit 304b02e
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 6 deletions.
92 changes: 92 additions & 0 deletions cue/testdata/comprehensions/nested2.txtar
Original file line number Diff line number Diff line change
@@ -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
}
}
}
}
14 changes: 8 additions & 6 deletions internal/core/eval/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -1482,11 +1482,11 @@ func (n *nodeContext) expandOne() (done bool) {
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
}

Expand Down Expand Up @@ -1542,7 +1542,7 @@ func (n *nodeContext) injectDynamic() (progress bool) {
// 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
Expand All @@ -1554,12 +1554,13 @@ func (n *nodeContext) injectEmbedded(all []envYield) (a []envYield, progress boo
}

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.
Expand All @@ -1573,7 +1574,8 @@ func (n *nodeContext) injectEmbedded(all []envYield) (a []envYield, progress boo
}
}

return all[:k], k < len(all)
*all = (*all)[:k]
return k < len(*all)
}

// addLists
Expand Down

0 comments on commit 304b02e

Please sign in to comment.