use lift_core::context::Context;
use lift_quantum::gates::QuantumGate;
use std::fmt::Write;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum QasmExportError {
#[error("Unsupported gate for QASM export: {0}")]
UnsupportedGate(String),
#[error("Export error: {0}")]
General(String),
}
#[derive(Debug)]
pub struct QasmExporter;
impl QasmExporter {
pub fn new() -> Self {
Self
}
pub fn export(&self, ctx: &Context) -> Result<String, QasmExportError> {
let mut output = String::new();
let _ = writeln!(output, "OPENQASM 3.0;");
let _ = writeln!(output, "// Generated by LIFT framework");
let _ = writeln!(output);
let mut max_qubits = 0usize;
for (_val_key, val) in &ctx.values {
if ctx.is_qubit_type(val.ty) {
max_qubits += 1;
}
}
let mut qubit_args = 0;
for (_block_key, block) in &ctx.blocks {
for &arg in &block.args {
if let Some(val) = ctx.get_value(arg) {
if ctx.is_qubit_type(val.ty) {
qubit_args += 1;
}
}
}
}
let num_qubits = if qubit_args > 0 {
qubit_args
} else {
max_qubits.max(1)
};
let _ = writeln!(output, "qubit[{}] q;", num_qubits);
let _ = writeln!(output, "bit[{}] c;", num_qubits);
let _ = writeln!(output);
let mut qubit_counter = 0usize;
for (_op_key, op) in &ctx.ops {
let op_name = ctx.strings.resolve(op.name).to_string();
if let Some(gate) = QuantumGate::from_name(&op_name) {
let q0 = qubit_counter % num_qubits;
let q1 = (qubit_counter + 1) % num_qubits;
let q2 = (qubit_counter + 2) % num_qubits;
let angle = op.attrs.get_float("angle").unwrap_or(0.0);
let theta = op.attrs.get_float("theta").unwrap_or(0.0);
let phi = op.attrs.get_float("phi").unwrap_or(0.0);
let lambda = op.attrs.get_float("lambda").unwrap_or(0.0);
match gate {
QuantumGate::H => {
let _ = writeln!(output, "h q[{}];", q0);
}
QuantumGate::X => {
let _ = writeln!(output, "x q[{}];", q0);
}
QuantumGate::Y => {
let _ = writeln!(output, "y q[{}];", q0);
}
QuantumGate::Z => {
let _ = writeln!(output, "z q[{}];", q0);
}
QuantumGate::S => {
let _ = writeln!(output, "s q[{}];", q0);
}
QuantumGate::Sdg => {
let _ = writeln!(output, "sdg q[{}];", q0);
}
QuantumGate::T => {
let _ = writeln!(output, "t q[{}];", q0);
}
QuantumGate::Tdg => {
let _ = writeln!(output, "tdg q[{}];", q0);
}
QuantumGate::SX => {
let _ = writeln!(output, "sx q[{}];", q0);
}
QuantumGate::RX => {
let _ = writeln!(output, "rx({}) q[{}];", angle, q0);
}
QuantumGate::RY => {
let _ = writeln!(output, "ry({}) q[{}];", angle, q0);
}
QuantumGate::RZ => {
let _ = writeln!(output, "rz({}) q[{}];", angle, q0);
}
QuantumGate::P => {
let _ = writeln!(output, "p({}) q[{}];", angle, q0);
}
QuantumGate::U1 => {
let _ = writeln!(output, "u1({}) q[{}];", lambda, q0);
}
QuantumGate::U2 => {
let _ = writeln!(output, "u2({}, {}) q[{}];", phi, lambda, q0);
}
QuantumGate::U3 => {
let _ = writeln!(output, "u3({}, {}, {}) q[{}];", theta, phi, lambda, q0);
}
QuantumGate::Rx90 => {
let _ = writeln!(output, "rx(pi/2) q[{}];", q0);
}
QuantumGate::Rx180 => {
let _ = writeln!(output, "rx(pi) q[{}];", q0);
}
QuantumGate::VirtualRZ => {
let _ = writeln!(output, "rz({}) q[{}]; // virtual", angle, q0);
}
QuantumGate::GlobalPhase => {
let _ = writeln!(output, "gphase({});", angle);
}
QuantumGate::CX => {
let _ = writeln!(output, "cx q[{}], q[{}];", q0, q1);
}
QuantumGate::CZ => {
let _ = writeln!(output, "cz q[{}], q[{}];", q0, q1);
}
QuantumGate::CY => {
let _ = writeln!(output, "cy q[{}], q[{}];", q0, q1);
}
QuantumGate::SWAP => {
let _ = writeln!(output, "swap q[{}], q[{}];", q0, q1);
}
QuantumGate::ISWAP => {
let _ = writeln!(output, "iswap q[{}], q[{}];", q0, q1);
}
QuantumGate::ECR => {
let _ = writeln!(output, "ecr q[{}], q[{}];", q0, q1);
}
QuantumGate::RZX => {
let _ = writeln!(output, "rzx({}) q[{}], q[{}];", angle, q0, q1);
}
QuantumGate::CP => {
let _ = writeln!(output, "cp({}) q[{}], q[{}];", angle, q0, q1);
}
QuantumGate::CPhase => {
let _ = writeln!(output, "cphase({}) q[{}], q[{}];", angle, q0, q1);
}
QuantumGate::XX => {
let _ = writeln!(output, "rxx({}) q[{}], q[{}];", angle, q0, q1);
}
QuantumGate::YY => {
let _ = writeln!(output, "ryy({}) q[{}], q[{}];", angle, q0, q1);
}
QuantumGate::ZZ => {
let _ = writeln!(output, "rzz({}) q[{}], q[{}];", angle, q0, q1);
}
QuantumGate::XY => {
let _ = writeln!(output, "xy({}) q[{}], q[{}];", angle, q0, q1);
}
QuantumGate::MS => {
let _ = writeln!(output, "ms q[{}], q[{}];", q0, q1);
}
QuantumGate::CCX => {
let _ = writeln!(output, "ccx q[{}], q[{}], q[{}];", q0, q1, q2);
}
QuantumGate::CSWAP => {
let _ = writeln!(output, "cswap q[{}], q[{}], q[{}];", q0, q1, q2);
}
QuantumGate::MCX => {
let _ = writeln!(output, "mcx q[{}], q[{}], q[{}];", q0, q1, q2);
}
QuantumGate::MCZ => {
let _ = writeln!(output, "mcz q[{}], q[{}], q[{}];", q0, q1, q2);
}
QuantumGate::Measure => {
let _ = writeln!(output, "c[{}] = measure q[{}];", q0, q0);
}
QuantumGate::MeasureAll => {
for i in 0..num_qubits {
let _ = writeln!(output, "c[{}] = measure q[{}];", i, i);
}
}
QuantumGate::Reset => {
let _ = writeln!(output, "reset q[{}];", q0);
}
QuantumGate::Barrier => {
let _ = writeln!(output, "barrier q;");
}
QuantumGate::Init => {
let _ = writeln!(output, "reset q[{}];", q0);
}
QuantumGate::Delay => {
let _ = writeln!(output, "delay[100ns] q[{}];", q0);
}
QuantumGate::GPI => {
let _ = writeln!(output, "gpi({}) q[{}];", angle, q0);
}
QuantumGate::GPI2 => {
let _ = writeln!(output, "gpi2({}) q[{}];", angle, q0);
}
QuantumGate::IfElse => {
let _ = writeln!(output, "// if-else control flow");
}
QuantumGate::ParamGate => {
let _ = writeln!(output, "// parameterised gate: {}", op_name);
}
}
qubit_counter += 1;
}
}
Ok(output)
}
}
impl Default for QasmExporter {
fn default() -> Self {
Self::new()
}
}