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); push_border(&bottom_border, &mut disassembly);
let expected_length = self.predict_length(); let _ = disassembly.trim_end_matches('\n');
let actual_length = disassembly.len();
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 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)] #[derive(Debug, Clone, PartialEq)]

View File

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