Test various self reference cases.
-- in.cue --
@experiment(aliasv2)

// Basic self usage - top level
a: self.b  @test(eq, "hello")
b: "hello"

// Nested self usage - should refer to x struct
x: {
    y: self.z
    z: "world"
}  @test(eq, {y: "world", z: "world"})

// Shorthand notation - self should refer to foo struct
foo: bar: self.baz    @test(eq, "greeting")
foo: baz: "greeting"  @test(eq, "greeting") // TODO(inline): reference marking does not work with "self"

// Multiple levels of nesting
nested: {
    level1: {
        field: self.value
        value: "level1 value"
    }
}  @test(eq, {
	level1: {
		field: "level1 value"
		value: "level1 value"
	}
})

// Self in list context
listTest: {
    items: [1, 2, self[0], self[1]]
    first: 1
    second: 2
}  @test(eq, {
	items: [1, 2, 1, 2]
	first: 1
	second: 2
})

// Self with computed selectors
computed: {
    key: "test"
    value: self["key"]
}  @test(eq, {key: "test", value: "test"})

// Cyclic reference detection
cycle: self.cycle  @test(eq, _)

-- list.cue --
@experiment(aliasv2)
import "list"

#IntStrings: {list.Repeat([int, string], div(len(self), 2))}
listCheck: ok1: #IntStrings
listCheck: ok1: [1, "foo", 2, "bar"] @test(eq, [1, "foo", 2, "bar"])

listCheck: err: #IntStrings
listCheck: err: [1, "foo", "bar", 2] @test(err, code=eval, path=2, contains="conflicting values %s and %s (mismatched types %s and %s)", args=["bar", int, string, int], pos=[-5:14, -5:15, -5:28, -1:17, 0:28])

-- withlet.cue --
@experiment(try,aliasv2)

withLet: {
	let X = self
	foo: 1

	bar: {
		baz: X.foo
	}
} @test(eq, {foo: 1, bar: {baz: 1}})

// A let bound to self must capture fields produced by if/for/try
// comprehensions, not only statically declared ones.
// See https://cuelang.org/issue/4376.
withLetComprehension: {
	let X = self
	direct: "a"
	if true {
		viaIf: "b"
	}
	for k, v in {viaFor: "c"} {
		(k): v
	}
	try {
		viaTry: "d"
	}
	seeDirect: X.direct
	seeIf:     X.viaIf
	seeFor:    X.viaFor
	seeTry:    X.viaTry
} @test(eq, {
	direct:    "a"
	viaIf:     "b"
	viaFor:    "c"
	viaTry:    "d"
	seeDirect: "a"
	seeIf:     "b"
	seeFor:    "c"
	seeTry:    "d"
})
-- validator.cue --
@experiment(structcmp)
@experiment(aliasv2)

validator: {
	err1: {{{{== (self + 1)}}}}  @test(err, code=eval,
		contains="invalid value %v (out of bound %s)", args=[2, ==3],
		pos=[0:12, 0:8, 4:8]
	)
	err1: 2

	err2: {== (self + 1)}  @test(err, code=eval,
		contains="invalid value %v (out of bound %s)", args=[2, ==3],
		pos=[0:9, 0:8, 4:8]
	)
	err2: 2
}

cyclicErr: {
	err3: == (self + 1)  @test(err, code=eval,
		contains="invalid operands %s and %s to '%s' (type %s and %s)",
		pos=[0:12, -1:12, 0:19]
	)
	err3: 4
}

-- out/evalalpha --
Errors:
listCheck.err.2: conflicting values "bar" and int (mismatched types string and int):
    ./list.cue:4:14
    ./list.cue:4:15
    ./list.cue:4:28
    ./list.cue:8:17
    ./list.cue:9:28
listCheck.err.3: conflicting values 2 and string (mismatched types int and string):
    ./list.cue:4:14
    ./list.cue:4:15
    ./list.cue:4:33
    ./list.cue:8:17
    ./list.cue:9:35
validator.err1: invalid value 2 (out of bound ==3):
    ./validator.cue:5:12
    ./validator.cue:5:8
    ./validator.cue:6:8
validator.err2: invalid value 2 (out of bound ==3):
    ./validator.cue:8:9
    ./validator.cue:8:8
    ./validator.cue:9:8
cyclicErr.err3: invalid operands {err3:_|_(cyclicErr.err3: invalid operands value at path 'cyclicErr' and 1 to '+' (type struct and int))} and 1 to '+' (type struct and int):
    ./validator.cue:13:12
    ./validator.cue:12:12
    ./validator.cue:13:19

