1
0

Use new instruction features

This commit is contained in:
Jeff 2024-11-28 06:33:29 -05:00
parent 7e2ebf54c7
commit ef01499e38

View File

@ -7,8 +7,8 @@ use std::{
use crate::{ use crate::{
compile, instruction::*, AbstractValue, AnnotatedError, Argument, Chunk, ChunkError, compile, instruction::*, AbstractValue, AnnotatedError, Argument, Chunk, ChunkError,
ConcreteValue, Destination, DustError, Instruction, NativeFunction, NativeFunctionError, ConcreteValue, Destination, DustError, Instruction, NativeFunctionError, Operation, Span,
Operation, Span, Value, ValueError, ValueRef, Value, ValueError, ValueRef,
}; };
pub fn run(source: &str) -> Result<Option<ConcreteValue>, DustError> { pub fn run(source: &str) -> Result<Option<ConcreteValue>, DustError> {
@ -106,7 +106,7 @@ impl<'a> Vm<'a> {
self.set_register(register_index, register)?; self.set_register(register_index, register)?;
if jump_next { if jump_next {
self.ip += 1; self.jump(1, true);
} }
} }
Operation::LoadConstant => { Operation::LoadConstant => {
@ -284,7 +284,7 @@ impl<'a> Vm<'a> {
}; };
if boolean == test_value { if boolean == test_value {
self.ip += 1; self.jump(1, true);
} }
} }
Operation::TestSet => { Operation::TestSet => {
@ -306,7 +306,7 @@ impl<'a> Vm<'a> {
}; };
if boolean == test_value { if boolean == test_value {
self.ip += 1; self.jump(1, true);
} else { } else {
let pointer = match argument { let pointer = match argument {
Argument::Constant(constant_index) => Pointer::Constant(constant_index), Argument::Constant(constant_index) => Pointer::Constant(constant_index),
@ -345,11 +345,15 @@ impl<'a> Vm<'a> {
}; };
if is_equal == value { if is_equal == value {
self.ip += 1; self.jump(1, true);
} else { } else {
let jump = self.read()?; let jump = self.read()?;
let Jump {
offset,
is_positive,
} = Jump::from(&jump);
self.jump(jump); self.jump(offset as usize, is_positive);
} }
} }
Operation::Less => { Operation::Less => {
@ -371,11 +375,15 @@ impl<'a> Vm<'a> {
}; };
if is_less_than == value { if is_less_than == value {
self.ip += 1; self.jump(1, true);
} else { } else {
let jump = self.read()?; let jump = self.read()?;
let Jump {
offset,
is_positive,
} = Jump::from(&jump);
self.jump(jump); self.jump(offset as usize, is_positive);
} }
} }
Operation::LessEqual => { Operation::LessEqual => {
@ -401,11 +409,15 @@ impl<'a> Vm<'a> {
}; };
if is_less_than_or_equal == value { if is_less_than_or_equal == value {
self.ip += 1; self.jump(1, true);
} else { } else {
let jump = self.read()?; let jump = self.read()?;
let Jump {
offset,
is_positive,
} = Jump::from(&jump);
self.jump(jump); self.jump(offset as usize, is_positive);
} }
} }
Operation::Negate => { Operation::Negate => {
@ -438,7 +450,15 @@ impl<'a> Vm<'a> {
self.set_register(register_index, register)?; self.set_register(register_index, register)?;
} }
Operation::Jump => self.jump(instruction), Operation::Jump => {
let jump = self.read()?;
let Jump {
offset,
is_positive,
} = Jump::from(&jump);
self.jump(offset as usize, is_positive);
}
Operation::Call => { Operation::Call => {
let Call { let Call {
destination, destination,
@ -459,7 +479,7 @@ impl<'a> Vm<'a> {
}); });
}; };
let mut function_vm = Vm::new(chunk, Some(self)); let mut function_vm = Vm::new(chunk, Some(self));
let first_argument_index = register_index - argument_count; let first_argument_index = register_index - argument_count - 1;
for (argument_index, argument_register_index) in for (argument_index, argument_register_index) in
(first_argument_index..register_index).enumerate() (first_argument_index..register_index).enumerate()
@ -469,7 +489,9 @@ impl<'a> Vm<'a> {
Register::Pointer(Pointer::ParentStack(argument_register_index)), Register::Pointer(Pointer::ParentStack(argument_register_index)),
)?; )?;
function_vm.local_definitions[argument_index] = Some(argument_index as u16); function_vm
.local_definitions
.push(Some(argument_index as u16));
} }
let return_value = function_vm.run()?; let return_value = function_vm.run()?;
@ -599,17 +621,25 @@ impl<'a> Vm<'a> {
} }
/// DRY helper for handling JUMP instructions /// DRY helper for handling JUMP instructions
fn jump(&mut self, jump: Instruction) { fn jump(&mut self, offset: usize, is_positive: bool) {
let jump_distance = jump.b(); log::trace!(
let is_positive = jump.c_as_boolean(); "Jumping {}",
if is_positive {
format!("+{}", offset)
} else {
format!("-{}", offset + 1)
}
);
let new_ip = if is_positive { let new_ip = if is_positive {
self.ip + jump_distance as usize self.ip + offset
} else { } else {
self.ip - jump_distance as usize - 1 self.ip - offset - 1
}; };
self.ip = new_ip; self.ip = new_ip;
} }
/// DRY helper to get a register index from a Destination
fn get_destination(&self, destination: Destination) -> Result<u16, VmError> { fn get_destination(&self, destination: Destination) -> Result<u16, VmError> {
let index = match destination { let index = match destination {
Destination::Register(register_index) => register_index, Destination::Register(register_index) => register_index,
@ -627,7 +657,7 @@ impl<'a> Vm<'a> {
Ok(index) Ok(index)
} }
/// DRY helper to get a constant or register values /// DRY helper to get a value from an Argument
fn get_argument(&self, argument: Argument) -> Result<ValueRef, VmError> { fn get_argument(&self, argument: Argument) -> Result<ValueRef, VmError> {
let value_ref = match argument { let value_ref = match argument {
Argument::Constant(constant_index) => { Argument::Constant(constant_index) => {
@ -640,15 +670,6 @@ impl<'a> Vm<'a> {
Ok(value_ref) Ok(value_ref)
} }
/// DRY helper to get two arguments for binary operations
fn get_arguments(&self, instruction: Instruction) -> Result<(ValueRef, ValueRef), VmError> {
let (left, right) = instruction.b_and_c_as_arguments();
let left_value = self.get_argument(left)?;
let right_value = self.get_argument(right)?;
Ok((left_value, right_value))
}
fn set_register(&mut self, to_register: u16, register: Register) -> Result<(), VmError> { fn set_register(&mut self, to_register: u16, register: Register) -> Result<(), VmError> {
self.last_assigned_register = Some(to_register); self.last_assigned_register = Some(to_register);
@ -728,7 +749,7 @@ impl<'a> Vm<'a> {
position: self.current_position, position: self.current_position,
})?; })?;
self.ip += 1; self.jump(1, true);
self.current_position = *position; self.current_position = *position;
Ok(*instruction) Ok(*instruction)