use crate::core::QduId;
use crate::operations::Operation;
use std::collections::HashMap;
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum LockType {
BellPhiPlus,
BellPhiMinus,
BellPsiPlus,
BellPsiMinus,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Instruction {
QuantumOp(Operation),
Stabilize {
targets: Vec<QduId>
},
Record {
qdu: QduId,
register: String,
},
Label(String),
Jump(String),
BranchIfZero {
register: String,
label: String,
},
LoadImmediate {
register: String,
value: u64,
},
Copy {
source_reg: String,
dest_reg: String,
},
Halt,
NoOp,
Addi {
r_dest: String,
r_src: String,
value: u64,
},
OnqAdd {
r_dest: String,
r_src1: String,
r_src2: String,
},
OnqNot {
r_dest: String,
r_src: String,
},
And {
r_dest: String,
r_src1: String,
r_src2: String,
},
Or {
r_dest: String,
r_src1: String,
r_src2: String,
},
Xor {
r_dest: String,
r_src1: String,
r_src2: String,
},
Sub {
r_dest: String,
r_src1: String,
r_src2: String,
},
Mul {
r_dest: String,
r_src1: String,
r_src2: String,
},
CmpEq {
r_dest: String,
r_src1: String,
r_src2: String,
},
CmpGt {
r_dest: String,
r_src1: String,
r_src2: String,
},
CmpLt {
r_dest: String,
r_src1: String,
r_src2: String,
},
}
#[derive(Debug, Clone)] pub struct Program {
pub(crate) instructions: Vec<Instruction>,
pub(crate) label_map: HashMap<String, usize>,
}
impl Program {
fn _new() -> Self {
Program {
instructions: Vec::new(),
label_map: HashMap::new(),
}
}
pub(crate) fn get_instruction(&self, pc: usize) -> Option<&Instruction> {
self.instructions.get(pc)
}
pub(crate) fn get_label_pc(&self, label: &str) -> Option<usize> {
self.label_map.get(label).copied()
}
pub fn instruction_count(&self) -> usize {
self.instructions.len()
}
}
impl fmt::Display for Program {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "ONQ-VM Program ({} instructions)", self.instruction_count())?;
let pc_to_label: HashMap<usize, &String> = self.label_map.iter().map(|(l, pc)| (*pc, l)).collect();
for (pc, instruction) in self.instructions.iter().enumerate() {
if let Some(label) = pc_to_label.get(&pc) {
writeln!(f, "{}:", label)?;
}
writeln!(f, " {:04}: {:?}", pc, instruction)?;
}
Ok(())
}
}
#[derive(Default)]
pub struct ProgramBuilder {
instructions: Vec<Instruction>,
label_map: HashMap<String, usize>,
pending_labels: HashMap<String, Vec<usize>>, }
impl ProgramBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn pb_add(mut self, instruction: Instruction) -> Self {
if let Instruction::Label(label_name) = &instruction {
let current_pc = self.instructions.len();
if self.label_map.insert(label_name.clone(), current_pc).is_some() {
eprintln!("Warning: Duplicate label definition '{}' at PC {}", label_name, current_pc);
}
if let Some(_pcs) = self.pending_labels.remove(label_name) {
}
} else {
self.instructions.push(instruction);
}
self
}
pub fn add_many<I>(mut self, instructions: I) -> Self
where
I: IntoIterator<Item = Instruction>,
{
for instruction in instructions {
self = self.pb_add(instruction); }
self
}
pub fn build(self) -> Result<Program, String> {
let mut undefined_labels = Vec::new();
for instruction in &self.instructions {
match instruction {
Instruction::Jump(label) | Instruction::BranchIfZero { label, .. } => {
if !self.label_map.contains_key(label) {
if !undefined_labels.contains(label) {
undefined_labels.push(label.clone());
}
}
}
_ => {} }
}
if !undefined_labels.is_empty() {
Err(format!("Undefined labels found: {:?}", undefined_labels))
} else {
Ok(Program {
instructions: self.instructions,
label_map: self.label_map,
})
}
}
}