use crate::builder::{ TraitFunctionBuilder, TraitInstBuilder };
use crate::{ Block, ValueType, Value, Variable, resolve_type, Function };
use crate::opcode::Opcode;
use std::cell::RefCell;
pub type InstructionBlock = RefCell<Vec<Opcode>>;
pub struct FunctionBuilder {
pub signature: Function,
blocks: RefCell<Vec<InstructionBlock>>,
curr_block: u32,
variables: RefCell<Vec<ValueType>>
}
impl FunctionBuilder {
pub fn new(signature: Function) -> FunctionBuilder {
let v: Vec<ValueType> = Vec::new();
let vvec: RefCell<Vec<ValueType>> = RefCell::new(v);
vvec.borrow_mut().reserve(u32::MAX as usize);
let bv: Vec<InstructionBlock> = Vec::new();
let bvec: RefCell<Vec<InstructionBlock>> = RefCell::new(bv);
bvec.borrow_mut().push(RefCell::new(Vec::new()));
bvec.borrow_mut().reserve(u16::MAX as usize);
FunctionBuilder {
signature,
blocks: bvec,
curr_block: 0,
variables: vvec
}
}
}
impl TraitFunctionBuilder for FunctionBuilder {
fn create_block(self: &mut Self) -> Block {
self.blocks.borrow_mut().push(RefCell::new(Vec::new()));
Block(self.blocks.borrow().len() as u32 - 1)
}
fn use_block(self: &mut Self, bl: Block) {
self.curr_block = bl.0;
}
}
impl TraitInstBuilder for FunctionBuilder {
fn integer_add(self: &mut Self, x: Value, y: Value) -> Value {
let variable = Variable(self.variables.borrow().len() as u32);
unsafe {
let blocks = self.blocks.borrow_mut();
let block = blocks.get_unchecked(self.curr_block as usize);
block.borrow_mut().push(Opcode::IntegerAdd(Value::Variable(variable), x, y));
self.variables.borrow_mut().push(resolve_type(x, &self.variables));
Value::Variable(Variable(self.variables.borrow().len() as u32 - 1))
}
}
fn integer_negate(self: &mut Self, x: Value) -> Value {
let variable = Variable(self.variables.borrow().len() as u32);
unsafe {
let blocks = self.blocks.borrow_mut();
let block = blocks.get_unchecked(self.curr_block as usize);
block.borrow_mut().push(Opcode::IntegerNegate(Value::Variable(variable), x));
self.variables.borrow_mut().push(resolve_type(x, &self.variables));
Value::Variable(Variable(self.variables.borrow().len() as u32 - 1))
}
}
}