# Some new cases specific to v0.7
-- builtins.cue --
import "strings"

mutualBuiltin: t1: ok: {
	// Results in incomplete error in v0.6
	s3: strings.ContainsAny(s4)  @test(eq, strings.ContainsAny("dd"))
	s4: strings.ContainsAny(s3)
	s4: "dd" @test(eq, "dd")
}

mutualBuiltin: t2: ok: {
	s3: strings.ContainsAny(s5, "dd")  @test(eq, true)
	s5: s6
	s6: "dd"
}

-- comprehensions.cue --
comprehensions: t1: ok: {
	src: ["foo"]
	for v in src { "\(v)": v }
	@test(eq, {src: ["foo"], foo: "foo"})
}

-- dynamic.cue --
dynamic: t1: ok: {
	[X=string]: {name: X}
	(x.y): {}
	x: y: "foo"
	@test(eq, {
		x: {y: "foo", name: "x"}
		foo: {name: "foo"}
	})
}

dynamic: t2: ok: {
	foo: #X
	#X: {
		a: b: C: 1
		for _ in a {
			a: ("b"): D: 2
		}
	}
	@test(eq, {
		foo: {a: {b: {C: 1, D: 2}}}
		#X: {a: {b: {C: 1, D: 2}}}
	})
}

-- definition.cue --
definition: t0: err: {
	#D1: env: {}
	d1: env: c: "C" @test(err, code=eval, contains="field not allowed", pos=[0:11])
	d1: #D1
}

definition: t1: err: {
	a: #A
	a: c: 1 @test(err, code=eval, contains="field not allowed", pos=[0:5])
	// defining after first reference triggers notification mechanism to kick in.
	#A: {}
}

