use hugr::ops::OpType;
use hugr::IncomingPort;
use tk2op::NativeOp;
use tket_json_rs::circuit_json;
use super::super::extension::OpaqueTk1Op;
pub mod tk2op;
#[derive(Clone, Debug, PartialEq, derive_more::From)]
pub(crate) enum Tk1Op {
Native(NativeOp),
Opaque(OpaqueTk1Op),
}
impl Tk1Op {
pub fn from_serialised_op(
serial_op: circuit_json::Operation,
num_qubits: usize,
num_bits: usize,
) -> Self {
let op = if let Some(native) =
NativeOp::try_from_serial_optype(serial_op.op_type.clone(), num_qubits, num_bits)
{
Tk1Op::Native(native)
} else {
Tk1Op::Opaque(OpaqueTk1Op::new_from_op(serial_op, num_qubits, num_bits))
};
debug_assert_eq!(num_qubits, op.qubit_inputs().max(op.qubit_outputs()));
debug_assert_eq!(num_bits, op.bit_inputs().max(op.bit_outputs()));
op
}
pub fn optype(&self) -> OpType {
match self {
Tk1Op::Native(native_op) => native_op.optype().clone(),
Tk1Op::Opaque(json_op) => json_op.as_extension_op().into(),
}
}
pub fn into_optype(self) -> OpType {
match self {
Tk1Op::Native(native_op) => native_op.into_optype(),
Tk1Op::Opaque(json_op) => json_op.as_extension_op().into(),
}
}
pub fn param_ports(&self) -> impl Iterator<Item = IncomingPort> + '_ {
match self {
Tk1Op::Native(native_op) => itertools::Either::Left(native_op.param_ports()),
Tk1Op::Opaque(json_op) => itertools::Either::Right(json_op.param_ports()),
}
}
pub fn qubit_inputs(&self) -> usize {
match self {
Tk1Op::Native(native_op) => native_op.input_qubits,
Tk1Op::Opaque(json_op) => json_op.num_qubits,
}
}
pub fn bit_inputs(&self) -> usize {
match self {
Tk1Op::Native(native_op) => native_op.input_bits,
Tk1Op::Opaque(json_op) => json_op.num_bits,
}
}
pub fn qubit_outputs(&self) -> usize {
match self {
Tk1Op::Native(native_op) => native_op.output_qubits,
Tk1Op::Opaque(json_op) => json_op.num_qubits,
}
}
pub fn bit_outputs(&self) -> usize {
match self {
Tk1Op::Native(native_op) => native_op.output_bits,
Tk1Op::Opaque(json_op) => json_op.num_bits,
}
}
pub fn num_params(&self) -> usize {
match self {
Tk1Op::Native(native_op) => native_op.num_params,
Tk1Op::Opaque(json_op) => json_op.num_params,
}
}
}
impl From<Tk1Op> for OpType {
fn from(tk1_op: Tk1Op) -> Self {
tk1_op.into_optype()
}
}
impl From<&Tk1Op> for OpType {
fn from(tk1_op: &Tk1Op) -> Self {
tk1_op.optype()
}
}