diff --git a/hugr-core/src/std_extensions/collections/array.rs b/hugr-core/src/std_extensions/collections/array.rs index 655507b09..3c8812f67 100644 --- a/hugr-core/src/std_extensions/collections/array.rs +++ b/hugr-core/src/std_extensions/collections/array.rs @@ -15,14 +15,15 @@ use std::sync::Arc; use delegate::delegate; use lazy_static::lazy_static; +use crate::builder::{BuildError, Dataflow}; use crate::extension::resolution::{ExtensionResolutionError, WeakExtensionRegistry}; -use crate::extension::simple_op::{MakeOpDef, MakeRegisteredOp}; +use crate::extension::simple_op::{HasConcrete, MakeOpDef, MakeRegisteredOp}; use crate::extension::{ExtensionId, ExtensionSet, SignatureError, TypeDef, TypeDefBound}; use crate::ops::constant::{CustomConst, ValueName}; use crate::ops::{ExtensionOp, OpName}; use crate::types::type_param::{TypeArg, TypeParam}; use crate::types::{CustomCheckFailure, Type, TypeBound, TypeName}; -use crate::Extension; +use crate::{Extension, Wire}; pub use array_clone::{GenericArrayClone, GenericArrayCloneDef, ARRAY_CLONE_OP_ID}; pub use array_conversion::{Direction, GenericArrayConvert, GenericArrayConvertDef, FROM, INTO}; @@ -32,7 +33,8 @@ pub use array_op::{GenericArrayOp, GenericArrayOpDef}; pub use array_repeat::{GenericArrayRepeat, GenericArrayRepeatDef, ARRAY_REPEAT_OP_ID}; pub use array_scan::{GenericArrayScan, GenericArrayScanDef, ARRAY_SCAN_OP_ID}; pub use array_value::GenericArrayValue; -pub use op_builder::ArrayOpBuilder; + +use op_builder::GenericArrayOpBuilder; /// Reported unique name of the array type. pub const ARRAY_TYPENAME: TypeName = TypeName::new_inline("array"); @@ -170,6 +172,236 @@ pub fn new_array_op(element_ty: Type, size: u64) -> ExtensionOp { op.to_extension_op().unwrap() } +/// Trait for building array operations in a dataflow graph. +pub trait ArrayOpBuilder: GenericArrayOpBuilder { + /// Adds a new array operation to the dataflow graph and return the wire + /// representing the new array. + /// + /// # Arguments + /// + /// * `elem_ty` - The type of the elements in the array. + /// * `values` - An iterator over the values to initialize the array with. + /// + /// # Errors + /// + /// If building the operation fails. + /// + /// # Returns + /// + /// The wire representing the new array. + fn add_new_array( + &mut self, + elem_ty: Type, + values: impl IntoIterator, + ) -> Result { + self.add_new_generic_array::(elem_ty, values) + } + + /// Adds an array clone operation to the dataflow graph and return the wires + /// representing the originala and cloned array. + /// + /// # Arguments + /// + /// * `elem_ty` - The type of the elements in the array. + /// * `size` - The size of the array. + /// * `input` - The wire representing the array. + /// + /// # Errors + /// + /// If building the operation fails. + /// + /// # Returns + /// + /// The wires representing the original and cloned array. + fn add_array_clone( + &mut self, + elem_ty: Type, + size: u64, + input: Wire, + ) -> Result<(Wire, Wire), BuildError> { + self.add_generic_array_clone::(elem_ty, size, input) + } + + /// Adds an array discard operation to the dataflow graph. + /// + /// # Arguments + /// + /// * `elem_ty` - The type of the elements in the array. + /// * `size` - The size of the array. + /// * `input` - The wire representing the array. + /// + /// # Errors + /// + /// If building the operation fails. + fn add_array_discard( + &mut self, + elem_ty: Type, + size: u64, + input: Wire, + ) -> Result<(), BuildError> { + self.add_generic_array_discard::(elem_ty, size, input) + } + + /// Adds an array get operation to the dataflow graph. + /// + /// # Arguments + /// + /// * `elem_ty` - The type of the elements in the array. + /// * `size` - The size of the array. + /// * `input` - The wire representing the array. + /// * `index` - The wire representing the index to get. + /// + /// # Errors + /// + /// If building the operation fails. + /// + /// # Returns + /// + /// * The wire representing the value at the specified index in the array + /// * The wire representing the array + fn add_array_get( + &mut self, + elem_ty: Type, + size: u64, + input: Wire, + index: Wire, + ) -> Result<(Wire, Wire), BuildError> { + self.add_generic_array_get::(elem_ty, size, input, index) + } + + /// Adds an array set operation to the dataflow graph. + /// + /// This operation sets the value at a specified index in the array. + /// + /// # Arguments + /// + /// * `elem_ty` - The type of the elements in the array. + /// * `size` - The size of the array. + /// * `input` - The wire representing the array. + /// * `index` - The wire representing the index to set. + /// * `value` - The wire representing the value to set at the specified index. + /// + /// # Errors + /// + /// Returns an error if building the operation fails. + /// + /// # Returns + /// + /// The wire representing the updated array after the set operation. + fn add_array_set( + &mut self, + elem_ty: Type, + size: u64, + input: Wire, + index: Wire, + value: Wire, + ) -> Result { + self.add_generic_array_set::(elem_ty, size, input, index, value) + } + + /// Adds an array swap operation to the dataflow graph. + /// + /// This operation swaps the values at two specified indices in the array. + /// + /// # Arguments + /// + /// * `elem_ty` - The type of the elements in the array. + /// * `size` - The size of the array. + /// * `input` - The wire representing the array. + /// * `index1` - The wire representing the first index to swap. + /// * `index2` - The wire representing the second index to swap. + /// + /// # Errors + /// + /// Returns an error if building the operation fails. + /// + /// # Returns + /// + /// The wire representing the updated array after the swap operation. + fn add_array_swap( + &mut self, + elem_ty: Type, + size: u64, + input: Wire, + index1: Wire, + index2: Wire, + ) -> Result { + let op = GenericArrayOpDef::::swap.instantiate(&[size.into(), elem_ty.into()])?; + let [out] = self + .add_dataflow_op(op, vec![input, index1, index2])? + .outputs_arr(); + Ok(out) + } + + /// Adds an array pop-left operation to the dataflow graph. + /// + /// This operation removes the leftmost element from the array. + /// + /// # Arguments + /// + /// * `elem_ty` - The type of the elements in the array. + /// * `size` - The size of the array. + /// * `input` - The wire representing the array. + /// + /// # Errors + /// + /// Returns an error if building the operation fails. + /// + /// # Returns + /// + /// The wire representing the Option> + fn add_array_pop_left( + &mut self, + elem_ty: Type, + size: u64, + input: Wire, + ) -> Result { + self.add_generic_array_pop_left::(elem_ty, size, input) + } + + /// Adds an array pop-right operation to the dataflow graph. + /// + /// This operation removes the rightmost element from the array. + /// + /// # Arguments + /// + /// * `elem_ty` - The type of the elements in the array. + /// * `size` - The size of the array. + /// * `input` - The wire representing the array. + /// + /// # Errors + /// + /// Returns an error if building the operation fails. + /// + /// # Returns + /// + /// The wire representing the Option> + fn add_array_pop_right( + &mut self, + elem_ty: Type, + size: u64, + input: Wire, + ) -> Result { + self.add_generic_array_pop_right::(elem_ty, size, input) + } + + /// Adds an operation to discard an empty array from the dataflow graph. + /// + /// # Arguments + /// + /// * `elem_ty` - The type of the elements in the array. + /// * `input` - The wire representing the array. + /// + /// # Errors + /// + /// Returns an error if building the operation fails. + fn add_array_discard_empty(&mut self, elem_ty: Type, input: Wire) -> Result<(), BuildError> { + self.add_generic_array_discard_empty::(elem_ty, input) + } +} + +impl ArrayOpBuilder for D {} + #[cfg(test)] mod test { use crate::builder::{inout_sig, DFGBuilder, Dataflow, DataflowHugr}; diff --git a/hugr-core/src/std_extensions/collections/array/op_builder.rs b/hugr-core/src/std_extensions/collections/array/op_builder.rs index 135c96cfa..2e2a7acb1 100644 --- a/hugr-core/src/std_extensions/collections/array/op_builder.rs +++ b/hugr-core/src/std_extensions/collections/array/op_builder.rs @@ -1,6 +1,7 @@ //! Builder trait for array operations in the dataflow graph. use crate::std_extensions::collections::array::GenericArrayOpDef; +use crate::std_extensions::collections::value_array::ValueArray; use crate::{ builder::{BuildError, Dataflow}, extension::simple_op::HasConcrete as _, @@ -11,8 +12,13 @@ use itertools::Itertools as _; use super::{Array, ArrayKind, GenericArrayClone, GenericArrayDiscard}; -/// Trait for building array operations in a dataflow graph. -pub trait ArrayOpBuilder: Dataflow { +use crate::extension::prelude::{ + either_type, option_type, usize_t, ConstUsize, UnwrapBuilder as _, +}; + +/// Trait for building array operations in a dataflow graph that are generic +/// over the concrete array implementation. +pub trait GenericArrayOpBuilder: Dataflow { /// Adds a new array operation to the dataflow graph and return the wire /// representing the new array. /// @@ -28,7 +34,7 @@ pub trait ArrayOpBuilder: Dataflow { /// # Returns /// /// The wire representing the new array. - fn add_new_array( + fn add_new_generic_array( &mut self, elem_ty: Type, values: impl IntoIterator, @@ -59,7 +65,7 @@ pub trait ArrayOpBuilder: Dataflow { /// # Returns /// /// The wires representing the original and cloned array. - fn add_array_clone( + fn add_generic_array_clone( &mut self, elem_ty: Type, size: u64, @@ -81,7 +87,7 @@ pub trait ArrayOpBuilder: Dataflow { /// # Errors /// /// If building the operation fails. - fn add_array_discard( + fn add_generic_array_discard( &mut self, elem_ty: Type, size: u64, @@ -109,7 +115,7 @@ pub trait ArrayOpBuilder: Dataflow { /// /// * The wire representing the value at the specified index in the array /// * The wire representing the array - fn add_array_get( + fn add_generic_array_get( &mut self, elem_ty: Type, size: u64, @@ -140,7 +146,7 @@ pub trait ArrayOpBuilder: Dataflow { /// # Returns /// /// The wire representing the updated array after the set operation. - fn add_array_set( + fn add_generic_array_set( &mut self, elem_ty: Type, size: u64, @@ -174,7 +180,7 @@ pub trait ArrayOpBuilder: Dataflow { /// # Returns /// /// The wire representing the updated array after the swap operation. - fn add_array_swap( + fn add_generic_array_swap( &mut self, elem_ty: Type, size: u64, @@ -206,7 +212,7 @@ pub trait ArrayOpBuilder: Dataflow { /// # Returns /// /// The wire representing the Option> - fn add_array_pop_left( + fn add_generic_array_pop_left( &mut self, elem_ty: Type, size: u64, @@ -233,7 +239,7 @@ pub trait ArrayOpBuilder: Dataflow { /// # Returns /// /// The wire representing the Option> - fn add_array_pop_right( + fn add_generic_array_pop_right( &mut self, elem_ty: Type, size: u64, @@ -253,7 +259,11 @@ pub trait ArrayOpBuilder: Dataflow { /// # Errors /// /// Returns an error if building the operation fails. - fn add_array_discard_empty(&mut self, elem_ty: Type, input: Wire) -> Result<(), BuildError> { + fn add_generic_array_discard_empty( + &mut self, + elem_ty: Type, + input: Wire, + ) -> Result<(), BuildError> { self.add_dataflow_op( GenericArrayOpDef::::discard_empty .instantiate(&[elem_ty.into()]) @@ -264,86 +274,111 @@ pub trait ArrayOpBuilder: Dataflow { } } -impl ArrayOpBuilder for D {} +impl GenericArrayOpBuilder for D {} -#[cfg(test)] -mod test { - use crate::extension::prelude::PRELUDE_ID; - use crate::extension::ExtensionSet; - use crate::std_extensions::collections::array::{self, array_type}; - use crate::{ - builder::{DFGBuilder, HugrBuilder}, - extension::prelude::{either_type, option_type, usize_t, ConstUsize, UnwrapBuilder as _}, - types::Signature, - Hugr, +/// Helper function to build a Hugr that contains all basic array operations. +/// +/// Generic over the concrete array implementation. +pub fn build_all_array_ops_generic(mut builder: B) -> B { + let us0 = builder.add_load_value(ConstUsize::new(0)); + let us1 = builder.add_load_value(ConstUsize::new(1)); + let us2 = builder.add_load_value(ConstUsize::new(2)); + let arr = builder + .add_new_generic_array::(usize_t(), [us1, us2]) + .unwrap(); + let [arr] = { + let r = builder + .add_generic_array_swap::(usize_t(), 2, arr, us0, us1) + .unwrap(); + let res_sum_ty = { + let array_type = AK::ty(2, usize_t()); + either_type(array_type.clone(), array_type) + }; + builder.build_unwrap_sum(1, res_sum_ty, r).unwrap() }; - use rstest::rstest; - use super::*; + let ([elem_0], arr) = { + let (r, arr) = builder + .add_generic_array_get::(usize_t(), 2, arr, us0) + .unwrap(); + ( + builder + .build_unwrap_sum(1, option_type(usize_t()), r) + .unwrap(), + arr, + ) + }; - #[rstest::fixture] - #[default(DFGBuilder)] - pub fn all_array_ops( - #[default(DFGBuilder::new(Signature::new_endo(Type::EMPTY_TYPEROW) - .with_extension_delta(ExtensionSet::from_iter([ - PRELUDE_ID, - array::EXTENSION_ID - ]))).unwrap())] - mut builder: B, - ) -> B { - let us0 = builder.add_load_value(ConstUsize::new(0)); - let us1 = builder.add_load_value(ConstUsize::new(1)); - let us2 = builder.add_load_value(ConstUsize::new(2)); - let arr = builder.add_new_array(usize_t(), [us1, us2]).unwrap(); - let [arr] = { - let r = builder.add_array_swap(usize_t(), 2, arr, us0, us1).unwrap(); - let res_sum_ty = { - let array_type = array_type(2, usize_t()); - either_type(array_type.clone(), array_type) - }; - builder.build_unwrap_sum(1, res_sum_ty, r).unwrap() + let [_elem_1, arr] = { + let r = builder + .add_generic_array_set::(usize_t(), 2, arr, us1, elem_0) + .unwrap(); + let res_sum_ty = { + let row = vec![usize_t(), AK::ty(2, usize_t())]; + either_type(row.clone(), row) }; + builder.build_unwrap_sum(1, res_sum_ty, r).unwrap() + }; - let ([elem_0], arr) = { - let (r, arr) = builder.add_array_get(usize_t(), 2, arr, us0).unwrap(); - ( - builder - .build_unwrap_sum(1, option_type(usize_t()), r) - .unwrap(), - arr, - ) - }; + let [_elem_left, arr] = { + let r = builder + .add_generic_array_pop_left::(usize_t(), 2, arr) + .unwrap(); + builder + .build_unwrap_sum(1, option_type(vec![usize_t(), AK::ty(1, usize_t())]), r) + .unwrap() + }; + let [_elem_right, arr] = { + let r = builder + .add_generic_array_pop_right::(usize_t(), 1, arr) + .unwrap(); + builder + .build_unwrap_sum(1, option_type(vec![usize_t(), AK::ty(0, usize_t())]), r) + .unwrap() + }; - let [_elem_1, arr] = { - let r = builder - .add_array_set(usize_t(), 2, arr, us1, elem_0) - .unwrap(); - let res_sum_ty = { - let row = vec![usize_t(), array_type(2, usize_t())]; - either_type(row.clone(), row) - }; - builder.build_unwrap_sum(1, res_sum_ty, r).unwrap() - }; + builder + .add_generic_array_discard_empty::(usize_t(), arr) + .unwrap(); + builder +} - let [_elem_left, arr] = { - let r = builder.add_array_pop_left(usize_t(), 2, arr).unwrap(); - builder - .build_unwrap_sum(1, option_type(vec![usize_t(), array_type(1, usize_t())]), r) - .unwrap() - }; - let [_elem_right, arr] = { - let r = builder.add_array_pop_right(usize_t(), 1, arr).unwrap(); - builder - .build_unwrap_sum(1, option_type(vec![usize_t(), array_type(0, usize_t())]), r) - .unwrap() - }; +/// Helper function to build a Hugr that contains all basic array operations. +pub fn build_all_array_ops(builder: B) -> B { + build_all_array_ops_generic::(builder) +} - builder.add_array_discard_empty(usize_t(), arr).unwrap(); - builder +/// Helper function to build a Hugr that contains all basic array operations. +pub fn build_all_value_array_ops(builder: B) -> B { + build_all_array_ops_generic::(builder) +} + +/// Testing utilities to generate Hugrs that contain array operations. +#[cfg(test)] +mod test { + use crate::builder::{DFGBuilder, HugrBuilder}; + use crate::extension::prelude::PRELUDE_ID; + use crate::extension::ExtensionSet; + use crate::std_extensions::collections::array::{self}; + use crate::std_extensions::collections::value_array::{self}; + use crate::types::Signature; + + use super::*; + + #[test] + fn all_array_ops() { + let sig = Signature::new_endo(Type::EMPTY_TYPEROW) + .with_extension_delta(ExtensionSet::from_iter([PRELUDE_ID, array::EXTENSION_ID])); + let builder = DFGBuilder::new(sig).unwrap(); + build_all_array_ops(builder).finish_hugr().unwrap(); } - #[rstest] - fn build_all_ops(all_array_ops: DFGBuilder) { - all_array_ops.finish_hugr().unwrap(); + #[test] + fn all_value_array_ops() { + let sig = Signature::new_endo(Type::EMPTY_TYPEROW).with_extension_delta( + ExtensionSet::from_iter([PRELUDE_ID, value_array::EXTENSION_ID]), + ); + let builder = DFGBuilder::new(sig).unwrap(); + build_all_value_array_ops(builder).finish_hugr().unwrap(); } } diff --git a/hugr-core/src/std_extensions/collections/value_array.rs b/hugr-core/src/std_extensions/collections/value_array.rs index 15c8359a1..b1e9bff94 100644 --- a/hugr-core/src/std_extensions/collections/value_array.rs +++ b/hugr-core/src/std_extensions/collections/value_array.rs @@ -8,14 +8,16 @@ use std::sync::Arc; use delegate::delegate; use lazy_static::lazy_static; +use crate::builder::{BuildError, Dataflow}; use crate::extension::resolution::{ExtensionResolutionError, WeakExtensionRegistry}; -use crate::extension::simple_op::MakeOpDef; +use crate::extension::simple_op::{HasConcrete, MakeOpDef}; use crate::extension::{ExtensionId, ExtensionSet, SignatureError, TypeDef, TypeDefBound}; use crate::ops::constant::{CustomConst, ValueName}; use crate::types::type_param::{TypeArg, TypeParam}; use crate::types::{CustomCheckFailure, Type, TypeBound, TypeName}; -use crate::Extension; +use crate::{Extension, Wire}; +use super::array::op_builder::GenericArrayOpBuilder; use super::array::{ Array, ArrayKind, GenericArrayConvert, GenericArrayConvertDef, GenericArrayOp, GenericArrayOpDef, GenericArrayRepeat, GenericArrayRepeatDef, GenericArrayScan, @@ -142,3 +144,189 @@ pub fn value_array_type_parametric( ) -> Result { ValueArray::ty_parametric(size, element_ty) } + +/// Trait for building value array operations in a dataflow graph. +pub trait VArrayOpBuilder: GenericArrayOpBuilder { + /// Adds a new array operation to the dataflow graph and return the wire + /// representing the new array. + /// + /// # Arguments + /// + /// * `elem_ty` - The type of the elements in the array. + /// * `values` - An iterator over the values to initialize the array with. + /// + /// # Errors + /// + /// If building the operation fails. + /// + /// # Returns + /// + /// The wire representing the new array. + fn add_new_value_array( + &mut self, + elem_ty: Type, + values: impl IntoIterator, + ) -> Result { + self.add_new_generic_array::(elem_ty, values) + } + + /// Adds an array get operation to the dataflow graph. + /// + /// # Arguments + /// + /// * `elem_ty` - The type of the elements in the array. + /// * `size` - The size of the array. + /// * `input` - The wire representing the array. + /// * `index` - The wire representing the index to get. + /// + /// # Errors + /// + /// If building the operation fails. + /// + /// # Returns + /// + /// * The wire representing the value at the specified index in the array + /// * The wire representing the array + fn add_value_array_get( + &mut self, + elem_ty: Type, + size: u64, + input: Wire, + index: Wire, + ) -> Result<(Wire, Wire), BuildError> { + self.add_generic_array_get::(elem_ty, size, input, index) + } + + /// Adds an array set operation to the dataflow graph. + /// + /// This operation sets the value at a specified index in the array. + /// + /// # Arguments + /// + /// * `elem_ty` - The type of the elements in the array. + /// * `size` - The size of the array. + /// * `input` - The wire representing the array. + /// * `index` - The wire representing the index to set. + /// * `value` - The wire representing the value to set at the specified index. + /// + /// # Errors + /// + /// Returns an error if building the operation fails. + /// + /// # Returns + /// + /// The wire representing the updated array after the set operation. + fn add_value_array_set( + &mut self, + elem_ty: Type, + size: u64, + input: Wire, + index: Wire, + value: Wire, + ) -> Result { + self.add_generic_array_set::(elem_ty, size, input, index, value) + } + + /// Adds an array swap operation to the dataflow graph. + /// + /// This operation swaps the values at two specified indices in the array. + /// + /// # Arguments + /// + /// * `elem_ty` - The type of the elements in the array. + /// * `size` - The size of the array. + /// * `input` - The wire representing the array. + /// * `index1` - The wire representing the first index to swap. + /// * `index2` - The wire representing the second index to swap. + /// + /// # Errors + /// + /// Returns an error if building the operation fails. + /// + /// # Returns + /// + /// The wire representing the updated array after the swap operation. + fn add_value_array_swap( + &mut self, + elem_ty: Type, + size: u64, + input: Wire, + index1: Wire, + index2: Wire, + ) -> Result { + let op = + GenericArrayOpDef::::swap.instantiate(&[size.into(), elem_ty.into()])?; + let [out] = self + .add_dataflow_op(op, vec![input, index1, index2])? + .outputs_arr(); + Ok(out) + } + + /// Adds an array pop-left operation to the dataflow graph. + /// + /// This operation removes the leftmost element from the array. + /// + /// # Arguments + /// + /// * `elem_ty` - The type of the elements in the array. + /// * `size` - The size of the array. + /// * `input` - The wire representing the array. + /// + /// # Errors + /// + /// Returns an error if building the operation fails. + /// + /// # Returns + /// + /// The wire representing the Option> + fn add_array_pop_left( + &mut self, + elem_ty: Type, + size: u64, + input: Wire, + ) -> Result { + self.add_generic_array_pop_left::(elem_ty, size, input) + } + + /// Adds an array pop-right operation to the dataflow graph. + /// + /// This operation removes the rightmost element from the array. + /// + /// # Arguments + /// + /// * `elem_ty` - The type of the elements in the array. + /// * `size` - The size of the array. + /// * `input` - The wire representing the array. + /// + /// # Errors + /// + /// Returns an error if building the operation fails. + /// + /// # Returns + /// + /// The wire representing the Option> + fn add_array_pop_right( + &mut self, + elem_ty: Type, + size: u64, + input: Wire, + ) -> Result { + self.add_generic_array_pop_right::(elem_ty, size, input) + } + + /// Adds an operation to discard an empty array from the dataflow graph. + /// + /// # Arguments + /// + /// * `elem_ty` - The type of the elements in the array. + /// * `input` - The wire representing the array. + /// + /// # Errors + /// + /// Returns an error if building the operation fails. + fn add_array_discard_empty(&mut self, elem_ty: Type, input: Wire) -> Result<(), BuildError> { + self.add_generic_array_discard_empty::(elem_ty, input) + } +} + +impl VArrayOpBuilder for D {} diff --git a/hugr-llvm/src/extension/collections/array.rs b/hugr-llvm/src/extension/collections/array.rs index 67f89e001..4f0881a23 100644 --- a/hugr-llvm/src/extension/collections/array.rs +++ b/hugr-llvm/src/extension/collections/array.rs @@ -892,6 +892,7 @@ mod test { use hugr_core::extension::prelude::either_type; use hugr_core::extension::ExtensionSet; use hugr_core::ops::Tag; + use hugr_core::std_extensions::collections::array::op_builder::build_all_array_ops; use hugr_core::std_extensions::collections::array::{self, array_type, ArrayRepeat, ArrayScan}; use hugr_core::std_extensions::STD_REG; use hugr_core::types::Type; @@ -922,66 +923,12 @@ mod test { utils::{ArrayOpBuilder, IntOpBuilder, LogicOpBuilder}, }; - /// Build all array ops - /// Copied from `hugr_core::std_extensions::collections::array::builder::test` - fn all_array_ops(mut builder: B) -> B { - let us0 = builder.add_load_value(ConstUsize::new(0)); - let us1 = builder.add_load_value(ConstUsize::new(1)); - let us2 = builder.add_load_value(ConstUsize::new(2)); - let arr = builder.add_new_array(usize_t(), [us1, us2]).unwrap(); - let [arr] = { - let r = builder.add_array_swap(usize_t(), 2, arr, us0, us1).unwrap(); - let res_sum_ty = { - let array_type = array_type(2, usize_t()); - either_type(array_type.clone(), array_type) - }; - builder.build_unwrap_sum(1, res_sum_ty, r).unwrap() - }; - - let ([elem_0], arr) = { - let (r, arr) = builder.add_array_get(usize_t(), 2, arr, us0).unwrap(); - ( - builder - .build_unwrap_sum(1, option_type(usize_t()), r) - .unwrap(), - arr, - ) - }; - - let [_elem_1, arr] = { - let r = builder - .add_array_set(usize_t(), 2, arr, us1, elem_0) - .unwrap(); - let res_sum_ty = { - let row = vec![usize_t(), array_type(2, usize_t())]; - either_type(row.clone(), row) - }; - builder.build_unwrap_sum(1, res_sum_ty, r).unwrap() - }; - - let [_elem_left, arr] = { - let r = builder.add_array_pop_left(usize_t(), 2, arr).unwrap(); - builder - .build_unwrap_sum(1, option_type(vec![usize_t(), array_type(1, usize_t())]), r) - .unwrap() - }; - let [_elem_right, arr] = { - let r = builder.add_array_pop_right(usize_t(), 1, arr).unwrap(); - builder - .build_unwrap_sum(1, option_type(vec![usize_t(), array_type(0, usize_t())]), r) - .unwrap() - }; - - builder.add_array_discard_empty(usize_t(), arr).unwrap(); - builder - } - #[rstest] fn emit_all_ops(mut llvm_ctx: TestContext) { let hugr = SimpleHugrConfig::new() .with_extensions(STD_REG.to_owned()) .finish(|mut builder| { - all_array_ops(builder.dfg_builder_endo([]).unwrap()) + build_all_array_ops(builder.dfg_builder_endo([]).unwrap()) .finish_sub_container() .unwrap(); builder.finish_sub_container().unwrap()