-- in.cue --
import "list"

a1list: [{1}]
let A1 = a1list
a1: 100*A1[0] + A1[0]

a2list: [{2}]
let A2 = a2list
a2: b: 100*A2[0] + A2[0]

a3list: [{3}]
let A3 = a3list
a3: b: c: 100*A3[0] + A3[0]

a4list: [{4}]
let A4 = a4list
a4: [for x in A4 {v: 404}]

a5list: [{5}]
let A5 = a5list
a5: b: [for x in A5 {v: 505}]

a6list: [{6}]
let A6 = a6list
a6: b: c: [for x in A6 {v: 606}]

a7list: [{7}]
let A7 = a7list
a7: {for x in A7 {v: 707}}

a8list: [{8}]
let A8 = a8list
a8: b: {for x in A8 {v: 808}}

a9list: [{9}]
let A9 = a9list
a9: b: c: {for x in A9 {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
	}

	x: {
		if list.max < 0 {
		}
	}
}

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

issue1116: {
	a: {
		#a: ["a", "b"]
		let List = #a
		List[len(List)-1]
	}
	b: {
		let List = #a
		List[len(List)-1]
		#a: ["a", "b"]
	}
}
-- out/compile --
--- in.cue
{
  a1list: [
    {
      1
    },
  ]
  let A1#1 = 〈0;a1list〉
  a1: ((100 * 〈0;let A1#1〉[0]) + 〈0;let A1#1〉[0])
  a2list: [
    {
      2
    },
  ]
  let A2#2 = 〈0;a2list〉
  a2: {
    b: ((100 * 〈1;let A2#2〉[0]) + 〈1;let A2#2〉[0])
  }
  a3list: [
    {
      3
    },
  ]
  let A3#3 = 〈0;a3list〉
  a3: {
    b: {
      c: ((100 * 〈2;let A3#3〉[0]) + 〈2;let A3#3〉[0])
    }
  }
  a4list: [
    {
      4
    },
  ]
  let A4#4 = 〈0;a4list〉
  a4: [
    for _, x in 〈1;let A4#4〉 {
      v: 404
    },
  ]
  a5list: [
    {
      5
    },
  ]
  let A5#5 = 〈0;a5list〉
  a5: {
    b: [
      for _, x in 〈2;let A5#5〉 {
        v: 505
      },
    ]
  }
  a6list: [
    {
      6
    },
  ]
  let A6#6 = 〈0;a6list〉
  a6: {
    b: {
      c: [
        for _, x in 〈3;let A6#6〉 {
          v: 606
        },
      ]
    }
  }
  a7list: [
    {
      7
    },
  ]
  let A7#7 = 〈0;a7list〉
  a7: {
    for _, x in 〈1;let A7#7〉 {
      v: 707
    }
  }
  a8list: [
    {
      8
    },
  ]
  let A8#8 = 〈0;a8list〉
  a8: {
    b: {
      for _, x in 〈2;let A8#8〉 {
        v: 808
      }
    }
  }
  a9list: [
    {
      9
    },
  ]
  let A9#9 = 〈0;a9list〉
  a9: {
    b: {
      c: {
        for _, x in 〈3;let A9#9〉 {
          v: 909
        }
      }
    }
  }
  incompleteLet: {
    input: [
      1,
      2,
      3,
      4,
      5,
    ]
    last: {
      min: 〈import;list〉.Min(〈1;input〉)
      max: 〈import;list〉.Max(〈1;input〉)
    }
    bar: {
      let mn#A = 〈1;last〉.min
      let mx#B = 〈import;list〉.max
      min: 〈0;let mn#A〉
      max: 〈0;let mx#B〉
    }
    x: {
      if (〈import;list〉.max < 0) {}
    }
  }
  scalarReference: {
    inScalar: {
      p0: {
        5
        let x#C = 6
        #b: 〈0;let x#C〉
      }
    }
    inScalar: {
      p1: {
        #b: 〈0;let x#D〉
        let x#D = 6
        5
      }
    }
    inList: {
      p0: {
        let x#E = {
          a: 1
        }
        [
          〈1;let x#E〉,
        ]
      }
    }
    inList: {
      p1: {
        [
          〈1;let x#F〉,
        ]
        let x#F = {
          a: 1
        }
      }
    }
  }
  issue1116: {
    a: {
      #a: [
        "a",
        "b",
      ]
      let List#10 = 〈0;#a〉
      〈0;let List#10〉[(len(〈0;let List#10〉) - 1)]
    }
    b: {
      let List#11 = 〈0;#a〉
      〈0;let List#11〉[(len(〈0;let List#11〉) - 1)]
      #a: [
        "a",
        "b",
      ]
    }
  }
}
-- out/eval/stats --
Leaks:  3
Freed:  112
Reused: 107
Allocs: 8
Retain: 10

