mod array_clone;
mod array_conversion;
mod array_discard;
mod array_kind;
mod array_op;
mod array_repeat;
mod array_scan;
mod array_value;
pub mod op_builder;
use std::sync::{Arc, LazyLock};
use delegate::delegate;
use crate::builder::{BuildError, Dataflow};
use crate::extension::resolution::{ExtensionResolutionError, WeakExtensionRegistry};
use crate::extension::simple_op::{HasConcrete, MakeOpDef, MakeRegisteredOp};
use crate::extension::{ExtensionId, 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, Wire};
pub use array_clone::{ARRAY_CLONE_OP_ID, GenericArrayClone, GenericArrayCloneDef};
pub use array_conversion::{Direction, FROM, GenericArrayConvert, GenericArrayConvertDef, INTO};
pub use array_discard::{ARRAY_DISCARD_OP_ID, GenericArrayDiscard, GenericArrayDiscardDef};
pub use array_kind::ArrayKind;
pub use array_op::{GenericArrayOp, GenericArrayOpDef};
pub use array_repeat::{ARRAY_REPEAT_OP_ID, GenericArrayRepeat, GenericArrayRepeatDef};
pub use array_scan::{ARRAY_SCAN_OP_ID, GenericArrayScan, GenericArrayScanDef};
pub use array_value::GenericArrayValue;
use op_builder::GenericArrayOpBuilder;
pub const ARRAY_TYPENAME: TypeName = TypeName::new_inline("array");
pub const ARRAY_VALUENAME: TypeName = TypeName::new_inline("array");
pub const EXTENSION_ID: ExtensionId = ExtensionId::new_unchecked("collections.array");
pub const VERSION: semver::Version = semver::Version::new(0, 1, 1);
#[derive(Clone, Copy, Debug, derive_more::Display, Eq, PartialEq, Default)]
pub struct Array;
impl ArrayKind for Array {
const EXTENSION_ID: ExtensionId = EXTENSION_ID;
const TYPE_NAME: TypeName = ARRAY_TYPENAME;
const VALUE_NAME: ValueName = ARRAY_VALUENAME;
fn extension() -> &'static Arc<Extension> {
&EXTENSION
}
fn type_def() -> &'static TypeDef {
EXTENSION.get_type(&ARRAY_TYPENAME).unwrap()
}
}
pub type ArrayOpDef = GenericArrayOpDef<Array>;
pub type ArrayCloneDef = GenericArrayCloneDef<Array>;
pub type ArrayDiscardDef = GenericArrayDiscardDef<Array>;
pub type ArrayRepeatDef = GenericArrayRepeatDef<Array>;
pub type ArrayScanDef = GenericArrayScanDef<Array>;
pub type ArrayOp = GenericArrayOp<Array>;
pub type ArrayClone = GenericArrayClone<Array>;
pub type ArrayDiscard = GenericArrayDiscard<Array>;
pub type ArrayRepeat = GenericArrayRepeat<Array>;
pub type ArrayScan = GenericArrayScan<Array>;
pub type ArrayValue = GenericArrayValue<Array>;
pub static EXTENSION: LazyLock<Arc<Extension>> = LazyLock::new(|| {
Extension::new_arc(EXTENSION_ID, VERSION, |extension, extension_ref| {
extension
.add_type(
ARRAY_TYPENAME,
vec![TypeParam::max_nat_type(), TypeBound::Linear.into()],
"Fixed-length array".into(),
TypeDefBound::any(),
extension_ref,
)
.unwrap();
ArrayOpDef::load_all_ops(extension, extension_ref).unwrap();
ArrayCloneDef::new()
.add_to_extension(extension, extension_ref)
.unwrap();
ArrayDiscardDef::new()
.add_to_extension(extension, extension_ref)
.unwrap();
ArrayRepeatDef::new()
.add_to_extension(extension, extension_ref)
.unwrap();
ArrayScanDef::new()
.add_to_extension(extension, extension_ref)
.unwrap();
})
});
impl ArrayValue {
pub(crate) const CTR_NAME: &'static str = "collections.array.const";
}
#[typetag::serde(name = "ArrayValue")]
impl CustomConst for ArrayValue {
delegate! {
to self {
fn name(&self) -> ValueName;
fn validate(&self) -> Result<(), CustomCheckFailure>;
fn update_extensions(
&mut self,
extensions: &WeakExtensionRegistry,
) -> Result<(), ExtensionResolutionError>;
fn get_type(&self) -> Type;
}
}
fn equal_consts(&self, other: &dyn CustomConst) -> bool {
crate::ops::constant::downcast_equal_consts(self, other)
}
}
#[must_use]
pub fn array_type_def() -> &'static TypeDef {
Array::type_def()
}
#[must_use]
pub fn array_type(size: u64, element_ty: Type) -> Type {
Array::ty(size, element_ty)
}
pub fn array_type_parametric(
size: impl Into<TypeArg>,
element_ty: impl Into<TypeArg>,
) -> Result<Type, SignatureError> {
Array::ty_parametric(size, element_ty)
}
pub const NEW_ARRAY_OP_ID: OpName = OpName::new_inline("new_array");
#[must_use]
pub fn new_array_op(element_ty: Type, size: u64) -> ExtensionOp {
let op = ArrayOpDef::new_array.to_concrete(element_ty, size);
op.to_extension_op().unwrap()
}
pub trait ArrayOpBuilder: GenericArrayOpBuilder {
fn add_new_array(
&mut self,
elem_ty: Type,
values: impl IntoIterator<Item = Wire>,
) -> Result<Wire, BuildError> {
self.add_new_generic_array::<Array>(elem_ty, values)
}
fn add_array_unpack(
&mut self,
elem_ty: Type,
size: u64,
input: Wire,
) -> Result<Vec<Wire>, BuildError> {
self.add_generic_array_unpack::<Array>(elem_ty, size, input)
}
fn add_array_clone(
&mut self,
elem_ty: Type,
size: u64,
input: Wire,
) -> Result<(Wire, Wire), BuildError> {
self.add_generic_array_clone::<Array>(elem_ty, size, input)
}
fn add_array_discard(
&mut self,
elem_ty: Type,
size: u64,
input: Wire,
) -> Result<(), BuildError> {
self.add_generic_array_discard::<Array>(elem_ty, size, input)
}
fn add_array_get(
&mut self,
elem_ty: Type,
size: u64,
input: Wire,
index: Wire,
) -> Result<(Wire, Wire), BuildError> {
self.add_generic_array_get::<Array>(elem_ty, size, input, index)
}
fn add_array_set(
&mut self,
elem_ty: Type,
size: u64,
input: Wire,
index: Wire,
value: Wire,
) -> Result<Wire, BuildError> {
self.add_generic_array_set::<Array>(elem_ty, size, input, index, value)
}
fn add_array_swap(
&mut self,
elem_ty: Type,
size: u64,
input: Wire,
index1: Wire,
index2: Wire,
) -> Result<Wire, BuildError> {
let op = GenericArrayOpDef::<Array>::swap.instantiate(&[size.into(), elem_ty.into()])?;
let [out] = self
.add_dataflow_op(op, vec![input, index1, index2])?
.outputs_arr();
Ok(out)
}
fn add_array_pop_left(
&mut self,
elem_ty: Type,
size: u64,
input: Wire,
) -> Result<Wire, BuildError> {
self.add_generic_array_pop_left::<Array>(elem_ty, size, input)
}
fn add_array_pop_right(
&mut self,
elem_ty: Type,
size: u64,
input: Wire,
) -> Result<Wire, BuildError> {
self.add_generic_array_pop_right::<Array>(elem_ty, size, input)
}
fn add_array_discard_empty(&mut self, elem_ty: Type, input: Wire) -> Result<(), BuildError> {
self.add_generic_array_discard_empty::<Array>(elem_ty, input)
}
}
impl<D: Dataflow> ArrayOpBuilder for D {}
#[cfg(test)]
mod test {
use crate::builder::{DFGBuilder, Dataflow, DataflowHugr, inout_sig};
use crate::extension::prelude::qb_t;
use super::{array_type, new_array_op};
#[test]
fn test_new_array() {
let mut b = DFGBuilder::new(inout_sig(vec![qb_t(); 2], [array_type(2, qb_t())])).unwrap();
let [q1, q2] = b.input_wires_arr();
let op = new_array_op(qb_t(), 2);
let out = b.add_dataflow_op(op, [q1, q2]).unwrap();
b.finish_hugr_with_outputs(out.outputs()).unwrap();
}
}