// Tests various evaluator stability fixes: panic in recursive disjunctions with
// list.FlattenN (issue3750), negative reference counter panic with pattern
// constraints and comprehensions (issue3780), fields dropped by for loop in let
// binding with disjunction (issue3770), and unexpected uninitialized node panic
// with if comprehensions and list comprehensions (issue3824).
-- issue3750.cue --
package p

import "list"

// evalv3 panic "incDependent: already closed" triggered by recursive
// disjunctions combined with list.FlattenN comprehensions.
// https://cuelang.org/issue/3750
issue3750: original: {
	out: #Foo & {
		sub: #Foo
	}

	#Foo: {
		sub: #Foo | #Bar
		meta: {
			strs: [...string]
			for _, w in list.FlattenN([strs], 1) {}
		}
	}

	#Bar: {
		kind: "bar"
		meta: strs: [...string]
	}
}

issue3750: reduced: {
	out: Foo & {sub: Foo}

	Foo: {
		sub: Foo | {a: b: _}
		a: {
			b: _
			for _, w in list.FlattenN([b], 1) {}
		}
	}
}
-- issue3780.cue --
import "strings"

// evalv3 "negative reference counter" panic when combining pattern
// constraints with comprehensions and conditional logic.
// https://cuelang.org/issue/3780
issue3780: panic1: {
	objs: #Objects & {}
	param!: bool
	if param {
		objs: obj1: {
			one: 1
			two: 2
		}
	}
	#Objects: [strings.HasPrefix("obj")]: {
		kind: "object"
		...
	}
}
issue3780: panic2: {
	parent: {
		objs: #Objects & {}
		param?: bool
		if param != _|_ {
			objs: obj1: {
				one: 1
				two: 2
			}
		}
		#Objects: [strings.HasPrefix("obj")]: {
			kind: "object"
			...
		}
	}
}
-- issue3770.cue --
// evalv3 regression: fields generated by a for loop in a let binding were
// dropped after unifying with a disjunctive type constraint.
// https://cuelang.org/issue/3770
issue3770: task: {
	m: {
		let t = ["x"]
		for m in t {
			(m): a: 1
		}
		x: b: 1
	}
	m: null | {}
	out: m.x.a
}
-- issue3824.cue --
// evalv3 panic: "unexpected uninitialized node" when combining if comprehensions
// with list comprehensions and disjunctive type constraints.
// https://cuelang.org/issue/3824
issue3824: panic: {
	thing: {
		spec: name: string
		outputField: string
	}

	val: string
	things: [_]: thing

	things: [_]: {
		spec: *{
			name: "self-signed"
		} | {...}
	}

	if true {
		things: "name": {}
		val: things["name"].outputField
	}
}
-- out/compile --
--- issue3750.cue
{
  issue3750: {
    original: {
      out: (〈0;#Foo〉 & {
        sub: 〈1;#Foo〉
      })
      #Foo: {
        sub: (〈1;#Foo〉|〈1;#Bar〉)
        meta: {
          strs: [
            ...string,
          ]
          for _, w in 〈import;list〉.FlattenN([
            〈1;strs〉,
          ], 1) {}
        }
      }
      #Bar: {
        kind: "bar"
        meta: {
          strs: [
            ...string,
          ]
        }
      }
    }
  }
  issue3750: {
    reduced: {
      out: (〈0;Foo〉 & {
        sub: 〈1;Foo〉
      })
      Foo: {
        sub: (〈1;Foo〉|{
          a: {
            b: _
          }
        })
        a: {
          b: _
          for _, w in 〈import;list〉.FlattenN([
            〈1;b〉,
          ], 1) {}
        }
      }
    }
  }
}
--- issue3770.cue
{
  issue3770: {
    task: {
      m: {
        let t#1 = [
          "x",
        ]
        for _, m in 〈0;let t#1〉 {
          〈1;m〉: {
            a: 1
          }
        }
        x: {
          b: 1
        }
      }
      m: (null|{})
      out: 〈0;m〉.x.a
    }
  }
}
--- issue3780.cue
{
  issue3780: {
    panic1: {
      objs: (〈0;#Objects〉 & {})
      param!: bool
      if 〈0;param〉 {
        objs: {
          obj1: {
            one: 1
            two: 2
          }
        }
      }
      #Objects: {
        [〈import;strings〉.HasPrefix("obj")]: {
          kind: "object"
          ...
        }
      }
    }
  }
  issue3780: {
    panic2: {
      parent: {
        objs: (〈0;#Objects〉 & {})
        param?: bool
        if (〈0;param〉 != _|_(explicit error (_|_ literal) in source)) {
          objs: {
            obj1: {
              one: 1
              two: 2
            }
          }
        }
        #Objects: {
          [〈import;strings〉.HasPrefix("obj")]: {
            kind: "object"
            ...
          }
        }
      }
    }
  }
}
--- issue3824.cue
{
  issue3824: {
    panic: {
      thing: {
        spec: {
          name: string
        }
        outputField: string
      }
      val: string
      things: {
        [_]: 〈1;thing〉
      }
      things: {
        [_]: {
          spec: (*{
            name: "self-signed"
          }|{
            ...
          })
        }
      }
      if true {
        things: {
          name: {}
        }
        val: 〈0;things〉["name"].outputField
      }
    }
  }
}
