# This file has fine-grained sharing tests.
-- in.cue --
// In each case, the number of output nodes should be linear in the input size.
//
// This means that in each case, the next line should not retrigger the
// computation of the previous field.

// 26 Nodes computed:
// f1: 5
// f2+: +3 each
binexpr: {
	f1: { out: x: 2 }
	f2: { out: x: f1.out.x + 1 }
	f3: { out: x: f2.out.x + 1 }
	f4: { out: x: f3.out.x + 1 }
	f5: { out: x: f4.out.x + 1 }
	f6: { out: x: f5.out.x + 1 }
	f7: { out: x: f6.out.x + 1 }
	f8: { out: x: f7.out.x + 1 } @test(eq, {out: {x: 9}})
}

// 26 Nodes computed:
// f1: 5
// f2+: +3 each
parenthesized: {
	f1: { out: x: 2 }
	f2: { out: x: (f1.out).x + 1 }
	f3: { out: x: (f2.out).x + 1 }
	f4: { out: x: (f3.out).x + 1 }
	f5: { out: x: (f4.out).x + 1 }
	f6: { out: x: (f5.out).x + 1 }
	f7: { out: x: (f6.out).x + 1 }
	f8: { out: x: (f7.out).x + 1 }  @test(eq, {out: {x: 9}})
}

// TODO(perf): fix
// 82 Nodes computed [O(n^2)]:
// f1: 5
// fn: +(n*2 + 1)
// SHOULD BE:
// 26 Nodes computed:
// f1: 5
// f2+: +3 each
embedded: {
	f1: { out: x: 2 }
	f2: { out: x: {f1.out}.x + 1 }
	f3: { out: x: {f2.out}.x + 1 }
	f4: { out: x: {f3.out}.x + 1 }
	f5: { out: x: {f4.out}.x + 1 }
	f6: { out: x: {f5.out}.x + 1 }
	f7: { out: x: {f6.out}.x + 1 }
	f8: { out: x: {f7.out}.x + 1 } @test(eq, {out: {x: 9}})
}

// TODO(perf): fix
// 82 Nodes computed [O(n^2)]:
// f1: 5
// fn: +(n*2 + 1) each
// SHOULD BE:
// 26 Nodes computed:
// f1: 5
// f2+: +3 each
embeddedWithEmpty: {
	f1: { out: x: 2 }
	f2: { out: x: {f1.out & {}}.x + 1 }
	f3: { out: x: {f2.out & {}}.x + 1 }
	f4: { out: x: {f3.out & {}}.x + 1 }
	f5: { out: x: {f4.out & {}}.x + 1 }
	f6: { out: x: {f5.out & {}}.x + 1 }
	f7: { out: x: {f6.out & {}}.x + 1 }
	f8: { out: x: {f7.out & {}}.x + 1 } @test(eq, {out: {x: 9}})
}

// TODO(perf): fix
// This will visualize O(n^2) output size unless CUE allows for a bit more
// sophisticated sharing.
weave: {
	f:  X={
		out: in + 1
		in:  X.ref.out + 1
		ref: _ & {}
	}
	f8: f&{ ref: f7 }
	f7: f&{ ref: f6 }
	f6: f&{ ref: f5 }
	f5: f&{ ref: f4 }
	f4: f&{ ref: f3 }
	f3: f&{ ref: f2 } @test(eq, {ref: {ref: {out: 2}, out: 4, in: 3}, out: 6, in: 5 })
	f2: f&{ ref: f1 } @test(eq, {ref: {out: 2}, out: 4, in: 3})
	f1: { out: 2 }    @test(eq, {out: 2})
}
@test(eq, at=weave.f8, {
	ref: {
		ref: {
			ref: {
				ref: {
					ref: {
						ref: {ref: {out: 2}, out: 4, in: 3}
						out: 6
						in: 5
					}
					out: 8
					in: 7
				}
				out: 10
				in: 9
			}
			out: 12
			in: 11
		}
		out: 14
		in: 13
	}
	out: 16
	in: 15
})

// TODO(perf): fix
// This will visualize O(n^2) output size unless CUE supports fine-grained
// sharing.
weaveExtraField: {
	f:  X={
		out: in + 1
		in:  X.ref.out + 1
		ref: {y: 4} // Cannot share because of this, but sub arcs still can be.
	}
	f8: f&{ ref: f7 } @test(eq, 16, at=out)
	f7: f&{ ref: f6 }
	f6: f&{ ref: f5 }
	f5: f&{ ref: f4 }
	f4: f&{ ref: f3 }
	f3: f&{ ref: f2 }
	f2: f&{ ref: f1 } @test(eq, {ref: {y: 4, out: 2}, out: 4, in: 3})
	f1: { out: 2 }    @test(eq, {out: 2})
}
 @test(eq, at=weaveExtraField.f8, {
	ref: {
		y: 4
		ref: {
			y: 4
			ref: {
				y: 4
				ref: {
					y: 4
					ref: {
						y: 4
						ref: {
							y: 4
							ref: {y: 4, out: 2}
							out: 4
							in: 3
						}
						out: 6
						in: 5
					}
					out: 8
					in: 7
				}
				out: 10
				in: 9
			}
			out: 12
			in: 11
		}
		out: 14
		in: 13
	}
	out: 16
	in: 15
})
-- out/errors.txt --
[incomplete] weave.f.in: undefined field: out:
    ./in.cue:78:14
[incomplete] weave.f.in: undefined field: out:
    ./in.cue:78:14
[incomplete] weaveExtraField.f.in: undefined field: out:
    ./in.cue:122:14
[incomplete] weaveExtraField.f.in: undefined field: out:
    ./in.cue:122:14
-- out/eval/stats --
Leaks:  0
Freed:  452
Reused: 407
Allocs: 45
Retain: 0

Unifications: 452
Conjuncts:    845
Disjuncts:    0

NumCloseIDs: 238
-- out/todo.txt --
weave.f.out: v2 reports [cycle] error, v3 reports [incomplete] "undefined field: out".
weaveExtraField.f.out: same v2/v3 difference as weave.f.out.
