From 31d39b4cf7b4f6f43f9344307bb23b8e09316cb1 Mon Sep 17 00:00:00 2001 From: Alec Edgington Date: Thu, 9 May 2024 11:46:51 +0100 Subject: [PATCH 1/4] Give panic op a generic signature. --- hugr/src/extension/prelude.rs | 52 +++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/hugr/src/extension/prelude.rs b/hugr/src/extension/prelude.rs index 3a6b2637b..b291ed667 100644 --- a/hugr/src/extension/prelude.rs +++ b/hugr/src/extension/prelude.rs @@ -41,6 +41,49 @@ impl SignatureFromArgs for ArrayOpCustom { } } +fn list_of_type() -> TypeParam { + TypeParam::List { + param: Box::new(TypeParam::Type { b: TypeBound::Any }), + } +} + +struct GenericOpCustom; +impl SignatureFromArgs for GenericOpCustom { + fn compute_signature(&self, arg_values: &[TypeArg]) -> Result { + let [arg0, arg1] = arg_values else { + return Err(SignatureError::InvalidTypeArgs); + }; + let TypeArg::Sequence { elems: inp_args } = arg0 else { + return Err(SignatureError::InvalidTypeArgs); + }; + let TypeArg::Sequence { elems: out_args } = arg1 else { + return Err(SignatureError::InvalidTypeArgs); + }; + let mut inps: Vec = vec![Type::new_extension(ERROR_CUSTOM_TYPE)]; + for inp_arg in inp_args.iter() { + let TypeArg::Type { ty } = inp_arg else { + return Err(SignatureError::InvalidTypeArgs); + }; + inps.push(ty.clone()); + } + let mut outs: Vec = vec![]; + for out_arg in out_args.iter() { + let TypeArg::Type { ty } = out_arg else { + return Err(SignatureError::InvalidTypeArgs); + }; + outs.push(ty.clone()); + } + Ok(PolyFuncType::new(vec![], FunctionType::new(inps, outs))) + } + + fn static_params(&self) -> &[TypeParam] { + lazy_static! { + static ref PARAMS: [TypeParam; 2] = [list_of_type(), list_of_type()]; + } + PARAMS.as_slice() + } +} + /// Name of prelude extension. pub const PRELUDE_ID: ExtensionId = ExtensionId::new_unchecked("prelude"); lazy_static! { @@ -102,7 +145,7 @@ lazy_static! { .add_op( PANIC_OP_ID, "Panic with input error".to_string(), - FunctionType::new(type_row![Type::new_extension(ERROR_CUSTOM_TYPE)], type_row![]), + GenericOpCustom, ) .unwrap(); prelude @@ -348,8 +391,13 @@ mod test { let err = b.add_load_value(error_val); + const TYPE_ARG_NONE: TypeArg = TypeArg::Sequence { elems: vec![] }; let op = PRELUDE - .instantiate_extension_op(&PANIC_OP_ID, [], &PRELUDE_REGISTRY) + .instantiate_extension_op( + &PANIC_OP_ID, + [TYPE_ARG_NONE, TYPE_ARG_NONE], + &PRELUDE_REGISTRY, + ) .unwrap(); b.add_dataflow_op(op, [err]).unwrap(); From 356b1637aac8c7464724bb5f8c8ce6695d1db9f6 Mon Sep 17 00:00:00 2001 From: Alec Edgington Date: Fri, 10 May 2024 15:02:18 +0100 Subject: [PATCH 2/4] Add test for panic op with qubit inputs and outputs. --- hugr/src/extension/prelude.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/hugr/src/extension/prelude.rs b/hugr/src/extension/prelude.rs index b291ed667..0502e63dc 100644 --- a/hugr/src/extension/prelude.rs +++ b/hugr/src/extension/prelude.rs @@ -339,6 +339,7 @@ impl CustomConst for ConstError { mod test { use crate::{ builder::{DFGBuilder, Dataflow, DataflowHugr}, + utils::test_quantum_extension::cx_gate, Hugr, Wire, }; @@ -405,6 +406,36 @@ mod test { b.finish_prelude_hugr_with_outputs([]).unwrap(); } + #[test] + /// test the panic operation with input and output wires + fn test_panic_with_io() { + let error_val = ConstError::new(42, "PANIC"); + const TYPE_ARG_Q: TypeArg = TypeArg::Type { ty: QB_T }; + let type_arg_2q: TypeArg = TypeArg::Sequence { + elems: vec![TYPE_ARG_Q, TYPE_ARG_Q], + }; + let panic_op = PRELUDE + .instantiate_extension_op( + &PANIC_OP_ID, + [type_arg_2q.clone(), type_arg_2q.clone()], + &PRELUDE_REGISTRY, + ) + .unwrap(); + + let mut b = DFGBuilder::new(FunctionType::new_endo(type_row![QB_T, QB_T])).unwrap(); + let [q0, q1] = b.input_wires_arr(); + let [q0, q1] = b + .add_dataflow_op(cx_gate(), [q0, q1]) + .unwrap() + .outputs_arr(); + let err = b.add_load_value(error_val); + let [q0, q1] = b + .add_dataflow_op(panic_op, [err, q0, q1]) + .unwrap() + .outputs_arr(); + b.finish_prelude_hugr_with_outputs([q0, q1]).unwrap(); + } + #[test] /// Test string type. fn test_string_type() { From b01b52880de3ffad76fdc227867f690bedab351f Mon Sep 17 00:00:00 2001 From: Alec Edgington Date: Fri, 10 May 2024 15:18:37 +0100 Subject: [PATCH 3/4] Improve doc. --- hugr/src/extension/prelude.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hugr/src/extension/prelude.rs b/hugr/src/extension/prelude.rs index 0502e63dc..888e57889 100644 --- a/hugr/src/extension/prelude.rs +++ b/hugr/src/extension/prelude.rs @@ -183,7 +183,16 @@ pub fn array_type(size: impl Into, element_ty: Type) -> Type { /// Name of the operation in the prelude for creating new arrays. pub const NEW_ARRAY_OP_ID: OpName = OpName::new_inline("new_array"); + /// Name of the prelude panic operation. +/// +/// This operation can have any input and any output wires; it is instantiated +/// with two [TypeArg::Sequence]s representing these. The first input to the +/// operation is always an error type; the remaining inputs correspond to the +/// first sequence of types in its instantiation; the outputs correspond to the +/// second sequence of types in its instantiation. Note that the inputs and +/// outputs only exist so that structural constraints such as linearity can be +/// satisfied. pub const PANIC_OP_ID: OpName = OpName::new_inline("panic"); /// Initialize a new array op of element type `element_ty` of length `size` From c2a765b54cbf684f6470d020d7bcc705306029b7 Mon Sep 17 00:00:00 2001 From: Alec Edgington Date: Mon, 13 May 2024 08:02:29 +0100 Subject: [PATCH 4/4] Inline function. --- hugr/src/extension/prelude.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/hugr/src/extension/prelude.rs b/hugr/src/extension/prelude.rs index 888e57889..89719a6c0 100644 --- a/hugr/src/extension/prelude.rs +++ b/hugr/src/extension/prelude.rs @@ -41,12 +41,6 @@ impl SignatureFromArgs for ArrayOpCustom { } } -fn list_of_type() -> TypeParam { - TypeParam::List { - param: Box::new(TypeParam::Type { b: TypeBound::Any }), - } -} - struct GenericOpCustom; impl SignatureFromArgs for GenericOpCustom { fn compute_signature(&self, arg_values: &[TypeArg]) -> Result { @@ -77,6 +71,11 @@ impl SignatureFromArgs for GenericOpCustom { } fn static_params(&self) -> &[TypeParam] { + fn list_of_type() -> TypeParam { + TypeParam::List { + param: Box::new(TypeParam::Type { b: TypeBound::Any }), + } + } lazy_static! { static ref PARAMS: [TypeParam; 2] = [list_of_type(), list_of_type()]; }