// Tests comprehension evaluation including for-loop filters, let bindings in
// comprehensions, if-conditioned field insertions, and field-match ordering
// in structs. Also covers panic fixes for nested comprehensions with pattern
// constraints (issue 3691).
-- in.cue --
import "strings"

a: {x: 10, y: 100, z: 50}
b: {
	for k, v in a if v <= 50 {
		"\(k)": v
	}
	x: int
	if x > 3 {
		k: 20
	}
	k: int
	if k > 0 {
		l: 40
	}
}

c: {
	for k, v in a let y = v + 10 if y > 50 {
		"\(k)": y
	}
}

A: {
	X: run: "dfoo"
}

if true {
	A: X: {
		run:   string
		files: "\(strings.Join([run], "\n"))"
	}
}

matchOrder: {
	a1: {
		out: [string]: Val: 1
		out: in.a

		in: a: {
			if true {
				b: {}
			}
		}
	}
	a2: {
		out: [string]: Val: 1

		in: a: {
			if true {
				b: {}
			}
		}

		out: in.a
	}
	a3: {

		in: a: {
			if true {
				b: {}
			}
		}

		out: [string]: Val: 1
		out: in.a
	}
	a4: {
		out: in.a
		out: [string]: Val: 1

		in: a: {
			if true {
				b: {}
			}
		}
	}
	a5: {
		out: in.a

		in: a: {
			if true {
				b: {}
			}
		}

		out: [string]: Val: 1
	}
	a6: {
		in: a: {
			if true {
				b: {}
			}
		}

		out: in.a
		out: [string]: Val: 1
	}
}
-- issue3691.cue --
// evalv3 panic: incDependent "already closed" when processing conditional
// field definitions inside a comprehension with nested object structures.
// https://cuelang.org/issue/3691
// Ensure that parent nodes are properly processed, even when a pending arc
// is evaluated early.
issue3691: original: {
	X: [string]: string
	a: [string]: X
	a: {
		if true {
			b: c: 1
		}
	}
}
// Structural cycles follow a different code path.
issue3691: structuralCycle: {
	X: [string]: string
	a: [string]: X
	a: {
		if true {
			b: c: a
		}
	}
}
-- out/compile --
--- in.cue
{
  a: {
    x: 10
    y: 100
    z: 50
  }
  b: {
    for k, v in 〈1;a〉 if (〈0;v〉 <= 50) {
      "\(〈1;k〉)": 〈1;v〉
    }
    x: int
    if (〈0;x〉 > 3) {
      k: 20
    }
    k: int
    if (〈0;k〉 > 0) {
      l: 40
    }
  }
  c: {
    for k, v in 〈1;a〉 let y = (〈0;v〉 + 10) if (〈0;y〉 > 50) {
      "\(〈2;k〉)": 〈1;y〉
    }
  }
  A: {
    X: {
      run: "dfoo"
    }
  }
  if true {
    A: {
      X: {
        run: string
        files: "\(〈import;strings〉.Join([
          〈1;run〉,
        ], "\n"))"
      }
    }
  }
  matchOrder: {
    a1: {
      out: {
        [string]: {
          Val: 1
        }
      }
      out: 〈0;in〉.a
      in: {
        a: {
          if true {
            b: {}
          }
        }
      }
    }
    a2: {
      out: {
        [string]: {
          Val: 1
        }
      }
      in: {
        a: {
          if true {
            b: {}
          }
        }
      }
      out: 〈0;in〉.a
    }
    a3: {
      in: {
        a: {
          if true {
            b: {}
          }
        }
      }
      out: {
        [string]: {
          Val: 1
        }
      }
      out: 〈0;in〉.a
    }
    a4: {
      out: 〈0;in〉.a
      out: {
        [string]: {
          Val: 1
        }
      }
      in: {
        a: {
          if true {
            b: {}
          }
        }
      }
    }
    a5: {
      out: 〈0;in〉.a
      in: {
        a: {
          if true {
            b: {}
          }
        }
      }
      out: {
        [string]: {
          Val: 1
        }
      }
    }
    a6: {
      in: {
        a: {
          if true {
            b: {}
          }
        }
      }
      out: 〈0;in〉.a
      out: {
        [string]: {
          Val: 1
        }
      }
    }
  }
}
--- issue3691.cue
{
  issue3691: {
    original: {
      X: {
        [string]: string
      }
      a: {
        [string]: 〈1;X〉
      }
      a: {
        if true {
          b: {
            c: 1
          }
        }
      }
    }
  }
  issue3691: {
    structuralCycle: {
      X: {
        [string]: string
      }
      a: {
        [string]: 〈1;X〉
      }
      a: {
        if true {
          b: {
            c: 〈3;a〉
          }
        }
      }
    }
  }
}