Unifications: 115
Conjuncts:    169
Disjuncts:    117
-- out/evalalpha --
(struct){
  a1list: (#list){
    0: (int){ 1 }
  }
  let A1#1 = ~(a1list)
  a1: (int){ 101 }
  a2list: (#list){
    0: (int){ 2 }
  }
  let A2#2 = ~(a2list)
  a2: (struct){
    b: (int){ 202 }
  }
  a3list: (#list){
    0: (int){ 3 }
  }
  let A3#3 = ~(a3list)
  a3: (struct){
    b: (struct){
      c: (int){ 303 }
    }
  }
  a4list: (#list){
    0: (int){ 4 }
  }
  let A4#4 = ~(a4list)
  a4: (#list){
    0: (struct){
      v: (int){ 404 }
    }
  }
  a5list: (#list){
    0: (int){ 5 }
  }
  let A5#5 = ~(a5list)
  a5: (struct){
    b: (#list){
      0: (struct){
        v: (int){ 505 }
      }
    }
  }
  a6list: (#list){
    0: (int){ 6 }
  }
  let A6#6 = ~(a6list)
  a6: (struct){
    b: (struct){
      c: (#list){
        0: (struct){
          v: (int){ 606 }
        }
      }
    }
  }
  a7list: (#list){
    0: (int){ 7 }
  }
  let A7#7 = ~(a7list)
  a7: (struct){
    v: (int){ 707 }
  }
  a8list: (#list){
    0: (int){ 8 }
  }
  let A8#8 = ~(a8list)
  a8: (struct){
    b: (struct){
      v: (int){ 808 }
    }
  }
  a9list: (#list){
    0: (int){ 9 }
  }
  let A9#9 = ~(a9list)
  a9: (struct){
    b: (struct){
      c: (struct){
        v: (int){ 909 }
      }
    }
  }
  incompleteLet: (struct){
    input: (#list){
      0: (int){ 1 }
      1: (int){ 2 }
      2: (int){ 3 }
      3: (int){ 4 }
      4: (int){ 5 }
    }
    last: (struct){
      min: (int){ 1 }
      max: (int){ 5 }
    }
    bar: (struct){
      let mn#A = (int){ 1 }
      let mx#B = (_|_){
        // [incomplete] incompleteLet.bar.mx: undefined field: max:
        //     ./in.cue:54:17
      }
      min: (int){ 1 }
      max: (_|_){
        // [incomplete] incompleteLet.bar.max: undefined field: max:
        //     ./in.cue:54:17
      }
    }
    x: (_|_){
      // [incomplete] incompleteLet.x: undefined field: max:
      //     ./in.cue:61:11
    }
  }
  scalarReference: (struct){
    inScalar: (struct){
      p0: (int){
        5
        let x#C = (int){ 6 }
        #b: (int){ 6 }
      }
      p1: (int){
        5
        #b: (int){ 6 }
        let x#D = (int){ 6 }
      }
    }
    inList: (struct){
      p0: (#list){
        let x#E = (struct){
          a: (int){ 1 }
        }
        0: (struct){
          a: (int){ 1 }
        }
      }
      p1: (#list){
        let x#F = (struct){
          a: (int){ 1 }
        }
        0: (struct){
          a: (int){ 1 }
        }
      }
    }
  }
  issue1116: (struct){
    a: (string){
      "b"
      #a: (#list){
        0: (string){ "a" }
        1: (string){ "b" }
      }
      let List#10 = ~(issue1116.a.#a)
    }
    b: (string){
      "b"
      let List#11 = ~(issue1116.b.#a)
      #a: (#list){
        0: (string){ "a" }
        1: (string){ "b" }
      }
    }
  }
}
-- diff/-out/evalalpha<==>+out/eval --
diff old new
--- old
+++ new
@@ -2,16 +2,12 @@
   a1list: (#list){
     0: (int){ 1 }
   }
