1pub use bloq_circuit as circuit;
43pub use bloq_compile as compile;
44pub use bloq_graph as graph;
45pub use bloq_ir as ir;
46pub use bloq_stim as stim;
47pub use bloq_utils as utils;
48#[cfg(feature = "vm")]
49pub use bloq_vm as vm;
50
51mod error;
52pub use error::{Error, Result};
53
54use bloq_graph::BlockGraph;
55
56pub fn compile_to_stim(graph: &BlockGraph, distance: u32) -> Result<String> {
76 let bloq = bloq_compile::compile(graph, distance)?;
77 Ok(bloq_stim::emit_bloq_stim(&bloq)?)
78}
79
80pub mod prelude {
98 #[doc(no_inline)]
99 pub use bloq_circuit::NoiseModel;
100 #[doc(no_inline)]
101 pub use bloq_compile::{
102 CompileArtifacts, CompileConfig, CompileContext, CompileError, compile, compile_with,
103 };
104 #[doc(no_inline)]
105 pub use bloq_graph::prelude::*;
106 #[doc(no_inline)]
107 pub use bloq_ir::Bloq;
108 #[doc(no_inline)]
109 pub use bloq_stim::prelude::*;
110
111 #[doc(no_inline)]
112 pub use crate::{Error, Result, compile_to_stim};
113
114 #[doc(no_inline)]
116 pub use glam::IVec3;
117}
118
119#[cfg(doctest)]
122mod documentation {
123 #[doc = include_str!("../../README.md")]
124 mod readme {}
125 #[doc = include_str!("../../docs/guide.md")]
126 mod guide {}
127 #[doc = include_str!("../../docs/releasing.md")]
128 mod releasing {}
129}
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134
135 fn module_stim(source: &str, distance: u32) -> Result<String> {
136 use crate::prelude::*;
137
138 let source = BlockGraph::from_text(source)?;
139 let config = CompileConfig::try_new(distance)?;
140 let artifacts = CompileContext::new(config).compile(&source)?;
141 let program = Bloq::from_binary(&artifacts.bloq.to_binary())?;
142 let program = Bloq::from_text(&program.to_text())?;
143 program.validate()?;
144 Ok(emit_bloq_stim(&program)?)
145 }
146
147 #[test]
148 fn facade_result_composes_modules_compilation_and_codecs() -> Result {
149 use std::error::Error as _;
150
151 let source = graph::GalleryItem::CNOT.build().to_blog_text();
152 assert!(module_stim(&source, 3)?.contains("QUBIT_COORDS"));
153 let error = module_stim("invalid BLOG", 3).unwrap_err();
154 assert!(error.is::<graph::BlockGraphError>());
155 assert!(error.source().unwrap().is::<graph::BlockGraphError>());
156 assert!(matches!(
157 module_stim(&source, 4).unwrap_err().downcast_ref(),
158 Some(compile::InvalidDistance(4))
159 ));
160 Ok(())
161 }
162
163 #[test]
164 fn facade_error_retains_typed_sources_and_resource_failures() {
165 use std::error::Error as _;
166
167 fn assert_thread_safe<E: std::error::Error + Send + Sync + 'static>() {}
168 assert_thread_safe::<Error>();
169
170 let resource = utils::boolean::BooleanResourceError {
171 resource: "Boolean steps",
172 observed: 2,
173 limit: 1,
174 };
175 let source = compile::CompileError::from(resource);
176 let message = source.to_string();
177 let error = Error::from(source);
178 assert_eq!(error.to_string(), message);
179 let source = error
180 .source()
181 .unwrap()
182 .downcast_ref::<compile::CompileError>()
183 .unwrap();
184 assert!(source.is_resource_limited());
185 assert!(
186 matches!(source, compile::CompileError::BooleanResource(actual) if *actual == resource)
187 );
188 assert!(error.is::<compile::CompileError>());
189 assert!(error.downcast_ref::<graph::ParseError>().is_none());
190
191 let error = Error::from(std::io::Error::other("output write failed"));
192 assert_eq!(error.to_string(), "output write failed");
193 assert!(error.source().unwrap().is::<std::io::Error>());
194 }
195
196 #[cfg(feature = "vm")]
197 #[test]
198 fn facade_result_drives_vm_and_serializes_artifacts() -> Result {
199 let program = compile::compile(&graph::GalleryItem::CNOT.build(), 3)?;
200 let config = vm::LoweringConfig::default();
201 let program = vm::lower(&program, &config)?;
202 let result = program.run(config.runtime_config(42))?;
203 assert!(!result.artifact.discarded);
204 assert!(!result.artifact.to_json()?.is_empty());
205 Ok(())
206 }
207
208 #[test]
211 fn compile_to_stim_reports_which_stage_failed() {
212 assert!(matches!(
213 compile_to_stim(&graph::GalleryItem::CNOT.build(), 4)
214 .unwrap_err()
215 .downcast_ref(),
216 Some(compile::CompileError::InvalidDistance(4))
217 ));
218 assert!(
219 compile_to_stim(&graph::GalleryItem::T.build(), 3)
220 .unwrap_err()
221 .is::<stim::StimEmissionError>()
222 );
223 }
224}