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) {
match gate {
QuantumGate::H => {
let _ = writeln!(output, "h q[{}];", qubit_counter % num_qubits);
}
QuantumGate::X => {
let _ = writeln!(output, "x q[{}];", qubit_counter % num_qubits);
}
QuantumGate::Y => {
let _ = writeln!(output, "y q[{}];", qubit_counter % num_qubits);
}
QuantumGate::Z => {
let _ = writeln!(output, "z q[{}];", qubit_counter % num_qubits);
}
QuantumGate::CX => {
let q0 = qubit_counter % num_qubits;
let q1 = (qubit_counter + 1) % num_qubits;
let _ = writeln!(output, "cx q[{}], q[{}];", q0, q1);
}
QuantumGate::CZ => {
let q0 = qubit_counter % num_qubits;
let q1 = (qubit_counter + 1) % num_qubits;
let _ = writeln!(output, "cz q[{}], q[{}];", q0, q1);
}
QuantumGate::Measure => {
let q = qubit_counter % num_qubits;
let _ = writeln!(output, "c[{}] = measure q[{}];", q, q);
}
QuantumGate::RZ => {
let angle = op.attrs.get_float("angle").unwrap_or(0.0);
let _ = writeln!(output, "rz({}) q[{}];", angle, qubit_counter % num_qubits);
}
QuantumGate::RX => {
let angle = op.attrs.get_float("angle").unwrap_or(0.0);
let _ = writeln!(output, "rx({}) q[{}];", angle, qubit_counter % num_qubits);
}
QuantumGate::RY => {
let angle = op.attrs.get_float("angle").unwrap_or(0.0);
let _ = writeln!(output, "ry({}) q[{}];", angle, qubit_counter % num_qubits);
}
_ => {
let _ = writeln!(output, "// unsupported gate: {}", op_name);
}
}
qubit_counter += 1;
}
}
Ok(output)
}
}
impl Default for QasmExporter {
fn default() -> Self { Self::new() }
}