1use crate::cell::Cell;
2use crate::vm::heap::Heap;
3use crate::vm::opcode::OpCode;
4use crate::vm::stack::Stack;
5use crate::vm::vcell::VCell;
6
7#[derive(Debug)]
13pub struct StackFrame {
14 pub name: Option<String>,
15 pub desc: Option<Cell>,
16}
17
18#[derive(Debug)]
23pub struct StackTrace {
24 pub frames: Vec<StackFrame>,
25}
26
27impl StackTrace {
28 pub fn new(stack: &Stack, heap: &Heap, ip: (usize, usize), acc: VCell) -> StackTrace {
32 let mut frames = vec![];
33
34 let mut ip_idx = ip.1;
36 let ip = heap.get_at_index(ip.0).as_lambda().unwrap();
37
38 ip_idx -= 1;
40 while ip_idx > 0 && !matches!(ip.get(ip_idx).unwrap(), VCell::OpCode(_)) {
41 ip_idx -= 1;
42 }
43 let op_code = ip.get(ip_idx).unwrap().as_opcode().unwrap();
44
45 match op_code {
48 OpCode::TCallAcc | OpCode::CallAcc => {
49 if let VCell::BuiltInProc(proc) = heap.get(&acc) {
50 frames.push(StackFrame {
51 name: Some(proc.desc().to_owned()),
52 desc: None,
53 })
54 }
55 }
56 _ => {}
57 }
58
59 frames.push(StackFrame {
61 name: None,
62 desc: ip.desc_args.clone(),
63 });
64
65 for sp in (0..stack.get_sp()).rev() {
67 if let Ok(VCell::InstructionPointer(ip, _)) = stack.get(sp) {
68 let ip = heap.get_at_index(*ip).as_lambda().unwrap();
69 frames.push(StackFrame {
70 name: None,
71 desc: ip.desc_args.clone(),
72 });
73 }
74 }
75
76 StackTrace { frames }
77 }
78}