use crate::frame::FrameRef; use crate::obj::objtype::PyClassRef; use crate::pyobject::{PyClassImpl, PyContext, PyRef, PyValue}; use crate::vm::VirtualMachine; #[pyclass] #[derive(Debug)] pub struct PyTraceback { pub next: Option, // TODO: Make mutable pub frame: FrameRef, pub lasti: usize, pub lineno: usize, } pub type PyTracebackRef = PyRef; impl PyValue for PyTraceback { fn class(vm: &VirtualMachine) -> PyClassRef { vm.ctx.traceback_type() } } #[pyimpl] impl PyTraceback { pub fn new(next: Option, frame: FrameRef, lasti: usize, lineno: usize) -> Self { PyTraceback { next, frame, lasti, lineno, } } #[pyproperty(name = "tb_frame")] fn frame(&self, _vm: &VirtualMachine) -> FrameRef { self.frame.clone() } #[pyproperty(name = "tb_lasti")] fn lasti(&self, _vm: &VirtualMachine) -> usize { self.lasti } #[pyproperty(name = "tb_lineno")] fn lineno(&self, _vm: &VirtualMachine) -> usize { self.lineno } #[pyproperty(name = "tb_next")] fn next_get(&self, _vm: &VirtualMachine) -> Option { self.next.as_ref().cloned() } } impl PyTracebackRef { pub fn iter<'a>(&'a self) -> impl Iterator + 'a { std::iter::successors(Some(self.clone()), |tb| tb.next.clone()) } } pub fn init(context: &PyContext) { PyTraceback::extend_class(context, &context.types.traceback_type); } impl serde::Serialize for PyTraceback { fn serialize(&self, s: S) -> Result { use serde::ser::SerializeStruct; let mut struc = s.serialize_struct("PyTraceback", 3)?; struc.serialize_field("name", &self.frame.code.obj_name)?; struc.serialize_field("lineno", &self.lineno)?; struc.serialize_field("filename", &self.frame.code.source_path)?; struc.end() } }