Use new instruction features
This commit is contained in:
parent
7e2ebf54c7
commit
ef01499e38
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user