-- in.cue --
@experiment(aliasv2)

import "list"

expr: error1: {
	a: 3
	a: a + 1
	@test(err, code=eval, path=a, contains="conflicting values %s and %s", args=[4, 3], pos=[1:5, 2:5])
}
expr: error2: {
	a: a + 1
	a: 3
	@test(err, code=eval, path=a, contains="conflicting values %s and %s", args=[4, 3], pos=[1:5, 2:5])
}
listConcat: error1: {
	a: ["1", "2"]
	a: list.Concat([a, ["3"]])
	@test(err, code=structural_cycle, path=a, contains="error in call to %s", args=[list.Concat], pos=[2:5])
}

listConcat: error2: {
	a: list.Concat([["3"], a])
	a: ["1", "2"]
	@test(err, code=structural_cycle, path=a, contains="error in call to %s", args=[list.Concat], pos=[1:5])
}

selfEmbed: ok1: {
	a: x
	Y: x
	x: {Y}
	@test(eq, {a: {}, Y: {}, x: {}})
}

selfEmbed: ok2: {
	Y: x.b
	a: x
	x: b: {Y}
	@test(eq, {Y: {}, a: {b: {}}, x: {b: {}}})
}

selfEmbed: ok3: {
	Y: x
	a: x
	x: {Y}
	@test(eq, {Y: {}, a: {}, x: {}})
}

selfEmbed: ok4: {
	a: x
	x: {Y}
	Y: x
	@test(eq, {a: {}, x: {}, Y: {}})
}

selfEmbed: ok5: {
	x: {Y}
	a: x
	Y: x
	@test(eq, {x: {}, a: {}, Y: {}})
}

selfEmbed: ok6: {
	x: b: {Y}
	Y: x.b
	a: x
	@test(eq, {x: {b: {}}, Y: {}, a: {b: {}}})
}


