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