-- in.cue --
import "list"

a1list: [{1}]
let A1 = a1list
a1: 100*A1[0] + A1[0] @test(eq, 101)

a2list: [{2}]
let A2 = a2list
a2: b: 100*A2[0] + A2[0] @test(eq, 202)

a3list: [{3}]
let A3 = a3list
a3: b: c: 100*A3[0] + A3[0] @test(eq, 303)

a4list: [{4}]
let A4 = a4list
a4: [for x in A4 {v: 404}] @test(eq, [{v: 404}])

a5list: [{5}]
let A5 = a5list
a5: b: [for x in A5 {v: 505}] @test(eq, [{v: 505}])

a6list: [{6}]
let A6 = a6list
a6: b: c: [for x in A6 {v: 606}] @test(eq, [{v: 606}])

a7list: [{7}]
let A7 = a7list
a7: {for x in A7 {v: 707}} @test(eq, {v: 707})

a8list: [{8}]
let A8 = a8list
a8: b: {for x in A8 {v: 808}} @test(eq, {v: 808})

a9list: [{9}]
let A9 = a9list
a9: b: c: {for x in A9 {v: 909}} @test(eq, {v: 909})

// Issue #609:
// When a let value resolved to an incomplete value, it should pass this
// incomplete status to the expression in which it used. But 609 reported
// a gobbling of this incomplete status. The problem seemed to be not
// exclusive to the use of let, though.
incompleteLet: {
	input: [1, 2, 3, 4, 5]

	last: {
		min: list.Min(input)
		max: list.Max(input)
	}

	bar: {
		let mn = last.min
		let mx = list.max

		min: mn
		max: mx @test(err, code=incomplete, contains="undefined field: max", pos=[-3:17])
	}

	x: {
		if list.max < 0 {
		}
	}
	@test(eq, {
		input: [1, 2, 3, 4, 5]
		last: {min: 1, max: 5}
		bar: {
			min: 1
			max: _|_ @test(err, code=incomplete, contains="incompleteLet.bar.max: undefined field: max", pos=[10:17])
		}
		x: _|_ @test(err, code=incomplete, contains="incompleteLet.x: undefined field: max", pos=[17:11])
	})
}

// Let references should also work inside embedded scalars.
// Issue #1955
scalarReference: {
	inScalar: p0: {
		5
		let x = 6
		#b: x
		@test(eq, {5, #b: 6})
	}
	inScalar: p1: {
		#b: x
		let x = 6
		5
		@test(eq, {5, #b: 6})
	}
	inList: p0: {
		let x = { a: 1 }
		[ x ]
		@test(eq, [{a: 1}])
	}
	inList: p1: {
		[ x ]
		let x = { a: 1 }
		@test(eq, [{a: 1}])
	}
}

// Strange let declaration behavior: accessing the last element of a list via
// a let-bound variable failed when the let appeared before the list definition.
// https://cuelang.org/issue/1116
issue1116: {
	a: {
		#a: ["a", "b"]
		let List = #a
		List[len(List)-1]
		@test(eq, {"b", #a: ["a", "b"]})
	}
	b: {
		let List = #a
		List[len(List)-1]
		#a: ["a", "b"]
		@test(eq, {"b", #a: ["a", "b"]})
	}
}
-- out/errors.txt --
[incomplete] incompleteLet.bar.max: undefined field: max:
    ./in.cue:54:17
[incomplete] incompleteLet.x: undefined field: max:
    ./in.cue:61:11
-- out/todo.txt --
v2 reports a cycle error for issue1116.b (let List = #a before #a is defined):
  issue1116.b: let List#11 = (_|_){ // [incomplete] cycle error referencing #a }
v3 resolves this correctly using structure sharing: let List#11 = ~(issue1116.b.#a)
-- out/eval/stats --
Leaks:  4
Freed:  101
Reused: 73
Allocs: 32
Retain: 0

Unifications: 103
Conjuncts:    130
Disjuncts:    0
Notifications: 2

NumCloseIDs: 45
