1
0

Simplify and clean up

This commit is contained in:
Jeff 2024-10-19 03:06:14 -04:00
parent 6bcc5b1555
commit 8c79157fa7
3 changed files with 28 additions and 100 deletions

View File

@ -11,7 +11,7 @@ use crate::{AnnotatedError, Identifier, Instruction, Operation, Span, Type, Valu
#[derive(Clone, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Chunk { pub struct Chunk {
instructions: Vec<(Instruction, Span)>, instructions: Vec<(Instruction, Span)>,
constants: Vec<Option<Value>>, constants: Vec<Value>,
locals: Vec<Local>, locals: Vec<Local>,
scope_depth: usize, scope_depth: usize,
} }
@ -33,7 +33,7 @@ impl Chunk {
) -> Self { ) -> Self {
Self { Self {
instructions, instructions,
constants: constants.into_iter().map(Some).collect(), constants,
locals, locals,
scope_depth: 0, scope_depth: 0,
} }
@ -126,8 +126,8 @@ impl Chunk {
operations operations
} }
pub fn constants(&self) -> &[Option<Value>] { pub fn take_constants(self) -> Vec<Value> {
&self.constants self.constants
} }
pub fn get_constant(&self, index: u8, position: Span) -> Result<&Value, ChunkError> { pub fn get_constant(&self, index: u8, position: Span) -> Result<&Value, ChunkError> {
@ -136,21 +136,6 @@ impl Chunk {
self.constants self.constants
.get(index) .get(index)
.ok_or(ChunkError::ConstantIndexOutOfBounds { index, position }) .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> { 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) { if starting_length + 1 > (u8::MAX as usize) {
Err(ChunkError::ConstantOverflow { position }) Err(ChunkError::ConstantOverflow { position })
} else { } else {
self.constants.push(Some(value)); self.constants.push(value);
Ok(starting_length as u8) Ok(starting_length as u8)
} }
@ -518,7 +503,6 @@ impl<'a> ChunkDisassembler<'a> {
}; };
let push_function_disassembly = |function_disassembly: &str, disassembly: &mut String| { let push_function_disassembly = |function_disassembly: &str, disassembly: &mut String| {
disassembly.push_str(function_disassembly); disassembly.push_str(function_disassembly);
disassembly.push('\n');
}; };
let mut disassembly = String::new(); let mut disassembly = String::new();
let top_border = "".to_string() + &"".repeat(self.width - 2) + ""; let top_border = "".to_string() + &"".repeat(self.width - 2) + "";
@ -616,17 +600,12 @@ impl<'a> ChunkDisassembler<'a> {
push_header(line, &mut disassembly); push_header(line, &mut disassembly);
} }
for (index, value_option) in self.chunk.constants.iter().enumerate() { for (index, value) in self.chunk.constants.iter().enumerate() {
let value_display = value_option let constant_display = format!("{index:<5} {value:<5}");
.as_ref()
.map(|value| value.to_string())
.unwrap_or("empty".to_string());
let constant_display = format!("{index:<5} {value_display:<5}");
push_details(&constant_display, &mut disassembly); push_details(&constant_display, &mut disassembly);
if let Some(function_disassembly) = if let Some(function_disassembly) = match value {
value_option.as_ref().and_then(|value| match value {
Value::Function(function) => Some({ Value::Function(function) => Some({
let mut disassembler = function.chunk().disassembler("function"); let mut disassembler = function.chunk().disassembler("function");
disassembler.indent = self.indent + 1; disassembler.indent = self.indent + 1;
@ -636,8 +615,7 @@ impl<'a> ChunkDisassembler<'a> {
}), }),
Value::Primitive(_) => None, Value::Primitive(_) => None,
Value::Object(_) => None, Value::Object(_) => None,
}) } {
{
push_function_disassembly(&function_disassembly, &mut disassembly); push_function_disassembly(&function_disassembly, &mut disassembly);
} }
} }

View File

@ -1,6 +1,6 @@
use std::{ use std::{
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
mem::{replace, take}, mem::replace,
num::{ParseFloatError, ParseIntError}, num::{ParseFloatError, ParseIntError},
}; };

View File

@ -65,13 +65,7 @@ impl Vm {
); );
match instruction.operation() { match instruction.operation() {
Operation::Move => { Operation::Move => todo!(),
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::Close => { Operation::Close => {
let from_register = instruction.b(); let from_register = instruction.b();
let to_register = instruction.c(); let to_register = instruction.c();
@ -206,29 +200,7 @@ impl Vm {
self.ip += 1; self.ip += 1;
} }
} }
Operation::TestSet => { Operation::TestSet => todo!(),
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::Equal => { Operation::Equal => {
debug_assert_eq!( debug_assert_eq!(
self.chunk.get_instruction(self.ip, position)?.0.operation(), self.chunk.get_instruction(self.ip, position)?.0.operation(),
@ -398,8 +370,6 @@ impl Vm {
if let Some(value) = return_value { if let Some(value) = return_value {
self.set(function_index, value, position)?; self.set(function_index, value, position)?;
} else {
self.empty(function_index, position)?;
} }
} }
Operation::Return => { Operation::Return => {
@ -430,14 +400,14 @@ impl Vm {
match to_register.cmp(&length) { match to_register.cmp(&length) {
Ordering::Less => { 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); self.stack[to_register] = Register::Value(value);
Ok(()) Ok(())
} }
Ordering::Equal => { Ordering::Equal => {
log::trace!("Push R{to_register} with {value}"); log::trace!("Set R{to_register} to {value}");
self.stack.push(Register::Value(value)); self.stack.push(Register::Value(value));
@ -466,14 +436,14 @@ impl Vm {
match to_register.cmp(&length) { match to_register.cmp(&length) {
Ordering::Less => { 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); self.stack[to_register] = Register::Pointer(from_register);
Ok(()) Ok(())
} }
Ordering::Equal => { 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)); self.stack.push(Register::Pointer(from_register));
@ -501,7 +471,7 @@ impl Vm {
} }
if index == length { 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)); self.stack.push(Register::Constant(constant_index));
@ -509,7 +479,7 @@ impl Vm {
} }
if index < length { 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); 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> { fn empty(mut self, index: 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> {
let index = index as usize; let index = index as usize;
if index >= self.stack.len() { if index >= self.stack.len() {
@ -583,7 +533,7 @@ impl Vm {
Ok(value) Ok(value)
} }
Register::Constant(constant_index) => { 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) Ok(value)
} }