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

// Basic self usage - top level
a: self.b
b: "hello"

// Nested self usage - should refer to x struct
x: {
	y: self.z
	z: "world"
}

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

// Multiple levels of nesting
nested: {
	level1: {
		field: self.value
		value: "level1 value"
	}
}

// Self in list context
listTest: {
	items: [1, 2, self[0], self[1]]
	first:  1
	second: 2
}

// Self with computed selectors
computed: {
	key:   "test"
	value: self["key"]
}

// Cyclic reference detection
cycle: self.cycle
-- list.cue --
@experiment(aliasv2)
import "list"

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

listCheck: err: #IntStrings
listCheck: err: [1, "foo", "bar", 2]
-- withlet.cue --
@experiment(try,aliasv2)

withLet: {
	let X = self
	foo: 1

	bar: {
		baz: X.foo
	}
}

// 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
}
-- validator.cue --
@experiment(structcmp)
@experiment(aliasv2)

validator: {
	err1: {{{{==(self + 1)}}}}
	err1: 2

	err2: {==(self + 1)}
	err2: 2
}

cyclicErr: {
	err3: ==(self + 1)
	err3: 4
}
-- experiment_test.cue --
// Test self usage without experiment enabled (should fail)

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

-- out/compile --
--- in.cue
{
  a: 〈1〉.b
  b: "hello"
  x: {
    y: 〈1〉.z
    z: "world"
  }
  foo: {
    bar: 〈1〉.baz
  }
  foo: {
    baz: "greeting"
  }
  nested: {
    level1: {
      field: 〈1〉.value
      value: "level1 value"
    }
  }
  listTest: {
    items: [
      1,
      2,
      〈1〉[0],
      〈1〉[1],
    ]
    first: 1
    second: 2
  }
  computed: {
    key: "test"
    value: 〈1〉["key"]
  }
  cycle: 〈1〉.cycle
}
--- list.cue
{
  #IntStrings: {
    〈import;list〉.Repeat([
      int,
      string,
    ], div(len(〈1〉), 2))
  }
  listCheck: {
    ok1: 〈1;#IntStrings〉
  }
  listCheck: {
    ok1: [
      1,
      "foo",
      2,
      "bar",
    ]
  }
  listCheck: {
    err: 〈1;#IntStrings〉
  }
  listCheck: {
    err: [
      1,
      "foo",
      "bar",
      2,
    ]
  }
}
--- validator.cue
{
  validator: {
    err1: {
      {
        {
          {
            ==(〈1〉 + 1)
          }
        }
      }
    }
    err1: 2
    err2: {
      ==(〈1〉 + 1)
    }
    err2: 2
  }
  cyclicErr: {
    err3: ==(〈1〉 + 1)
    err3: 4
  }
}
--- withlet.cue
{
  withLet: {
    let X#1 = 〈1〉
    foo: 1
    bar: {
      baz: 〈1;let X#1〉.foo
    }
  }
  withLetComprehension: {
    let X#2 = 〈1〉
    direct: "a"
    if true {
      viaIf: "b"
    }
    for k, v in {
      viaFor: "c"
    } {
      〈1;k〉: 〈1;v〉
    }
    try {
      viaTry: "d"
    }
    seeDirect: 〈0;let X#2〉.direct
    seeIf: 〈0;let X#2〉.viaIf
    seeFor: 〈0;let X#2〉.viaFor
    seeTry: 〈0;let X#2〉.viaTry
  }
}
