
Issue #1969

-- in.cue --
import "list"

// All tests here should pass and the result of the okcN tests should be
// identical to those of the okoN tests.

xc: close({field: {}})
xo: field: {}

okc0: { if xc.undefined == _|_ {a: 1} }
oko0: { if xo.undefined == _|_ {a: 1} }

okc1: { if xc.undefined != _|_ {a: 1} }
oko1: { if xo.undefined != _|_ {a: 1} }

okc2: {
	if ({} & {s: [for y in xc.undefined {}]}) != _|_ {a: 1}
}

oko2: {
	if ({} & {s: [for y in xo.undefined {}]}) != _|_ {a: 1}
}

okc3: {
	if ({s: [for y in xc.undefined {}]}) != _|_ {a: 1}
}

oko3: {
	if ({s: [for y in xo.undefined {}]}) != _|_ {a: 1}
}

// Should Field s exist in okc or not? Depends on whether comparison to bottom
// is recursive or not. It probably should not.
// TODO: fix for new evaluator. But possibly address this with new builtins.
issue1969: okc: {
	let X = xc.undefined
	let Y = {} & {s: [for y in list.Range(0, X, 1) {}]}

	if Y != _|_ {Y}
}

issue1969: oko: {
	let X = xo.undefined
	let Y = {} & {s: [for y in list.Range(0, X, 1) {}]}

	if Y != _|_ {Y}
}
-- issue2245.cue --
yo: { f: int, g: f < 10 }
okyo: { if yo != _|_ {a: 1} }
okyog: { if yo.g != _|_ {a: 1} }

-- incomplete.cue --
// Comparing to string is not an error. But for legacy reasons we want to still
// support this. We intend to have more clean and precise behavior with the
// builtins isdefined, isvalid, and isconcrete.
checkIncomplete: t1: {
	f: [string]: {
		if a != _|_ {
			b: "d\(a)"
		}
		a: string
	}
	f: blah: {}
}

-- structs.cue --
structs: {
	bare: t1: ({y: 2} & {x: 3}) != _|_
	bare: f2: ({y: 2} & {x: 3}) == _|_
	bare: f3: ({x: 1, y: 2} & {x: 3}) != _|_
	bare: t4: ({x: 1, y: 2} & {x: 3}) == _|_

	select: t1: ({y: 2} & {x: 3}).y != _|_
	select: f2: ({y: 2} & {x: 3}).y == _|_
	select: f3: ({x: 1, y: 2} & {x: 3}).y != _|_
	select: t4: ({x: 1, y: 2} & {x: 3}).y == _|_
}

-- out/eval/stats --
Leaks:  7
Freed:  95
Reused: 90
Allocs: 12
Retain: 22

