1use thiserror::Error;
89
90use crate::extension::SignatureError;
91use crate::extension::simple_op::OpLoadError;
92use crate::hugr::ValidationError;
93use crate::hugr::linking::NodeLinkingError;
94use crate::ops::handle::{BasicBlockID, CfgID, ConditionalID, DfgID, FuncID, TailLoopID};
95use crate::ops::{NamedOp, OpType};
96use crate::types::Type;
97use crate::types::{ConstTypeError, Signature, TypeRow};
98use crate::{Node, Port, Wire};
99
100pub mod handle;
101pub use handle::BuildHandle;
102
103mod build_traits;
104pub use build_traits::{
105 Container, Dataflow, DataflowHugr, DataflowSubContainer, HugrBuilder, SubContainer,
106};
107
108pub mod dataflow;
109pub use dataflow::{DFGBuilder, DFGWrapper, FunctionBuilder};
110
111mod module;
112pub use module::ModuleBuilder;
113
114mod cfg;
115pub use cfg::{BlockBuilder, CFGBuilder};
116
117mod tail_loop;
118pub use tail_loop::TailLoopBuilder;
119
120mod conditional;
121pub use conditional::{CaseBuilder, ConditionalBuilder};
122
123mod circuit;
124pub use circuit::{CircuitBuildError, CircuitBuilder};
125
126pub fn endo_sig(types: impl Into<TypeRow>) -> Signature {
128 Signature::new_endo(types)
129}
130
131pub fn inout_sig(inputs: impl Into<TypeRow>, outputs: impl Into<TypeRow>) -> Signature {
133 Signature::new(inputs, outputs)
134}
135
136#[derive(Debug, Clone, PartialEq, Error)]
137#[non_exhaustive]
138pub enum BuildError {
140 #[error("The constructed HUGR is invalid: {0}.")]
142 InvalidHUGR(#[from] ValidationError<Node>),
143 #[error(transparent)]
146 SignatureError(#[from] SignatureError),
147 #[error("Constant failed typechecking: {0}")]
151 BadConstant(#[from] ConstTypeError),
152 #[error("CFG entry node already built for CFG node: {0}.")]
154 EntryBuiltError(Node),
155 #[error(
158 "Cannot initialize hugr for a BasicBlockBuilder with complex sum-rows. Use a CFGBuilder instead."
159 )]
160 BasicBlockTooComplex,
161 #[error("Node with index {node} does not have type {op_desc} as expected.")]
163 #[allow(missing_docs)]
164 UnexpectedType {
165 node: Node,
167 op_desc: &'static str,
169 },
170 #[error("Error building Conditional node: {0}.")]
172 ConditionalError(#[from] conditional::ConditionalBuildError),
173
174 #[error("{node} not found in the Hugr")]
176 NodeNotFound {
177 node: Node,
179 },
180
181 #[error{"In inserting Hugr: {0}"}]
183 HugrInsertionError(#[from] NodeLinkingError<Node, Node>),
184
185 #[error("In inserting HugrView: {0}")]
189 HugrViewInsertionError(String),
190
191 #[error("Wire not found in Hugr: {0}.")]
193 WireNotFound(Wire),
194
195 #[error("Error in CircuitBuilder: {0}.")]
197 CircuitError(#[from] circuit::CircuitBuildError),
198
199 #[error("Found an error while setting the outputs of a {} container, {container_node}. {error}", .container_op.name())]
201 #[allow(missing_docs)]
202 OutputWiring {
203 container_op: Box<OpType>,
204 container_node: Node,
205 #[source]
206 error: BuilderWiringError,
207 },
208
209 #[error("Got an input wire while adding a {} to the circuit. {error}", .op.name())]
213 #[allow(missing_docs)]
214 OperationWiring {
215 op: Box<OpType>,
216 #[source]
217 error: BuilderWiringError,
218 },
219
220 #[error("Failed to load an extension op: {0}")]
221 #[allow(missing_docs)]
222 ExtensionOp(#[from] OpLoadError),
223}
224
225#[derive(Debug, Clone, PartialEq, Error)]
226#[non_exhaustive]
227pub enum BuilderWiringError {
229 #[error("Cannot copy linear type {typ} from output {src_offset} of node {src}")]
231 #[allow(missing_docs)]
232 NoCopyLinear {
233 typ: Box<Type>,
234 src: Node,
235 src_offset: Port,
236 },
237 #[error(
239 "Cannot connect an inter-graph edge between unrelated nodes. Tried connecting {src} ({src_offset}) with {dst} ({dst_offset})."
240 )]
241 #[allow(missing_docs)]
242 NoRelationIntergraph {
243 src: Node,
244 src_offset: Port,
245 dst: Node,
246 dst_offset: Port,
247 },
248 #[error(
250 "Inter-graph edges cannot carry non-copyable data {typ}. Tried connecting {src} ({src_offset}) with {dst} ({dst_offset})."
251 )]
252 #[allow(missing_docs)]
253 NonCopyableIntergraph {
254 src: Node,
255 src_offset: Port,
256 dst: Node,
257 dst_offset: Port,
258 typ: Box<Type>,
259 },
260}
261
262#[cfg(test)]
263pub(crate) mod test {
264 use rstest::fixture;
265
266 use crate::Hugr;
267 use crate::extension::prelude::{bool_t, usize_t};
268 use crate::hugr::{HugrMut, views::HugrView};
269 use crate::ops;
270 use crate::package::Package;
271 use crate::types::{PolyFuncType, Signature};
272
273 use super::handle::BuildHandle;
274 use super::{
275 BuildError, CFGBuilder, DFGBuilder, Dataflow, DataflowHugr, FuncID, FunctionBuilder,
276 ModuleBuilder,
277 };
278 use super::{DataflowSubContainer, HugrBuilder};
279
280 pub(crate) fn n_identity<T: DataflowSubContainer>(
282 dataflow_builder: T,
283 ) -> Result<T::ContainerHandle, BuildError> {
284 let w = dataflow_builder.input_wires();
285 dataflow_builder.finish_with_outputs(w)
286 }
287
288 pub(crate) fn build_main(
289 signature: PolyFuncType,
290 f: impl FnOnce(FunctionBuilder<&mut Hugr>) -> Result<BuildHandle<FuncID<true>>, BuildError>,
291 ) -> Result<Hugr, BuildError> {
292 let mut module_builder = ModuleBuilder::new();
293 let f_builder = module_builder.define_function("main", signature)?;
294
295 f(f_builder)?;
296
297 Ok(module_builder.finish_hugr()?)
298 }
299
300 #[fixture]
301 pub(crate) fn simple_dfg_hugr() -> Hugr {
302 let dfg_builder = DFGBuilder::new(Signature::new(vec![bool_t()], vec![bool_t()])).unwrap();
303 let [i1] = dfg_builder.input_wires_arr();
304 dfg_builder.finish_hugr_with_outputs([i1]).unwrap()
305 }
306
307 #[fixture]
308 pub(crate) fn simple_funcdef_hugr() -> Hugr {
309 let fn_builder =
310 FunctionBuilder::new("test", Signature::new(vec![bool_t()], vec![bool_t()])).unwrap();
311 let [i1] = fn_builder.input_wires_arr();
312 fn_builder.finish_hugr_with_outputs([i1]).unwrap()
313 }
314
315 #[fixture]
316 pub(crate) fn simple_module_hugr() -> Hugr {
317 let mut builder = ModuleBuilder::new();
318 let sig = Signature::new(vec![bool_t()], vec![bool_t()]);
319 builder.declare("test", sig.into()).unwrap();
320 builder.finish_hugr().unwrap()
321 }
322
323 #[fixture]
324 pub(crate) fn simple_cfg_hugr() -> Hugr {
325 let mut cfg_builder =
326 CFGBuilder::new(Signature::new(vec![usize_t()], vec![usize_t()])).unwrap();
327 super::cfg::test::build_basic_cfg(&mut cfg_builder).unwrap();
328 cfg_builder.finish_hugr().unwrap()
329 }
330
331 #[fixture]
332 pub(crate) fn simple_package() -> Package {
333 let hugr = simple_module_hugr();
334 Package::new([hugr])
335 }
336
337 #[fixture]
338 pub(crate) fn multi_module_package() -> Package {
339 let hugr0 = simple_module_hugr();
340 let hugr1 = simple_module_hugr();
341 Package::new([hugr0, hugr1])
342 }
343
344 pub(crate) fn closed_dfg_root_hugr(signature: Signature) -> Hugr {
348 let mut hugr = Hugr::new_with_entrypoint(ops::DFG {
349 signature: signature.clone(),
350 })
351 .unwrap();
352 hugr.add_node_with_parent(
353 hugr.entrypoint(),
354 ops::Input {
355 types: signature.input,
356 },
357 );
358 hugr.add_node_with_parent(
359 hugr.entrypoint(),
360 ops::Output {
361 types: signature.output,
362 },
363 );
364 hugr
365 }
366
367 #[fixture]
371 pub(crate) fn dfg_calling_defn_decl() -> (Hugr, FuncID<true>, FuncID<false>) {
372 let mut dfb = DFGBuilder::new(Signature::new(vec![], bool_t())).unwrap();
373 let new_defn = {
374 let mut mb = dfb.module_root_builder();
375 let fb = mb
376 .define_function("helper_id", Signature::new_endo(bool_t()))
377 .unwrap();
378 let [f_inp] = fb.input_wires_arr();
379 fb.finish_with_outputs([f_inp]).unwrap()
380 };
381 let new_decl = dfb
382 .module_root_builder()
383 .declare("helper2", Signature::new_endo(bool_t()).into())
384 .unwrap();
385 let cst = dfb.add_load_value(ops::Value::true_val());
386 let [c1] = dfb
387 .call(new_defn.handle(), &[], [cst])
388 .unwrap()
389 .outputs_arr();
390 let [c2] = dfb.call(&new_decl, &[], [c1]).unwrap().outputs_arr();
391 (
392 dfb.finish_hugr_with_outputs([c2]).unwrap(),
393 *new_defn.handle(),
394 new_decl,
395 )
396 }
397}