1
0

Make more optimizations to the VM

This commit is contained in:
Jeff 2024-12-14 16:17:02 -05:00
parent ec5033a32f
commit 9d544d789c
13 changed files with 87 additions and 324 deletions

View File

@ -199,7 +199,7 @@ fn main() {
let chunk = compiler.finish(None, None); let chunk = compiler.finish(None, None);
let compile_end = start_time.elapsed(); let compile_end = start_time.elapsed();
let vm = Vm::new(&source, &chunk, None, None); let vm = Vm::new(&chunk, None, None);
let return_value = vm.run(); let return_value = vm.run();
let run_end = start_time.elapsed(); let run_end = start_time.elapsed();

View File

@ -17,7 +17,7 @@ use std::io::Write;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use smallvec::SmallVec; use smallvec::SmallVec;
use crate::{ConcreteValue, DustString, FunctionType, Instruction, Span, Value}; use crate::{DustString, FunctionType, Instruction, Span, Value};
/// In-memory representation of a Dust program or function. /// In-memory representation of a Dust program or function.
/// ///

View File

@ -5,7 +5,7 @@ use std::fmt::{self, Display, Formatter};
use annotate_snippets::{Level, Renderer, Snippet}; use annotate_snippets::{Level, Renderer, Snippet};
use smallvec::SmallVec; use smallvec::SmallVec;
use crate::{CompileError, Span, VmError}; use crate::{CompileError, Span};
/// A top-level error that can occur during the interpretation of Dust code. /// A top-level error that can occur during the interpretation of Dust code.
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@ -14,10 +14,6 @@ pub enum DustError<'src> {
error: CompileError, error: CompileError,
source: &'src str, source: &'src str,
}, },
Runtime {
error: VmError,
source: &'src str,
},
} }
impl<'src> DustError<'src> { impl<'src> DustError<'src> {
@ -25,10 +21,6 @@ impl<'src> DustError<'src> {
DustError::Compile { error, source } DustError::Compile { error, source }
} }
pub fn runtime(error: VmError, source: &'src str) -> Self {
DustError::Runtime { error, source }
}
pub fn report(&self) -> String { pub fn report(&self) -> String {
let (title, description, detail_snippets, help_snippets) = self.error_data(); let (title, description, detail_snippets, help_snippets) = self.error_data();
let label = format!("{}: {}", title, description); let label = format!("{}: {}", title, description);
@ -65,19 +57,12 @@ impl<'src> DustError<'src> {
error.detail_snippets(), error.detail_snippets(),
error.help_snippets(), error.help_snippets(),
), ),
Self::Runtime { error, .. } => (
VmError::title(),
error.description(),
error.detail_snippets(),
error.help_snippets(),
),
} }
} }
fn source(&self) -> &str { fn source(&self) -> &str {
match self { match self {
Self::Compile { source, .. } => source, Self::Compile { source, .. } => source,
Self::Runtime { source, .. } => source,
} }
} }
} }

View File

@ -48,7 +48,7 @@ pub use crate::native_function::{NativeFunction, NativeFunctionError};
pub use crate::r#type::{EnumType, FunctionType, StructType, Type, TypeConflict}; pub use crate::r#type::{EnumType, FunctionType, StructType, Type, TypeConflict};
pub use crate::token::{Token, TokenKind, TokenOwned}; pub use crate::token::{Token, TokenKind, TokenOwned};
pub use crate::value::{AbstractValue, ConcreteValue, DustString, RangeValue, Value, ValueError}; pub use crate::value::{AbstractValue, ConcreteValue, DustString, RangeValue, Value, ValueError};
pub use crate::vm::{run, Vm, VmError}; pub use crate::vm::{run, Vm};
use std::fmt::Display; use std::fmt::Display;

View File

