// Tests dynamic field key resolution including string interpolations, chained
// resolution, and comprehension with let bindings. Covers panic fix for issue799
// (struct used in string interpolation) and issue3828 (let inside comprehension
// with dynamic field key).
-- in.cue --
a: "foo"
"\(a)": b: c: d: e
e: 2 @test(eq, 2)

b: "bar"
X="\(b)": {
	a: 1
}
c: X @test(eq, {a: 1})

withError: {
	// Panic when running cue eval with a struct used in a string interpolation.
	// https://cuelang.org/issue/799
	issue799: {key: int32} & {"\(1 & 2)": 123}
	// TODO(inline): access _wrapped_ error somehow: underlying error is
	// "conflicting values 2 and 1".
	@test(err, code=eval, contains="invalid interpolation", pos=[3:28, 3:31, 3:35])
}

parenExprRefParent: {
	a: (x): {}
	x: "foo"
	@test(eq, {a: {foo: {}}, x: "foo"})
}
parenExprRefEqual: {
	(x): {}
	x: "foo"
	@test(eq, {x: "foo", foo: {}})
}
chainedResolution: x: {
	@test(permute, count=6)
	(x.baz): "bar"
	(x.foo): "baz"
	baz: "foo"
	@test(eq, {
		baz: "foo", foo: "bar", bar: "baz"
	})
}

// A dynamic field key that references an incomplete value (string interpolation
// using abstract string) must produce an "incomplete" error, not a spurious
// "cycle error". The error should also include path and position information.
// https://cuelang.org/issue/1407
noCycleError: {
	foo: [_]: {
		#ID: "\(string)"
	}
	foo: bar: entries: (foo.baz.#ID): true
	foo: baz: {}
	@test(err, at=foo.bar.entries, code=incomplete,
		suberr=(code=incomplete, contains="dynamic field must be concrete", pos=[4:22]),
		suberr=(code=incomplete, contains="non-concrete value string", pos=[2:8, 2:11]),
	)
	@test(err, at=foo.bar.#ID, code=incomplete, contains="non-concrete value string", pos=[2:8, 2:11])
	@test(err, at=foo.baz.#ID, code=incomplete, contains="non-concrete value string", pos=[2:8, 2:11])

	@test(eq, {
		foo: {
			bar: {
				entries: _|_
				#ID: _|_
			}
			baz: { #ID: _|_ }
		}
	})
}

-- constraints.cue --
constraints: {
	t1: "foo"
	t2: "bar"
	(t1)?: (t2)!: 3
	@test(eq, {t1: "foo", t2: "bar", foo?: {bar!: 3}})
}
-- issue3828.cue --
// evalv3 regression: a let inside a comprehension with a dynamic field key
// failed to produce the correct output due to a "cycle with field" error.
// https://cuelang.org/issue/3828
issue3828: reduced: {
	a: b: {}
	a: [_]: {
		if true let x=str {
			(x): true
		}
	}
	str: "foobot1"
	@test(eq, {a: {b: {foobot1: true}}, str: "foobot1"})
}
issue3828: full: {
	orgs: org1: {
		repos: repo1: {}
	}
	botUser: "bot1"
	orgs: [_]: config={
		for repo_name, _ in config.repos
		let orgBotUser = botUser {
			collaborators: (repo_name): (orgBotUser): true
		}
	}
	@test(eq, {
		orgs: org1: {
			repos: {repo1: {}}
			collaborators: {repo1: {bot1: true}}
		}
		botUser: "bot1"
	})
}
-- out/errors.txt --
[eval] invalid interpolation: conflicting values 2 and 1:
    ./in.cue:14:28
    ./in.cue:14:31
    ./in.cue:14:35
[incomplete] noCycleError.foo.baz.#ID: invalid interpolation: non-concrete value string (type string):
    ./in.cue:46:8
    ./in.cue:46:11
noCycleError.foo.bar.entries: key value of dynamic field must be concrete, found _|_(noCycleError.foo.baz.#ID: invalid interpolation: non-concrete value string (type string)):
    ./in.cue:48:22
[incomplete] noCycleError.foo.bar.#ID: invalid interpolation: non-concrete value string (type string):
    ./in.cue:46:8
    ./in.cue:46:11
[incomplete] noCycleError.foo.baz.#ID: invalid interpolation: non-concrete value string (type string):
    ./in.cue:46:8
    ./in.cue:46:11
-- out/eval/stats --
Leaks:  4
Freed:  74
Reused: 51
Allocs: 27
Retain: 0

Unifications: 78
Conjuncts:    91
Disjuncts:    0

NumCloseIDs: 4
-- out/todo.txt --
c: v3 uses structure sharing (~(bar)), v2 expands it.
noCycleError: v3 adds extra error message about key value; v2 only reports invalid interpolation.
