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]>
10 KiB
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 |
== != < <= > >=, `&& |
!` | |
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 &&, ` |
, !` |
|
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.