Expand description
Expression-based classical control-flow IR.
This module defines the third layer of cqlib’s dynamic-circuit classical control model: structured control-flow operations that consume typed, side-effect-free classical expressions.
The model is intentionally split into three layers:
- Runtime classical values and storage are defined by
crate::circuit::classical. Those types identify circuit-local classical storage and value types. - Classical expressions are defined by
ClassicalExpr. Expressions are strongly typed and have no side effects. They only read runtime classical variables, combine literals, cast explicitly, compare values, select between values, or extract/pack bits. - Control-flow operations are defined in this module by
ClassicalControlOpand the concrete operation structs. They consumeClassicalExprvalues to decide which structured body executes.
This module is IR only. It does not allocate classical storage, execute a circuit, or lower control flow to backend instructions.
§Core Concepts
ClassicalExpr represents a runtime classical computation. It has a
static crate::circuit::ClassicalType and can report the classical
variables and immutable values it reads. The expression layer does not write
storage, measure qubits, branch, or loop.
ControlBody owns the operations inside a structured control-flow region.
A body is a sequence of ordinary circuit crate::circuit::Operation values
that belongs to an operation such as IfOp, WhileOp, ForOp, or
SwitchOp.
ClassicalControlOp is the sum type for structured classical control
operations:
IfOpexecutes athenbody, and optionally anelsebody, when a boolean condition is evaluated at runtime.WhileOprepeats a body while a boolean condition remains true.ForOpmodels an unsigned half-open runtime range loop,[start, stop), with an explicit unsigned loop variable and step.SwitchOpselects one body by matching an unsigned expression against exact case values. Cases do not fall through.ClassicalControlOp::Breakexits the nearest enclosing loop or switch.ClassicalControlOp::Continueadvances the nearest enclosing loop.
Conditions for IfOp and WhileOp must have type Bool; measured
Bit values must be explicitly cast with
ClassicalExpr::bit_to_bool.
Ordered comparisons are restricted to UInt expressions. Bit-vector to
integer interpretation is explicit through
ClassicalExpr::bit_vec_to_uint,
preserving the rule that bit index 0 is the least-significant bit.
§Resource Queries
Control-flow IR nodes expose lightweight dependency queries:
classical_var_reads()returns classical variables read by controlling expressions.classical_value_reads()returns immutable classical values read by controlling expressions.classical_writes()currently reports direct writes introduced by the control operation itself, such as aForOploop variable.used_qubits()reports qubits referenced directly by structured bodies.
These methods are structural summaries for validation, remapping, and future lowering passes. They are not a complete data-flow analysis for nested dynamic-circuit execution.
Classical handles are circuit-local. When circuits are composed, classical variables and values from the source circuit are copied into the destination circuit’s classical tables and every expression/control body reference is remapped to the new local ID.
§Examples
Build a boolean condition from a measured bit-like variable:
bit_var: ClassicalVar<Bit>
bit_expr = ClassicalExpr::var(bit_var)
condition = ClassicalExpr::bit_to_bool(bit_expr)
if_op = IfOp::new(condition, then_body, else_body)Build an unsigned comparison for a loop or branch condition:
counter: ClassicalVar<UInt(8)>
lhs = ClassicalExpr::var(counter)
rhs = ClassicalExpr::uint_literal(8, 10)
condition = ClassicalExpr::lt(lhs, rhs)
while_op = WhileOp::new(condition, body)Build a switch over an unsigned runtime expression:
state: ClassicalVar<UInt(2)>
target = ClassicalExpr::var(state)
cases = [
SwitchCase::new(0, zero_body),
SwitchCase::new(1, one_body),
SwitchCase::new(2, two_body),
]
switch = SwitchOp::new(target, cases, default_body)Build a runtime for loop:
i: ClassicalVar<UInt(8)>
start = ClassicalExpr::uint_literal(8, 0)
stop = ClassicalExpr::uint_literal(8, 16)
step = ClassicalExpr::uint_literal(8, 1)
for_op = ForOp::new(i, start, stop, step, body)§Design Boundaries
This module deliberately does not define post-selection or runtime assertions as first-class control-flow operations. Post-selection belongs to execution/result filtering semantics, while assertions belong to diagnostics or verification. They can be added later as separate IR families once their backend behavior and failure model are specified.
Structs§
- Control
Body - Structured control-flow body.
- ForOp
- Unsigned runtime range loop with half-open
[start, stop)semantics. - IfOp
- Conditional execution controlled by a boolean classical expression.
- Switch
Case - Exact-value switch case.
- Switch
Op - Exact-value switch over an unsigned classical expression.
- WhileOp
- Loop controlled by a boolean classical expression.
Enums§
- Classical
Control Kind - Stable category of a classical control-flow operation.
- Classical
Control Op - Expression-based classical control-flow operation.