Consume VM and chunk when running the VM
This commit is contained in:
parent
8b70a1dcc4
commit
bfade78a0d
@ -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)]
|
||||
|
@ -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 })?;
|
||||
|
Loading…
Reference in New Issue
Block a user