disjSelf: ok1: {
	#A: string | #A
	x: #A
	@test(eq, {#A: string | _, x: string | _})
}

disjSelf: ok2: {
	x: #A
	#A: string | #A
	@test(eq, {x: string | _, #A: string | _})
}

disjSelf: ok3: {
	#A: #A | string
	x: #A
	@test(eq, {#A: _ | string, x: _ | string})
}

disjSelf: ok4: {
	x: #A
	#A: #A | string
	@test(eq, {x: _ | string, #A: _ | string})
}

disjEmbed: ok1: {
	#A: string | {#A}
	x: #A
	@test(eq, {#A: string | {}, x: string | {}})
}

disjEmbed: ok2: {
	x: #A
	#A: string | {#A}
	@test(eq, {x: string | {}, #A: string | {}})
}

disjEmbed: ok3: {
	#A: {#A} | string
	x: #A
	@test(eq, {#A: {} | string, x: {} | string})
}

disjEmbed: ok4: {
	x: #A
	#A: {#A} | string
	@test(eq, {x: {} | string, #A: {} | string})
}

// x and #A should yield the same result.
disjList: _
disjList: ok1: {
	#A: string | [#A]
	x: #A

	y: x
	y: [[[[string]]]]
	@test(eq, {
		#A: string
		x: string
		y: [[[[string]]]]
	})
}

disjList: ok2: {
	x: #A
	#A: string | [#A]
	@test(eq, {x: string, #A: string})
}

disjList: ok3: {
	#A: [#A] | string
	x: #A
	@test(eq, {#A: string, x: string})
}

disjList: ok4: {
	x: #A
	#A: [#A] | string
	@test(eq, {x: string, #A: string})
}

-- old.cue --
name: "foo"
dynamicSelf: ok1: {
	X=(name): string | X
	x: X
	@test(eq, {x: string | _, foo: string | _})
}

dynamicSelf: ok2: {
	x: X
	X=(name): string | X
	@test(eq, {x: string | _, foo: string | _})
}

dynamicSelf: ok3: {
	X=(name): X | string
	x: X
	@test(eq, {x: _ | string, foo: _ | string})
}

dynamicSelf: ok4: {
	x: X
	X=(name): X | string
	@test(eq, {x: _ | string, foo: _ | string})
}

dynamicEmbed: ok1: {
	X=(name): string | {X}
	x: X
	@test(eq, {x: string | {}, foo: string | {}})
}

dynamicEmbed: ok2: {
	x: X
	X=(name): string | {X}
	@test(eq, {x: string | {}, foo: string | {}})
}

dynamicEmbed: ok3: {
	X=(name): {X} | string
	x: X
	@test(eq, {x: {} | string, foo: {} | string})
}

dynamicEmbed: ok4: {
	x: X
	X=(name): {X} | string
	@test(eq, {x: {} | string, foo: {} | string})
}

dynamicList: _
dynamicList: ok1: {
	X=(name): string | [X]
	x: X

	y: x
	y: [[[[string]]]]
	@test(eq, {
		x: string
		y: [[[[string]]]]
		foo: string
	})
}

dynamicList: ok2: {
	x: X
	X=(name): string | [X]
	@test(eq, {x: string, foo: string})
}

dynamicList: ok3: {
	X=(name): [X] | string
	x: X
	@test(eq, {x: string, foo: string})
}

dynamicList: ok4: {
	x: X
	X=(name): [X] | string
	@test(eq, {x: string, foo: string})
}

dynamicPatternSelf: ok1: {
	X=[string]: string | X
	@test(eq, {})
}
dynamicPatternSelf: ok2: {
	X=[string]: X | string
	@test(eq, {})
}
dynamicPatternEmbed: ok1: {
	X=[string]: string | {X}
	@test(eq, {})
}
dynamicPatternEmbed: ok2: {
	X=[string]: {X} | string
	@test(eq, {})
}
dynamicPatternList: ok1: {
	X=[string]: string | [X]
	@test(eq, {})
}
dynamicPatternList: ok2: {
	X=[string]: [X] | string
	@test(eq, {})
}

valueSelf: ok1: {
	y: X={string | X}
	x: y
	@test(eq, {y: string | {}, x: string | {}})
}

valueSelf: ok2: {
	x: y
	y: X={string | X}
	@test(eq, {x: string | {}, y: string | {}})
}

valueSelf: ok3: {
	y: X={X | string}
	x: y
	@test(eq, {y: {} | string, x: {} | string})
}

valueSelf: ok4: {
	x: y
	y: X={X | string}
	@test(eq, {x: {} | string, y: {} | string})
}

valueEmbed: ok1: {
	y: X={string | {X}}
	x: y
	@test(eq, {y: string | {}, x: string | {}})
}

valueEmbed: ok2: {
	x: y
	y: X={string | {X}}
	@test(eq, {x: string | {}, y: string | {}})
}

valueEmbed: ok3: {
	y: X={{X} | string}
	x: y
	@test(eq, {y: {} | string, x: {} | string})
}

valueEmbed: ok4: {
	x: y
	y: X={{X} | string}
	@test(eq, {x: {} | string, y: {} | string})
}

valueList: ok1: {
	y: X={string | [X]}
	x: y
	@test(eq, {y: string, x: string})
}

valueList: ok2: {
	x: y
	y: X={string | [X]}
	@test(eq, {x: string, y: string})
}

valueList: ok3: {
	y: X={[X] | string}
	x: y
	@test(eq, {y: string, x: string})
}

valueList: ok4: {
	x: y
	y: X={[X] | string}
	@test(eq, {x: string, y: string})
}

// Issue #1729
issue1729: t1: {
	#x: { #x | {} }
	x: #x & {}
	@test(eq, {#x: {}, x: {}})
}

issue1729: t2: {
	x: #x & {}
	#x: { #x | {} }
	@test(eq, {x: {}, #x: {}})
}

-- selfnew.cue --
@experiment(aliasv2)

issue4125: t1_self: {
	let Root = self
	a: Root.a
	@test(eq, {a: _})
}
-- selfold.cue --
issue4125: t2_alias: X={
	let Y = X
	b: Y.b
	@test(eq, {b: _})
}

-- out/errors.txt --
[eval] expr.error1.a: conflicting values 4 and 3:
    ./in.cue:6:5
    ./in.cue:7:5
[eval] expr.error2.a: conflicting values 4 and 3:
    ./in.cue:11:5
    ./in.cue:12:5
[structural_cycle] listConcat.error1.a: error in call to list.Concat: structural cycle:
    ./in.cue:17:5
[structural_cycle] listConcat.error2.a: error in call to list.Concat: structural cycle:
    ./in.cue:22:5
-- out/todo.txt --
listConcat.error1/error2.a: v2 shows list elements inside structural cycle error, v3 shows proper error message.
selfEmbed.ok2.a and ok6.a: v2 expands a as independent struct, v3 uses structure sharing ~(x).
issue4125: not present in v2 (feature added later), only evaluated in v3.
-- out/eval/stats --
Leaks:  42
Freed:  297
Reused: 275
Allocs: 64
Retain: 0

Unifications: 219
Conjuncts:    435
Disjuncts:    100

NumCloseIDs: 86
