1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// This code is part of Cqlib.
//
// (C) Copyright China Telecom Quantum Group 2026
//
// This code is licensed under the Apache License, Version 2.0. You may
// obtain a copy of this license in the LICENSE.txt file in the root directory
// of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
//
// Any modifications or derivative works of this code must retain this
// copyright notice, and modified files need to carry a notice indicating
// that they have been altered from the originals.
//! 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:
//!
//! 1. Runtime classical values and storage are defined by
//! [`crate::circuit::classical`]. Those types identify circuit-local
//! classical storage and value types.
//! 2. Classical expressions are defined by
//! [`ClassicalExpr`](crate::circuit::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.
//! 3. Control-flow operations are defined in this module by
//! [`ClassicalControlOp`] and the concrete operation structs. They consume
//! [`ClassicalExpr`](crate::circuit::ClassicalExpr) values 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`](crate::circuit::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:
//!
//! - [`IfOp`] executes a `then` body, and optionally an `else` body, when a
//! boolean condition is evaluated at runtime.
//! - [`WhileOp`] repeats a body while a boolean condition remains true.
//! - [`ForOp`] models an unsigned half-open runtime range loop,
//! `[start, stop)`, with an explicit unsigned loop variable and step.
//! - [`SwitchOp`] selects one body by matching an unsigned expression against
//! exact case values. Cases do not fall through.
//! - [`ClassicalControlOp::Break`] exits the nearest enclosing loop or switch.
//! - [`ClassicalControlOp::Continue`] advances 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`](crate::circuit::ClassicalExpr::bit_to_bool).
//! Ordered comparisons are restricted to `UInt` expressions. Bit-vector to
//! integer interpretation is explicit through
//! [`ClassicalExpr::bit_vec_to_uint`](crate::circuit::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 a [`ForOp`] loop 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:
//!
//! ```text
//! 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:
//!
//! ```text
//! 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:
//!
//! ```text
//! 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:
//!
//! ```text
//! 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.
pub use ControlBody;
pub use ;
pub use ForOp;
pub use IfOp;
pub use ;
pub use ;
pub use WhileOp;