Result:
(_|_){
  // [eval]
  a: (string){ "hello" }
  b: (string){ "hello" }
  x: (struct){
    y: (string){ "world" }
    z: (string){ "world" }
  }
  foo: (struct){
    bar: (string){ "greeting" }
    baz: (string){ "greeting" }
  }
  nested: (struct){
    level1: (struct){
      field: (string){ "level1 value" }
      value: (string){ "level1 value" }
    }
  }
  listTest: (struct){
    items: (#list){
      0: (int){ 1 }
      1: (int){ 2 }
      2: (int){ 1 }
      3: (int){ 2 }
    }
    first: (int){ 1 }
    second: (int){ 2 }
  }
  computed: (struct){
    key: (string){ "test" }
    value: (string){ "test" }
  }
  cycle: (_){ _ }
  #IntStrings: (#list){
  }
  listCheck: (_|_){
    // [eval]
    ok1: (#list){
      0: (int){ 1 }
      1: (string){ "foo" }
      2: (int){ 2 }
      3: (string){ "bar" }
    }
    err: (_|_){
      // [eval]
      0: (int){ 1 }
      1: (string){ "foo" }
      2: (_|_){
        // [eval] listCheck.err.2: conflicting values "bar" and int (mismatched types string and int):
        //     ./list.cue:4:14
        //     ./list.cue:4:15
        //     ./list.cue:4:28
        //     ./list.cue:8:17
        //     ./list.cue:9:28
      }
      3: (_|_){
        // [eval] listCheck.err.3: conflicting values 2 and string (mismatched types int and string):
        //     ./list.cue:4:14
        //     ./list.cue:4:15
        //     ./list.cue:4:33
        //     ./list.cue:8:17
        //     ./list.cue:9:35
      }
    }
  }
  validator: (_|_){
    // [eval]
    err1: (_|_){
      // [eval] validator.err1: invalid value 2 (out of bound ==3):
      //     ./validator.cue:5:12
      //     ./validator.cue:5:8
      //     ./validator.cue:6:8
    }
    err2: (_|_){
      // [eval] validator.err2: invalid value 2 (out of bound ==3):
      //     ./validator.cue:8:9
      //     ./validator.cue:8:8
      //     ./validator.cue:9:8
    }
  }
  cyclicErr: (_|_){
    // [eval]
    err3: (_|_){
      // [eval] cyclicErr.err3: invalid operands {err3:_|_(cyclicErr.err3: invalid operands value at path 'cyclicErr' and 1 to '+' (type struct and int))} and 1 to '+' (type struct and int):
      //     ./validator.cue:13:12
      //     ./validator.cue:12:12
      //     ./validator.cue:13:19
    }
  }
  withLet: (struct){
    let X#1 = (_|_){
      // [structural_cycle] withLet.X: structural cycle
    }
    foo: (int){ 1 }
    bar: (struct){
      baz: (int){ 1 }
    }
  }
}
-- experiment_test.cue --
// Test self usage without experiment enabled (should fail)

a: {
    b: self.c
    c: 3
}

-- out/errors.txt --
[eval] listCheck.err.2: conflicting values "bar" and int (mismatched types string and int):
    ./list.cue:4:14
    ./list.cue:4:15
    ./list.cue:4:28
    ./list.cue:8:17
    ./list.cue:9:28
[eval] listCheck.err.3: conflicting values 2 and string (mismatched types int and string):
    ./list.cue:4:14
    ./list.cue:4:15
    ./list.cue:4:33
    ./list.cue:8:17
    ./list.cue:9:35
[eval] validator.err1: invalid value 2 (out of bound ==3):
    ./validator.cue:5:12
    ./validator.cue:5:8
    ./validator.cue:9:8
[eval] validator.err2: invalid value 2 (out of bound ==3):
    ./validator.cue:11:9
    ./validator.cue:11:8
    ./validator.cue:15:8
[eval] cyclicErr.err3: invalid operands {err3:_|_(cyclicErr.err3: invalid operands value at path 'cyclicErr' and 1 to '+' (type struct and int))} and 1 to '+' (type struct and int):
    ./validator.cue:19:12
    ./validator.cue:18:12
    ./validator.cue:19:19
-- out/eval/stats --
Leaks:  16
Freed:  72
Reused: 45
Allocs: 43
Retain: 0

Unifications: 76
Conjuncts:    132
Disjuncts:    0

NumCloseIDs: 42
