#[derive(Clone, Copy, Debug)]
pub struct Frame {
pub return_addr: u16,
pub parent: Option<u32>,
pub saved_depth: u32,
}
#[derive(Debug)]
pub struct FrameArena {
frames: Vec<Frame>,
current: Option<u32>,
}
impl FrameArena {
pub fn new() -> Self {
Self {
frames: Vec::new(),
current: None,
}
}
pub fn push(&mut self, return_addr: u16, saved_depth: u32) -> u32 {
let idx = self.frames.len() as u32;
self.frames.push(Frame {
return_addr,
parent: self.current,
saved_depth,
});
self.current = Some(idx);
idx
}
pub fn pop(&mut self) -> (u16, u32) {
let current_idx = self.current.expect("pop on empty frame stack");
let frame = self.frames[current_idx as usize];
self.current = frame.parent;
(frame.return_addr, frame.saved_depth)
}
#[inline]
pub fn restore(&mut self, frame_index: Option<u32>) {
self.current = frame_index;
}
#[inline]
pub fn current(&self) -> Option<u32> {
self.current
}
#[inline]
pub fn is_empty(&self) -> bool {
self.current.is_none()
}
#[allow(dead_code)]
pub fn depth(&self) -> u32 {
let mut depth = 0;
let mut idx = self.current;
while let Some(i) = idx {
depth += 1;
idx = self.frames[i as usize].parent;
}
depth
}
pub fn prune(&mut self, max_referenced: Option<u32>) {
let keep = match (self.current, max_referenced) {
(Some(a), Some(b)) => Some(a.max(b)),
(a, b) => a.or(b),
};
if let Some(high_water) = keep {
self.frames.truncate(high_water as usize + 1);
}
}
}
impl Default for FrameArena {
fn default() -> Self {
Self::new()
}
}