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);
|
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)]
|
||||||
|
@ -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 })?;
|
||||||
|
Loading…
Reference in New Issue
Block a user