Simplify and clean up
This commit is contained in:
parent
6bcc5b1555
commit
8c79157fa7
@ -11,7 +11,7 @@ use crate::{AnnotatedError, Identifier, Instruction, Operation, Span, Type, Valu
|
||||
#[derive(Clone, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct Chunk {
|
||||
instructions: Vec<(Instruction, Span)>,
|
||||
constants: Vec<Option<Value>>,
|
||||
constants: Vec<Value>,
|
||||
locals: Vec<Local>,
|
||||
scope_depth: usize,
|
||||
}
|
||||
@ -33,7 +33,7 @@ impl Chunk {
|
||||
) -> Self {
|
||||
Self {
|
||||
instructions,
|
||||
constants: constants.into_iter().map(Some).collect(),
|
||||
constants,
|
||||
locals,
|
||||
scope_depth: 0,
|
||||
}
|
||||
@ -126,8 +126,8 @@ impl Chunk {
|
||||
operations
|
||||
}
|
||||
|
||||
pub fn constants(&self) -> &[Option<Value>] {
|
||||
&self.constants
|
||||
pub fn take_constants(self) -> Vec<Value> {
|
||||
self.constants
|
||||
}
|
||||
|
||||
pub fn get_constant(&self, index: u8, position: Span) -> Result<&Value, ChunkError> {
|
||||
@ -136,21 +136,6 @@ impl Chunk {
|
||||
self.constants
|
||||
.get(index)
|
||||
.ok_or(ChunkError::ConstantIndexOutOfBounds { index, position })
|
||||
.and_then(|value| {
|
||||
value
|
||||
.as_ref()
|
||||
.ok_or(ChunkError::ConstantAlreadyUsed { index, position })
|
||||
})
|
||||
}
|
||||
|
||||
pub fn take_constant(&mut self, index: u8, position: Span) -> Result<Value, ChunkError> {
|
||||
let index = index as usize;
|
||||
|
||||
self.constants
|
||||
.get_mut(index)
|
||||
.ok_or_else(|| ChunkError::ConstantIndexOutOfBounds { index, position })?
|
||||
.take()
|
||||
.ok_or(ChunkError::ConstantAlreadyUsed { index, position })
|
||||
}
|
||||
|
||||
pub fn push_constant(&mut self, value: Value, position: Span) -> Result<u8, ChunkError> {
|
||||
@ -159,7 +144,7 @@ impl Chunk {
|
||||
if starting_length + 1 > (u8::MAX as usize) {
|
||||
Err(ChunkError::ConstantOverflow { position })
|
||||
} else {
|
||||
self.constants.push(Some(value));
|
||||
self.constants.push(value);
|
||||
|
||||
Ok(starting_length as u8)
|
||||
}
|
||||
@ -518,7 +503,6 @@ impl<'a> ChunkDisassembler<'a> {
|
||||
};
|
||||
let push_function_disassembly = |function_disassembly: &str, disassembly: &mut String| {
|
||||
disassembly.push_str(function_disassembly);
|
||||
disassembly.push('\n');
|
||||
};
|
||||
let mut disassembly = String::new();
|
||||
let top_border = "┌".to_string() + &"─".repeat(self.width - 2) + "┐";
|
||||
@ -616,28 +600,22 @@ impl<'a> ChunkDisassembler<'a> {
|
||||
push_header(line, &mut disassembly);
|
||||
}
|
||||
|
||||
for (index, value_option) in self.chunk.constants.iter().enumerate() {
|
||||
let value_display = value_option
|
||||
.as_ref()
|
||||
.map(|value| value.to_string())
|
||||
.unwrap_or("empty".to_string());
|
||||
let constant_display = format!("{index:<5} {value_display:<5}");
|
||||
for (index, value) in self.chunk.constants.iter().enumerate() {
|
||||
let constant_display = format!("{index:<5} {value:<5}");
|
||||
|
||||
push_details(&constant_display, &mut disassembly);
|
||||
|
||||
if let Some(function_disassembly) =
|
||||
value_option.as_ref().and_then(|value| match value {
|
||||
Value::Function(function) => Some({
|
||||
let mut disassembler = function.chunk().disassembler("function");
|
||||
disassembler.indent = self.indent + 1;
|
||||
if let Some(function_disassembly) = match value {
|
||||
Value::Function(function) => Some({
|
||||
let mut disassembler = function.chunk().disassembler("function");
|
||||
disassembler.indent = self.indent + 1;
|
||||
|
||||
disassembler.styled(self.styled);
|
||||
disassembler.disassemble()
|
||||
}),
|
||||
Value::Primitive(_) => None,
|
||||
Value::Object(_) => None,
|
||||
})
|
||||
{
|
||||
disassembler.styled(self.styled);
|
||||
disassembler.disassemble()
|
||||
}),
|
||||
Value::Primitive(_) => None,
|
||||
Value::Object(_) => None,
|
||||
} {
|
||||
push_function_disassembly(&function_disassembly, &mut disassembly);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::{
|
||||
fmt::{self, Display, Formatter},
|
||||
mem::{replace, take},
|
||||
mem::replace,
|
||||
num::{ParseFloatError, ParseIntError},
|
||||
};
|
||||
|
||||
|
@ -65,13 +65,7 @@ impl Vm {
|
||||
);
|
||||
|
||||
match instruction.operation() {
|
||||
Operation::Move => {
|
||||
let to_register = instruction.a();
|
||||
let from_register = instruction.b();
|
||||
let value = self.take(from_register, to_register, position)?;
|
||||
|
||||
self.set(to_register, value, position)?;
|
||||
}
|
||||
Operation::Move => todo!(),
|
||||
Operation::Close => {
|
||||
let from_register = instruction.b();
|
||||
let to_register = instruction.c();
|
||||
@ -206,29 +200,7 @@ impl Vm {
|
||||
self.ip += 1;
|
||||
}
|
||||
}
|
||||
Operation::TestSet => {
|
||||
let to_register = instruction.a();
|
||||
let argument = instruction.b();
|
||||
let test_value = instruction.c_as_boolean();
|
||||
let borrowed_value = self.get(argument, position)?;
|
||||
let boolean =
|
||||
if let Value::Primitive(Primitive::Boolean(boolean)) = borrowed_value {
|
||||
*boolean
|
||||
} else {
|
||||
return Err(VmError::ExpectedBoolean {
|
||||
found: borrowed_value.clone(),
|
||||
position,
|
||||
});
|
||||
};
|
||||
|
||||
if boolean == test_value {
|
||||
let value = self.take(argument, to_register, position)?;
|
||||
|
||||
self.set(to_register, value, position)?;
|
||||
} else {
|
||||
self.ip += 1;
|
||||
}
|
||||
}
|
||||
Operation::TestSet => todo!(),
|
||||
Operation::Equal => {
|
||||
debug_assert_eq!(
|
||||
self.chunk.get_instruction(self.ip, position)?.0.operation(),
|
||||
@ -398,8 +370,6 @@ impl Vm {
|
||||
|
||||
if let Some(value) = return_value {
|
||||
self.set(function_index, value, position)?;
|
||||
} else {
|
||||
self.empty(function_index, position)?;
|
||||
}
|
||||
}
|
||||
Operation::Return => {
|
||||
@ -430,14 +400,14 @@ impl Vm {
|
||||
|
||||
match to_register.cmp(&length) {
|
||||
Ordering::Less => {
|
||||
log::trace!("Replace R{to_register} with {value}");
|
||||
log::trace!("Change R{to_register} to {value}");
|
||||
|
||||
self.stack[to_register] = Register::Value(value);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Ordering::Equal => {
|
||||
log::trace!("Push R{to_register} with {value}");
|
||||
log::trace!("Set R{to_register} to {value}");
|
||||
|
||||
self.stack.push(Register::Value(value));
|
||||
|
||||
@ -466,14 +436,14 @@ impl Vm {
|
||||
|
||||
match to_register.cmp(&length) {
|
||||
Ordering::Less => {
|
||||
log::trace!("Replace R{to_register} with R{from_register}");
|
||||
log::trace!("Change R{to_register} to R{from_register}");
|
||||
|
||||
self.stack[to_register] = Register::Pointer(from_register);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Ordering::Equal => {
|
||||
log::trace!("Push R{to_register} with R{from_register}");
|
||||
log::trace!("Set R{to_register} to R{from_register}");
|
||||
|
||||
self.stack.push(Register::Pointer(from_register));
|
||||
|
||||
@ -501,7 +471,7 @@ impl Vm {
|
||||
}
|
||||
|
||||
if index == length {
|
||||
log::trace!("Push register {index} with constant {constant_index}");
|
||||
log::trace!("Change register {index} to C{constant_index}");
|
||||
|
||||
self.stack.push(Register::Constant(constant_index));
|
||||
|
||||
@ -509,7 +479,7 @@ impl Vm {
|
||||
}
|
||||
|
||||
if index < length {
|
||||
log::trace!("Replace register {index} with constant {constant_index}");
|
||||
log::trace!("Set register {index} to C{constant_index}");
|
||||
|
||||
self.stack[index] = Register::Constant(constant_index);
|
||||
|
||||
@ -546,27 +516,7 @@ impl Vm {
|
||||
}
|
||||
}
|
||||
|
||||
fn take(&mut self, index: u8, point_to: u8, position: Span) -> Result<Value, VmError> {
|
||||
let index = index as usize;
|
||||
let register = replace(&mut self.stack[index], Register::Pointer(point_to));
|
||||
|
||||
match register {
|
||||
Register::Value(value) => Ok(value),
|
||||
Register::Pointer(register_index) => {
|
||||
let value = self.take(register_index, point_to, position)?;
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
Register::Constant(constant_index) => {
|
||||
let value = self.chunk.take_constant(constant_index, position)?;
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
Register::Empty => Err(VmError::EmptyRegister { index, position }),
|
||||
}
|
||||
}
|
||||
|
||||
fn empty(&mut self, index: u8, position: Span) -> Result<Value, VmError> {
|
||||
fn empty(mut self, index: u8, position: Span) -> Result<Value, VmError> {
|
||||
let index = index as usize;
|
||||
|
||||
if index >= self.stack.len() {
|
||||
@ -583,7 +533,7 @@ impl Vm {
|
||||
Ok(value)
|
||||
}
|
||||
Register::Constant(constant_index) => {
|
||||
let value = self.chunk.take_constant(constant_index, position)?;
|
||||
let value = self.chunk.take_constants().remove(constant_index as usize);
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user