diff --git a/dust-lang/src/chunk.rs b/dust-lang/src/chunk.rs index 51c4730..5c16aaa 100644 --- a/dust-lang/src/chunk.rs +++ b/dust-lang/src/chunk.rs @@ -529,7 +529,7 @@ impl<'a> ChunkDisassembler<'a> { if let Some(source) = self.source { push( - &source.replace("\n", ""), + &source.split_whitespace().collect::>().join(" "), &mut disassembly, self.width, self.indent, diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index 8c8d29e..6cd87f1 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -1170,7 +1170,6 @@ impl<'src> Parser<'src> { } self.parse_expression()?; - self.increment_register()?; argument_count += 1; } diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index df528f6..d1b91fd 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -1,4 +1,4 @@ -use std::mem::replace; +use std::{cmp::Ordering, mem::replace}; use crate::{ parse, value::Primitive, AnnotatedError, Chunk, ChunkError, DustError, Identifier, Instruction, @@ -126,9 +126,8 @@ impl Vm { let to_register = instruction.a(); let local_index = instruction.b(); 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 => { let register = instruction.a(); @@ -385,7 +384,7 @@ impl Vm { let last_argument_index = first_argument_index + argument_count - 1; 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)); } @@ -416,35 +415,71 @@ impl Vm { 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 index = index as usize; + let to_register = to_register as usize; if length == Self::STACK_LIMIT { return Err(VmError::StackOverflow { position }); } - if index == length { - log::trace!("Push register {index} with value {value}"); + match to_register.cmp(&length) { + 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 { - log::trace!("Replace register {index} with value {value}"); + match to_register.cmp(&length) { + 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( @@ -488,7 +523,7 @@ impl Vm { let register = self .stack .get(index) - .ok_or_else(|| VmError::RegisterIndexOutOfBounds { position })?; + .ok_or_else(|| VmError::RegisterIndexOutOfBounds { index, position })?; match register { Register::Value(value) => Ok(value), @@ -530,7 +565,7 @@ impl Vm { let index = index as usize; 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); @@ -587,6 +622,7 @@ pub enum VmError { position: Span, }, RegisterIndexOutOfBounds { + index: usize, position: Span, }, InvalidInstruction { @@ -649,6 +685,9 @@ impl AnnotatedError for VmError { match self { Self::EmptyRegister { index, .. } => Some(format!("Register {index} is empty")), 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, .. } => { Some(format!("{identifier} is not in scope")) } @@ -664,7 +703,7 @@ impl AnnotatedError for VmError { Self::EmptyRegister { position, .. } => *position, Self::ExpectedBoolean { position, .. } => *position, Self::ExpectedFunction { position, .. } => *position, - Self::RegisterIndexOutOfBounds { position } => *position, + Self::RegisterIndexOutOfBounds { position, .. } => *position, Self::InvalidInstruction { position, .. } => *position, Self::SkippedRegister { position, .. } => *position, Self::StackUnderflow { position } => *position,