Make more optimizations to the VM
This commit is contained in:
parent
ec5033a32f
commit
9d544d789c
@ -199,7 +199,7 @@ fn main() {
|
||||
let chunk = compiler.finish(None, None);
|
||||
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 run_end = start_time.elapsed();
|
||||
|
||||
|
@ -17,7 +17,7 @@ use std::io::Write;
|
||||
use serde::{Deserialize, Serialize};
|
||||
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.
|
||||
///
|
||||
|
@ -5,7 +5,7 @@ use std::fmt::{self, Display, Formatter};
|
||||
use annotate_snippets::{Level, Renderer, Snippet};
|
||||
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.
|
||||
#[derive(Debug, PartialEq)]
|
||||
@ -14,10 +14,6 @@ pub enum DustError<'src> {
|
||||
error: CompileError,
|
||||
source: &'src str,
|
||||
},
|
||||
Runtime {
|
||||
error: VmError,
|
||||
source: &'src str,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'src> DustError<'src> {
|
||||
@ -25,10 +21,6 @@ impl<'src> DustError<'src> {
|
||||
DustError::Compile { error, source }
|
||||
}
|
||||
|
||||
pub fn runtime(error: VmError, source: &'src str) -> Self {
|
||||
DustError::Runtime { error, source }
|
||||
}
|
||||
|
||||
pub fn report(&self) -> String {
|
||||
let (title, description, detail_snippets, help_snippets) = self.error_data();
|
||||
let label = format!("{}: {}", title, description);
|
||||
@ -65,19 +57,12 @@ impl<'src> DustError<'src> {
|
||||
error.detail_snippets(),
|
||||
error.help_snippets(),
|
||||
),
|
||||
Self::Runtime { error, .. } => (
|
||||
VmError::title(),
|
||||
error.description(),
|
||||
error.detail_snippets(),
|
||||
error.help_snippets(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn source(&self) -> &str {
|
||||
match self {
|
||||
Self::Compile { source, .. } => source,
|
||||
Self::Runtime { source, .. } => source,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ pub use crate::native_function::{NativeFunction, NativeFunctionError};
|
||||
pub use crate::r#type::{EnumType, FunctionType, StructType, Type, TypeConflict};
|
||||
pub use crate::token::{Token, TokenKind, TokenOwned};
|
||||
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;
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
use std::panic;
|
||||
|
||||
use annotate_snippets::{Level, Renderer, Snippet};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::{DustString, NativeFunctionError, Value, Vm};
|
||||
@ -12,10 +11,7 @@ pub fn panic(
|
||||
let mut message: Option<DustString> = None;
|
||||
|
||||
for value_ref in arguments {
|
||||
let string = match value_ref.display(vm) {
|
||||
Ok(string) => string,
|
||||
Err(error) => return Err(NativeFunctionError::Vm(Box::new(error))),
|
||||
};
|
||||
let string = value_ref.display(vm);
|
||||
|
||||
match message {
|
||||
Some(ref mut message) => message.push_str(&string),
|
||||
@ -23,24 +19,9 @@ pub fn panic(
|
||||
}
|
||||
}
|
||||
|
||||
let position = vm.current_position();
|
||||
let error_output = Level::Error.title("Explicit Panic").snippet(
|
||||
Snippet::source(vm.source()).fold(false).annotation(
|
||||
Level::Error
|
||||
.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);
|
||||
if let Some(message) = message {
|
||||
panic!("{message}");
|
||||
} else {
|
||||
panic!("Explicit panic");
|
||||
}
|
||||
}));
|
||||
|
||||
panic!();
|
||||
}
|
||||
|
@ -29,10 +29,7 @@ pub fn write(
|
||||
let mut stdout = stdout();
|
||||
|
||||
for argument in arguments {
|
||||
let string = match argument.display(vm) {
|
||||
Ok(string) => string,
|
||||
Err(error) => return Err(NativeFunctionError::Vm(Box::new(error))),
|
||||
};
|
||||
let string = argument.display(vm);
|
||||
|
||||
stdout
|
||||
.write_all(string.as_bytes())
|
||||
@ -52,10 +49,7 @@ pub fn write_line(
|
||||
let mut stdout = stdout();
|
||||
|
||||
for argument in arguments {
|
||||
let string = match argument.display(vm) {
|
||||
Ok(string) => string,
|
||||
Err(error) => return Err(NativeFunctionError::Vm(Box::new(error))),
|
||||
};
|
||||
let string = argument.display(vm);
|
||||
|
||||
stdout
|
||||
.write_all(string.as_bytes())
|
||||
|
@ -15,7 +15,7 @@ use std::{
|
||||
use serde::{Deserialize, Serialize};
|
||||
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 {
|
||||
($(($name:ident, $bytes:literal, $str:expr, $type:expr, $function:expr)),*) => {
|
||||
@ -30,9 +30,9 @@ macro_rules! define_native_function {
|
||||
}
|
||||
|
||||
impl NativeFunction {
|
||||
pub fn call<'a>(
|
||||
pub fn call(
|
||||
&self,
|
||||
vm: &Vm<'a>,
|
||||
vm: &Vm<'_>,
|
||||
arguments: SmallVec<[&Value; 4]>,
|
||||
) -> Result<Option<Value>, NativeFunctionError> {
|
||||
match self {
|
||||
@ -269,7 +269,6 @@ pub enum NativeFunctionError {
|
||||
error: IoErrorKind,
|
||||
position: Span,
|
||||
},
|
||||
Vm(Box<VmError>),
|
||||
}
|
||||
|
||||
impl AnnotatedError for NativeFunctionError {
|
||||
@ -285,7 +284,6 @@ impl AnnotatedError for NativeFunctionError {
|
||||
NativeFunctionError::Panic { .. } => "Explicit panic",
|
||||
NativeFunctionError::Parse { .. } => "Failed to parse value",
|
||||
NativeFunctionError::Io { .. } => "I/O error",
|
||||
NativeFunctionError::Vm(error) => error.description(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,10 +14,7 @@ pub fn to_string(
|
||||
});
|
||||
}
|
||||
|
||||
let argument_string = match arguments[0].display(vm) {
|
||||
Ok(string) => string,
|
||||
Err(error) => return Err(NativeFunctionError::Vm(Box::new(error))),
|
||||
};
|
||||
let argument_string = arguments[0].display(vm);
|
||||
|
||||
Ok(Some(Value::Concrete(ConcreteValue::string(
|
||||
argument_string,
|
||||
|
@ -1,6 +1,6 @@
|
||||
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)]
|
||||
pub enum AbstractValue {
|
||||
@ -16,7 +16,7 @@ impl AbstractValue {
|
||||
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 {
|
||||
AbstractValue::FunctionSelf => ConcreteValue::function(vm.chunk().clone()),
|
||||
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();
|
||||
|
||||
match self {
|
||||
@ -53,7 +53,7 @@ impl AbstractValue {
|
||||
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);
|
||||
}
|
||||
@ -62,7 +62,7 @@ impl AbstractValue {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(display)
|
||||
display
|
||||
}
|
||||
|
||||
pub fn r#type(&self) -> Type {
|
||||
|
@ -47,7 +47,7 @@ impl ConcreteValue {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_dust_string(&self) -> DustString {
|
||||
pub fn display(&self) -> DustString {
|
||||
DustString::from(self.to_string())
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use std::fmt::{self, Debug, Display, Formatter};
|
||||
|
||||
use crate::{Type, Vm, VmError};
|
||||
use crate::{Type, Vm};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
pub enum Value {
|
||||
@ -20,7 +20,7 @@ pub enum 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 {
|
||||
Value::Abstract(abstract_value) => abstract_value.to_concrete_owned(vm),
|
||||
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 {
|
||||
Value::Abstract(abstract_value) => abstract_value.to_dust_string(vm),
|
||||
Value::Concrete(concrete_value) => Ok(concrete_value.to_dust_string()),
|
||||
Value::Abstract(abstract_value) => abstract_value.display(vm),
|
||||
Value::Concrete(concrete_value) => concrete_value.display(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,15 @@
|
||||
//! Virtual machine and errors
|
||||
mod runners;
|
||||
mod runner;
|
||||
|
||||
use std::{
|
||||
fmt::{self, Display, Formatter},
|
||||
io, iter,
|
||||
rc::Rc,
|
||||
};
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
use runners::Runner;
|
||||
use smallvec::SmallVec;
|
||||
use runner::Runner;
|
||||
|
||||
use crate::{
|
||||
compile, instruction::*, AbstractValue, AnnotatedError, Chunk, ConcreteValue, DustError,
|
||||
NativeFunctionError, Span, Value, ValueError,
|
||||
};
|
||||
use crate::{compile, instruction::*, Chunk, DustError, Span, Value};
|
||||
|
||||
pub fn run(source: &str) -> Result<Option<Value>, DustError> {
|
||||
let chunk = compile(source)?;
|
||||
let vm = Vm::new(source, &chunk, None, None);
|
||||
let vm = Vm::new(&chunk, None, None);
|
||||
|
||||
Ok(vm.run())
|
||||
}
|
||||
@ -35,17 +27,11 @@ pub struct Vm<'a> {
|
||||
|
||||
ip: usize,
|
||||
last_assigned_register: Option<u8>,
|
||||
source: &'a str,
|
||||
return_value: Option<Value>,
|
||||
}
|
||||
|
||||
impl<'a> Vm<'a> {
|
||||
pub fn new(
|
||||
source: &'a str,
|
||||
chunk: &'a Chunk,
|
||||
parent: Option<&'a Vm<'a>>,
|
||||
runners: Option<Vec<Runner>>,
|
||||
) -> Self {
|
||||
pub fn new(chunk: &'a Chunk, parent: Option<&'a Vm<'a>>, runners: Option<Vec<Runner>>) -> Self {
|
||||
let stack = vec![Register::Empty; chunk.stack_size()];
|
||||
let runners = runners.unwrap_or_else(|| {
|
||||
let mut runners = Vec::with_capacity(chunk.instructions().len());
|
||||
@ -66,19 +52,14 @@ impl<'a> Vm<'a> {
|
||||
parent,
|
||||
ip: 0,
|
||||
last_assigned_register: None,
|
||||
source,
|
||||
return_value: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chunk(&self) -> &Chunk {
|
||||
pub fn chunk(&'a self) -> &'a Chunk {
|
||||
self.chunk
|
||||
}
|
||||
|
||||
pub fn source(&self) -> &'a str {
|
||||
self.source
|
||||
}
|
||||
|
||||
pub fn current_position(&self) -> Span {
|
||||
let index = self.ip.saturating_sub(1);
|
||||
let (_, position) = self.chunk.instructions()[index];
|
||||
@ -87,9 +68,7 @@ impl<'a> Vm<'a> {
|
||||
}
|
||||
|
||||
pub fn run(mut self) -> Option<Value> {
|
||||
while self.ip < self.runners.len() && self.return_value.is_none() {
|
||||
self.execute_next_runner();
|
||||
}
|
||||
|
||||
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
|
||||
fn get_argument(&self, index: u8, is_constant: bool) -> &Value {
|
||||
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)]
|
||||
mod tests {
|
||||
use runners::{RunnerLogic, RUNNER_LOGIC_TABLE};
|
||||
use runner::{RunnerLogic, RUNNER_LOGIC_TABLE};
|
||||
|
||||
use super::*;
|
||||
|
||||
const ALL_OPERATIONS: [(Operation, RunnerLogic); 24] = [
|
||||
(Operation::MOVE, runners::r#move),
|
||||
(Operation::CLOSE, runners::close),
|
||||
(Operation::LOAD_BOOLEAN, runners::load_boolean),
|
||||
(Operation::LOAD_CONSTANT, runners::load_constant),
|
||||
(Operation::LOAD_LIST, runners::load_list),
|
||||
(Operation::LOAD_SELF, runners::load_self),
|
||||
(Operation::GET_LOCAL, runners::get_local),
|
||||
(Operation::SET_LOCAL, runners::set_local),
|
||||
(Operation::ADD, runners::add),
|
||||
(Operation::SUBTRACT, runners::subtract),
|
||||
(Operation::MULTIPLY, runners::multiply),
|
||||
(Operation::DIVIDE, runners::divide),
|
||||
(Operation::MODULO, runners::modulo),
|
||||
(Operation::TEST, runners::test),
|
||||
(Operation::TEST_SET, runners::test_set),
|
||||
(Operation::EQUAL, runners::equal),
|
||||
(Operation::LESS, runners::less),
|
||||
(Operation::LESS_EQUAL, runners::less_equal),
|
||||
(Operation::NEGATE, runners::negate),
|
||||
(Operation::NOT, runners::not),
|
||||
(Operation::CALL, runners::call),
|
||||
(Operation::CALL_NATIVE, runners::call_native),
|
||||
(Operation::JUMP, runners::jump),
|
||||
(Operation::RETURN, runners::r#return),
|
||||
(Operation::MOVE, runner::r#move),
|
||||
(Operation::CLOSE, runner::close),
|
||||
(Operation::LOAD_BOOLEAN, runner::load_boolean),
|
||||
(Operation::LOAD_CONSTANT, runner::load_constant),
|
||||
(Operation::LOAD_LIST, runner::load_list),
|
||||
(Operation::LOAD_SELF, runner::load_self),
|
||||
(Operation::GET_LOCAL, runner::get_local),
|
||||
(Operation::SET_LOCAL, runner::set_local),
|
||||
(Operation::ADD, runner::add),
|
||||
(Operation::SUBTRACT, runner::subtract),
|
||||
(Operation::MULTIPLY, runner::multiply),
|
||||
(Operation::DIVIDE, runner::divide),
|
||||
(Operation::MODULO, runner::modulo),
|
||||
(Operation::TEST, runner::test),
|
||||
(Operation::TEST_SET, runner::test_set),
|
||||
(Operation::EQUAL, runner::equal),
|
||||
(Operation::LESS, runner::less),
|
||||
(Operation::LESS_EQUAL, runner::less_equal),
|
||||
(Operation::NEGATE, runner::negate),
|
||||
(Operation::NOT, runner::not),
|
||||
(Operation::CALL, runner::call),
|
||||
(Operation::CALL_NATIVE, runner::call_native),
|
||||
(Operation::JUMP, runner::jump),
|
||||
(Operation::RETURN, runner::r#return),
|
||||
];
|
||||
|
||||
#[test]
|
||||
|
@ -1,5 +1,3 @@
|
||||
use std::{borrow::BorrowMut, cell::RefCell, rc::Rc};
|
||||
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::{AbstractValue, ConcreteValue, NativeFunction, Type, Value};
|
||||
@ -24,7 +22,7 @@ impl Runner {
|
||||
Self { logic, data }
|
||||
}
|
||||
|
||||
pub fn run(&self, vm: &mut Vm) {
|
||||
pub fn run(self, vm: &mut Vm) {
|
||||
(self.logic)(vm, self.data);
|
||||
}
|
||||
}
|
||||
@ -75,8 +73,7 @@ pub fn r#move(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn close<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn close(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData { b, c, .. } = instruction_data;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn load_boolean<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn load_boolean(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData { a, b, c, .. } = instruction_data;
|
||||
let boolean = ConcreteValue::Boolean(b != 0).to_value();
|
||||
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();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn load_constant<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn load_constant(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData { a, b, c, .. } = instruction_data;
|
||||
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();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn load_list<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn load_list(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData { a, b, .. } = instruction_data;
|
||||
let mut item_pointers = Vec::with_capacity((a - b) as usize);
|
||||
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);
|
||||
}
|
||||
|
||||
let list_value = AbstractValue::List {
|
||||
let list_value = Value::Abstract(AbstractValue::List {
|
||||
item_type,
|
||||
item_pointers,
|
||||
}
|
||||
.to_value();
|
||||
});
|
||||
let register = Register::Value(list_value);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn load_self<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn load_self(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData { a, .. } = instruction_data;
|
||||
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();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn get_local<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn get_local(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData { a, b, .. } = instruction_data;
|
||||
let local_register_index = vm.get_local_register(b);
|
||||
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();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn set_local<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn set_local(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData { b, c, .. } = instruction_data;
|
||||
let local_register_index = vm.get_local_register(c);
|
||||
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();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn add<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn add(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData {
|
||||
a,
|
||||
b,
|
||||
@ -237,8 +226,7 @@ pub fn add<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn subtract<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn subtract(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData {
|
||||
a,
|
||||
b,
|
||||
@ -267,8 +255,7 @@ pub fn subtract<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn multiply<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn multiply(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData {
|
||||
a,
|
||||
b,
|
||||
@ -297,8 +284,7 @@ pub fn multiply<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn divide<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn divide(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData {
|
||||
a,
|
||||
b,
|
||||
@ -327,8 +313,7 @@ pub fn divide<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn modulo<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn modulo(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData {
|
||||
a,
|
||||
b,
|
||||
@ -357,8 +342,7 @@ pub fn modulo<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn test<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn test(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData {
|
||||
b,
|
||||
b_is_constant,
|
||||
@ -385,8 +369,7 @@ pub fn test<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn test_set<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn test_set(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData {
|
||||
a,
|
||||
b,
|
||||
@ -423,8 +406,7 @@ pub fn test_set<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn equal<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn equal(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData {
|
||||
b,
|
||||
c,
|
||||
@ -468,8 +450,7 @@ pub fn less(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn less_equal<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn less_equal(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData {
|
||||
b,
|
||||
c,
|
||||
@ -491,8 +472,7 @@ pub fn less_equal<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData)
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn negate<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn negate(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData {
|
||||
a,
|
||||
b,
|
||||
@ -517,8 +497,7 @@ pub fn negate<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn not<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn not(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData {
|
||||
a,
|
||||
b,
|
||||
@ -539,8 +518,7 @@ pub fn not<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn jump<'c>(vm: &mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn jump(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData { b, c, .. } = instruction_data;
|
||||
let offset = b as usize;
|
||||
let is_positive = c != 0;
|
||||
@ -554,8 +532,7 @@ pub fn jump<'c>(vm: &mut Vm<'c>, instruction_data: InstructionData) {
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn call<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn call(vm: &mut Vm<'_>, instruction_data: InstructionData) {
|
||||
let InstructionData {
|
||||
a,
|
||||
b,
|
||||
@ -565,9 +542,9 @@ pub fn call<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
} = instruction_data;
|
||||
let function = vm.get_argument(b, b_is_constant);
|
||||
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 {
|
||||
Vm::new(vm.source, vm.chunk, Some(vm), Some(vm.runners.clone()))
|
||||
Vm::new(vm.chunk, Some(vm), Some(vm.runners.clone()))
|
||||
} else {
|
||||
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();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn call_native<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn call_native(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData { a, b, c, .. } = instruction_data;
|
||||
let first_argument_index = (a - c) 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();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn r#return<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn r#return(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let should_return_value = instruction_data.b != 0;
|
||||
|
||||
if !should_return_value {
|
Loading…
Reference in New Issue
Block a user