### wai-quantum: OpenQASM 3 generators — one program for a family of circuits

- **The reader takes generators** (`qasm::parse_with`, `qasm::inputs`). `input int n;` and `input
  uint n;` take an integer given when the program is read. `const int k = …;` names one. `for i
  in [a:b] { … }` (also `[a:step:b]`, both ends included as OpenQASM 3 reads a range, and `{a, b,
  c}`, nested) is unrolled once per value. Indices and sizes take integer arithmetic (`q[2 * i +
  1]`, `qubit[n + 1] q;`): `+ - * / %` with C's truncating division, `**`, comparisons, `&& ||
  !`. An `if` whose condition reads only integers is decided on reading; one that reads bits
  stays classical control. A gate a loop makes keeps the line of the statement in the loop's
  body, so a critique still points into the generator.
- **An instance written out** (`qasm::instantiate`): the circuit at given inputs as plain
  OpenQASM, with no `input`, `const` or loop left, for any surface that takes a program as
  text. Reading it gives the same program, gate for gate.
- **Bounded.** A program unrolls to at most 20 million tokens, every integer operation is
  checked for overflow, and a name an integer would shadow (a register, a gate's parameter or
  qubit, a word of the language) is refused with its line. A loop variable may still share a
  gate's name, such as the identity `i`. `while`, `inv` and `pow` are still refused.
- **The command line** takes `--input NAME=VALUE` on every command, so `run`, `plan`,
  `critique`, `equivalent`, `shortcuts` and the rest each read one circuit of the family.
  `wai-quantum instance gen.qasm --input n=5` prints that circuit.
- A program with no `input`, `const` or `for` reads exactly as before.

