1use thiserror::Error;
89
90use crate::extension::simple_op::OpLoadError;
91use crate::extension::SignatureError;
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("Cannot initialize hugr for a BasicBlockBuilder with complex sum-rows. Use a CFGBuilder instead.")]
157 BasicBlockTooComplex,
158 #[error("Node with index {node} does not have type {op_desc} as expected.")]
160 #[allow(missing_docs)]
161 UnexpectedType {
162 node: Node,
164 op_desc: &'static str,
166 },
167 #[error("Error building Conditional node: {0}.")]
169 ConditionalError(#[from] conditional::ConditionalBuildError),
170
171 #[error("{node} not found in the Hugr")]
173 NodeNotFound {
174 node: Node,
176 },
177
178 #[error("Wire not found in Hugr: {0}.")]
180 WireNotFound(Wire),
181
182 #[error("Error in CircuitBuilder: {0}.")]
184 CircuitError(#[from] circuit::CircuitBuildError),
185
186 #[error("Found an error while setting the outputs of a {} container, {container_node}. {error}", .container_op.name())]
188 #[allow(missing_docs)]
189 OutputWiring {
190 container_op: OpType,
191 container_node: Node,
192 #[source]
193 error: BuilderWiringError,
194 },
195
196 #[error("Got an input wire while adding a {} to the circuit. {error}", .op.name())]
200 #[allow(missing_docs)]
201 OperationWiring {
202 op: OpType,
203 #[source]
204 error: BuilderWiringError,
205 },
206
207 #[error("Failed to load an extension op: {0}")]
208 #[allow(missing_docs)]
209 ExtensionOp(#[from] OpLoadError),
210}
211
212#[derive(Debug, Clone, PartialEq, Error)]
213#[non_exhaustive]
214pub enum BuilderWiringError {
216 #[error("Cannot copy linear type {typ} from output {src_offset} of node {src}")]
218 #[allow(missing_docs)]
219 NoCopyLinear {
220 typ: Type,
221 src: Node,
222 src_offset: Port,
223 },
224 #[error("Cannot connect an inter-graph edge between unrelated nodes. Tried connecting {src} ({src_offset}) with {dst} ({dst_offset}).")]
226 #[allow(missing_docs)]
227 NoRelationIntergraph {
228 src: Node,
229 src_offset: Port,
230 dst: Node,
231 dst_offset: Port,
232 },
233 #[error("Inter-graph edges cannot carry non-copyable data {typ}. Tried connecting {src} ({src_offset}) with {dst} ({dst_offset}).")]
235 #[allow(missing_docs)]
236 NonCopyableIntergraph {
237 src: Node,
238 src_offset: Port,
239 dst: Node,
240 dst_offset: Port,
241 typ: Type,
242 },
243}
244
245#[cfg(test)]
246pub(crate) mod test {
247 use rstest::fixture;
248
249 use crate::extension::prelude::{bool_t, usize_t};
250 use crate::hugr::{views::HugrView, HugrMut};
251 use crate::ops;
252 use crate::package::Package;
253 use crate::types::{PolyFuncType, Signature};
254 use crate::Hugr;
255
256 use super::handle::BuildHandle;
257 use super::{
258 BuildError, CFGBuilder, Container, DFGBuilder, Dataflow, DataflowHugr, FuncID,
259 FunctionBuilder, ModuleBuilder,
260 };
261 use super::{DataflowSubContainer, HugrBuilder};
262
263 pub(crate) fn n_identity<T: DataflowSubContainer>(
265 dataflow_builder: T,
266 ) -> Result<T::ContainerHandle, BuildError> {
267 let w = dataflow_builder.input_wires();
268 dataflow_builder.finish_with_outputs(w)
269 }
270
271 pub(crate) fn build_main(
272 signature: PolyFuncType,
273 f: impl FnOnce(FunctionBuilder<&mut Hugr>) -> Result<BuildHandle<FuncID<true>>, BuildError>,
274 ) -> Result<Hugr, BuildError> {
275 let mut module_builder = ModuleBuilder::new();
276 let f_builder = module_builder.define_function("main", signature)?;
277
278 f(f_builder)?;
279
280 Ok(module_builder.finish_hugr()?)
281 }
282
283 #[fixture]
284 pub(crate) fn simple_dfg_hugr() -> Hugr {
285 let dfg_builder = DFGBuilder::new(Signature::new(vec![bool_t()], vec![bool_t()])).unwrap();
286 let [i1] = dfg_builder.input_wires_arr();
287 dfg_builder.finish_hugr_with_outputs([i1]).unwrap()
288 }
289
290 #[fixture]
291 pub(crate) fn simple_funcdef_hugr() -> Hugr {
292 let fn_builder =
293 FunctionBuilder::new("test", Signature::new(vec![bool_t()], vec![bool_t()])).unwrap();
294 let [i1] = fn_builder.input_wires_arr();
295 fn_builder.finish_hugr_with_outputs([i1]).unwrap()
296 }
297
298 #[fixture]
299 pub(crate) fn simple_module_hugr() -> Hugr {
300 let mut builder = ModuleBuilder::new();
301 let sig = Signature::new(vec![bool_t()], vec![bool_t()]);
302 builder.declare("test", sig.into()).unwrap();
303 builder.finish_hugr().unwrap()
304 }
305
306 #[fixture]
307 pub(crate) fn simple_cfg_hugr() -> Hugr {
308 let mut cfg_builder =
309 CFGBuilder::new(Signature::new(vec![usize_t()], vec![usize_t()])).unwrap();
310 super::cfg::test::build_basic_cfg(&mut cfg_builder).unwrap();
311 cfg_builder.finish_hugr().unwrap()
312 }
313
314 #[fixture]
315 pub(crate) fn simple_package() -> Package {
316 let hugr = simple_module_hugr();
317 Package::new([hugr])
318 }
319
320 #[fixture]
321 pub(crate) fn multi_module_package() -> Package {
322 let hugr0 = simple_module_hugr();
323 let hugr1 = simple_module_hugr();
324 Package::new([hugr0, hugr1])
325 }
326
327 pub(crate) fn closed_dfg_root_hugr(signature: Signature) -> Hugr {
331 let mut hugr = Hugr::new_with_entrypoint(ops::DFG {
332 signature: signature.clone(),
333 })
334 .unwrap();
335 hugr.add_node_with_parent(
336 hugr.entrypoint(),
337 ops::Input {
338 types: signature.input,
339 },
340 );
341 hugr.add_node_with_parent(
342 hugr.entrypoint(),
343 ops::Output {
344 types: signature.output,
345 },
346 );
347 hugr
348 }
349}