Improve disassembler output; Fix return positions
This commit is contained in:
parent
61d633392c
commit
c1e372d7cf
@ -408,28 +408,31 @@ impl<'a> ChunkDisassembler<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn disassemble(&self) -> String {
|
pub fn disassemble(&self) -> String {
|
||||||
let center_and_style = |line: &str, style: bool| {
|
|
||||||
if style {
|
|
||||||
format!("|{line:^width$}|", line = line.bold(), width = self.width)
|
|
||||||
} else {
|
|
||||||
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 indent = "│ ".repeat(self.indent);
|
||||||
|
let top_border = "┌".to_string() + &"─".repeat(self.width) + "┐";
|
||||||
|
|
||||||
if self.indent > 0 {
|
disassembly.push_str(&indent);
|
||||||
disassembly.push_str(" ");
|
disassembly.push_str(&top_border);
|
||||||
}
|
|
||||||
|
|
||||||
disassembly.push('|');
|
|
||||||
disassembly.push_str(&"-".repeat(self.width));
|
|
||||||
disassembly.push('|');
|
|
||||||
disassembly.push('\n');
|
disassembly.push('\n');
|
||||||
|
|
||||||
let mut push_line = |line: &str, style: bool| {
|
let center_and_style = |line: &str, style: bool| {
|
||||||
|
if style {
|
||||||
|
format!("│{line:^width$}│", line = line.bold(), width = self.width)
|
||||||
|
} else {
|
||||||
|
format!("│{line:^width$}│", width = self.width)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut push = |line: &str, style: bool| {
|
||||||
|
if line.lines().count() > 1 {
|
||||||
|
disassembly.push_str(line);
|
||||||
|
disassembly.push('\n');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for _ in 0..self.indent {
|
for _ in 0..self.indent {
|
||||||
disassembly.push_str("| ");
|
disassembly.push_str("│ ");
|
||||||
}
|
}
|
||||||
|
|
||||||
let line = center_and_style(line, style);
|
let line = center_and_style(line, style);
|
||||||
@ -438,7 +441,7 @@ impl<'a> ChunkDisassembler<'a> {
|
|||||||
disassembly.push('\n');
|
disassembly.push('\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
push_line(self.name, self.styled);
|
push(self.name, self.styled);
|
||||||
|
|
||||||
let info_line = format!(
|
let info_line = format!(
|
||||||
"{} instructions, {} constants, {} locals",
|
"{} instructions, {} constants, {} locals",
|
||||||
@ -448,10 +451,10 @@ impl<'a> ChunkDisassembler<'a> {
|
|||||||
)
|
)
|
||||||
.dimmed();
|
.dimmed();
|
||||||
|
|
||||||
push_line(&info_line, false);
|
push(&info_line, false);
|
||||||
|
|
||||||
for line in Self::INSTRUCTION_HEADER {
|
for line in Self::INSTRUCTION_HEADER {
|
||||||
push_line(line, self.styled);
|
push(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 +485,42 @@ 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(&instruction_display, false);
|
push(&instruction_display, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for line in Self::LOCAL_HEADER {
|
||||||
|
push(line, self.styled);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (
|
||||||
|
index,
|
||||||
|
Local {
|
||||||
|
identifier,
|
||||||
|
r#type,
|
||||||
|
depth,
|
||||||
|
register_index,
|
||||||
|
is_mutable: mutable,
|
||||||
|
},
|
||||||
|
) in self.chunk.locals.iter().enumerate()
|
||||||
|
{
|
||||||
|
let register_display = register_index
|
||||||
|
.as_ref()
|
||||||
|
.map(|value| value.to_string())
|
||||||
|
.unwrap_or_else(|| "empty".to_string());
|
||||||
|
let identifier_display = identifier.as_str();
|
||||||
|
let type_display = r#type
|
||||||
|
.as_ref()
|
||||||
|
.map(|r#type| r#type.to_string())
|
||||||
|
.unwrap_or("unknown".to_string());
|
||||||
|
let local_display = format!(
|
||||||
|
"{index:<5} {identifier_display:10} {type_display:8} {mutable:7} {depth:<5} {register_display:8}"
|
||||||
|
);
|
||||||
|
|
||||||
|
push(&local_display, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for line in Self::CONSTANT_HEADER {
|
for line in Self::CONSTANT_HEADER {
|
||||||
push_line(line, self.styled);
|
push(line, self.styled);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (index, value_option) in self.chunk.constants.iter().enumerate() {
|
for (index, value_option) in self.chunk.constants.iter().enumerate() {
|
||||||
@ -502,7 +536,7 @@ impl<'a> ChunkDisassembler<'a> {
|
|||||||
format!("{index:<5} {value_display:<trucated_length$}")
|
format!("{index:<5} {value_display:<trucated_length$}")
|
||||||
};
|
};
|
||||||
|
|
||||||
push_line(&constant_display, false);
|
push(&constant_display, false);
|
||||||
|
|
||||||
if let Some(function_disassembly) =
|
if let Some(function_disassembly) =
|
||||||
value_option.as_ref().and_then(|value| match value {
|
value_option.as_ref().and_then(|value| match value {
|
||||||
@ -537,47 +571,15 @@ impl<'a> ChunkDisassembler<'a> {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
push_line(&function_disassembly, false);
|
push(&function_disassembly, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for line in Self::LOCAL_HEADER {
|
let indent = "│ ".repeat(self.indent);
|
||||||
push_line(line, self.styled);
|
let bottom_border = "└".to_string() + &"─".repeat(self.width) + "┘";
|
||||||
}
|
|
||||||
|
|
||||||
for (
|
disassembly.push_str(&indent);
|
||||||
index,
|
disassembly.push_str(&bottom_border);
|
||||||
Local {
|
|
||||||
identifier,
|
|
||||||
r#type,
|
|
||||||
depth,
|
|
||||||
register_index,
|
|
||||||
is_mutable: mutable,
|
|
||||||
},
|
|
||||||
) in self.chunk.locals.iter().enumerate()
|
|
||||||
{
|
|
||||||
let register_display = register_index
|
|
||||||
.as_ref()
|
|
||||||
.map(|value| value.to_string())
|
|
||||||
.unwrap_or_else(|| "empty".to_string());
|
|
||||||
let identifier_display = identifier.as_str();
|
|
||||||
let type_display = r#type
|
|
||||||
.as_ref()
|
|
||||||
.map(|r#type| r#type.to_string())
|
|
||||||
.unwrap_or("unknown".to_string());
|
|
||||||
let local_display = format!(
|
|
||||||
"{index:<5} {identifier_display:10} {type_display:8} {mutable:7} {depth:<5} {register_display:8}"
|
|
||||||
);
|
|
||||||
|
|
||||||
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();
|
||||||
|
@ -926,6 +926,8 @@ impl<'src> Parser<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_return(&mut self, allowed: Allowed) -> Result<(), ParseError> {
|
fn parse_return(&mut self, allowed: Allowed) -> Result<(), ParseError> {
|
||||||
|
let start = self.current_position.0;
|
||||||
|
|
||||||
if !allowed.explicit_return {
|
if !allowed.explicit_return {
|
||||||
return Err(ParseError::UnexpectedReturn {
|
return Err(ParseError::UnexpectedReturn {
|
||||||
position: self.current_position,
|
position: self.current_position,
|
||||||
@ -948,7 +950,9 @@ impl<'src> Parser<'src> {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.emit_instruction(Instruction::r#return(), self.current_position);
|
let end = self.current_position.1;
|
||||||
|
|
||||||
|
self.emit_instruction(Instruction::r#return(), Span(start, end));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user