diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index 8b359cc0f..79924df9c 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -1,5 +1,5 @@ use crate::function::PyFuncArgs; -use crate::obj::objsequence; +use crate::obj::objtraceback::PyTracebackRef; use crate::obj::objtuple::{PyTuple, PyTupleRef}; use crate::obj::objtype; use crate::obj::objtype::PyClassRef; @@ -83,44 +83,15 @@ fn print_source_line(mut output: W, filename: &str, lineno: usize) -> } /// Print exception occurrence location from traceback element -fn print_traceback_entry( - mut output: W, - vm: &VirtualMachine, - tb_entry: &PyObjectRef, -) -> io::Result<()> { - if objtype::isinstance(&tb_entry, &vm.ctx.tuple_type()) { - let location_attrs = objsequence::get_elements_tuple(&tb_entry); +fn print_traceback_entry(mut output: W, tb_entry: &PyTracebackRef) -> io::Result<()> { + let filename = tb_entry.frame.code.source_path.to_string(); + writeln!( + output, + r##" File "{}", line {}, in {}"##, + filename, tb_entry.lineno, tb_entry.frame.code.obj_name + )?; + print_source_line(output, &filename, tb_entry.lineno)?; - let filename = vm.to_str(&location_attrs[0]); - let filename = if let Ok(ref x) = filename { - x.as_str() - } else { - "" - }; - - let lineno = vm.to_str(&location_attrs[1]); - let lineno = if let Ok(ref x) = lineno { - x.as_str() - } else { - "" - }; - - let obj_name = vm.to_str(&location_attrs[2]); - let obj_name = if let Ok(ref x) = obj_name { - x.as_str() - } else { - "" - }; - - writeln!( - output, - r##" File "{}", line {}, in {}"##, - filename, lineno, obj_name - )?; - print_source_line(output, filename, lineno.parse().unwrap())?; - } else { - writeln!(output, " File ??")?; - } Ok(()) } @@ -131,15 +102,15 @@ pub fn print_exception_inner( exc: &PyObjectRef, ) -> io::Result<()> { if let Ok(tb) = vm.get_attribute(exc.clone(), "__traceback__") { - if objtype::isinstance(&tb, &vm.ctx.list_type()) { - let mut tb_entries = objsequence::get_elements_list(&tb).to_vec(); - tb_entries.reverse(); - - if !tb_entries.is_empty() { - writeln!(output, "Traceback (most recent call last):")?; - } - for exc_location in tb_entries.iter() { - print_traceback_entry(&mut output, vm, exc_location)?; + if objtype::isinstance(&tb, &vm.ctx.traceback_type()) { + writeln!(output, "Traceback (most recent call last):")?; + let mut tb: PyTracebackRef = tb.downcast().expect(" must be a traceback object"); + loop { + print_traceback_entry(&mut output, &tb)?; + tb = match &tb.next { + Some(tb) => tb.clone(), + None => break, + }; } } } else { diff --git a/vm/src/obj/objtraceback.rs b/vm/src/obj/objtraceback.rs index 5547db691..03497b5fb 100644 --- a/vm/src/obj/objtraceback.rs +++ b/vm/src/obj/objtraceback.rs @@ -6,13 +6,13 @@ use crate::vm::VirtualMachine; #[pyclass] #[derive(Debug)] pub struct PyTraceback { - next: Option, - frame: FrameRef, - lasti: usize, - lineno: usize, + pub next: Option, + pub frame: FrameRef, + pub lasti: usize, + pub lineno: usize, } -type PyTracebackRef = PyRef; +pub type PyTracebackRef = PyRef; impl PyValue for PyTraceback { fn class(vm: &VirtualMachine) -> PyClassRef {