docs/qasm-feature-matrix.md lists every construct of OpenQASM 3.1 (and the OpenQASM 2 forms in common use) with what the reader does with it, supported, lowered, carried, preserved or refused, and its code. The crate's README describes the one reader (feature quantum_lang) and links the matrix, the table of codes and the corpus; the command line's README gives `diagnostics` and the codes in lint; the Studio's says the editor marks each problem with its code. The changelog entry is in wai/CHANGELOG.md. Co-Authored-By: Claude Opus 5.5 <[email protected]>
175 lines
10 KiB
Markdown
175 lines
10 KiB
Markdown
# OpenQASM 3.1: what the reader does with each construct
|
||
|
||
The reader (`wai_quantum::qasm`) is the one grammar every surface takes: the job
|
||
service, the command line, both MCP servers, the Studio, the desktop app, the
|
||
edge component and the in-browser IDE. This page lists every construct of
|
||
OpenQASM 3.1, and the OpenQASM 2 forms in common use, with what the reader does
|
||
with it and the diagnostic code it gives (`qasm-diagnostics.md` has the table
|
||
of codes).
|
||
|
||
- **supported**: read as the language defines it.
|
||
- **lowered**: read and lowered exactly to the engine's gates and steps.
|
||
- **carried**: kept in the program as written (timing, outputs); it changes
|
||
nothing a method computes, and the result says so where it matters.
|
||
- **preserved**: kept verbatim for export, never executed.
|
||
- **refused**: the program is not read; the refusal names the line, says what
|
||
to write instead, and ends with its code.
|
||
|
||
The conformance corpus (`wai/quantum-conformance/qasm3/`) holds the
|
||
specification's example programs and a program for each construct below, each
|
||
with what the reader must do with it; CI runs it natively, under wasm32-wasip2
|
||
and in the browser build.
|
||
|
||
## Program structure
|
||
|
||
| Construct | Status | Codes |
|
||
|---|---|---|
|
||
| `OPENQASM 3.1;`, `OPENQASM 3;`, `OPENQASM 2.0;`, or none | supported; another version is read as OpenQASM 3 | Q010 |
|
||
| `include "stdgates.inc"`, `include "qelib1.inc"` | supported: the libraries are built in | Q012 |
|
||
| `include` of any other file | warned: its definitions are not read | Q011 |
|
||
| Comments `//` and `/* */` | supported; an unclosed block comment is refused | Q003 |
|
||
| Identifiers, Unicode letters included (`θ`, `π`) | supported | |
|
||
| Statements and blocks `{ }`, scopes | supported; qubits, gates, subroutines and externs are declared at the top level | Q105 |
|
||
| `pragma …`, `#pragma …`, annotations `@keyword …` | warned: kept, not applied; `@wai.max_iterations N` bounds the `while` after it | Q013 |
|
||
|
||
## Literals
|
||
|
||
| Construct | Status | Codes |
|
||
|---|---|---|
|
||
| Integers: decimal, `0x`, `0o`, `0b`, with `_` | supported | Q002 |
|
||
| Floats, exponents, `.5` | supported | Q002 |
|
||
| Imaginary `2.5im` | supported | |
|
||
| `true`, `false` | supported | |
|
||
| Bit strings `"0101"` | supported | Q110 |
|
||
| Durations `ns`, `us`, `µs`, `ms`, `s`, `dt` | supported | Q406 |
|
||
| `pi` `π`, `tau` `τ`, `euler` `ℯ` | supported; not redeclarable | Q106 |
|
||
|
||
## Declarations and types
|
||
|
||
| Construct | Status | Codes |
|
||
|---|---|---|
|
||
| `qubit q;`, `qubit[n] q;`, `qreg q[n];` | supported (at most 65 536 qubits) | Q101, Q105, Q111 |
|
||
| Physical qubits `$0`, `$1` | supported, in a program that declares none | Q124 |
|
||
| `bit c;`, `bit[n] c;`, `creg c[n];` | supported: written by measurement; a value known on reading (`bit[2] f = "11";`) is held until a measurement writes the bit | Q319 |
|
||
| A bit declared inside a block or a subroutine | lowered: a bit of its own, which the steps read and the results do not show | Q322 |
|
||
| `int`, `int[n]`, `uint`, `uint[n]` (n ≤ 64) | supported; range-checked | Q112, Q122 |
|
||
| `float`, `float[16]`, `float[32]`, `float[64]` | supported, rounded to the width as defined; `float[128]` refused | Q121, Q122 |
|
||
| `angle`, `angle[n]` (n ≤ 64) | supported: `angle[n]` holds n bits of a turn, so it is dyadic and the bit-exact method takes it | Q121 |
|
||
| `complex`, `complex[float[n]]` | supported; a complex gate parameter is refused | Q110 |
|
||
| `bool` | supported | |
|
||
| `duration` | supported: SI units and `dt`, not mixed | Q406 |
|
||
| `stretch` | carried by name, or as the expression that holds it, for a scheduler | Q403 |
|
||
| `array[T, d1, d2, …]`, nested values, `sizeof` | supported | Q107, Q110 |
|
||
| `const` | supported: known on reading; not assignable | Q127 |
|
||
| `input int n;`, `input uint n;` | supported: given when the program is read (a generator) | Q114 |
|
||
| `input` of another type | refused: only integers take values | Q115 |
|
||
| `output` | carried into the result: a bit register's places in each outcome, or a value | Q600, Q601 |
|
||
| `let a = q[0:2] ++ r;` | supported; a `let` that reuses an enclosing scope's name is refused | Q101 |
|
||
| `extern f(…) -> T;` | supported as a declaration; a call is refused | Q125 |
|
||
|
||
## Indexing
|
||
|
||
| Construct | Status | Codes |
|
||
|---|---|---|
|
||
| `q[i]`, negative `q[-1]` | supported | Q107 |
|
||
| Slices `q[a:b]`, `q[a:s:b]`, `q[a:]`, `q[:]` | supported | Q107, Q313 |
|
||
| Index sets `q[{0, 2, 5}]` | supported | Q107 |
|
||
| Multi-dimensional `m[i, j]`, `m[i][j]`, array slices and slice assignment | supported | Q107, Q110 |
|
||
| An integer's bits `k[i]` | supported | |
|
||
|
||
## Expressions
|
||
|
||
| Construct | Status | Codes |
|
||
|---|---|---|
|
||
| `+ - * / % **`, unary `-` | supported; integer overflow refused | Q112, Q113 |
|
||
| Integer division with a remainder used as a real (`1/2` in a gate) | refused: OpenQASM 3 truncates it, OpenQASM 2 does not | Q118 |
|
||
| `& | ~ << >>` | supported on integers and bits | |
|
||
| `^` | exclusive or in an OpenQASM 3 program; a power in OpenQASM 2; between integers with no version stated it is refused, between reals read as a power with a warning | Q119, Q120 |
|
||
| `== != < <= > >=`, `&& || !` | supported | |
|
||
| Casts `int[8](x)`, `float(x)`, `angle[n](b)`, `bit[n](i)`, `bool(x)` | supported (a cast to `int` truncates; bits to a signed integer of their width read as two's complement) | Q123 |
|
||
| `sin cos tan arcsin arccos arctan exp log ln sqrt ceiling floor mod pow popcount rotl rotr real imag sizeof` | supported, computed with the crate's own functions, the same bits on every platform | Q104 |
|
||
| `durationof({ … })` | refused: it needs gate durations the program does not give | Q405 |
|
||
| Arithmetic on measured bits at run time (`int k = c;`) | refused: the steps branch on bits and hold no other run-time value | Q306 |
|
||
| A value that depends on a measurement where one is needed on reading | refused | Q116 |
|
||
|
||
## Gates
|
||
|
||
| Construct | Status | Codes |
|
||
|---|---|---|
|
||
| `U(θ, φ, λ)`, `gphase(θ)` | supported; a global phase is dropped, and under controls is a phase on the controls | Q206 |
|
||
| The standard library: `p x y z h s sdg t tdg sx rx ry rz cx cy cz cp crx cry crz ch swap ccx cswap cu CX phase cphase id u1 u2 u3`, and `sxdg iswap rxx ryy rzz ccz cnot toffoli fredkin u cu1 cu3` | supported, each checked against its definition in `U` and `CX` (`cu(θ, φ, λ, γ)` is controlled `e^{iγ}U(θ, φ, λ)`) | Q012 |
|
||
| `gate name(params) qubits { … }` | lowered: inlined at each call; a redefinition of a standard gate keeps the standard one | Q200, Q212 |
|
||
| `opaque` gates | refused at a call: no matrix | Q126 |
|
||
| A call on whole registers (broadcast) | supported | Q108 |
|
||
| A gate's duration `x[20ns] q;` | carried in the timing | Q407 |
|
||
| Wrong parameters or qubits, a qubit named twice, an unknown gate | refused | Q103, Q104, Q109 |
|
||
|
||
## Modifiers
|
||
|
||
| Construct | Status | Codes |
|
||
|---|---|---|
|
||
| `ctrl @`, `ctrl(n) @`, `negctrl @`, `negctrl(n) @` on any gate, user gates included | lowered exactly (a negative control is a control between two `x`); at most 16 added controls | Q201, Q207, Q208 |
|
||
| `inv @` on any gate | lowered exactly: each gate's inverse, in reverse order | Q202 |
|
||
| `pow(k) @`, `k` a whole number | lowered exactly: angles scaled or the gate repeated; negative `k` repeats the inverse | Q203 |
|
||
| `pow(r) @`, `r` fractional | lowered where an exact principal root exists (`pow(1/2) @ x` is `sx`; rotations by less than 2π; phases; controlled forms); refused otherwise (`u`, `cu`, user gates) | Q204, Q205 |
|
||
| A modifier on a subroutine, or nested as deep as 32 | refused | Q211, Q209 |
|
||
|
||
## Measurement and reset
|
||
|
||
| Construct | Status | Codes |
|
||
|---|---|---|
|
||
| `c = measure q;`, `c[0] = measure q[0];`, `bit c = measure q;` | supported | Q321 |
|
||
| `measure q -> c;` | supported | Q321 |
|
||
| `measure q;` | supported where no bit register is declared | Q320 |
|
||
| Mid-circuit measurement, measurement again, a gate after it | lowered: the program runs as steps (counts by shot splitting, exact expectation values) | |
|
||
| `reset q;` | supported: before a qubit's first gate it changes nothing; after it, the program runs as steps | |
|
||
| `barrier`, `barrier q;` | carried in the timing | Q404 |
|
||
|
||
## Classical control
|
||
|
||
| Construct | Status | Codes |
|
||
|---|---|---|
|
||
| `if`/`else` known on reading | decided on reading | Q300 |
|
||
| `if`/`else` on measured bits: `c[0]`, `c == 3`, `c >= 2`, `int[2](c) != 0`, with `&&`, `||`, `!` | lowered: steps that branch forward | Q301, Q302, Q303, Q304, Q305, Q307 |
|
||
| `for` over a range, a set or an array | lowered: unrolled | Q308, Q313, Q312 |
|
||
| `while` known on reading | lowered: unrolled until it fails (at most 1 000 000 times) | Q309, Q312 |
|
||
| `while` on measured bits | lowered under `@wai.max_iterations N`, with a warning that runs still meeting the condition stop there; refused with no bound | Q310, Q311 |
|
||
| `switch` / `case` / `default` | decided on reading, or a chain of conditions on measured bits | Q317 |
|
||
| `break`, `continue` | supported; under a condition on measured bits, jumps forward | Q316, Q314 |
|
||
| `end` | supported | Q316 |
|
||
|
||
## Subroutines
|
||
|
||
| Construct | Status | Codes |
|
||
|---|---|---|
|
||
| `def f(T x, qubit q, qubit[n] r) -> T { … }` | lowered: inlined, classical arguments by value, qubits by reference | Q318, Q104 |
|
||
| `return v;`, `return measure q;` | supported; a returned measurement writes the caller's bit | Q315 |
|
||
| `readonly` / `mutable` array arguments, `#dim` | supported | |
|
||
| Bits declared in a subroutine | lowered: bits of its own, fed forward | Q322 |
|
||
| A subroutine called as a gate (`f(1) q, r;`) | supported | |
|
||
| Recursion | refused past 32 calls deep | Q209 |
|
||
|
||
## Timing
|
||
|
||
| Construct | Status | Codes |
|
||
|---|---|---|
|
||
| `delay[d] q;` | carried | Q401 |
|
||
| `box`, `box [d]` | carried, around the gates it holds | Q402 |
|
||
| `stretch` | carried | Q403 |
|
||
| Durations in a result | no method applies them; a result of a program that states durations says so (`timing.applied: false`) | Q400 |
|
||
|
||
## Calibration (OpenPulse)
|
||
|
||
| Construct | Status | Codes |
|
||
|---|---|---|
|
||
| `defcalgrammar "openpulse";` | preserved | Q452 |
|
||
| `cal { … }` | preserved, never run | Q451 |
|
||
| `defcal …` | preserved, never run; the gate's matrix comes from its definition or the library | Q450, Q126 |
|
||
|
||
## The bit-exact method
|
||
|
||
The bit-exact state vector takes the reader's program under its own
|
||
restriction, refusing with a code: dyadic angles only (Q500), at most 255
|
||
qubits (Q501), and measurements all at the end (Q502). A controlled gate the
|
||
modifiers write is held whole, under all its controls. The methods in double
|
||
precision take any angle.
|