Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: Allow panic operation to have any input and output wires #1024

Merged
merged 4 commits into from
May 13, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 89 additions & 2 deletions hugr/src/extension/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,48 @@ impl SignatureFromArgs for ArrayOpCustom {
}
}

struct GenericOpCustom;
impl SignatureFromArgs for GenericOpCustom {
fn compute_signature(&self, arg_values: &[TypeArg]) -> Result<PolyFuncType, SignatureError> {
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<Type> = 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<Type> = 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] {
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()];
}
PARAMS.as_slice()
}
}

/// Name of prelude extension.
pub const PRELUDE_ID: ExtensionId = ExtensionId::new_unchecked("prelude");
lazy_static! {
Expand Down Expand Up @@ -102,7 +144,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
Expand Down Expand Up @@ -140,7 +182,16 @@ pub fn array_type(size: impl Into<TypeArg>, 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`
Expand Down Expand Up @@ -296,6 +347,7 @@ impl CustomConst for ConstError {
mod test {
use crate::{
builder::{DFGBuilder, Dataflow, DataflowHugr},
utils::test_quantum_extension::cx_gate,
Hugr, Wire,
};

Expand Down Expand Up @@ -348,15 +400,50 @@ 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();

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() {
Expand Down