definition: t2: ok: p1: {
	#A: {
		...
		{a: int}
	}
	x: #A & { c: int }
	@test(eq, {#A: {a: int}, x: {c: int, a: int}})
}

definition: t2: ok: p2: {
	#A: {
		{a: int}
		...
	}
	x: #A & { c: int }
	@test(eq, {#A: {a: int}, x: {c: int, a: int}})
}

definition: t2: ok: p3: {
	x: #A & { c: int }
	#A: {
		...
		{a: int}
	}
	@test(eq, {x: {c: int, a: int}, #A: {a: int}})
}

definition: t2: ok: p4: {
	x: #A & { c: int }
	#A: {
		{a: int}
		...
	}
	@test(eq, {x: {c: int, a: int}, #A: {a: int}})
}

-- expr.cue --
expr: t1: ok: {
	a: X
	X: 5.0
	X: Y / 2
	Y: a * 2
	@test(eq, {a: 5.0, X: 5.0, Y: 10.0})
}

expr: t2: ok: {
	A: X + 2
	X: 5      
	X: A - 2  
	@test(eq, {A: 7, X: 5})
}

expr: t3: ok: p1: {
	a0: X
	X:  5.0
	X:  a0 * 1
	@test(eq, {a0: 5.0, X: 5.0})
}

expr: t3: ok: p2: {
	b: Y * 1
	Y: b * 1
	Y: 5.0
	@test(eq, {b: 5.0, Y: 5.0})
}

expr: t4: ok: {
	// -> a0 -> X -> b1 -> b0 -> a1 -> a0
	a0: X        @test(eq, 5.0) // Need all conjuncts known from X
	b0: a1       @test(eq, 7.0)
	a1: a0 + 2   @test(eq, 7.0)
	b1: b0 - 2   @test(eq, 5.0)
	a0: X        // defined earlier
	X:  b1
	X:  5.0      @test(eq, 5.0)
}

-- in.cue --
mutual: t0: ok: {
	c: e & {b: 2}
	e: {a: 1}
	e: c
	@test(eq, {c: {b: 2, a: 1}, e: {a: 1, b: 2}})
}

mutual: t1: ok: {
	a: {
		b
		b: {b: f: 1}
	}
	a: a.b
	a: b: {b: f: 1}
	@test(eq, {a: {b: {b: {f: 1}, f: 1}, f: 1}})
}

mutual: t2: ok: {
	x: a: a: f: 1
	x: y.a
	y: a: a: e: 1
	y: x.a
	@test(eq, {
		x: {a: {a: {f: 1}, e: 1}, f: 1}
		y: {a: {a: {e: 1}, f: 1}, e: 1}
	})
}

mutual: t3: ok: {
	d: e: f: 1
	d
	d: d: e: g: 1
	@test(eq, {
		d: {e: {f: 1, g: 1}, d: {e: {g: 1}}}
		e: {f: 1, g: 1}
	})
}

// This test fails for some permutations in v0.6.
mutual: t4: ok: {
	p0: {
		z: x.b
		x: b: y.c
		x: b: {d: b: 2}
		y: c: z.d
		z: d: {a: 1}
		@test(eq, {
			z: {d: {a: 1, b: 2}, a: 1, b: 2}
			x: {b: {d: {b: 2}, a: 1, b: 2}}
			y: {c: {a: 1, b: 2}}
		})
	}

	p1: {
		x: b: y.c
		z: x.b
		x: b: {d: b: 2}
		y: c: z.d
		z: d: {a: 1}
		@test(eq, {
			x: {b: {d: {b: 2}, a: 1, b: 2}}
			z: {d: {a: 1, b: 2}, a: 1, b: 2}
			y: {c: {a: 1, b: 2}}
		})
	}

	p2: {
		x: b: y.c
		x: b: {d: b: 2}
		y: c: z.d
		z: x.b
		z: d: {a: 1}
		@test(eq, {
			x: {b: {d: {b: 2}, a: 1, b: 2}}
			y: {c: {a: 1, b: 2}}
			z: {d: {a: 1, b: 2}, a: 1, b: 2}
		})
	}

	p3: {
		x: b: {d: b: 2}
		y: c: z.d
		z: x.b
		x: b: y.c
		z: d: {a: 1}
		@test(eq, {
			x: {b: {d: {b: 2}, a: 1, b: 2}}
			y: {c: {a: 1, b: 2}}
			z: {d: {a: 1, b: 2}, a: 1, b: 2}
		})
	}

	p4: {
		z: x.b
		x: b: {d: b: 2}
		y: c: z.d
		x: b: y.c
		z: d: {a: 1}
		@test(eq, {
			z: {d: {a: 1, b: 2}, a: 1, b: 2}
			x: {b: {d: {b: 2}, a: 1, b: 2}}
			y: {c: {a: 1, b: 2}}
		})
	}

	p5: {
		x: b: {d: b: 2}
		y: c: z.d
		x: b: y.c
		z: x.b
		z: d: {a: 1}
		@test(eq, {
			x: {b: {d: {b: 2}, a: 1, b: 2}}
			y: {c: {a: 1, b: 2}}
			z: {d: {a: 1, b: 2}, a: 1, b: 2}
		})
	}

	check: p1 & p2 & p3 & p4 & p5 @test(eq, {
		x: {b: {d: {b: 2}, a: 1, b: 2}}
		z: {d: {a: 1, b: 2}, a: 1, b: 2}
		y: {c: {a: 1, b: 2}}
	})
}

-- equality.cue --
// evalv3 nil pointer dereference panic in equalTerminal with repeated
// unifications of the same default disjunction inside a close() call.
// https://cuelang.org/issue/3194
issue3194: reduced: {
	A: *0 | >10
	A: *0 | >10
	{
		out: close({ b: A })
		out: b: A
	}.out

	@test(eq, {A: *0 | >10, b: *0 | >10})
}

-- chained.cue --
import "encoding/yaml"

// evalv3 "field set was already referenced" regression when a chained field
// lookup resolves through a dynamic field to a yaml.Marshal call.
// https://cuelang.org/issue/3925
issue3925: reduced: {
	out: yaml.Marshal(in.b.actual)
	in: {
		a: "actual"
		a: "actual" | "other"
		b: (a): c: "str"
	}

	@test(eq, {
		out: """
		c: str

		"""
		in: {a: "actual", b: {actual: {c: "str"}}}
	})
}
issue3925: full: {
	for name, _ in _inputs {
		out: (name): early: "early value"
	}
	_inputs: input1: {
		name: "actual"
		config: (name): one: "one value"
	}
	_inputs: [_]: {
		name: "actual" | "other"
	}
	for name, input in _inputs {
		out: (name): lateYAML: yaml.Marshal(input.config[input.name])
	}

	@test(eq, {
		out: {
			input1: {
				early: "early value"
				lateYAML: """
					one: one value

					"""
			}
		}
		_inputs: {
			input1: {
				name: "actual"
				config: {actual: {one: "one value"}}
			}
		}
	})
}
-- out/errors.txt --
[eval] definition.t0.err.d1.env.c: field not allowed:
    ./definition.cue:3:11
[eval] definition.t1.err.a.c: field not allowed:
    ./definition.cue:9:5
-- out/eval/stats --
Leaks:  2
Freed:  284
Reused: 250
Allocs: 36
Retain: 0

Unifications: 273
Conjuncts:    599
Disjuncts:    10
Notifications: 10

NumCloseIDs: 86
-- out/todo.txt --
v3 uses structure sharing (~) for dynamic.t2.ok.foo/\#X and mutual.t4.ok's y.c fields. v3 reports fewer error positions for definition.t0.err and definition.t1.err (missing some context positions).