@ -1,6 +1,5 @@
use std::panic; use std::panic;
use annotate_snippets::{Level, Renderer, Snippet};
use smallvec::SmallVec; use smallvec::SmallVec;
use crate::{DustString, NativeFunctionError, Value, Vm}; use crate::{DustString, NativeFunctionError, Value, Vm};
@ -12,10 +11,7 @@ pub fn panic(
let mut message: Option<DustString> = None; let mut message: Option<DustString> = None;
for value_ref in arguments { for value_ref in arguments {
let string = match value_ref.display(vm) { let string = value_ref.display(vm);
Ok(string) => string,
Err(error) => return Err(NativeFunctionError::Vm(Box::new(error))),
};
match message { match message {
Some(ref mut message) => message.push_str(&string), Some(ref mut message) => message.push_str(&string),
@ -23,24 +19,9 @@ pub fn panic(
} }
} }
let position = vm.current_position(); if let Some(message) = message {
let error_output = Level::Error.title("Explicit Panic").snippet( panic!("{message}");
Snippet::source(vm.source()).fold(false).annotation( } else {
Level::Error panic!("Explicit panic");
.span(position.0..position.1) }
.label("Explicit panic occured here"),
),
);
let renderer = Renderer::plain();
let report = renderer.render(error_output).to_string();
panic::set_hook(Box::new(move |_| {
println!("{}", report);
if let Some(message) = &message {
println!("{}", message);
}
}));
panic!();
} }

View File

