use super::{err_stack_overflow, DEFAULT_MAX_RECURSION_DEPTH};
use crate::{core::TrapCode, engine::code_map::InstructionPtr, Instance};
use alloc::vec::Vec;
#[derive(Debug, Copy, Clone)]
pub struct FuncFrame {
ip: InstructionPtr,
instance: Instance,
}
impl FuncFrame {
pub fn new(ip: InstructionPtr, instance: Instance) -> Self {
Self { ip, instance }
}
pub fn ip(&self) -> InstructionPtr {
self.ip
}
pub fn update_ip(&mut self, new_ip: InstructionPtr) {
self.ip = new_ip;
}
pub fn instance(&self) -> &Instance {
&self.instance
}
}
#[derive(Debug)]
pub struct CallStack {
frames: Vec<FuncFrame>,
recursion_limit: usize,
}
impl Default for CallStack {
fn default() -> Self {
Self::new(DEFAULT_MAX_RECURSION_DEPTH)
}
}
impl CallStack {
pub fn new(recursion_limit: usize) -> Self {
Self {
frames: Vec::new(),
recursion_limit,
}
}
pub(crate) fn init(&mut self, ip: InstructionPtr, instance: Instance) -> FuncFrame {
self.clear();
FuncFrame::new(ip, instance)
}
pub(crate) fn push(&mut self, caller: FuncFrame) -> Result<(), TrapCode> {
if self.len() == self.recursion_limit {
return Err(err_stack_overflow());
}
self.frames.push(caller);
Ok(())
}
pub fn pop(&mut self) -> Option<FuncFrame> {
self.frames.pop()
}
fn len(&self) -> usize {
self.frames.len()
}
pub fn clear(&mut self) {
self.frames.clear();
}
}