Add a VM method; Refactor and clean up
This commit is contained in:
parent
055f0a4100
commit
5eb901f468
@ -529,7 +529,7 @@ impl<'a> ChunkDisassembler<'a> {
|
|||||||
|
|
||||||
if let Some(source) = self.source {
|
if let Some(source) = self.source {
|
||||||
push(
|
push(
|
||||||
&source.replace("\n", ""),
|
&source.split_whitespace().collect::<Vec<&str>>().join(" "),
|
||||||
&mut disassembly,
|
&mut disassembly,
|
||||||
self.width,
|
self.width,
|
||||||
self.indent,
|
self.indent,
|
||||||
|
@ -1170,7 +1170,6 @@ impl<'src> Parser<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.parse_expression()?;
|
self.parse_expression()?;
|
||||||
self.increment_register()?;
|
|
||||||
|
|
||||||
argument_count += 1;
|
argument_count += 1;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::mem::replace;
|
use std::{cmp::Ordering, mem::replace};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
parse, value::Primitive, AnnotatedError, Chunk, ChunkError, DustError, Identifier, Instruction,
|
parse, value::Primitive, AnnotatedError, Chunk, ChunkError, DustError, Identifier, Instruction,
|
||||||
@ -126,9 +126,8 @@ impl Vm {
|
|||||||
let to_register = instruction.a();
|
let to_register = instruction.a();
|
||||||
let local_index = instruction.b();
|
let local_index = instruction.b();
|
||||||
let local = self.chunk.get_local(local_index, position)?;
|
let local = self.chunk.get_local(local_index, position)?;
|
||||||
let value = self.take(local.register_index, to_register, position)?;
|
|
||||||
|
|
||||||
self.set(to_register, value, position)?;
|
self.set_pointer(to_register, local.register_index, position)?;
|
||||||
}
|
}
|
||||||
Operation::SetLocal => {
|
Operation::SetLocal => {
|
||||||
let register = instruction.a();
|
let register = instruction.a();
|
||||||
@ -385,7 +384,7 @@ impl Vm {
|
|||||||
let last_argument_index = first_argument_index + argument_count - 1;
|
let last_argument_index = first_argument_index + argument_count - 1;
|
||||||
|
|
||||||
for argument_index in first_argument_index..=last_argument_index {
|
for argument_index in first_argument_index..=last_argument_index {
|
||||||
let argument = self.empty(argument_index, position)?;
|
let argument = self.get(argument_index, position)?.clone();
|
||||||
|
|
||||||
function_vm.stack.push(Register::Value(argument));
|
function_vm.stack.push(Register::Value(argument));
|
||||||
}
|
}
|
||||||
@ -416,35 +415,71 @@ impl Vm {
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set(&mut self, index: u8, value: Value, position: Span) -> Result<(), VmError> {
|
fn set(&mut self, to_register: u8, value: Value, position: Span) -> Result<(), VmError> {
|
||||||
let length = self.stack.len();
|
let length = self.stack.len();
|
||||||
let index = index as usize;
|
let to_register = to_register as usize;
|
||||||
|
|
||||||
if length == Self::STACK_LIMIT {
|
if length == Self::STACK_LIMIT {
|
||||||
return Err(VmError::StackOverflow { position });
|
return Err(VmError::StackOverflow { position });
|
||||||
}
|
}
|
||||||
|
|
||||||
if index == length {
|
match to_register.cmp(&length) {
|
||||||
log::trace!("Push register {index} with value {value}");
|
Ordering::Less => {
|
||||||
|
log::trace!("Replace R{to_register} with {value}");
|
||||||
|
|
||||||
self.stack.push(Register::Value(value));
|
self.stack[to_register] = Register::Value(value);
|
||||||
|
|
||||||
return Ok(());
|
Ok(())
|
||||||
|
}
|
||||||
|
Ordering::Equal => {
|
||||||
|
log::trace!("Push R{to_register} with {value}");
|
||||||
|
|
||||||
|
self.stack.push(Register::Value(value));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Ordering::Greater => Err(VmError::SkippedRegister {
|
||||||
|
index: to_register,
|
||||||
|
length,
|
||||||
|
position,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_pointer(
|
||||||
|
&mut self,
|
||||||
|
to_register: u8,
|
||||||
|
from_register: u8,
|
||||||
|
position: Span,
|
||||||
|
) -> Result<(), VmError> {
|
||||||
|
let length = self.stack.len();
|
||||||
|
let to_register = to_register as usize;
|
||||||
|
|
||||||
|
if length == Self::STACK_LIMIT {
|
||||||
|
return Err(VmError::StackOverflow { position });
|
||||||
}
|
}
|
||||||
|
|
||||||
if index < length {
|
match to_register.cmp(&length) {
|
||||||
log::trace!("Replace register {index} with value {value}");
|
Ordering::Less => {
|
||||||
|
log::trace!("Replace R{to_register} with R{from_register}");
|
||||||
|
|
||||||
self.stack[index] = Register::Value(value);
|
self.stack[to_register] = Register::Pointer(from_register);
|
||||||
|
|
||||||
return Ok(());
|
Ok(())
|
||||||
|
}
|
||||||
|
Ordering::Equal => {
|
||||||
|
log::trace!("Push R{to_register} with R{from_register}");
|
||||||
|
|
||||||
|
self.stack.push(Register::Pointer(from_register));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Ordering::Greater => Err(VmError::SkippedRegister {
|
||||||
|
index: to_register,
|
||||||
|
length,
|
||||||
|
position,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(VmError::SkippedRegister {
|
|
||||||
index,
|
|
||||||
length: self.stack.len(),
|
|
||||||
position,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_constant(
|
fn set_constant(
|
||||||
@ -488,7 +523,7 @@ impl Vm {
|
|||||||
let register = self
|
let register = self
|
||||||
.stack
|
.stack
|
||||||
.get(index)
|
.get(index)
|
||||||
.ok_or_else(|| VmError::RegisterIndexOutOfBounds { position })?;
|
.ok_or_else(|| VmError::RegisterIndexOutOfBounds { index, position })?;
|
||||||
|
|
||||||
match register {
|
match register {
|
||||||
Register::Value(value) => Ok(value),
|
Register::Value(value) => Ok(value),
|
||||||
@ -530,7 +565,7 @@ impl Vm {
|
|||||||
let index = index as usize;
|
let index = index as usize;
|
||||||
|
|
||||||
if index >= self.stack.len() {
|
if index >= self.stack.len() {
|
||||||
return Err(VmError::RegisterIndexOutOfBounds { position });
|
return Err(VmError::RegisterIndexOutOfBounds { index, position });
|
||||||
}
|
}
|
||||||
|
|
||||||
let register = replace(&mut self.stack[index], Register::Empty);
|
let register = replace(&mut self.stack[index], Register::Empty);
|
||||||
@ -587,6 +622,7 @@ pub enum VmError {
|
|||||||
position: Span,
|
position: Span,
|
||||||
},
|
},
|
||||||
RegisterIndexOutOfBounds {
|
RegisterIndexOutOfBounds {
|
||||||
|
index: usize,
|
||||||
position: Span,
|
position: Span,
|
||||||
},
|
},
|
||||||
InvalidInstruction {
|
InvalidInstruction {
|
||||||
@ -649,6 +685,9 @@ impl AnnotatedError for VmError {
|
|||||||
match self {
|
match self {
|
||||||
Self::EmptyRegister { index, .. } => Some(format!("Register {index} is empty")),
|
Self::EmptyRegister { index, .. } => Some(format!("Register {index} is empty")),
|
||||||
Self::ExpectedFunction { found, .. } => Some(format!("{found} is not a function")),
|
Self::ExpectedFunction { found, .. } => Some(format!("{found} is not a function")),
|
||||||
|
Self::RegisterIndexOutOfBounds { index, .. } => {
|
||||||
|
Some(format!("R{index} does not exist at this time"))
|
||||||
|
}
|
||||||
Self::UndefinedVariable { identifier, .. } => {
|
Self::UndefinedVariable { identifier, .. } => {
|
||||||
Some(format!("{identifier} is not in scope"))
|
Some(format!("{identifier} is not in scope"))
|
||||||
}
|
}
|
||||||
@ -664,7 +703,7 @@ impl AnnotatedError for VmError {
|
|||||||
Self::EmptyRegister { position, .. } => *position,
|
Self::EmptyRegister { position, .. } => *position,
|
||||||
Self::ExpectedBoolean { position, .. } => *position,
|
Self::ExpectedBoolean { position, .. } => *position,
|
||||||
Self::ExpectedFunction { position, .. } => *position,
|
Self::ExpectedFunction { position, .. } => *position,
|
||||||
Self::RegisterIndexOutOfBounds { position } => *position,
|
Self::RegisterIndexOutOfBounds { position, .. } => *position,
|
||||||
Self::InvalidInstruction { position, .. } => *position,
|
Self::InvalidInstruction { position, .. } => *position,
|
||||||
Self::SkippedRegister { position, .. } => *position,
|
Self::SkippedRegister { position, .. } => *position,
|
||||||
Self::StackUnderflow { position } => *position,
|
Self::StackUnderflow { position } => *position,
|
||||||
|
Loading…
Reference in New Issue
Block a user