use std::fmt;
use il::*;
#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Block {
index: u64,
next_instruction_index: u64,
next_temp_index: u64,
instructions: Vec<Instruction>,
}
impl Block {
pub(crate) fn new(index: u64) -> Block {
Block {
index: index,
next_instruction_index: 0,
next_temp_index: 0,
instructions: Vec::new()
}
}
fn new_instruction_index(&mut self) -> u64 {
let instruction_index = self.next_instruction_index;
self.next_instruction_index = instruction_index + 1;
instruction_index
}
fn push(&mut self, instruction: Instruction) {
self.instructions.push(instruction);
}
pub fn append(&mut self, other: &Block) {
for instruction in other.instructions().iter() {
let instruction = instruction.clone_new_index(self.new_instruction_index());
self.instructions.push(instruction);
}
}
pub fn index(&self) -> u64 {
self.index
}
pub fn instructions(&self) -> &Vec<Instruction> {
&self.instructions
}
pub fn instructions_mut(&mut self) -> &mut Vec<Instruction> {
&mut self.instructions
}
pub fn is_empty(&self) -> bool {
self.instructions.is_empty()
}
pub fn instruction(&self, index: u64) -> Option<&Instruction> {
for instruction in &self.instructions {
if instruction.index() == index {
return Some(instruction);
}
}
None
}
pub fn instruction_mut<>(&mut self, index: u64) -> Option<&mut Instruction> {
for i in 0..self.instructions.len() {
if self.instructions[i].index() == index {
return Some(&mut self.instructions[i]);
}
}
None
}
pub fn remove_instruction(&mut self, index: u64) -> Result<()> {
let mut vec_index = None;
for i in 0..self.instructions.len() {
if self.instructions[i].index() == index {
vec_index = Some(i);
break;
}
}
match vec_index {
Some(index) => {
self.instructions.remove(index);
Ok(())
},
None => Err(format!("No instruction with index {} found", index).into()),
}
}
pub(crate) fn clone_new_index(&self, index: u64) -> Block {
let mut clone = self.clone();
clone.index = index;
clone
}
pub fn temp(&mut self, bits: usize) -> Scalar {
let next_index = self.next_temp_index;
self.next_temp_index = next_index + 1;
Scalar::new(format!("temp_{}.{}", self.index, next_index), bits)
}
pub fn assign(&mut self, dst: Scalar, src: Expression) {
let index = self.new_instruction_index();
self.push(Instruction::assign(index, dst, src));
}
pub fn store(&mut self, dst: Array, address: Expression, src: Expression) {
let index = self.new_instruction_index();
self.push(Instruction::store(index, dst, address, src))
}
pub fn load(&mut self, dst: Scalar, address: Expression, src: Array) {
let index = self.new_instruction_index();
self.push(Instruction::load(index, dst, address, src));
}
pub fn brc(&mut self, dst: Expression, condition: Expression) {
let index = self.new_instruction_index();
self.push(Instruction::brc(index, dst, condition));
}
pub fn raise(&mut self, expr: Expression) {
let index = self.new_instruction_index();
self.push(Instruction::raise(index, expr));
}
}
impl graph::Vertex for Block {
fn index (&self) -> u64 { self.index }
fn dot_label(&self) -> String { format!("{}", self) }
}
impl fmt::Display for Block {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(writeln!(f, "[ Block: 0x{:X} ]", self.index));
for instruction in self.instructions() {
try!(writeln!(f, "{}", instruction));
}
Ok(())
}
}