use crate::{obj::prelude::*, vm::inst::Inst}; use std::{collections::BTreeMap, sync::Arc}; use std::fmt::{self, Formatter, Debug}; pub type FrameBindings = BTreeMap; #[derive(Debug)] pub enum Frame { User(UserFrame), Native(NativeFrame), } impl Frame { pub fn user_frame(&self) -> Option<&UserFrame> { if let Frame::User(frame) = self { Some(frame) } else { None } } pub fn user_frame_mut(&mut self) -> Option<&mut UserFrame> { if let Frame::User(frame) = self { Some(frame) } else { None } } pub fn native_frame(&self) -> Option<&NativeFrame> { if let Frame::Native(frame) = self { Some(frame) } else { None } } pub fn native_frame_mut(&mut self) -> Option<&mut NativeFrame> { if let Frame::Native(frame) = self { Some(frame) } else { None } } } #[derive(Debug, Clone)] pub struct UserFrame { callee: ObjRef, bindings: FrameBindings, last_pc: usize, code: Arc>, } impl UserFrame { pub fn new(callee: ObjRef, bindings: FrameBindings, last_pc: usize, code: Arc>) -> Self { Self { callee, bindings, last_pc, code, } } pub fn bindings(&self) -> &FrameBindings { &self.bindings } pub fn bindings_mut(&mut self) -> &mut FrameBindings { &mut self.bindings } pub fn last_pc(&self) -> usize { self.last_pc } pub fn code(&self) -> &Arc> { &self.code } pub fn callee(&self) -> &ObjRef { &self.callee } } pub struct NativeFrame { callee: ObjRef, fun_ptr: NativeFunPtr, args: Vec, } impl NativeFrame { pub fn new(callee: ObjRef, fun_ptr: NativeFunPtr, args: Vec) -> Self { Self { callee, fun_ptr, args } } pub fn fun_ptr(&self) -> &NativeFunPtr { &self.fun_ptr } pub fn args(&self) -> &Vec { &self.args } pub fn callee(&self) -> &ObjRef { &self.callee } } impl Debug for NativeFrame { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { fmt.debug_struct("NativeFrame") .field("fun_ptr", &format!("{:#x}", &self.fun_ptr as *const _ as usize)) .finish() } }