cardinal_backend 0.1.1

Cardinal's back end.
Documentation
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,

	/// A list of blocks and their corresponding
	/// instructions.
	blocks: RefCell<Vec<InstructionBlock>>,

	/// The current block that is being written to.
	curr_block: u32,

	/// A list of variables and their associated 
	/// types.
	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);

		// reserve variables
		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()));

		// reserve blocks
		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);

		// build instruction
		//let block = unsafe { self.blocks.borrow().get_unchecked(self.curr_block as usize) };
		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);

		// build instruction
		//let block = unsafe { self.blocks.borrow().get_unchecked(self.curr_block as usize) };
		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))
		}
	}
}