sphinx/debug/
snapshot.rs

1use core::fmt::{Display, Formatter, Result};
2use crate::codegen::opcodes::OpCode;
3use crate::runtime::Variant;
4use crate::runtime::module::Chunk;
5
6
7pub struct VMSnapshot {
8    pub calls: Vec<VMFrameSnapshot>,
9    pub frame: VMFrameSnapshot,
10    pub stack: Vec<Variant>,
11    pub locals: Vec<Variant>,
12}
13
14impl Display for VMSnapshot {
15    fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
16        
17        writeln!(fmt, "== Call Stack ==")?;
18        
19        for (idx, state) in self.calls.iter().enumerate() {
20            write!(fmt, "{: >4}: Module: {}, Chunk: ", idx, state.module)?;
21            format_chunk_id(fmt,state.chunk_id)?;
22            writeln!(fmt, ", Frame: {}, Locals: {}", state.stack_idx, state.local_idx)?;
23        }
24        
25        write!(fmt, "{: >4}: Module: {}, Chunk: ", self.calls.len(), self.frame.module)?;
26        format_chunk_id(fmt, self.frame.chunk_id)?;
27        writeln!(fmt, ", Frame: {}, Locals: {}", self.frame.stack_idx, self.frame.local_idx)?;
28        
29        writeln!(fmt, "\n== Locals ==")?;
30        for (idx, chunk) in self.locals.chunks(10).enumerate() {
31            write!(fmt, "{: >4}: ", idx * 10)?;
32            let items = chunk.iter().map(|value| format!("{:?}", value))
33                .collect::<Vec<String>>()
34                .join(", ");
35            writeln!(fmt, "{}", items)?;
36        }
37        
38        writeln!(fmt, "\n== Temporaries ==")?;
39        for (idx, chunk) in self.stack.chunks(10).enumerate() {
40            write!(fmt, "{: >4}: ", idx * 10)?;
41            let items = chunk.iter().map(|value| format!("{:?}", value))
42                .collect::<Vec<String>>()
43                .join(", ");
44            writeln!(fmt, "{}", items)?;
45        }
46        
47        writeln!(fmt, "\n== Active Frame ==")?;
48        writeln!(fmt, "{}", self.frame)?;
49        
50        Ok(())
51    }
52}
53
54
55pub struct VMFrameSnapshot {
56    pub module: String,
57    pub chunk_id: Chunk,
58    pub stack_idx: usize,
59    pub local_idx: usize,
60    pub pc: usize,
61    pub next_instr: Option<Vec<u8>>,
62}
63
64impl Display for VMFrameSnapshot {
65    fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
66        
67        write!(fmt, "Module: {}, Chunk: ", self.module)?;
68        format_chunk_id(fmt, self.chunk_id)?;
69        writeln!(fmt)?;
70        
71        writeln!(fmt, "Frame: {}, Locals: {}", self.stack_idx, self.local_idx)?;
72        
73        write!(fmt, "PC: {:#X}", self.pc)?;
74        if let Some(instr) = self.next_instr.as_ref() {
75            let opcode = OpCode::try_from(instr[0])
76                .map_or("INVALID".to_string(), |opcode| format!("{}", opcode));
77            
78            let bytes = instr.iter()
79                .map(|b| format!("{:0>2X}", b))
80                .collect::<Vec<String>>()
81                .join(" ");
82            
83            write!(fmt, ", Next: {} [{}]", opcode, bytes)?;
84        }
85        writeln!(fmt)?;
86        
87        Ok(())
88    }
89}
90
91fn format_chunk_id(fmt: &mut Formatter<'_>, chunk_id: Chunk) -> Result {
92    match chunk_id {
93        Chunk::Main => fmt.write_str("<main>"),
94        Chunk::Function(fun_id) => write!(fmt, "{}", fun_id),
95    }
96}
97