The table groups its codes in tens by theme, and J040 and J041 go to another branch's codes. PARAMS is now J050, GRADIENT J051, OPTIMIZE J052 and BUILD J053, in the table and its page, every message and test, the service's OpenAPI and tool descriptions, the job schema, the reference page, the feature matrix, the changelog entry and the regenerated agent docs. No released code changes: these four were never released. Co-Authored-By: Claude Opus 5.5 <[email protected]>
12 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 float theta;, input angle phi; |
a parameter: a job's params binds it as a const at exactly the double given before the program is read (left without a value, the job is refused with Q114 and J050); the reader alone gives it no value |
Q115 |
| a parameter followed into a gradient | supported through arithmetic, the built-in functions, loops and gate definitions into gates' arguments; refused under a modifier, in a classical variable, a condition, an index, a size, a loop's range, a subroutine, or a type that rounds it | Q129 |
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; in a pulse run, read (another grammar is refused) | Q452, Q454 |
cal { … } |
preserved, never run by the circuit methods; in a pulse run, read as OpenPulse and run in order | Q451, Q453 |
defcal … |
preserved, never run by the circuit methods; the gate's matrix comes from its definition or the library. In a pulse run, read as OpenPulse and run at each call on its physical qubits | Q450, Q126, Q453, Q459 |
Ports, frames, waveforms (constant, gaussian, sech, gaussian_square, drag, sine, explicit samples) |
in a pulse run, lowered to the schedule | Q453, Q455 to Q458 |
play, delay, shift_phase, set_phase, shift_frequency, set_frequency, capture_v0 to capture_v4, barrier |
in a pulse run, lowered to the schedule on frames | Q453, Q457, Q458, Q461 |
| Plays on a measurement port | in a pulse run, scheduled and timed; the readout is not simulated | Q462 |
A pulse run is the job method pulse; the pulse page gives the
model, the bound and the options.
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.