use crate::prelude::*;
use crate::StackAddress;
use crate::shared::typed_ids::BindingId;
#[derive(Copy, Clone, PartialEq)]
pub enum LocalOrigin {
Binding,
Argument,
}
#[derive(Copy, Clone)]
pub struct Local {
pub index: StackAddress,
pub origin: LocalOrigin,
}
pub struct StackFrame {
pub map : Map<BindingId, Local>,
pub arg_pos : StackAddress,
pub var_pos : StackAddress,
pub ret_size: u8,
pub exit_placeholder: Vec<StackAddress>,
}
impl StackFrame {
const UNKNOWN_BINDING: &'static str = "Unknown local binding";
pub fn new() -> Self {
StackFrame {
map : Map::new(),
arg_pos : 0,
var_pos : 0,
ret_size: 0,
exit_placeholder: Vec::new(),
}
}
pub fn insert(self: &mut Self, binding_id: BindingId, index: StackAddress, origin: LocalOrigin) {
self.map.insert(binding_id, Local { index, origin });
}
pub fn lookup(self: &Self, binding_id: BindingId) -> Local {
*self.map.get(&binding_id).expect(Self::UNKNOWN_BINDING)
}
}
pub struct StackFrames(Vec<StackFrame>);
impl StackFrames {
const NO_STACK: &'static str = "Attempted to access empty LocalsStack";
pub fn new() -> Self {
StackFrames(Vec::new())
}
pub fn push(self: &mut Self, frame: StackFrame) {
self.0.push(frame);
}
pub fn pop(self: &mut Self) -> StackFrame {
self.0.pop().expect(Self::NO_STACK)
}
pub fn lookup(self: &mut Self, binding_id: BindingId) -> Local {
self.0.last().expect(Self::NO_STACK).lookup(binding_id)
}
pub fn add_exit_placeholder(self: &mut Self, address: StackAddress) {
self.0.last_mut().expect(Self::NO_STACK).exit_placeholder.push(address);
}
}