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 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();
|
||||||
|
|
||||||
|
@ -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.
|
||||||
///
|
///
|
||||||
|
@ -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,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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!();
|
|
||||||
}
|
}
|
||||||
|
@ -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())
|
||||||
|
@ -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(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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 {
|
||||||
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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]
|
||||||
|
@ -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 {
|
Loading…
Reference in New Issue
Block a user