-- 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}] } } // This should result in an incomplete error (a reference cycle error classifies // as incomplete). 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 }, ] } } // Issue #1666 issue1666: { #E: { f1: [string]: #E | [...#E] f2: [string]: t: #E } _e: #E _e: f2: a: _ e: _e & { f1: { for fk, s in _e.f2 { (fk): s.t } } } } // Issue #779: bidirectional projection // Should be allowed as long as the set of fields is not modified as a result // of a comprehension. issue779: { X: Y.message STATE: { for k, v in Y { if k != "message" { "\(k)": v } } } Y: STATE & { message: X } X: "test" STATE: { code: 101 } } // Comprehension ends up inserting in the same arcs over which it // is iterating. This is fine as long as the set is not altered. // Issue #1934 selfReferential: T1: { S: d: "bar" T: e: S: a: "foo" for s, v in S for t, _ in T { T: (t): S: (s): v } } // selfReferential comprehenion for list. // Issue #1934 selfReferential: list: { panels: [ for i, _ in panels { id: i } ] panels: [{}, {}, {}] } selfReferential: insertionError: { A: { foo: 1 for x in A { // May not insert foo3. Use dynamic references to force the // comprehension to be evaluated in the struct in which it is // defined. ("foo3"): 1 } } } // A comprehension should not recursively evaluated arcs, so that a // structural cycle can be avoided when unnecessary. selfReferential: acrossOr: t1: p1: { o: #Output & { retry: reject: "ok" } #AllOutputs: { reject: string resource: string retry: #Output } #Output: or([for name, config in #AllOutputs { (name): config }]) } selfReferential: acrossOr: t1: p2: { #Output: or([for name, config in #AllOutputs { (name): config }]) o: #Output & { retry: reject: "ok" } #AllOutputs: { reject: string resource: string retry: #Output } } selfReferential: acrossOr: t1: p3: { #Output: or([for name, config in #AllOutputs { (name): config }]) #AllOutputs: { reject: string resource: string retry: #Output } o: #Output & { retry: reject: "ok" } } selfReferential: acrossOr: t2: p1: { d: or([for x, y in #A { y }]) o: d & { b: 2 } #A: { d1: int d2: string d3: b: d } } selfReferential: acrossOr: t2: p2: { o: d & { b: 2 } d: or([for x, y in #A { y }]) #A: { d1: int d2: string d3: b: d } } selfReferential: acrossOr: t2: p3: { o: d & { b: 2 } #A: { d1: int d2: string d3: b: d } d: or([for x, y in #A { y }]) } issue1881: p1: { o: #Output & { retry: output: reject: "ok" } #AllOutputs: { reject: string resource: string retry: output: #Output } #Output: or([for name, config in #AllOutputs { (name): config }]) } issue1881: p2: { #AllOutputs: { reject: string resource: string retry: output: #Output } o: #Output & { retry: output: reject: "ok" } #Output: or([for name, config in #AllOutputs { (name): config }]) } issue1881: p3: { #AllOutputs: { reject: string resource: string retry: output: #Output } #Output: or([for name, config in #AllOutputs { (name): config }]) o: #Output & { retry: output: reject: "ok" } } siblingInsertion: t1: p1: { D: "logging": _ deployment: _ for k, v in deployment for k1, v2 in v.env2 { deployment: (k): env: (k1): v2 } for id, v in D { deployment: (id): env2: ENV: "True" } } siblingInsertion: t1: p2: { D: "logging": _ deployment: _ for id, v in D { deployment: (id): env2: ENV: "True" } for k, v in deployment for k1, v2 in v.env2 { deployment: (k): env: (k1): v2 } } siblingInsertion: t2: p1: { D: "logging": _ deployment: _ for k, v in deployment { for k1, v2 in v.env2 { deployment: (k): env: (k1): v2 } } for id, v in D { deployment: (id): env2: ENV: "True" } } siblingInsertion: t2: p2: { D: "logging": _ deployment: _ for k, v in deployment { for k1, v2 in v.env2 { deployment: (k): env: (k1): v2 } } for id, v in D { deployment: (id): env2: ENV: "True" } } // Issue #1407 // Ensure there is a useful error message. selfReferential: fail: { a: {} b: a.x != "" if b { } } // avoid infinite recursion issue2367: { a: _ for x in [a] {a: x} } -- out/eval/stats -- Leaks: 50 Freed: 1270 Reused: 1260 Allocs: 60 Retain: 145 Unifications: 832 Conjuncts: 2525 Disjuncts: 1404 -- out/eval -- Errors: selfReferential.insertionError.A: field foo3 not allowed by earlier comprehension or reference cycle Result: (_|_){ // [eval] 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){ } } } } issue1666: (struct){ #E: (#struct){ f1: (#struct){ } f2: (#struct){ } } _e: (#struct){ f1: (#struct){ } f2: (#struct){ a: (#struct){ t: (#struct){ f1: (#struct){ } f2: (#struct){ } } } } } e: (#struct){ f1: (#struct){ a: (#struct){ f1: (#struct){ } f2: (#struct){ } } } f2: (#struct){ a: (#struct){ t: (#struct){ f1: (#struct){ } f2: (#struct){ } } } } } } issue779: (struct){ X: (string){ "test" } STATE: (struct){ code: (int){ 101 } } Y: (struct){ message: (string){ "test" } code: (int){ 101 } } } selfReferential: (_|_){ // [eval] T1: (struct){ S: (struct){ d: (string){ "bar" } } T: (struct){ e: (struct){ S: (struct){ a: (string){ "foo" } d: (string){ "bar" } } } } } list: (struct){ panels: (#list){ 0: (struct){ id: (int){ 0 } } 1: (struct){ id: (int){ 1 } } 2: (struct){ id: (int){ 2 } } } } insertionError: (_|_){ // [eval] A: (_|_){ // [eval] selfReferential.insertionError.A: field foo3 not allowed by earlier comprehension or reference cycle foo: (int){ 1 } foo3: (int){ 1 } } } acrossOr: (struct){ t1: (struct){ p1: (struct){ o: (#struct){ retry: (#struct){ reject: (string){ "ok" } } } #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } p2: (struct){ #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } o: (#struct){ retry: (#struct){ reject: (string){ "ok" } } } #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } } p3: (struct){ #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } o: (#struct){ retry: (#struct){ reject: (string){ "ok" } } } } } t2: (struct){ p1: (struct){ d: ((int|string)){ |((int){ int }, (string){ string }) } o: (struct){ b: (int){ 2 } } #A: (#struct){ d1: (int){ int } d2: (string){ string } d3: (#struct){ b: ((int|string)){ |((int){ int }, (string){ string }) } } } } p2: (struct){ o: (struct){ b: (int){ 2 } } d: ((int|string)){ |((int){ int }, (string){ string }) } #A: (#struct){ d1: (int){ int } d2: (string){ string } d3: (#struct){ b: ((int|string)){ |((int){ int }, (string){ string }) } } } } p3: (struct){ o: (struct){ b: (int){ 2 } } #A: (#struct){ d1: (int){ int } d2: (string){ string } d3: (#struct){ b: ((int|string)){ |((int){ int }, (string){ string }) } } } d: ((int|string)){ |((int){ int }, (string){ string }) } } } } fail: (_|_){ // [incomplete] selfReferential.fail.b: undefined field: x: // ./in.cue:300:7 a: (struct){ } b: (_|_){ // [incomplete] selfReferential.fail.b: undefined field: x: // ./in.cue:300:7 } } } issue1881: (struct){ p1: (struct){ o: (#struct){ retry: (#struct){ output: (#struct){ reject: (string){ "ok" } } } } #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } } #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } p2: (struct){ #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } } o: (#struct){ retry: (#struct){ output: (#struct){ reject: (string){ "ok" } } } } #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } p3: (struct){ #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } } #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } o: (#struct){ retry: (#struct){ output: (#struct){ reject: (string){ "ok" } } } } } } siblingInsertion: (struct){ t1: (struct){ p1: (struct){ D: (struct){ logging: (_){ _ } } deployment: (struct){ logging: (struct){ env2: (struct){ ENV: (string){ "True" } } env: (struct){ ENV: (string){ "True" } } } } } p2: (struct){ D: (struct){ logging: (_){ _ } } deployment: (struct){ logging: (struct){ env2: (struct){ ENV: (string){ "True" } } env: (struct){ ENV: (string){ "True" } } } } } } t2: (struct){ p1: (struct){ D: (struct){ logging: (_){ _ } } deployment: (struct){ logging: (struct){ env2: (struct){ ENV: (string){ "True" } } env: (struct){ ENV: (string){ "True" } } } } } p2: (struct){ D: (struct){ logging: (_){ _ } } deployment: (struct){ logging: (struct){ env2: (struct){ ENV: (string){ "True" } } env: (struct){ ENV: (string){ "True" } } } } } } } issue2367: (struct){ a: (_){ _ } } } -- out/compile -- --- in.cue { A: { a: { parent: "" children: [ for k, v in 〈3;A〉 if (〈0;v〉.parent == 〈0;k〉) { 〈1;k〉 }, ] } b: { parent: "a" children: [ for k, v in 〈3;A〉 if (〈0;v〉.parent == 〈0;k〉) { 〈1;k〉 }, ] } } B: { a: { parent: "" children: [ for k, v in 〈3;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 〈3;A〉 if (〈0;v〉.parent == 〈3;-〉) { 〈1;k〉 }, ] } } } issue1666: { #E: { f1: { [string]: (〈2;#E〉|[ ...〈3;#E〉, ]) } f2: { [string]: { t: 〈3;#E〉 } } } _e: 〈0;#E〉 _e: { f2: { a: _ } } e: (〈0;_e〉 & { f1: { for fk, s in 〈2;_e〉.f2 { 〈1;fk〉: 〈1;s〉.t } } }) } issue779: { X: 〈0;Y〉.message STATE: { for k, v in 〈1;Y〉 { if (〈1;k〉 != "message") { "\(〈2;k〉)": 〈2;v〉 } } } Y: (〈0;STATE〉 & { message: 〈1;X〉 }) X: "test" STATE: { code: 101 } } selfReferential: { T1: { S: { d: "bar" } T: { e: { S: { a: "foo" } } } for s, v in 〈0;S〉 for t, _ in 〈1;T〉 { T: { 〈2;t〉: { S: { 〈5;s〉: 〈5;v〉 } } } } } } selfReferential: { list: { panels: [ for i, _ in 〈1;panels〉 { id: 〈1;i〉 }, ] panels: [ {}, {}, {}, ] } } selfReferential: { insertionError: { A: { foo: 1 for _, x in 〈1;A〉 { "foo3": 1 } } } } selfReferential: { acrossOr: { t1: { p1: { o: (〈0;#Output〉 & { retry: { reject: "ok" } }) #AllOutputs: { reject: string resource: string retry: 〈1;#Output〉 } #Output: or([ for name, config in 〈1;#AllOutputs〉 { 〈1;name〉: 〈1;config〉 }, ]) } } } } selfReferential: { acrossOr: { t1: { p2: { #Output: or([ for name, config in 〈1;#AllOutputs〉 { 〈1;name〉: 〈1;config〉 }, ]) o: (〈0;#Output〉 & { retry: { reject: "ok" } }) #AllOutputs: { reject: string resource: string retry: 〈1;#Output〉 } } } } } selfReferential: { acrossOr: { t1: { p3: { #Output: or([ for name, config in 〈1;#AllOutputs〉 { 〈1;name〉: 〈1;config〉 }, ]) #AllOutputs: { reject: string resource: string retry: 〈1;#Output〉 } o: (〈0;#Output〉 & { retry: { reject: "ok" } }) } } } } selfReferential: { acrossOr: { t2: { p1: { d: or([ for x, y in 〈1;#A〉 { 〈1;y〉 }, ]) o: (〈0;d〉 & { b: 2 }) #A: { d1: int d2: string d3: { b: 〈2;d〉 } } } } } } selfReferential: { acrossOr: { t2: { p2: { o: (〈0;d〉 & { b: 2 }) d: or([ for x, y in 〈1;#A〉 { 〈1;y〉 }, ]) #A: { d1: int d2: string d3: { b: 〈2;d〉 } } } } } } selfReferential: { acrossOr: { t2: { p3: { o: (〈0;d〉 & { b: 2 }) #A: { d1: int d2: string d3: { b: 〈2;d〉 } } d: or([ for x, y in 〈1;#A〉 { 〈1;y〉 }, ]) } } } } issue1881: { p1: { o: (〈0;#Output〉 & { retry: { output: { reject: "ok" } } }) #AllOutputs: { reject: string resource: string retry: { output: 〈2;#Output〉 } } #Output: or([ for name, config in 〈1;#AllOutputs〉 { 〈1;name〉: 〈1;config〉 }, ]) } } issue1881: { p2: { #AllOutputs: { reject: string resource: string retry: { output: 〈2;#Output〉 } } o: (〈0;#Output〉 & { retry: { output: { reject: "ok" } } }) #Output: or([ for name, config in 〈1;#AllOutputs〉 { 〈1;name〉: 〈1;config〉 }, ]) } } issue1881: { p3: { #AllOutputs: { reject: string resource: string retry: { output: 〈2;#Output〉 } } #Output: or([ for name, config in 〈1;#AllOutputs〉 { 〈1;name〉: 〈1;config〉 }, ]) o: (〈0;#Output〉 & { retry: { output: { reject: "ok" } } }) } } siblingInsertion: { t1: { p1: { D: { logging: _ } deployment: _ for k, v in 〈0;deployment〉 for k1, v2 in 〈0;v〉.env2 { deployment: { 〈3;k〉: { env: { 〈4;k1〉: 〈4;v2〉 } } } } for id, v in 〈0;D〉 { deployment: { 〈2;id〉: { env2: { ENV: "True" } } } } } } } siblingInsertion: { t1: { p2: { D: { logging: _ } deployment: _ for id, v in 〈0;D〉 { deployment: { 〈2;id〉: { env2: { ENV: "True" } } } } for k, v in 〈0;deployment〉 for k1, v2 in 〈0;v〉.env2 { deployment: { 〈3;k〉: { env: { 〈4;k1〉: 〈4;v2〉 } } } } } } } siblingInsertion: { t2: { p1: { D: { logging: _ } deployment: _ for k, v in 〈0;deployment〉 { for k1, v2 in 〈1;v〉.env2 { deployment: { 〈4;k〉: { env: { 〈4;k1〉: 〈4;v2〉 } } } } } for id, v in 〈0;D〉 { deployment: { 〈2;id〉: { env2: { ENV: "True" } } } } } } } siblingInsertion: { t2: { p2: { D: { logging: _ } deployment: _ for k, v in 〈0;deployment〉 { for k1, v2 in 〈1;v〉.env2 { deployment: { 〈4;k〉: { env: { 〈4;k1〉: 〈4;v2〉 } } } } } for id, v in 〈0;D〉 { deployment: { 〈2;id〉: { env2: { ENV: "True" } } } } } } } selfReferential: { fail: { a: {} b: (〈0;a〉.x != "") if 〈0;b〉 {} } } issue2367: { a: _ for _, x in [ 〈1;a〉, ] { a: 〈1;x〉 } } }