@ -29,10 +29,7 @@ pub fn write(
let mut stdout = stdout(); let mut stdout = stdout();
for argument in arguments { for argument in arguments {
let string = match argument.display(vm) { let string = argument.display(vm);
Ok(string) => string,
Err(error) => return Err(NativeFunctionError::Vm(Box::new(error))),
};
stdout stdout
.write_all(string.as_bytes()) .write_all(string.as_bytes())
@ -52,10 +49,7 @@ pub fn write_line(
let mut stdout = stdout(); let mut stdout = stdout();
for argument in arguments { for argument in arguments {
let string = match argument.display(vm) { let string = argument.display(vm);
Ok(string) => string,
Err(error) => return Err(NativeFunctionError::Vm(Box::new(error))),
};
stdout stdout
.write_all(string.as_bytes()) .write_all(string.as_bytes())

View File

@ -15,7 +15,7 @@ use std::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use crate::{AnnotatedError, FunctionType, Span, Type, Value, Vm, VmError}; use crate::{AnnotatedError, FunctionType, Span, Type, Value, Vm};
macro_rules! define_native_function { macro_rules! define_native_function {
($(($name:ident, $bytes:literal, $str:expr, $type:expr, $function:expr)),*) => { ($(($name:ident, $bytes:literal, $str:expr, $type:expr, $function:expr)),*) => {
@ -30,9 +30,9 @@ macro_rules! define_native_function {
} }
impl NativeFunction { impl NativeFunction {
pub fn call<'a>( pub fn call(
&self, &self,
vm: &Vm<'a>, vm: &Vm<'_>,
arguments: SmallVec<[&Value; 4]>, arguments: SmallVec<[&Value; 4]>,
) -> Result<Option<Value>, NativeFunctionError> { ) -> Result<Option<Value>, NativeFunctionError> {
match self { match self {
@ -269,7 +269,6 @@ pub enum NativeFunctionError {
error: IoErrorKind, error: IoErrorKind,
position: Span, position: Span,
}, },
Vm(Box<VmError>),
} }
impl AnnotatedError for NativeFunctionError { impl AnnotatedError for NativeFunctionError {
@ -285,7 +284,6 @@ impl AnnotatedError for NativeFunctionError {
NativeFunctionError::Panic { .. } => "Explicit panic", NativeFunctionError::Panic { .. } => "Explicit panic",
NativeFunctionError::Parse { .. } => "Failed to parse value", NativeFunctionError::Parse { .. } => "Failed to parse value",
NativeFunctionError::Io { .. } => "I/O error", NativeFunctionError::Io { .. } => "I/O error",
NativeFunctionError::Vm(error) => error.description(),
} }
} }

View File

@ -14,10 +14,7 @@ pub fn to_string(
}); });
} }
let argument_string = match arguments[0].display(vm) { let argument_string = arguments[0].display(vm);
Ok(string) => string,
Err(error) => return Err(NativeFunctionError::Vm(Box::new(error))),
};
Ok(Some(Value::Concrete(ConcreteValue::string( Ok(Some(Value::Concrete(ConcreteValue::string(
argument_string, argument_string,

View File

@ -1,6 +1,6 @@
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use crate::{vm::Pointer, ConcreteValue, DustString, Type, Value, Vm, VmError}; use crate::{vm::Pointer, ConcreteValue, DustString, Type, Value, Vm};
#[derive(Debug, PartialEq, PartialOrd)] #[derive(Debug, PartialEq, PartialOrd)]
pub enum AbstractValue { pub enum AbstractValue {
@ -16,7 +16,7 @@ impl AbstractValue {
Value::Abstract(self) Value::Abstract(self)
} }
pub fn to_concrete_owned(&self, vm: &Vm) -> ConcreteValue { pub fn to_concrete_owned<'a>(&self, vm: &'a Vm<'a>) -> ConcreteValue {
match self { match self {
AbstractValue::FunctionSelf => ConcreteValue::function(vm.chunk().clone()), AbstractValue::FunctionSelf => ConcreteValue::function(vm.chunk().clone()),
AbstractValue::List { item_pointers, .. } => { AbstractValue::List { item_pointers, .. } => {
@ -37,7 +37,7 @@ impl AbstractValue {
} }
} }
pub fn to_dust_string(&self, vm: &Vm) -> Result<DustString, VmError> { pub fn display(&self, vm: &Vm) -> DustString {
let mut display = DustString::new(); let mut display = DustString::new();
match self { match self {
@ -53,7 +53,7 @@ impl AbstractValue {
display.push_str(", "); display.push_str(", ");
} }
let item_display = vm.follow_pointer(*item).display(vm)?; let item_display = vm.follow_pointer(*item).display(vm);
display.push_str(&item_display); display.push_str(&item_display);
} }
@ -62,7 +62,7 @@ impl AbstractValue {
} }
} }
Ok(display) display
} }
pub fn r#type(&self) -> Type { pub fn r#type(&self) -> Type {

View File

@ -47,7 +47,7 @@ impl ConcreteValue {
} }
} }
pub fn to_dust_string(&self) -> DustString { pub fn display(&self) -> DustString {
DustString::from(self.to_string()) DustString::from(self.to_string())
} }

View File

@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};
use std::fmt::{self, Debug, Display, Formatter}; use std::fmt::{self, Debug, Display, Formatter};
use crate::{Type, Vm, VmError}; use crate::{Type, Vm};
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub enum Value { pub enum Value {
@ -20,7 +20,7 @@ pub enum Value {
} }
impl Value { impl Value {
pub fn into_concrete_owned(self, vm: &Vm) -> ConcreteValue { pub fn into_concrete_owned<'a>(self, vm: &'a Vm<'a>) -> ConcreteValue {
match self { match self {
Value::Abstract(abstract_value) => abstract_value.to_concrete_owned(vm), Value::Abstract(abstract_value) => abstract_value.to_concrete_owned(vm),
Value::Concrete(concrete_value) => concrete_value, Value::Concrete(concrete_value) => concrete_value,
@ -132,10 +132,10 @@ impl Value {
} }
} }
pub fn display(&self, vm: &Vm) -> Result<DustString, VmError> { pub fn display(&self, vm: &Vm) -> DustString {
match self { match self {
Value::Abstract(abstract_value) => abstract_value.to_dust_string(vm), Value::Abstract(abstract_value) => abstract_value.display(vm),
Value::Concrete(concrete_value) => Ok(concrete_value.to_dust_string()), Value::Concrete(concrete_value) => concrete_value.display(),
} }
} }
} }

View File

@ -1,23 +1,15 @@
//! Virtual machine and errors //! Virtual machine and errors
mod runners; mod runner;
use std::{ use std::fmt::{self, Display, Formatter};
fmt::{self, Display, Formatter},
io, iter,
rc::Rc,
};
use runners::Runner; use runner::Runner;
use smallvec::SmallVec;
use crate::{ use crate::{compile, instruction::*, Chunk, DustError, Span, Value};
compile, instruction::*, AbstractValue, AnnotatedError, Chunk, ConcreteValue, DustError,
NativeFunctionError, Span, Value, ValueError,
};
pub fn run(source: &str) -> Result<Option<Value>, DustError> { pub fn run(source: &str) -> Result<Option<Value>, DustError> {
let chunk = compile(source)?; let chunk = compile(source)?;
let vm = Vm::new(source, &chunk, None, None); let vm = Vm::new(&chunk, None, None);
Ok(vm.run()) Ok(vm.run())
} }
@ -35,17 +27,11 @@ pub struct Vm<'a> {
ip: usize, ip: usize,
last_assigned_register: Option<u8>, last_assigned_register: Option<u8>,
source: &'a str,
return_value: Option<Value>, return_value: Option<Value>,
} }
impl<'a> Vm<'a> { impl<'a> Vm<'a> {
pub fn new( pub fn new(chunk: &'a Chunk, parent: Option<&'a Vm<'a>>, runners: Option<Vec<Runner>>) -> Self {
source: &'a str,
chunk: &'a Chunk,
parent: Option<&'a Vm<'a>>,
runners: Option<Vec<Runner>>,
) -> Self {
let stack = vec![Register::Empty; chunk.stack_size()]; let stack = vec![Register::Empty; chunk.stack_size()];
let runners = runners.unwrap_or_else(|| { let runners = runners.unwrap_or_else(|| {
let mut runners = Vec::with_capacity(chunk.instructions().len()); let mut runners = Vec::with_capacity(chunk.instructions().len());
@ -66,19 +52,14 @@ impl<'a> Vm<'a> {
parent, parent,
ip: 0, ip: 0,
last_assigned_register: None, last_assigned_register: None,
source,
return_value: None, return_value: None,
} }
} }
pub fn chunk(&self) -> &Chunk { pub fn chunk(&'a self) -> &'a Chunk {
self.chunk self.chunk
} }
pub fn source(&self) -> &'a str {
self.source
}
pub fn current_position(&self) -> Span { pub fn current_position(&self) -> Span {
let index = self.ip.saturating_sub(1); let index = self.ip.saturating_sub(1);
let (_, position) = self.chunk.instructions()[index]; let (_, position) = self.chunk.instructions()[index];
@ -87,9 +68,7 @@ impl<'a> Vm<'a> {
} }
pub fn run(mut self) -> Option<Value> { pub fn run(mut self) -> Option<Value> {
while self.ip < self.runners.len() && self.return_value.is_none() { self.execute_next_runner();
self.execute_next_runner();
}
self.return_value self.return_value
} }
@ -189,24 +168,6 @@ impl<'a> Vm<'a> {
} }
} }
/// DRY helper for handling JUMP instructions
fn jump_instructions(&mut self, offset: usize, is_positive: bool) {
log::trace!(
"Jumping {}",
if is_positive {
format!("+{}", offset)
} else {
format!("-{}", offset)
}
);
if is_positive {
self.ip += offset
} else {
self.ip -= offset + 1
}
}
/// DRY helper to get a value from an Argument /// DRY helper to get a value from an Argument
fn get_argument(&self, index: u8, is_constant: bool) -> &Value { fn get_argument(&self, index: u8, is_constant: bool) -> &Value {
if is_constant { if is_constant {
@ -289,165 +250,37 @@ impl Display for Pointer {
} }
} }
#[derive(Clone, Debug, PartialEq)]
pub enum VmError {
// Stack errors
StackOverflow {
position: Span,
},
StackUnderflow {
position: Span,
},
// Register errors
EmptyRegister {
index: usize,
position: Span,
},
ExpectedConcreteValue {
found: AbstractValue,
position: Span,
},
ExpectedValue {
found: Register,
position: Span,
},
RegisterIndexOutOfBounds {
index: usize,
position: Span,
},
// Local errors
UndefinedLocal {
local_index: u8,
position: Span,
},
// Execution errors
ExpectedBoolean {
found: Value,
position: Span,
},
ExpectedFunction {
found: ConcreteValue,
position: Span,
},
ExpectedParent {
position: Span,
},
ValueDisplay {
error: io::ErrorKind,
position: Span,
},
// Chunk errors
ConstantIndexOutOfBounds {
index: usize,
position: Span,
},
InstructionIndexOutOfBounds {
index: usize,
position: Span,
},
LocalIndexOutOfBounds {
index: usize,
position: Span,
},
// Wrappers for foreign errors
NativeFunction(NativeFunctionError),
Value {
error: ValueError,
position: Span,
},
}
impl AnnotatedError for VmError {
fn title() -> &'static str {
"Runtime Error"
}
fn description(&self) -> &'static str {
match self {
Self::ConstantIndexOutOfBounds { .. } => "Constant index out of bounds",
Self::EmptyRegister { .. } => "Empty register",
Self::ExpectedBoolean { .. } => "Expected boolean",
Self::ExpectedConcreteValue { .. } => "Expected concrete value",
Self::ExpectedFunction { .. } => "Expected function",
Self::ExpectedParent { .. } => "Expected parent",
Self::ExpectedValue { .. } => "Expected value",
Self::InstructionIndexOutOfBounds { .. } => "Instruction index out of bounds",
Self::LocalIndexOutOfBounds { .. } => "Local index out of bounds",
Self::NativeFunction(error) => error.description(),
Self::RegisterIndexOutOfBounds { .. } => "Register index out of bounds",
Self::StackOverflow { .. } => "Stack overflow",
Self::StackUnderflow { .. } => "Stack underflow",
Self::UndefinedLocal { .. } => "Undefined local",
Self::Value { .. } => "Value error",
Self::ValueDisplay { .. } => "Value display error",
}
}
fn detail_snippets(&self) -> SmallVec<[(String, Span); 2]> {
match self {
VmError::StackOverflow { position } => todo!(),
VmError::StackUnderflow { position } => todo!(),
VmError::EmptyRegister { index, position } => todo!(),
VmError::ExpectedConcreteValue { found, position } => todo!(),
VmError::ExpectedValue { found, position } => todo!(),
VmError::RegisterIndexOutOfBounds { index, position } => todo!(),
VmError::UndefinedLocal {
local_index,
position,
} => todo!(),
VmError::ExpectedBoolean { found, position } => todo!(),
VmError::ExpectedFunction { found, position } => todo!(),
VmError::ExpectedParent { position } => todo!(),
VmError::ValueDisplay { error, position } => todo!(),
VmError::ConstantIndexOutOfBounds { index, position } => todo!(),
VmError::InstructionIndexOutOfBounds { index, position } => todo!(),
VmError::LocalIndexOutOfBounds { index, position } => todo!(),
VmError::NativeFunction(native_function_error) => todo!(),
VmError::Value { error, position } => todo!(),
}
}
fn help_snippets(&self) -> SmallVec<[(String, Span); 2]> {
todo!()
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use runners::{RunnerLogic, RUNNER_LOGIC_TABLE}; use runner::{RunnerLogic, RUNNER_LOGIC_TABLE};
use super::*; use super::*;
const ALL_OPERATIONS: [(Operation, RunnerLogic); 24] = [ const ALL_OPERATIONS: [(Operation, RunnerLogic); 24] = [
(Operation::MOVE, runners::r#move), (Operation::MOVE, runner::r#move),
(Operation::CLOSE, runners::close), (Operation::CLOSE, runner::close),
(Operation::LOAD_BOOLEAN, runners::load_boolean), (Operation::LOAD_BOOLEAN, runner::load_boolean),
(Operation::LOAD_CONSTANT, runners::load_constant), (Operation::LOAD_CONSTANT, runner::load_constant),
(Operation::LOAD_LIST, runners::load_list), (Operation::LOAD_LIST, runner::load_list),
(Operation::LOAD_SELF, runners::load_self), (Operation::LOAD_SELF, runner::load_self),
(Operation::GET_LOCAL, runners::get_local), (Operation::GET_LOCAL, runner::get_local),
(Operation::SET_LOCAL, runners::set_local), (Operation::SET_LOCAL, runner::set_local),
(Operation::ADD, runners::add), (Operation::ADD, runner::add),
(Operation::SUBTRACT, runners::subtract), (Operation::SUBTRACT, runner::subtract),
(Operation::MULTIPLY, runners::multiply), (Operation::MULTIPLY, runner::multiply),
(Operation::DIVIDE, runners::divide), (Operation::DIVIDE, runner::divide),
(Operation::MODULO, runners::modulo), (Operation::MODULO, runner::modulo),
(Operation::TEST, runners::test), (Operation::TEST, runner::test),
(Operation::TEST_SET, runners::test_set), (Operation::TEST_SET, runner::test_set),
(Operation::EQUAL, runners::equal), (Operation::EQUAL, runner::equal),
(Operation::LESS, runners::less), (Operation::LESS, runner::less),
(Operation::LESS_EQUAL, runners::less_equal), (Operation::LESS_EQUAL, runner::less_equal),
(Operation::NEGATE, runners::negate), (Operation::NEGATE, runner::negate),
(Operation::NOT, runners::not), (Operation::NOT, runner::not),
(Operation::CALL, runners::call), (Operation::CALL, runner::call),
(Operation::CALL_NATIVE, runners::call_native), (Operation::CALL_NATIVE, runner::call_native),
(Operation::JUMP, runners::jump), (Operation::JUMP, runner::jump),
(Operation::RETURN, runners::r#return), (Operation::RETURN, runner::r#return),
]; ];
#[test] #[test]

View File

@ -1,5 +1,3 @@
use std::{borrow::BorrowMut, cell::RefCell, rc::Rc};
use smallvec::SmallVec; use smallvec::SmallVec;
use crate::{AbstractValue, ConcreteValue, NativeFunction, Type, Value}; use crate::{AbstractValue, ConcreteValue, NativeFunction, Type, Value};
@ -24,7 +22,7 @@ impl Runner {
Self { logic, data } Self { logic, data }
} }
pub fn run(&self, vm: &mut Vm) { pub fn run(self, vm: &mut Vm) {
(self.logic)(vm, self.data); (self.logic)(vm, self.data);
} }
} }
@ -75,8 +73,7 @@ pub fn r#move(vm: &mut Vm, instruction_data: InstructionData) {
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn close(vm: &mut Vm, instruction_data: InstructionData) {
pub fn close<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { b, c, .. } = instruction_data; let InstructionData { b, c, .. } = instruction_data;
assert!(b < c, "Runtime Error: Malformed instruction"); assert!(b < c, "Runtime Error: Malformed instruction");
@ -95,8 +92,7 @@ pub fn close<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn load_boolean(vm: &mut Vm, instruction_data: InstructionData) {
pub fn load_boolean<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { a, b, c, .. } = instruction_data; let InstructionData { a, b, c, .. } = instruction_data;
let boolean = ConcreteValue::Boolean(b != 0).to_value(); let boolean = ConcreteValue::Boolean(b != 0).to_value();
let register = Register::Value(boolean); let register = Register::Value(boolean);
@ -112,8 +108,7 @@ pub fn load_boolean<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionDat
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn load_constant(vm: &mut Vm, instruction_data: InstructionData) {
pub fn load_constant<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { a, b, c, .. } = instruction_data; let InstructionData { a, b, c, .. } = instruction_data;
let register = Register::Pointer(Pointer::Constant(b)); let register = Register::Pointer(Pointer::Constant(b));
@ -128,8 +123,7 @@ pub fn load_constant<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionDa
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn load_list(vm: &mut Vm, instruction_data: InstructionData) {
pub fn load_list<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { a, b, .. } = instruction_data; let InstructionData { a, b, .. } = instruction_data;
let mut item_pointers = Vec::with_capacity((a - b) as usize); let mut item_pointers = Vec::with_capacity((a - b) as usize);
let stack = vm.stack.as_slice(); let stack = vm.stack.as_slice();
@ -155,11 +149,10 @@ pub fn load_list<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData)
item_pointers.push(pointer); item_pointers.push(pointer);
} }
let list_value = AbstractValue::List { let list_value = Value::Abstract(AbstractValue::List {
item_type, item_type,
item_pointers, item_pointers,
} });
.to_value();
let register = Register::Value(list_value); let register = Register::Value(list_value);
vm.set_register(a, register); vm.set_register(a, register);
@ -169,8 +162,7 @@ pub fn load_list<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData)
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn load_self(vm: &mut Vm, instruction_data: InstructionData) {
pub fn load_self<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { a, .. } = instruction_data; let InstructionData { a, .. } = instruction_data;
let register = Register::Value(AbstractValue::FunctionSelf.to_value()); let register = Register::Value(AbstractValue::FunctionSelf.to_value());
@ -181,8 +173,7 @@ pub fn load_self<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData)
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn get_local(vm: &mut Vm, instruction_data: InstructionData) {
pub fn get_local<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { a, b, .. } = instruction_data; let InstructionData { a, b, .. } = instruction_data;
let local_register_index = vm.get_local_register(b); let local_register_index = vm.get_local_register(b);
let register = Register::Pointer(Pointer::Stack(local_register_index)); let register = Register::Pointer(Pointer::Stack(local_register_index));
@ -194,8 +185,7 @@ pub fn get_local<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData)
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn set_local(vm: &mut Vm, instruction_data: InstructionData) {
pub fn set_local<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { b, c, .. } = instruction_data; let InstructionData { b, c, .. } = instruction_data;
let local_register_index = vm.get_local_register(c); let local_register_index = vm.get_local_register(c);
let register = Register::Pointer(Pointer::Stack(b)); let register = Register::Pointer(Pointer::Stack(b));
@ -207,8 +197,7 @@ pub fn set_local<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData)
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn add(vm: &mut Vm, instruction_data: InstructionData) {
pub fn add<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { let InstructionData {
a, a,
b, b,
@ -237,8 +226,7 @@ pub fn add<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn subtract(vm: &mut Vm, instruction_data: InstructionData) {
pub fn subtract<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { let InstructionData {
a, a,
b, b,
@ -267,8 +255,7 @@ pub fn subtract<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn multiply(vm: &mut Vm, instruction_data: InstructionData) {
pub fn multiply<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { let InstructionData {
a, a,
b, b,
@ -297,8 +284,7 @@ pub fn multiply<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn divide(vm: &mut Vm, instruction_data: InstructionData) {
pub fn divide<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { let InstructionData {
a, a,
b, b,
@ -327,8 +313,7 @@ pub fn divide<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn modulo(vm: &mut Vm, instruction_data: InstructionData) {
pub fn modulo<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { let InstructionData {
a, a,
b, b,
@ -357,8 +342,7 @@ pub fn modulo<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn test(vm: &mut Vm, instruction_data: InstructionData) {
pub fn test<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { let InstructionData {
b, b,
b_is_constant, b_is_constant,
@ -385,8 +369,7 @@ pub fn test<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn test_set(vm: &mut Vm, instruction_data: InstructionData) {
pub fn test_set<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { let InstructionData {
a, a,
b, b,
@ -423,8 +406,7 @@ pub fn test_set<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn equal(vm: &mut Vm, instruction_data: InstructionData) {
pub fn equal<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { let InstructionData {
b, b,
c, c,
@ -468,8 +450,7 @@ pub fn less(vm: &mut Vm, instruction_data: InstructionData) {
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn less_equal(vm: &mut Vm, instruction_data: InstructionData) {
pub fn less_equal<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { let InstructionData {
b, b,
c, c,
@ -491,8 +472,7 @@ pub fn less_equal<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData)
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn negate(vm: &mut Vm, instruction_data: InstructionData) {
pub fn negate<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { let InstructionData {
a, a,
b, b,
@ -517,8 +497,7 @@ pub fn negate<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn not(vm: &mut Vm, instruction_data: InstructionData) {
pub fn not<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { let InstructionData {
a, a,
b, b,
@ -539,8 +518,7 @@ pub fn not<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn jump(vm: &mut Vm, instruction_data: InstructionData) {
pub fn jump<'c>(vm: &mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { b, c, .. } = instruction_data; let InstructionData { b, c, .. } = instruction_data;
let offset = b as usize; let offset = b as usize;
let is_positive = c != 0; let is_positive = c != 0;
@ -554,8 +532,7 @@ pub fn jump<'c>(vm: &mut Vm<'c>, instruction_data: InstructionData) {
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn call(vm: &mut Vm<'_>, instruction_data: InstructionData) {
pub fn call<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { let InstructionData {
a, a,
b, b,
@ -565,9 +542,9 @@ pub fn call<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
} = instruction_data; } = instruction_data;
let function = vm.get_argument(b, b_is_constant); let function = vm.get_argument(b, b_is_constant);
let mut function_vm = if let Value::Concrete(ConcreteValue::Function(chunk)) = function { let mut function_vm = if let Value::Concrete(ConcreteValue::Function(chunk)) = function {
Vm::new(vm.source, chunk, Some(vm), None) Vm::new(chunk, Some(vm), None)
} else if let Value::Abstract(AbstractValue::FunctionSelf) = function { } else if let Value::Abstract(AbstractValue::FunctionSelf) = function {
Vm::new(vm.source, vm.chunk, Some(vm), Some(vm.runners.clone())) Vm::new(vm.chunk, Some(vm), Some(vm.runners.clone()))
} else { } else {
panic!("VM Error: Expected function") panic!("VM Error: Expected function")
}; };
@ -603,8 +580,7 @@ pub fn call<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn call_native(vm: &mut Vm, instruction_data: InstructionData) {
pub fn call_native<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { a, b, c, .. } = instruction_data; let InstructionData { a, b, c, .. } = instruction_data;
let first_argument_index = (a - c) as usize; let first_argument_index = (a - c) as usize;
let argument_range = first_argument_index..a as usize; let argument_range = first_argument_index..a as usize;
@ -642,8 +618,7 @@ pub fn call_native<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData
vm.execute_next_runner(); vm.execute_next_runner();
} }
#[allow(clippy::needless_lifetimes)] pub fn r#return(vm: &mut Vm, instruction_data: InstructionData) {
pub fn r#return<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let should_return_value = instruction_data.b != 0; let should_return_value = instruction_data.b != 0;
if !should_return_value { if !should_return_value {