Skip to content

Commit

Permalink
internal/core/eval: fix hang in cyclic in comprehension evaluation
Browse files Browse the repository at this point in the history
Fixes #486

Change-Id: I8a7e42c3eaff476c3bae23b40f7cb0ae5658975c
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7502
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
  • Loading branch information
mpvl committed Oct 23, 2020
1 parent 635fbdd commit 1a2105e
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 3 deletions.
155 changes: 155 additions & 0 deletions cue/testdata/cycle/comprehension.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
-- in.cue --
// Allow lookup in partially evaluated struct as long as the end result is
// concrete.
A: {
a: {
parent: ""
children: [ for k, v in A if v.parent == k { k } ]
}
b: {
parent: "a"
children: [ for k, v in A if v.parent == k { k } ]
}
}

// TODO(errors): this should result in an incomplete error.
// A simplified control flow should help here.
B: {
a: {
parent: ""
children: [ for k, v in B for _, w in v.children { k } ]
}
}

// Issue #486
Issue486: {
A: {
a: {
parent: ""
children: [...string]
}
b: {
parent: "a"
children: [...string]
}
c: {
parent: "b"
children: [...string]
}
}

A: [Name=string]: {
children: [
for k, v in A
if v.parent == Name {
k
}
]
}
}
-- out/eval --
(struct){
A: (struct){
a: (struct){
parent: (string){ "" }
children: (#list){
}
}
b: (struct){
parent: (string){ "a" }
children: (#list){
}
}
}
B: (struct){
a: (struct){
parent: (string){ "" }
children: (#list){
}
}
}
Issue486: (struct){
A: (struct){
a: (struct){
parent: (string){ "" }
children: (#list){
0: (string){ "b" }
}
}
b: (struct){
parent: (string){ "a" }
children: (#list){
0: (string){ "c" }
}
}
c: (struct){
parent: (string){ "b" }
children: (#list){
}
}
}
}
}
-- out/compile --
--- in.cue
{
A: {
a: {
parent: ""
children: [
for k, v in 〈2;A〉 if (〈0;v〉.parent == 〈0;k〉) {
〈1;k〉
},
]
}
b: {
parent: "a"
children: [
for k, v in 〈2;A〉 if (〈0;v〉.parent == 〈0;k〉) {
〈1;k〉
},
]
}
}
B: {
a: {
parent: ""
children: [
for k, v in 〈2;B〉 for _, w in 〈0;v〉.children {
〈2;k〉
},
]
}
}
Issue486: {
A: {
a: {
parent: ""
children: [
...string,
]
}
b: {
parent: "a"
children: [
...string,
]
}
c: {
parent: "b"
children: [
...string,
]
}
}
A: {
[string]: {
children: [
for k, v in 〈2;A〉 if (〈0;v〉.parent == 〈2;-〉) {
〈1;k〉
},
]
}
}
}
}
8 changes: 5 additions & 3 deletions internal/core/adt/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ func (x *SelectorExpr) Source() ast.Node {
}

func (x *SelectorExpr) resolve(c *OpContext) *Vertex {
n := c.node(x.X, Partial)
n := c.node(x.X, EvaluatingArcs)
return c.lookup(n, x.Src.Sel.Pos(), x.Sel)
}

Expand All @@ -605,7 +605,7 @@ func (x *IndexExpr) Source() ast.Node {

func (x *IndexExpr) resolve(ctx *OpContext) *Vertex {
// TODO: support byte index.
n := ctx.node(x.X, Partial)
n := ctx.node(x.X, EvaluatingArcs)
i := ctx.value(x.Index)
f := ctx.Label(i)
return ctx.lookup(n, x.Src.Index.Pos(), f)
Expand Down Expand Up @@ -1171,8 +1171,10 @@ func (x *ForClause) Source() ast.Node {
}

func (x *ForClause) yield(c *OpContext, f YieldFunc) {
n := c.node(x.Src, Finalized)
n := c.node(x.Src, EvaluatingArcs)
for _, a := range n.Arcs {
c.Unify(c, a, Partial)

if !a.Label.IsRegular() {
continue
}
Expand Down

0 comments on commit 1a2105e

Please sign in to comment.