Skip to content

Commit 03d5320

Browse files
committed
feat: Generalise array op builers to arbitrary array kinds
1 parent ddb92ce commit 03d5320

File tree

4 files changed

+543
-141
lines changed

4 files changed

+543
-141
lines changed

hugr-core/src/std_extensions/collections/array.rs

Lines changed: 235 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ use std::sync::Arc;
1515
use delegate::delegate;
1616
use lazy_static::lazy_static;
1717

18+
use crate::builder::{BuildError, Dataflow};
1819
use crate::extension::resolution::{ExtensionResolutionError, WeakExtensionRegistry};
19-
use crate::extension::simple_op::{MakeOpDef, MakeRegisteredOp};
20+
use crate::extension::simple_op::{HasConcrete, MakeOpDef, MakeRegisteredOp};
2021
use crate::extension::{ExtensionId, ExtensionSet, SignatureError, TypeDef, TypeDefBound};
2122
use crate::ops::constant::{CustomConst, ValueName};
2223
use crate::ops::{ExtensionOp, OpName};
2324
use crate::types::type_param::{TypeArg, TypeParam};
2425
use crate::types::{CustomCheckFailure, Type, TypeBound, TypeName};
25-
use crate::Extension;
26+
use crate::{Extension, Wire};
2627

2728
pub use array_clone::{GenericArrayClone, GenericArrayCloneDef, ARRAY_CLONE_OP_ID};
2829
pub use array_conversion::{Direction, GenericArrayConvert, GenericArrayConvertDef, FROM, INTO};
@@ -32,7 +33,8 @@ pub use array_op::{GenericArrayOp, GenericArrayOpDef};
3233
pub use array_repeat::{GenericArrayRepeat, GenericArrayRepeatDef, ARRAY_REPEAT_OP_ID};
3334
pub use array_scan::{GenericArrayScan, GenericArrayScanDef, ARRAY_SCAN_OP_ID};
3435
pub use array_value::GenericArrayValue;
35-
pub use op_builder::ArrayOpBuilder;
36+
37+
use op_builder::GenericArrayOpBuilder;
3638

3739
/// Reported unique name of the array type.
3840
pub const ARRAY_TYPENAME: TypeName = TypeName::new_inline("array");
@@ -170,6 +172,236 @@ pub fn new_array_op(element_ty: Type, size: u64) -> ExtensionOp {
170172
op.to_extension_op().unwrap()
171173
}
172174

