1use thiserror::Error;
89
90use crate::extension::SignatureError;
91use crate::extension::simple_op::OpLoadError;
92use crate::hugr::ValidationError;
93use crate::ops::handle::{BasicBlockID, CfgID, ConditionalID, DfgID, FuncID, TailLoopID};
94use crate::ops::{NamedOp, OpType};
95use crate::types::Type;
96use crate::types::{ConstTypeError, Signature, TypeRow};
97use crate::{Node, Port, Wire};
98
99pub mod handle;
100pub use handle::BuildHandle;
101
102mod build_traits;
103pub use build_traits::{
104 Container, Dataflow, DataflowHugr, DataflowSubContainer, HugrBuilder, SubContainer,
105};
106
107mod dataflow;
108pub use dataflow::{DFGBuilder, DFGWrapper, FunctionBuilder};
109
110mod module;
111pub use module::ModuleBuilder;
112
113mod cfg;
114pub use cfg::{BlockBuilder, CFGBuilder};
115
116mod tail_loop;
117pub use tail_loop::TailLoopBuilder;
118
119mod conditional;
120pub use conditional::{CaseBuilder, ConditionalBuilder};
121
122mod circuit;
123pub use circuit::{CircuitBuildError, CircuitBuilder};
124
125pub fn endo_sig(types: impl Into<TypeRow>) -> Signature {
127 Signature::new_endo(types)
128}
129
130pub fn inout_sig(inputs: impl Into<TypeRow>, outputs: impl Into<TypeRow>) -> Signature {
132 Signature::new(inputs, outputs)
133}
134
135#[derive(Debug, Clone, PartialEq, Error)]
136#[non_exhaustive]
137pub enum BuildError {
139 #[error("The constructed HUGR is invalid: {0}.")]
141 InvalidHUGR(#[from] ValidationError<Node>),
142 #[error(transparent)]
145 SignatureError(#[from] SignatureError),
146 #[error("Constant failed typechecking: {0}")]
150 BadConstant(#[from] ConstTypeError),
151 #[error("CFG entry node already built for CFG node: {0}.")]
153 EntryBuiltError(Node),
154 #[error(
157 "Cannot initialize hugr for a BasicBlockBuilder with complex sum-rows. Use a CFGBuilder instead."
158 )]
159 BasicBlockTooComplex,
160 #[error("Node with index {node} does not have type {op_desc} as expected.")]
162 #[allow(missing_docs)]
163 UnexpectedType {
164 node: Node,
166 op_desc: &'static str,
168 },
169 #[error("Error building Conditional node: {0}.")]
171 ConditionalError(#[from] conditional::ConditionalBuildError),
172
173 #[error("{node} not found in the Hugr")]
175 NodeNotFound {
176 node: Node,
178 },
179
180 #[error("Wire not found in Hugr: {0}.")]
182 WireNotFound(Wire),
183
184 #[error("Error in CircuitBuilder: {0}.")]
186 CircuitError(#[from] circuit::CircuitBuildError),
187
188 #[error("Found an error while setting the outputs of a {} container, {container_node}. {error}", .container_op.name())]
190 #[allow(missing_docs)]
191 OutputWiring {
192 container_op: Box<OpType>,
193 container_node: Node,
194 #[source]
195 error: BuilderWiringError,
196 },
197
198 #[error("Got an input wire while adding a {} to the circuit. {error}", .op.name())]
202 #[allow(missing_docs)]
203 OperationWiring {
204 op: Box<OpType>,
205 #[source]
206 error: BuilderWiringError,
207 },
208
209 #[error("Failed to load an extension op: {0}")]
210 #[allow(missing_docs)]
211 ExtensionOp(#[from] OpLoadError),
212}
213
214#[derive(Debug, Clone, PartialEq, Error)]
215#[non_exhaustive]
216pub enum BuilderWiringError {
218 #[error("Cannot copy linear type {typ} from output {src_offset} of node {src}")]
220 #[allow(missing_docs)]
221 NoCopyLinear {
222 typ: Box<Type>,
223 src: Node,
224 src_offset: Port,
225 },
226 #[error(
228 "Cannot connect an inter-graph edge between unrelated nodes. Tried connecting {src} ({src_offset}) with {dst} ({dst_offset})."
229 )]
230 #[allow(missing_docs)]
231 NoRelationIntergraph {
232 src: Node,
233 src_offset: Port,
234 dst: Node,
235 dst_offset: Port,
236 },
237 #[error(
239 "Inter-graph edges cannot carry non-copyable data {typ}. Tried connecting {src} ({src_offset}) with {dst} ({dst_offset})."
240 )]
241 #[allow(missing_docs)]
242 NonCopyableIntergraph {
243 src: Node,
244 src_offset: Port,
245 dst: Node,
246 dst_offset: Port,
247 typ: Box<Type>,
248 },
249}
250
251#[cfg(test)]
252pub(crate) mod test {
253 use rstest::fixture;
254
255 use crate::Hugr;
256 use crate::extension::prelude::{bool_t, usize_t};
257 use crate::hugr::{HugrMut, views::HugrView};
258 use crate::ops;
259 use crate::package::Package;
260 use crate::types::{PolyFuncType, Signature};
261
262 use super::handle::BuildHandle;
263 use super::{
264 BuildError, CFGBuilder, DFGBuilder, Dataflow, DataflowHugr, FuncID, FunctionBuilder,
265 ModuleBuilder,
266 };
267 use super::{DataflowSubContainer, HugrBuilder};
268
269 pub(crate) fn n_identity<T: DataflowSubContainer>(
271 dataflow_builder: T,
272 ) -> Result<T::ContainerHandle, BuildError> {
273 let w = dataflow_builder.input_wires();
274 dataflow_builder.finish_with_outputs(w)
275 }
276
277 pub(crate) fn build_main(
278 signature: PolyFuncType,
279 f: impl FnOnce(FunctionBuilder<&mut Hugr>) -> Result<BuildHandle<FuncID<true>>, BuildError>,
280 ) -> Result<Hugr, BuildError> {
281 let mut module_builder = ModuleBuilder::new();
282 let f_builder = module_builder.define_function("main", signature)?;
283
284 f(f_builder)?;
285
286 Ok(module_builder.finish_hugr()?)
287 }
288
289 #[fixture]
290 pub(crate) fn simple_dfg_hugr() -> Hugr {
291 let dfg_builder = DFGBuilder::new(Signature::new(vec![bool_t()], vec![bool_t()])).unwrap();
292 let [i1] = dfg_builder.input_wires_arr();
293 dfg_builder.finish_hugr_with_outputs([i1]).unwrap()
294 }
295
296 #[fixture]
297 pub(crate) fn simple_funcdef_hugr() -> Hugr {
298 let fn_builder =
299 FunctionBuilder::new("test", Signature::new(vec![bool_t()], vec![bool_t()])).unwrap();
300 let [i1] = fn_builder.input_wires_arr();
301 fn_builder.finish_hugr_with_outputs([i1]).unwrap()
302 }
303
304 #[fixture]
305 pub(crate) fn simple_module_hugr() -> Hugr {
306 let mut builder = ModuleBuilder::new();
307 let sig = Signature::new(vec![bool_t()], vec![bool_t()]);
308 builder.declare("test", sig.into()).unwrap();
309 builder.finish_hugr().unwrap()
310 }
311
312 #[fixture]
313 pub(crate) fn simple_cfg_hugr() -> Hugr {
314 let mut cfg_builder =
315 CFGBuilder::new(Signature::new(vec![usize_t()], vec![usize_t()])).unwrap();
316 super::cfg::test::build_basic_cfg(&mut cfg_builder).unwrap();
317 cfg_builder.finish_hugr().unwrap()
318 }
319
320 #[fixture]
321 pub(crate) fn simple_package() -> Package {
322 let hugr = simple_module_hugr();
323 Package::new([hugr])
324 }
325
326 #[fixture]
327 pub(crate) fn multi_module_package() -> Package {
328 let hugr0 = simple_module_hugr();
329 let hugr1 = simple_module_hugr();
330 Package::new([hugr0, hugr1])
331 }
332
333 pub(crate) fn closed_dfg_root_hugr(signature: Signature) -> Hugr {
337 let mut hugr = Hugr::new_with_entrypoint(ops::DFG {
338 signature: signature.clone(),
339 })
340 .unwrap();
341 hugr.add_node_with_parent(
342 hugr.entrypoint(),
343 ops::Input {
344 types: signature.input,
345 },
346 );
347 hugr.add_node_with_parent(
348 hugr.entrypoint(),
349 ops::Output {
350 types: signature.output,
351 },
352 );
353 hugr
354 }
355}