1
0

Consume VM and chunk when running the VM

This commit is contained in:
Jeff 2024-10-18 23:34:48 -04:00
parent 8b70a1dcc4
commit bfade78a0d
2 changed files with 11 additions and 51 deletions

View File

@ -644,50 +644,10 @@ impl<'a> ChunkDisassembler<'a> {
push_border(&bottom_border, &mut disassembly);
let expected_length = self.predict_length();
let actual_length = disassembly.len();
let _ = disassembly.trim_end_matches('\n');
if !self.styled && expected_length != actual_length {
log::debug!(
"Chunk disassembly was not optimized correctly, expected string length {expected_length}, got {actual_length}",
);
}
if self.styled && expected_length > actual_length {
log::debug!(
"Chunk disassembly was not optimized correctly, expected string length to be at least {expected_length}, got {actual_length}",
);
}
disassembly.pop(); // Remove the last newline character
disassembly
}
/// Predicts the capacity of the disassembled output. This is used to pre-allocate the string
/// buffer to avoid reallocations.
///
/// The capacity is calculated as follows:
/// - Get the number of static lines, i.e. lines that are always present in the disassembly
/// - Get the number of dynamic lines, i.e. lines that are generated from the chunk
/// - Add an one to the width to account for the newline character
/// - Multiply the total number of lines by the width of the disassembly output
///
/// The result is accurate only if the output is not styled. Otherwise the extra bytes added by
/// the ANSI escape codes will make the result too low. It still works as a lower bound in that
/// case.
fn predict_length(&self) -> usize {
const EXTRA_LINES: usize = 2; // There is one info line and one empty line after the name
let static_line_count = Self::INSTRUCTION_HEADER.len()
+ Self::CONSTANT_HEADER.len()
+ Self::LOCAL_HEADER.len()
+ EXTRA_LINES;
let dynamic_line_count =
self.chunk.instructions.len() + self.chunk.constants.len() + self.chunk.locals.len();
let total_line_count = static_line_count + dynamic_line_count;
total_line_count * self.width
}
}
#[derive(Debug, Clone, PartialEq)]

View File

@ -7,7 +7,7 @@ use crate::{
pub fn run(source: &str) -> Result<Option<Value>, DustError> {
let chunk = parse(source)?;
let mut vm = Vm::new(chunk);
let vm = Vm::new(chunk);
vm.run()
.map_err(|error| DustError::Runtime { error, source })
@ -31,7 +31,7 @@ impl Vm {
}
}
pub fn run(&mut self) -> Result<Option<Value>, VmError> {
pub fn run(mut self) -> Result<Option<Value>, VmError> {
// DRY helper to get constant or register values for binary operations
fn get_arguments(
vm: &mut Vm,
@ -150,7 +150,7 @@ impl Vm {
self.chunk.define_local(local_index, register, position)?;
}
Operation::Add => {
let (left, right) = get_arguments(self, instruction, position)?;
let (left, right) = get_arguments(&mut self, instruction, position)?;
let sum = left
.add(right)
.map_err(|error| VmError::Value { error, position })?;
@ -158,7 +158,7 @@ impl Vm {
self.set(instruction.a(), sum, position)?;
}
Operation::Subtract => {
let (left, right) = get_arguments(self, instruction, position)?;
let (left, right) = get_arguments(&mut self, instruction, position)?;
let difference = left
.subtract(right)
.map_err(|error| VmError::Value { error, position })?;
@ -166,7 +166,7 @@ impl Vm {
self.set(instruction.a(), difference, position)?;
}
Operation::Multiply => {
let (left, right) = get_arguments(self, instruction, position)?;
let (left, right) = get_arguments(&mut self, instruction, position)?;
let product = left
.multiply(right)
.map_err(|error| VmError::Value { error, position })?;
@ -174,7 +174,7 @@ impl Vm {
self.set(instruction.a(), product, position)?;
}
Operation::Divide => {
let (left, right) = get_arguments(self, instruction, position)?;
let (left, right) = get_arguments(&mut self, instruction, position)?;
let quotient = left
.divide(right)
.map_err(|error| VmError::Value { error, position })?;
@ -182,7 +182,7 @@ impl Vm {
self.set(instruction.a(), quotient, position)?;
}
Operation::Modulo => {
let (left, right) = get_arguments(self, instruction, position)?;
let (left, right) = get_arguments(&mut self, instruction, position)?;
let remainder = left
.modulo(right)
.map_err(|error| VmError::Value { error, position })?;
@ -235,7 +235,7 @@ impl Vm {
Operation::Jump
);
let (left, right) = get_arguments(self, instruction, position)?;
let (left, right) = get_arguments(&mut self, instruction, position)?;
let equal_result = left
.equal(right)
.map_err(|error| VmError::Value { error, position })?;
@ -271,7 +271,7 @@ impl Vm {
Operation::Jump
);
let (left, right) = get_arguments(self, instruction, position)?;
let (left, right) = get_arguments(&mut self, instruction, position)?;
let less_result = left
.less_than(right)
.map_err(|error| VmError::Value { error, position })?;
@ -307,7 +307,7 @@ impl Vm {
Operation::Jump
);
let (left, right) = get_arguments(self, instruction, position)?;
let (left, right) = get_arguments(&mut self, instruction, position)?;
let less_or_equal_result = left
.less_than_or_equal(right)
.map_err(|error| VmError::Value { error, position })?;