1use thiserror::Error;
90
91use crate::extension::simple_op::OpLoadError;
92use crate::extension::{SignatureError, TO_BE_INFERRED};
93use crate::hugr::ValidationError;
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
108mod 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 {
129 Signature::new_endo(types).with_extension_delta(TO_BE_INFERRED)
130}
131
132pub fn inout_sig(inputs: impl Into<TypeRow>, outputs: impl Into<TypeRow>) -> Signature {
135 Signature::new(inputs, outputs).with_extension_delta(TO_BE_INFERRED)
136}
137
138#[derive(Debug, Clone, PartialEq, Error)]
139#[non_exhaustive]
140pub enum BuildError {
142 #[error("The constructed HUGR is invalid: {0}.")]
144 InvalidHUGR(#[from] ValidationError),
145 #[error(transparent)]
148 SignatureError(#[from] SignatureError),
149 #[error("Constant failed typechecking: {0}")]
153 BadConstant(#[from] ConstTypeError),
154 #[error("CFG entry node already built for CFG node: {0}.")]
156 EntryBuiltError(Node),
157 #[error("Node with index {node} does not have type {op_desc} as expected.")]
159 #[allow(missing_docs)]
160 UnexpectedType {
161 node: Node,
163 op_desc: &'static str,
165 },
166 #[error("Error building Conditional node: {0}.")]
168 ConditionalError(#[from] conditional::ConditionalBuildError),
169
170 #[error("Wire not found in Hugr: {0}.")]
172 WireNotFound(Wire),
173
174 #[error("Error in CircuitBuilder: {0}.")]
176 CircuitError(#[from] circuit::CircuitBuildError),
177
178 #[error("Found an error while setting the outputs of a {} container, {container_node}. {error}", .container_op.name())]
180 #[allow(missing_docs)]
181 OutputWiring {
182 container_op: OpType,
183 container_node: Node,
184 #[source]
185 error: BuilderWiringError,
186 },
187
188 #[error("Got an input wire while adding a {} to the circuit. {error}", .op.name())]
192 #[allow(missing_docs)]
193 OperationWiring {
194 op: OpType,
195 #[source]
196 error: BuilderWiringError,
197 },
198
199 #[error("Failed to load an extension op: {0}")]
200 #[allow(missing_docs)]
201 ExtensionOp(#[from] OpLoadError),
202}
203
204#[derive(Debug, Clone, PartialEq, Error)]
205#[non_exhaustive]
206pub enum BuilderWiringError {
208 #[error("Cannot copy linear type {typ} from output {src_offset} of node {src}")]
210 #[allow(missing_docs)]
211 NoCopyLinear {
212 typ: Type,
213 src: Node,
214 src_offset: Port,
215 },
216 #[error("Cannot connect an inter-graph edge between unrelated nodes. Tried connecting {src} ({src_offset}) with {dst} ({dst_offset}).")]
218 #[allow(missing_docs)]
219 NoRelationIntergraph {
220 src: Node,
221 src_offset: Port,
222 dst: Node,
223 dst_offset: Port,
224 },
225 #[error("Inter-graph edges cannot carry non-copyable data {typ}. Tried connecting {src} ({src_offset}) with {dst} ({dst_offset}).")]
227 #[allow(missing_docs)]
228 NonCopyableIntergraph {
229 src: Node,
230 src_offset: Port,
231 dst: Node,
232 dst_offset: Port,
233 typ: Type,
234 },
235}
236
237#[cfg(test)]
238pub(crate) mod test {
239 use rstest::fixture;
240
241 use crate::extension::prelude::{bool_t, usize_t};
242 use crate::hugr::{views::HugrView, HugrMut};
243 use crate::ops;
244 use crate::package::Package;
245 use crate::types::{PolyFuncType, Signature};
246 use crate::Hugr;
247
248 use super::handle::BuildHandle;
249 use super::{
250 BuildError, CFGBuilder, Container, DFGBuilder, Dataflow, DataflowHugr, FuncID,
251 FunctionBuilder, ModuleBuilder,
252 };
253 use super::{DataflowSubContainer, HugrBuilder};
254
255 pub(crate) fn n_identity<T: DataflowSubContainer>(
257 dataflow_builder: T,
258 ) -> Result<T::ContainerHandle, BuildError> {
259 let w = dataflow_builder.input_wires();
260 dataflow_builder.finish_with_outputs(w)
261 }
262
263 pub(crate) fn build_main(
264 signature: PolyFuncType,
265 f: impl FnOnce(FunctionBuilder<&mut Hugr>) -> Result<BuildHandle<FuncID<true>>, BuildError>,
266 ) -> Result<Hugr, BuildError> {
267 let mut module_builder = ModuleBuilder::new();
268 let f_builder = module_builder.define_function("main", signature)?;
269
270 f(f_builder)?;
271
272 Ok(module_builder.finish_hugr()?)
273 }
274
275 #[fixture]
276 pub(crate) fn simple_dfg_hugr() -> Hugr {
277 let dfg_builder = DFGBuilder::new(Signature::new(vec![bool_t()], vec![bool_t()])).unwrap();
278 let [i1] = dfg_builder.input_wires_arr();
279 dfg_builder.finish_hugr_with_outputs([i1]).unwrap()
280 }
281
282 #[fixture]
283 pub(crate) fn simple_funcdef_hugr() -> Hugr {
284 let fn_builder =
285 FunctionBuilder::new("test", Signature::new(vec![bool_t()], vec![bool_t()])).unwrap();
286 let [i1] = fn_builder.input_wires_arr();
287 fn_builder.finish_hugr_with_outputs([i1]).unwrap()
288 }
289
290 #[fixture]
291 pub(crate) fn simple_module_hugr() -> Hugr {
292 let mut builder = ModuleBuilder::new();
293 let sig = Signature::new(vec![bool_t()], vec![bool_t()]);
294 builder.declare("test", sig.into()).unwrap();
295 builder.finish_hugr().unwrap()
296 }
297
298 #[fixture]
299 pub(crate) fn simple_cfg_hugr() -> Hugr {
300 let mut cfg_builder =
301 CFGBuilder::new(Signature::new(vec![usize_t()], vec![usize_t()])).unwrap();
302 super::cfg::test::build_basic_cfg(&mut cfg_builder).unwrap();
303 cfg_builder.finish_hugr().unwrap()
304 }
305
306 #[fixture]
307 pub(crate) fn simple_package() -> Package {
308 let hugr = simple_module_hugr();
309 Package::new([hugr]).unwrap()
310 }
311
312 #[fixture]
313 pub(crate) fn multi_module_package() -> Package {
314 let hugr0 = simple_module_hugr();
315 let hugr1 = simple_module_hugr();
316 Package::new([hugr0, hugr1]).unwrap()
317 }
318
319 pub(crate) fn closed_dfg_root_hugr(signature: Signature) -> Hugr {
323 let mut hugr = Hugr::new(ops::DFG {
324 signature: signature.clone(),
325 });
326 hugr.add_node_with_parent(
327 hugr.root(),
328 ops::Input {
329 types: signature.input,
330 },
331 );
332 hugr.add_node_with_parent(
333 hugr.root(),
334 ops::Output {
335 types: signature.output,
336 },
337 );
338 hugr
339 }
340}