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)]
|
#[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,28 +600,22 @@ 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;
|
|
||||||
|
|
||||||
disassembler.styled(self.styled);
|
disassembler.styled(self.styled);
|
||||||
disassembler.disassemble()
|
disassembler.disassemble()
|
||||||
}),
|
}),
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user