use lift_core::context::Context;
use lift_quantum::gates::QuantumGate;
use thiserror::Error;
use std::fmt::Write;
#[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() }
}