Unifications: 102
Conjuncts:    138
Disjuncts:    109
-- out/eval --
(struct){
  xc: (#struct){
    field: (struct){
    }
  }
  xo: (struct){
    field: (struct){
    }
  }
  okc0: (struct){
    a: (int){ 1 }
  }
  oko0: (struct){
    a: (int){ 1 }
  }
  okc1: (struct){
  }
  oko1: (struct){
  }
  okc2: (struct){
  }
  oko2: (struct){
    a: (int){ 1 }
  }
  okc3: (struct){
  }
  oko3: (struct){
    a: (int){ 1 }
  }
  issue1969: (struct){
    okc: (struct){
      let X#1 = (_|_){
        // [eval] issue1969.okc.X: undefined field: undefined:
        //     ./in.cue:35:13
      }
      let Y#2 = (_|_){
        // [eval]
        s: (_|_){
          // [eval] issue1969.okc.X: undefined field: undefined:
          //     ./in.cue:35:13
        }
      }
    }
    oko: (struct){
      let X#3 = (_|_){
        // [incomplete] issue1969.oko.X: undefined field: undefined:
        //     ./in.cue:42:13
      }
      let Y#4 = (struct){
        s: (_|_){
          // [incomplete] issue1969.oko.X: undefined field: undefined:
          //     ./in.cue:42:13
        }
      }
      s: (_|_){
        // [incomplete] issue1969.oko.X: undefined field: undefined:
        //     ./in.cue:42:13
      }
    }
  }
  checkIncomplete: (struct){
    t1: (struct){
      f: (struct){
        blah: (struct){
          a: (string){ string }
        }
      }
    }
  }
  yo: (struct){
    f: (int){ int }
    g: (_|_){
      // [incomplete] yo.g: non-concrete value int in operand to <:
      //     ./issue2245.cue:1:18
      //     ./issue2245.cue:1:10
    }
  }
  okyo: (struct){
    a: (int){ 1 }
  }
  okyog: (struct){
  }
  structs: (struct){
    bare: (struct){
      t1: (bool){ true }
      f2: (bool){ false }
      f3: (bool){ false }
      t4: (bool){ true }
    }
    select: (struct){
      t1: (bool){ true }
      f2: (bool){ false }
      f3: (bool){ false }
      t4: (bool){ true }
    }
  }
}
-- out/compile --
--- in.cue
{
  xc: close({
    field: {}
  })
  xo: {
    field: {}
  }
  okc0: {
    if (〈1;xc〉.undefined == _|_(explicit error (_|_ literal) in source)) {
      a: 1
    }
  }
  oko0: {
    if (〈1;xo〉.undefined == _|_(explicit error (_|_ literal) in source)) {
      a: 1
    }
  }
  okc1: {
    if (〈1;xc〉.undefined != _|_(explicit error (_|_ literal) in source)) {
      a: 1
    }
  }
  oko1: {
    if (〈1;xo〉.undefined != _|_(explicit error (_|_ literal) in source)) {
      a: 1
    }
  }
  okc2: {
    if (({} & {
      s: [
        for _, y in 〈3;xc〉.undefined {},
      ]
    }) != _|_(explicit error (_|_ literal) in source)) {
      a: 1
    }
  }
  oko2: {
    if (({} & {
      s: [
        for _, y in 〈3;xo〉.undefined {},
      ]
    }) != _|_(explicit error (_|_ literal) in source)) {
      a: 1
    }
  }
  okc3: {
    if ({
      s: [
        for _, y in 〈3;xc〉.undefined {},
      ]
    } != _|_(explicit error (_|_ literal) in source)) {
      a: 1
    }
  }
  oko3: {
    if ({
      s: [
        for _, y in 〈3;xo〉.undefined {},
      ]
    } != _|_(explicit error (_|_ literal) in source)) {
      a: 1
    }
  }
  issue1969: {
    okc: {
      let X#1 = 〈2;xc〉.undefined
      let Y#2 = ({} & {
        s: [
          for _, y in 〈import;list〉.Range(0, 〈2;let X#1〉, 1) {},
        ]
      })
      if (〈0;let Y#2〉 != _|_(explicit error (_|_ literal) in source)) {
        〈1;let Y#2〉
      }
    }
  }
  issue1969: {
    oko: {
      let X#3 = 〈2;xo〉.undefined
      let Y#4 = ({} & {
        s: [
          for _, y in 〈import;list〉.Range(0, 〈2;let X#3〉, 1) {},
        ]
      })
      if (〈0;let Y#4〉 != _|_(explicit error (_|_ literal) in source)) {
        〈1;let Y#4〉
      }
    }
  }
}
--- incomplete.cue
{
  checkIncomplete: {
    t1: {
      f: {
        [string]: {
          if (〈0;a〉 != _|_(explicit error (_|_ literal) in source)) {
            b: "d\(〈1;a〉)"
          }
          a: string
        }
      }
      f: {
        blah: {}
      }
    }
  }
}
--- issue2245.cue
{
  yo: {
    f: int
    g: (〈0;f〉 < 10)
  }
  okyo: {
    if (〈1;yo〉 != _|_(explicit error (_|_ literal) in source)) {
      a: 1
    }
  }
  okyog: {
    if (〈1;yo〉.g != _|_(explicit error (_|_ literal) in source)) {
      a: 1
    }
  }
}
--- structs.cue
{
  structs: {
    bare: {
      t1: (({
        y: 2
      } & {
        x: 3
      }) != _|_(explicit error (_|_ literal) in source))
    }
    bare: {
      f2: (({
        y: 2
      } & {
        x: 3
      }) == _|_(explicit error (_|_ literal) in source))
    }
    bare: {
      f3: (({
        x: 1
        y: 2
      } & {
        x: 3
      }) != _|_(explicit error (_|_ literal) in source))
    }
    bare: {
      t4: (({
        x: 1
        y: 2
      } & {
        x: 3
      }) == _|_(explicit error (_|_ literal) in source))
    }
    select: {
      t1: (({
        y: 2
      } & {
        x: 3
      }).y != _|_(explicit error (_|_ literal) in source))
    }
    select: {
      f2: (({
        y: 2
      } & {
        x: 3
      }).y == _|_(explicit error (_|_ literal) in source))
    }
    select: {
      f3: (({
        x: 1
        y: 2
      } & {
        x: 3
      }).y != _|_(explicit error (_|_ literal) in source))
    }
    select: {
      t4: (({
        x: 1
        y: 2
      } & {
        x: 3
      }).y == _|_(explicit error (_|_ literal) in source))
    }
  }
}