175+
/// Trait for building array operations in a dataflow graph.
176+
pub trait ArrayOpBuilder: GenericArrayOpBuilder {
177+
/// Adds a new array operation to the dataflow graph and return the wire
178+
/// representing the new array.
179+
///
180+
/// # Arguments
181+
///
182+
/// * `elem_ty` - The type of the elements in the array.
183+
/// * `values` - An iterator over the values to initialize the array with.
184+
///
185+
/// # Errors
186+
///
187+
/// If building the operation fails.
188+
///
189+
/// # Returns
190+
///
191+
/// The wire representing the new array.
192+
fn add_new_array(
193+
&mut self,
194+
elem_ty: Type,
195+
values: impl IntoIterator<Item = Wire>,
196+
) -> Result<Wire, BuildError> {
197+
self.add_new_generic_array::<Array>(elem_ty, values)
198+
}
199+
200+
/// Adds an array clone operation to the dataflow graph and return the wires
201+
/// representing the originala and cloned array.
202+
///
203+
/// # Arguments
204+
///
205+
/// * `elem_ty` - The type of the elements in the array.
206+
/// * `size` - The size of the array.
207+
/// * `input` - The wire representing the array.
208+
///
209+
/// # Errors
210+
///
211+
/// If building the operation fails.
212+
///
213+
/// # Returns
214+
///
215+
/// The wires representing the original and cloned array.
216+
fn add_array_clone(
217+
&mut self,
218+
elem_ty: Type,
219+
size: u64,
220+
input: Wire,
221+
) -> Result<(Wire, Wire), BuildError> {
222+
self.add_generic_array_clone::<Array>(elem_ty, size, input)
223+
}
224+
225+
/// Adds an array discard operation to the dataflow graph.
226+
///
227+
/// # Arguments
228+
///
229+
/// * `elem_ty` - The type of the elements in the array.
230+
/// * `size` - The size of the array.
231+
/// * `input` - The wire representing the array.
232+
///
233+
/// # Errors
234+
///
235+
/// If building the operation fails.
236+
fn add_array_discard(
237+
&mut self,
238+
elem_ty: Type,
239+
size: u64,
240+
input: Wire,
241+
) -> Result<(), BuildError> {
242+
self.add_generic_array_discard::<Array>(elem_ty, size, input)
243+
}
244+
245+
/// Adds an array get operation to the dataflow graph.
246+
///
247+
/// # Arguments
248+
///
249+
/// * `elem_ty` - The type of the elements in the array.
250+
/// * `size` - The size of the array.
251+
/// * `input` - The wire representing the array.
252+
/// * `index` - The wire representing the index to get.
253+
///
254+
/// # Errors
255+
///
256+
/// If building the operation fails.
257+
///
258+
/// # Returns
259+
///
260+
/// * The wire representing the value at the specified index in the array
261+
/// * The wire representing the array
262+
fn add_array_get(
263+
&mut self,
264+
elem_ty: Type,
265+
size: u64,
266+
input: Wire,
267+
index: Wire,
268+
) -> Result<(Wire, Wire), BuildError> {
269+
self.add_generic_array_get::<Array>(elem_ty, size, input, index)
270+
}
271+
272+
/// Adds an array set operation to the dataflow graph.
273+
///
274+
/// This operation sets the value at a specified index in the array.
275+
///
276+
/// # Arguments
277+
///
278+
/// * `elem_ty` - The type of the elements in the array.
279+
/// * `size` - The size of the array.
280+
/// * `input` - The wire representing the array.
281+
/// * `index` - The wire representing the index to set.
282+
/// * `value` - The wire representing the value to set at the specified index.
283+
///
284+
/// # Errors
285+
///
286+
/// Returns an error if building the operation fails.
287+
///
288+
/// # Returns
289+
///
290+
/// The wire representing the updated array after the set operation.
291+
fn add_array_set(
292+
&mut self,
293+
elem_ty: Type,
294+
size: u64,
295+
input: Wire,
296+
index: Wire,
297+
value: Wire,
298+
) -> Result<Wire, BuildError> {
299+
self.add_generic_array_set::<Array>(elem_ty, size, input, index, value)
300+
}
301+
302+
/// Adds an array swap operation to the dataflow graph.
303+
///
304+
/// This operation swaps the values at two specified indices in the array.
305+
///
306+
/// # Arguments
307+
///
308+
/// * `elem_ty` - The type of the elements in the array.
309+
/// * `size` - The size of the array.
310+
/// * `input` - The wire representing the array.
311+
/// * `index1` - The wire representing the first index to swap.
312+
/// * `index2` - The wire representing the second index to swap.
313+
///
314+
/// # Errors
315+
///
316+
/// Returns an error if building the operation fails.
317+
///
318+
/// # Returns
319+
///
320+
/// The wire representing the updated array after the swap operation.
321+
fn add_array_swap(
322+
&mut self,
323+
elem_ty: Type,
324+
size: u64,
325+
input: Wire,
326+
index1: Wire,
327+
index2: Wire,
328+
) -> Result<Wire, BuildError> {
329+
let op = GenericArrayOpDef::<Array>::swap.instantiate(&[size.into(), elem_ty.into()])?;
330+
let [out] = self
331+
.add_dataflow_op(op, vec![input, index1, index2])?
332+
.outputs_arr();
333+
Ok(out)
334+
}
335+
336+
/// Adds an array pop-left operation to the dataflow graph.
337+
///
338+
/// This operation removes the leftmost element from the array.
339+
///
340+
/// # Arguments
341+
///
342+
/// * `elem_ty` - The type of the elements in the array.
343+
/// * `size` - The size of the array.
344+
/// * `input` - The wire representing the array.
345+
///
346+
/// # Errors
347+
///
348+
/// Returns an error if building the operation fails.
349+
///
350+
/// # Returns
351+
///
352+
/// The wire representing the Option<elemty, array<SIZE-1, elemty>>
353+
fn add_array_pop_left(
354+
&mut self,
355+
elem_ty: Type,
356+
size: u64,
357+
input: Wire,
358+
) -> Result<Wire, BuildError> {
359+
self.add_generic_array_pop_left::<Array>(elem_ty, size, input)
360+
}
361+
362+
/// Adds an array pop-right operation to the dataflow graph.
363+
///
364+
/// This operation removes the rightmost element from the array.
365+
///
366+
/// # Arguments
367+
///
368+
/// * `elem_ty` - The type of the elements in the array.
369+
/// * `size` - The size of the array.
370+
/// * `input` - The wire representing the array.
371+
///
372+
/// # Errors
373+
///
374+
/// Returns an error if building the operation fails.
375+
///
376+
/// # Returns
377+
///
378+
/// The wire representing the Option<elemty, array<SIZE-1, elemty>>
379+
fn add_array_pop_right(
380+
&mut self,
381+
elem_ty: Type,
382+
size: u64,
383+
input: Wire,
384+
) -> Result<Wire, BuildError> {
385+
self.add_generic_array_pop_right::<Array>(elem_ty, size, input)
386+
}
387+
388+
/// Adds an operation to discard an empty array from the dataflow graph.
389+
///
390+
/// # Arguments
391+
///
392+
/// * `elem_ty` - The type of the elements in the array.
393+
/// * `input` - The wire representing the array.
394+
///
395+
/// # Errors
396+
///
397+
/// Returns an error if building the operation fails.
398+
fn add_array_discard_empty(&mut self, elem_ty: Type, input: Wire) -> Result<(), BuildError> {
399+
self.add_generic_array_discard_empty::<Array>(elem_ty, input)
400+
}
401+
}
402+
403+
impl<D: Dataflow> ArrayOpBuilder for D {}
404+
173405
#[cfg(test)]
174406
mod test {
175407
use crate::builder::{inout_sig, DFGBuilder, Dataflow, DataflowHugr};

0 commit comments

Comments
 (0)