1
0

Improve disassembler output

This commit is contained in:
Jeff 2024-10-09 17:34:11 -04:00
parent b6c3b1e5ba
commit 61d633392c

View File

@ -286,9 +286,7 @@ impl Display for Chunk {
write!( write!(
f, f,
"{}", "{}",
self.disassembler("Chunk Display") self.disassembler("Chunk").styled(true).disassemble()
.styled(true)
.disassemble()
) )
} }
} }
@ -298,9 +296,7 @@ impl Debug for Chunk {
write!( write!(
f, f,
"{}", "{}",
self.disassembler("Chunk Debug Display") self.disassembler("Chunk").styled(false).disassemble()
.styled(false)
.disassemble()
) )
} }
} }
@ -345,7 +341,7 @@ impl Local {
pub struct ChunkDisassembler<'a> { pub struct ChunkDisassembler<'a> {
name: &'a str, name: &'a str,
chunk: &'a Chunk, chunk: &'a Chunk,
width: Option<usize>, width: usize,
styled: bool, styled: bool,
indent: usize, indent: usize,
} }
@ -380,21 +376,21 @@ impl<'a> ChunkDisassembler<'a> {
pub fn default_width() -> usize { pub fn default_width() -> usize {
let longest_line = Self::INSTRUCTION_HEADER[4]; let longest_line = Self::INSTRUCTION_HEADER[4];
longest_line.chars().count() longest_line.chars().count().max(80)
} }
pub fn new(name: &'a str, chunk: &'a Chunk) -> Self { pub fn new(name: &'a str, chunk: &'a Chunk) -> Self {
Self { Self {
name, name,
chunk, chunk,
width: None, width: Self::default_width(),
styled: false, styled: false,
indent: 0, indent: 0,
} }
} }
pub fn width(&mut self, width: usize) -> &mut Self { pub fn width(&mut self, width: usize) -> &mut Self {
self.width = Some(width); self.width = width;
self self
} }
@ -412,46 +408,50 @@ impl<'a> ChunkDisassembler<'a> {
} }
pub fn disassemble(&self) -> String { pub fn disassemble(&self) -> String {
let width = self.width.unwrap_or_else(Self::default_width); let center_and_style = |line: &str, style: bool| {
let center = |line: &str| format!("{line:^width$}\n"); if style {
let style = |line: String| { format!("|{line:^width$}|", line = line.bold(), width = self.width)
if self.styled {
line.bold().to_string()
} else { } else {
line format!("|{line:^width$}|", width = self.width)
} }
}; };
let mut disassembly = String::with_capacity(self.predict_length()); let mut disassembly = String::with_capacity(self.predict_length());
let mut push_line = |line: &str| {
if self.indent > 0 {
disassembly.push_str(" ");
}
disassembly.push('|');
disassembly.push_str(&"-".repeat(self.width));
disassembly.push('|');
disassembly.push('\n');
let mut push_line = |line: &str, style: bool| {
for _ in 0..self.indent { for _ in 0..self.indent {
disassembly.push_str(" "); disassembly.push_str("| ");
} }
disassembly.push_str(line); let line = center_and_style(line, style);
disassembly.push_str(&line);
disassembly.push('\n');
}; };
let name_line = style(center(self.name));
push_line(&name_line); push_line(self.name, self.styled);
let info_line = center(&format!( let info_line = format!(
"{} instructions, {} constants, {} locals", "{} instructions, {} constants, {} locals",
self.chunk.instructions.len(), self.chunk.instructions.len(),
self.chunk.constants.len(), self.chunk.constants.len(),
self.chunk.locals.len() self.chunk.locals.len()
)); )
let styled_info_line = { .dimmed();
if self.styled {
info_line.dimmed().to_string()
} else {
info_line
}
};
push_line(&styled_info_line); push_line(&info_line, false);
for line in Self::INSTRUCTION_HEADER { for line in Self::INSTRUCTION_HEADER {
push_line(&style(center(line))); push_line(line, self.styled);
} }
for (index, (instruction, position)) in self.chunk.instructions.iter().enumerate() { for (index, (instruction, position)) in self.chunk.instructions.iter().enumerate() {
@ -482,11 +482,11 @@ impl<'a> ChunkDisassembler<'a> {
"{index:<5} {bytecode:<08X} {operation:15} {info:25} {jump_offset:8} {position:8}" "{index:<5} {bytecode:<08X} {operation:15} {info:25} {jump_offset:8} {position:8}"
); );
push_line(&center(&instruction_display)); push_line(&instruction_display, false);
} }
for line in Self::CONSTANT_HEADER { for line in Self::CONSTANT_HEADER {
push_line(&style(center(line))); push_line(line, self.styled);
} }
for (index, value_option) in self.chunk.constants.iter().enumerate() { for (index, value_option) in self.chunk.constants.iter().enumerate() {
@ -502,27 +502,47 @@ impl<'a> ChunkDisassembler<'a> {
format!("{index:<5} {value_display:<trucated_length$}") format!("{index:<5} {value_display:<trucated_length$}")
}; };
push_line(&center(&constant_display)); push_line(&constant_display, false);
if let Some(chunk) = value_option.as_ref().and_then(|value| match value { if let Some(function_disassembly) =
Value::Raw(value_data) => value_data.as_function().map(|function| function.body()), value_option.as_ref().and_then(|value| match value {
Value::Reference(arc) => arc.as_function().map(|function| function.body()), Value::Raw(value_data) => value_data.as_function().map(|function| {
Value::Mutable(arc) => todo!(), function
}) { .body()
let mut function_disassembler = chunk.disassembler("function"); .disassembler("function")
.styled(self.styled)
function_disassembler .indent(self.indent + 1)
.styled(self.styled) .width(self.width)
.indent(self.indent + 1); .disassemble()
}),
let function_disassembly = function_disassembler.disassemble(); Value::Reference(arc) => arc.as_function().map(|function| {
function
push_line(&function_disassembly); .body()
.disassembler("function")
.styled(self.styled)
.indent(self.indent + 1)
.width(self.width)
.disassemble()
}),
Value::Mutable(rw_lock) => {
rw_lock.read().unwrap().as_function().map(|function| {
function
.body()
.disassembler("function")
.styled(self.styled)
.indent(self.indent + 1)
.width(self.width)
.disassemble()
})
}
})
{
push_line(&function_disassembly, false);
} }
} }
for line in Self::LOCAL_HEADER { for line in Self::LOCAL_HEADER {
push_line(&style(center(line))); push_line(line, self.styled);
} }
for ( for (
@ -549,9 +569,16 @@ impl<'a> ChunkDisassembler<'a> {
"{index:<5} {identifier_display:10} {type_display:8} {mutable:7} {depth:<5} {register_display:8}" "{index:<5} {identifier_display:10} {type_display:8} {mutable:7} {depth:<5} {register_display:8}"
); );
push_line(&center(&local_display)); push_line(&local_display, false);
} }
for _ in 0..self.indent {
disassembly.push_str("| ");
}
disassembly.push('|');
disassembly.push_str(&"-".repeat(self.width));
let expected_length = self.predict_length(); let expected_length = self.predict_length();
let actual_length = disassembly.len(); let actual_length = disassembly.len();
@ -592,9 +619,8 @@ impl<'a> ChunkDisassembler<'a> {
let dynamic_line_count = let dynamic_line_count =
self.chunk.instructions.len() + self.chunk.constants.len() + self.chunk.locals.len(); self.chunk.instructions.len() + self.chunk.constants.len() + self.chunk.locals.len();
let total_line_count = static_line_count + dynamic_line_count; let total_line_count = static_line_count + dynamic_line_count;
let width = self.width.unwrap_or_else(Self::default_width) + 1;
total_line_count * width total_line_count * self.width
} }
} }