-  let A1#1 = (#list){
-    0: (int){ 1 }
-  }
+  let A1#1 = ~(a1list)
   a1: (int){ 101 }
   a2list: (#list){
     0: (int){ 2 }
   }
-  let A2#2 = (#list){
-    0: (int){ 2 }
-  }
+  let A2#2 = ~(a2list)
   a2: (struct){
     b: (int){ 202 }
   }
@@ -18,9 +14,7 @@
   a3list: (#list){
     0: (int){ 3 }
   }
-  let A3#3 = (#list){
-    0: (int){ 3 }
-  }
+  let A3#3 = ~(a3list)
   a3: (struct){
     b: (struct){
       c: (int){ 303 }
@@ -29,9 +23,7 @@
   a4list: (#list){
     0: (int){ 4 }
   }
-  let A4#4 = (#list){
-    0: (int){ 4 }
-  }
+  let A4#4 = ~(a4list)
   a4: (#list){
     0: (struct){
       v: (int){ 404 }
@@ -40,9 +32,7 @@
   a5list: (#list){
     0: (int){ 5 }
   }
-  let A5#5 = (#list){
-    0: (int){ 5 }
-  }
+  let A5#5 = ~(a5list)
   a5: (struct){
     b: (#list){
       0: (struct){
@@ -53,9 +43,7 @@
   a6list: (#list){
     0: (int){ 6 }
   }
-  let A6#6 = (#list){
-    0: (int){ 6 }
-  }
+  let A6#6 = ~(a6list)
   a6: (struct){
     b: (struct){
       c: (#list){
@@ -68,9 +56,7 @@
   a7list: (#list){
     0: (int){ 7 }
   }
-  let A7#7 = (#list){
-    0: (int){ 7 }
-  }
+  let A7#7 = ~(a7list)
   a7: (struct){
     v: (int){ 707 }
   }
@@ -77,9 +63,7 @@
   a8list: (#list){
     0: (int){ 8 }
   }
-  let A8#8 = (#list){
-    0: (int){ 8 }
-  }
+  let A8#8 = ~(a8list)
   a8: (struct){
     b: (struct){
       v: (int){ 808 }
@@ -88,9 +72,7 @@
   a9list: (#list){
     0: (int){ 9 }
   }
-  let A9#9 = (#list){
-    0: (int){ 9 }
-  }
+  let A9#9 = ~(a9list)
   a9: (struct){
     b: (struct){
       c: (struct){
@@ -166,17 +148,11 @@
         0: (string){ "a" }
         1: (string){ "b" }
       }
-      let List#10 = (#list){
-        0: (string){ "a" }
-        1: (string){ "b" }
-      }
+      let List#10 = ~(issue1116.a.#a)
     }
     b: (string){
       "b"
-      let List#11 = (_|_){
-        // [incomplete] issue1116.b.List: cycle error referencing #a:
-        //     ./in.cue:96:14
-      }
+      let List#11 = ~(issue1116.b.#a)
       #a: (#list){
         0: (string){ "a" }
         1: (string){ "b" }
-- out/eval --
(struct){
  a1list: (#list){
    0: (int){ 1 }
  }
  let A1#1 = (#list){
    0: (int){ 1 }
  }
  a1: (int){ 101 }
  a2list: (#list){
    0: (int){ 2 }
  }
  let A2#2 = (#list){
    0: (int){ 2 }
  }
  a2: (struct){
    b: (int){ 202 }
  }
  a3list: (#list){
    0: (int){ 3 }
  }
  let A3#3 = (#list){
    0: (int){ 3 }
  }
  a3: (struct){
    b: (struct){
      c: (int){ 303 }
    }
  }
  a4list: (#list){
    0: (int){ 4 }
  }
  let A4#4 = (#list){
    0: (int){ 4 }
  }
  a4: (#list){
    0: (struct){
      v: (int){ 404 }
    }
  }
  a5list: (#list){
    0: (int){ 5 }
  }
  let A5#5 = (#list){
    0: (int){ 5 }
  }
  a5: (struct){
    b: (#list){
      0: (struct){
        v: (int){ 505 }
      }
    }
  }
  a6list: (#list){
    0: (int){ 6 }
  }
  let A6#6 = (#list){
    0: (int){ 6 }
  }
  a6: (struct){
    b: (struct){
      c: (#list){
        0: (struct){
          v: (int){ 606 }
        }
      }
    }
  }
  a7list: (#list){
    0: (int){ 7 }
  }
  let A7#7 = (#list){
    0: (int){ 7 }
  }
  a7: (struct){
    v: (int){ 707 }
  }
  a8list: (#list){
    0: (int){ 8 }
  }
  let A8#8 = (#list){
    0: (int){ 8 }
  }
  a8: (struct){
    b: (struct){
      v: (int){ 808 }
    }
  }
  a9list: (#list){
    0: (int){ 9 }
  }
  let A9#9 = (#list){
    0: (int){ 9 }
  }
  a9: (struct){
    b: (struct){
      c: (struct){
        v: (int){ 909 }
      }
    }
  }
  incompleteLet: (struct){
    input: (#list){
      0: (int){ 1 }
      1: (int){ 2 }
      2: (int){ 3 }
      3: (int){ 4 }
      4: (int){ 5 }
    }
    last: (struct){
      min: (int){ 1 }
      max: (int){ 5 }
    }
    bar: (struct){
      let mn#A = (int){ 1 }
      let mx#B = (_|_){
        // [incomplete] incompleteLet.bar.mx: undefined field: max:
        //     ./in.cue:54:17
      }
      min: (int){ 1 }
      max: (_|_){
        // [incomplete] incompleteLet.bar.max: undefined field: max:
        //     ./in.cue:54:17
      }
    }
    x: (_|_){
      // [incomplete] incompleteLet.x: undefined field: max:
      //     ./in.cue:61:11
    }
  }
  scalarReference: (struct){
    inScalar: (struct){
      p0: (int){
        5
        let x#C = (int){ 6 }
        #b: (int){ 6 }
      }
      p1: (int){
        5
        #b: (int){ 6 }
        let x#D = (int){ 6 }
      }
    }
    inList: (struct){
      p0: (#list){
        let x#E = (struct){
          a: (int){ 1 }
        }
        0: (struct){
          a: (int){ 1 }
        }
      }
      p1: (#list){
        let x#F = (struct){
          a: (int){ 1 }
        }
        0: (struct){
          a: (int){ 1 }
        }
      }
    }
  }
  issue1116: (struct){
    a: (string){
      "b"
      #a: (#list){
        0: (string){ "a" }
        1: (string){ "b" }
      }
      let List#10 = (#list){
        0: (string){ "a" }
        1: (string){ "b" }
      }
    }
    b: (string){
      "b"
      let List#11 = (_|_){
        // [incomplete] issue1116.b.List: cycle error referencing #a:
        //     ./in.cue:96:14
      }
      #a: (#list){
        0: (string){ "a" }
        1: (string){ "b" }
      }
    }
  }
}
