Skip to main content

bloq_ir/
lib.rs

1//! Program IR for bloq compiler output.
2//!
3//! [`Bloq`] is the public, circuit-bearing graph IR produced by `bloq_compile`
4//! and consumed by backend emitters.
5//!
6//! ## Traversal
7//!
8//! Reads are id-native: every graph level (the [`Bloq`] top level or a region
9//! [`SubGraph`] body) exposes the same accessors — [`SubGraph::node`],
10//! [`SubGraph::nodes`], [`SubGraph::incoming`]/[`SubGraph::outgoing`] (yielding
11//! [`BloqEdgeRef`]s), the dataflow queries [`SubGraph::value_inputs`] /
12//! [`SubGraph::value_output`] / [`SubGraph::boundary_outputs`] — and [`Bloq::walk`]/[`Bloq::levels`]
13//! recurse through region bodies with a [`LevelPath`] for cross-level node
14//! identity. The underlying petgraph storage is not public API.
15//!
16//! ## Derived reads
17//!
18//! Three layers sit on top of raw traversal, for questions a consumer would
19//! otherwise answer by matching on node variants itself:
20//!
21//! - **Structural queries** ([`Bloq::regions_of`], [`Bloq::selection_seams`],
22//!   [`Bloq::node_by_block`], [`SubGraph::quantum_tail`], …) name a program's
23//!   recurring landmarks. Callers use them to construct [`MemoryRoundTarget`]s
24//!   for [`Bloq::insert_memory_rounds`] or [`Bloq::insert_memory_rounds_batch`].
25//! - **[`Bloq::resolve_classical`]** folds the classical dataflow graph under
26//!   a fixed path into the measurement recipe behind a node's value, and
27//!   **[`Bloq::classical_value`]** answers the other half of the same
28//!   question: the bit that path already fixes, including an activation predicate.
29//! - **[`NodeKey`]** is a provenance-derived node identity that survives
30//!   recompilation, for lining one program up against another compile of the
31//!   same block graph.
32//!
33//! ## Exhaustive data enums (deliberate)
34//!
35//! The data enums ([`BloqNodeKind`], [`ClassicalNode`], [`RegionNode`],
36//! [`NodeProvenance`], [`ValueRole`], …) are intentionally **not**
37//! `#[non_exhaustive]`: a backend must fail to compile — not silently
38//! wildcard — when the IR grows a construct, because an unhandled node kind
39//! would emit wrong output rather than error (e.g. `bloq_stim` rejects each region
40//! variant by name). Do not "fix" this by adding `#[non_exhaustive]` to them;
41//! error enums, by contrast, are non-exhaustive.
42
43mod alignment;
44mod binary;
45mod detslice;
46mod edit;
47mod flatten;
48mod instantiation;
49mod ir;
50mod key;
51mod membership;
52mod optimize;
53mod pin;
54mod query;
55mod resolve;
56mod stats;
57#[cfg(test)]
58mod test_fixture;
59mod text;
60mod traverse;
61mod validation;
62
63pub use alignment::{
64    AlignedLayer, AlignedMomentRef, AlignedSlot, MomentAlignmentError, MomentLane,
65    align_moment_lanes, aligned_moment_segments,
66};
67pub use binary::{
68    BLOQ_BINARY_EXTENSION, BLOQ_BINARY_MAGIC, BLOQ_BINARY_VERSION, BinaryDecodeError,
69};
70// Types that appear in this crate's own signatures, re-exported so a consumer
71// can name them without depending on `bloq_circuit`/`bloq_utils` directly
72// (C-REEXPORT). The whole circuit vocabulary lives in `circuit` (below).
73pub use bloq_circuit::{Basis, CoordinateOverflowError, FlattenLimits};
74pub use bloq_utils::PortRole;
75pub use detslice::{
76    MomentKind, MomentSegment, MomentSegmenter, NodeRef, NodeSlices, ProgramRegion,
77    ProgramRegionBreak, ProgramRegionId, ProgramSliceError, ProgramSliceOptions, ProgramSlices,
78    RegionView, moment_segments, program_detector_slices, program_detector_slices_with_options,
79};
80pub use edit::{EditError, MemoryRoundTarget};
81pub use flatten::FlattenError;
82pub use ir::{
83    Bloq, BloqEdge, BloqEdgeRef, BloqNode, BloqNodeId, BloqNodeKind, BodySelector, BoundaryFace,
84    BundleDetector, BundleMeasurement, ClassicalExpr, ClassicalNode, CycleDetected, DetectorBundle,
85    DetectorBundleError, DetectorBundleId, DetectorBundlePool, DetectorBundleUse, FramePair,
86    InstanceProvenance, LogicalInput, LogicalOutput, MetadataValue, NodeDetector,
87    NodeDetectorAddress, NodeDetectorParity, NodeDetectorView, NodeDetectors, NodeProvenance,
88    ObservableOutput, PathScratch, PipePadding, PipeSeam, QuantumEdge, QuantumGuard, QuantumNode,
89    QuantumTimeline, RegionNode, SourceBlockRef, SpatialPortPart, SubGraph, TemplateDetector,
90    TemplateId, TemporalPipeRef, ValueInput, ValueRef, ValueRole,
91};
92pub use key::NodeKey;
93pub use pin::MembershipPinError;
94pub use query::{RegionKind, RegionRef, StructureError};
95pub use resolve::{ClassicalAssignment, ClassicalResolution, ResolveError};
96pub use stats::{BloqStats, BloqStatsError};
97pub use text::{BLOQ_TEXT_EXTENSION, BLOQ_TEXT_VERSION, TextParseError};
98pub use traverse::{LevelPath, LevelSegment, NodeCx, WalkControl};
99pub use validation::{BloqValidationError, ValidatedPlans};
100
101// Template instantiation and per-instance machinery is compiler/backend
102// lowering surface, public only through `lowering` (below). These crate-visible
103// aliases keep it reachable as `crate::Foo` so the lowering-pipeline modules
104// need not spell out `lowering::`.
105pub(crate) use instantiation::NodeTemplateInstanceMergeError;
106pub(crate) use ir::{
107    BloqTemplate, BloqTemplatePool, InstanceBoundaryOperator, InstanceMeasurement, NodeRestart,
108    TemplateDetectorParity, TemplateDetectorScope, TemplateInstance, TemplateInstanceId,
109    TemplateRepeatState, TemplateRestart,
110};
111
112/// Graph visualization shared with the editor.
113pub mod visualization;
114
115/// Compiler and backend lowering surface.
116///
117/// This contains template instantiation and per-instance machinery a backend
118/// consumes when emitting a [`Bloq`]. Kept
119/// separate from the stable program-graph API at the crate root; arms-length
120/// graph consumers should not need these.
121pub mod lowering {
122    pub use crate::edit::{PaddingInstance, drain_composed_chains};
123    pub use crate::instantiation::{
124        InstantiationOptions, NodeEmissionPlan, NodeTemplateInstanceMergeError,
125        validate_template_circuit,
126    };
127    pub use crate::ir::{
128        BloqTemplate, BloqTemplatePool, InstanceBoundaryOperator, InstanceMeasurement, NodeRestart,
129        TemplateDetectorParity, TemplateDetectorScope, TemplateInstance, TemplateInstanceId,
130        TemplateRepeatState, TemplateRestart,
131    };
132    pub use crate::membership::PredicateAnalysis;
133}
134
135/// Circuit vocabulary embedded by Bloq IR templates and annotations.
136///
137/// Execution backends depend on `bloq_ir` alone and use this module instead of
138/// reaching through the IR to its `bloq_circuit` implementation dependency. The
139/// glob is deliberate: the whole vocabulary travels together, and enumerating it
140/// here would only add a second list to keep in step with `bloq_circuit`.
141///
142/// The few circuit types that appear in `bloq_ir`'s own signatures
143/// ([`Basis`], [`CoordinateOverflowError`], [`FlattenLimits`]) are *also* at the
144/// crate root, so those have two paths on purpose — the root one so a signature
145/// is nameable without this module, this one so a backend can take the lot.
146pub mod circuit {
147    pub use bloq_circuit::*;
148}
149
150pub(crate) type FxMap<K, V> = rustc_hash::FxHashMap<K, V>;
151pub(crate) type FxSet<T> = rustc_hash::FxHashSet<T>;
152
153/// The most commonly used items, for `use bloq_ir::prelude::*`.
154///
155/// Also available as `bloq::ir::prelude` through the facade crate.
156pub mod prelude {
157    #[doc(no_inline)]
158    pub use crate::{Bloq, BloqNode, BloqNodeId, BloqNodeKind, SubGraph};
159}