1
0

Continue VM optimizations

This commit is contained in:
Jeff 2024-12-14 08:49:02 -05:00
parent cd4fa6bef5
commit ec5033a32f
13 changed files with 175 additions and 239 deletions

View File

@ -46,7 +46,7 @@ use std::{
use colored::{ColoredString, Colorize}; use colored::{ColoredString, Colorize};
use crate::{value::ConcreteValue, Chunk, Local}; use crate::{value::ConcreteValue, Chunk, Local, Value};
const INSTRUCTION_COLUMNS: [(&str, usize); 4] = const INSTRUCTION_COLUMNS: [(&str, usize); 4] =
[("i", 5), ("POSITION", 12), ("OPERATION", 17), ("INFO", 24)]; [("i", 5), ("POSITION", 12), ("OPERATION", 17), ("INFO", 24)];
@ -336,7 +336,7 @@ impl<'a, W: Write> Disassembler<'a, W> {
self.write_centered_with_border(CONSTANT_BORDERS[1])?; self.write_centered_with_border(CONSTANT_BORDERS[1])?;
for (index, value) in self.chunk.constants().iter().enumerate() { for (index, value) in self.chunk.constants().iter().enumerate() {
let is_function = matches!(value, ConcreteValue::Function(_)); let is_function = matches!(value, Value::Concrete(ConcreteValue::Function(_)));
let type_display = value.r#type().to_string(); let type_display = value.r#type().to_string();
let value_display = if is_function { let value_display = if is_function {
"Function displayed below".to_string() "Function displayed below".to_string()
@ -353,7 +353,7 @@ impl<'a, W: Write> Disassembler<'a, W> {
self.write_centered_with_border(&constant_display)?; self.write_centered_with_border(&constant_display)?;
if let ConcreteValue::Function(chunk) = value { if let Value::Concrete(ConcreteValue::Function(chunk)) = value {
let function_disassembler = chunk let function_disassembler = chunk
.disassembler(self.writer) .disassembler(self.writer)
.style(self.style) .style(self.style)

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}; use crate::{ConcreteValue, DustString, FunctionType, Instruction, Span, Value};
/// In-memory representation of a Dust program or function. /// In-memory representation of a Dust program or function.
/// ///
@ -28,7 +28,7 @@ pub struct Chunk {
r#type: FunctionType, r#type: FunctionType,
instructions: SmallVec<[(Instruction, Span); 32]>, instructions: SmallVec<[(Instruction, Span); 32]>,
constants: SmallVec<[ConcreteValue; 16]>, constants: SmallVec<[Value; 16]>,
locals: SmallVec<[Local; 8]>, locals: SmallVec<[Local; 8]>,
stack_size: usize, stack_size: usize,
@ -39,7 +39,7 @@ impl Chunk {
name: Option<DustString>, name: Option<DustString>,
r#type: FunctionType, r#type: FunctionType,
instructions: SmallVec<[(Instruction, Span); 32]>, instructions: SmallVec<[(Instruction, Span); 32]>,
constants: SmallVec<[ConcreteValue; 16]>, constants: SmallVec<[Value; 16]>,
locals: SmallVec<[Local; 8]>, locals: SmallVec<[Local; 8]>,
stack_size: usize, stack_size: usize,
) -> Self { ) -> Self {
@ -57,7 +57,7 @@ impl Chunk {
name: Option<DustString>, name: Option<DustString>,
r#type: FunctionType, r#type: FunctionType,
instructions: impl Into<SmallVec<[(Instruction, Span); 32]>>, instructions: impl Into<SmallVec<[(Instruction, Span); 32]>>,
constants: impl Into<SmallVec<[ConcreteValue; 16]>>, constants: impl Into<SmallVec<[Value; 16]>>,
locals: impl Into<SmallVec<[Local; 8]>>, locals: impl Into<SmallVec<[Local; 8]>>,
) -> Self { ) -> Self {
Self { Self {
@ -82,7 +82,7 @@ impl Chunk {
self.instructions.is_empty() self.instructions.is_empty()
} }
pub fn constants(&self) -> &SmallVec<[ConcreteValue; 16]> { pub fn constants(&self) -> &SmallVec<[Value; 16]> {
&self.constants &self.constants
} }

View File

@ -24,7 +24,7 @@ use crate::{
Not, Return, SetLocal, Test, Not, Return, SetLocal, Test,
}, },
Argument, Chunk, ConcreteValue, DustError, DustString, FunctionType, Instruction, Lexer, Local, Argument, Chunk, ConcreteValue, DustError, DustString, FunctionType, Instruction, Lexer, Local,
NativeFunction, Operation, Scope, Span, Token, TokenKind, Type, NativeFunction, Operation, Scope, Span, Token, TokenKind, Type, Value,
}; };
/// Compiles the input and returns a chunk. /// Compiles the input and returns a chunk.
@ -58,7 +58,7 @@ pub fn compile(source: &str) -> Result<Chunk, DustError> {
pub struct Compiler<'src> { pub struct Compiler<'src> {
self_name: Option<DustString>, self_name: Option<DustString>,
instructions: SmallVec<[(Instruction, Type, Span); 32]>, instructions: SmallVec<[(Instruction, Type, Span); 32]>,
constants: SmallVec<[ConcreteValue; 16]>, constants: SmallVec<[Value; 16]>,
locals: SmallVec<[(Local, Type); 8]>, locals: SmallVec<[(Local, Type); 8]>,
stack_size: usize, stack_size: usize,
@ -203,11 +203,12 @@ impl<'src> Compiler<'src> {
.rev() .rev()
.find_map(|(index, (local, _))| { .find_map(|(index, (local, _))| {
let constant = self.constants.get(local.identifier_index as usize)?; let constant = self.constants.get(local.identifier_index as usize)?;
let identifier = if let ConcreteValue::String(identifier) = constant { let identifier =
identifier if let Value::Concrete(ConcreteValue::String(identifier)) = constant {
} else { identifier
return None; } else {
}; return None;
};
if identifier == identifier_text { if identifier == identifier_text {
Some(index as u8) Some(index as u8)
@ -231,7 +232,7 @@ impl<'src> Compiler<'src> {
) -> (u8, u8) { ) -> (u8, u8) {
log::info!("Declaring local {identifier}"); log::info!("Declaring local {identifier}");
let identifier = ConcreteValue::string(identifier); let identifier = Value::Concrete(ConcreteValue::string(identifier));
let identifier_index = self.push_or_get_constant(identifier); let identifier_index = self.push_or_get_constant(identifier);
let local_index = self.locals.len() as u8; let local_index = self.locals.len() as u8;
@ -253,7 +254,7 @@ impl<'src> Compiler<'src> {
}) })
} }
fn push_or_get_constant(&mut self, value: ConcreteValue) -> u8 { fn push_or_get_constant(&mut self, value: Value) -> u8 {
if let Some(index) = self if let Some(index) = self
.constants .constants
.iter() .iter()
@ -405,7 +406,7 @@ impl<'src> Compiler<'src> {
position: Span, position: Span,
) -> Result<(), CompileError> { ) -> Result<(), CompileError> {
let r#type = constant.r#type(); let r#type = constant.r#type();
let constant_index = self.push_or_get_constant(constant); let constant_index = self.push_or_get_constant(Value::Concrete(constant));
let destination = self.next_register(); let destination = self.next_register();
let load_constant = Instruction::load_constant(destination, constant_index, false); let load_constant = Instruction::load_constant(destination, constant_index, false);
@ -1618,7 +1619,7 @@ impl<'src> Compiler<'src> {
let function_end = function_compiler.previous_position.1; let function_end = function_compiler.previous_position.1;
let chunk = function_compiler.finish(None, value_parameters.clone()); let chunk = function_compiler.finish(None, value_parameters.clone());
let function = ConcreteValue::function(chunk); let function = Value::Concrete(ConcreteValue::function(chunk));
let constant_index = self.push_or_get_constant(function); let constant_index = self.push_or_get_constant(function);
let destination = self.next_register(); let destination = self.next_register();
let function_type = FunctionType { let function_type = FunctionType {

View File

@ -47,9 +47,7 @@ pub use crate::lexer::{lex, LexError, Lexer};
pub use crate::native_function::{NativeFunction, NativeFunctionError}; 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::{ pub use crate::value::{AbstractValue, ConcreteValue, DustString, RangeValue, Value, ValueError};
AbstractValue, ConcreteValue, DustString, RangeValue, Value, ValueError, ValueRef,
};
pub use crate::vm::{run, Vm, VmError}; pub use crate::vm::{run, Vm, VmError};
use std::fmt::Display; use std::fmt::Display;

View File

@ -3,11 +3,11 @@ use std::panic;
use annotate_snippets::{Level, Renderer, Snippet}; use annotate_snippets::{Level, Renderer, Snippet};
use smallvec::SmallVec; use smallvec::SmallVec;
use crate::{DustString, NativeFunctionError, Value, ValueRef, Vm}; use crate::{DustString, NativeFunctionError, Value, Vm};
pub fn panic( pub fn panic(
vm: &Vm, vm: &Vm,
arguments: SmallVec<[ValueRef; 4]>, arguments: SmallVec<[&Value; 4]>,
) -> Result<Option<Value>, NativeFunctionError> { ) -> Result<Option<Value>, NativeFunctionError> {
let mut message: Option<DustString> = None; let mut message: Option<DustString> = None;

View File

@ -2,12 +2,9 @@ use std::io::{stdin, stdout, Write};
use smallvec::SmallVec; use smallvec::SmallVec;
use crate::{ConcreteValue, NativeFunctionError, Value, ValueRef, Vm}; use crate::{ConcreteValue, NativeFunctionError, Value, Vm};
pub fn read_line( pub fn read_line(vm: &Vm, _: SmallVec<[&Value; 4]>) -> Result<Option<Value>, NativeFunctionError> {
vm: &Vm,
_: SmallVec<[ValueRef; 4]>,
) -> Result<Option<Value>, NativeFunctionError> {
let mut buffer = String::new(); let mut buffer = String::new();
match stdin().read_line(&mut buffer) { match stdin().read_line(&mut buffer) {
@ -27,7 +24,7 @@ pub fn read_line(
pub fn write( pub fn write(
vm: &Vm, vm: &Vm,
arguments: SmallVec<[ValueRef; 4]>, arguments: SmallVec<[&Value; 4]>,
) -> Result<Option<Value>, NativeFunctionError> { ) -> Result<Option<Value>, NativeFunctionError> {
let mut stdout = stdout(); let mut stdout = stdout();
@ -50,7 +47,7 @@ pub fn write(
pub fn write_line( pub fn write_line(
vm: &Vm, vm: &Vm,
arguments: SmallVec<[ValueRef; 4]>, arguments: SmallVec<[&Value; 4]>,
) -> Result<Option<Value>, NativeFunctionError> { ) -> Result<Option<Value>, NativeFunctionError> {
let mut stdout = stdout(); let mut stdout = stdout();

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, ValueRef, Vm, VmError}; use crate::{AnnotatedError, FunctionType, Span, Type, Value, Vm, VmError};
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)),*) => {
@ -33,7 +33,7 @@ macro_rules! define_native_function {
pub fn call<'a>( pub fn call<'a>(
&self, &self,
vm: &Vm<'a>, vm: &Vm<'a>,
arguments: SmallVec<[ValueRef<'a>; 4]>, arguments: SmallVec<[&Value; 4]>,
) -> Result<Option<Value>, NativeFunctionError> { ) -> Result<Option<Value>, NativeFunctionError> {
match self { match self {
$( $(

View File

@ -1,10 +1,10 @@
use smallvec::SmallVec; use smallvec::SmallVec;
use crate::{ConcreteValue, NativeFunctionError, Value, ValueRef, Vm}; use crate::{ConcreteValue, NativeFunctionError, Value, Vm};
pub fn to_string( pub fn to_string(
vm: &Vm, vm: &Vm,
arguments: SmallVec<[ValueRef; 4]>, arguments: SmallVec<[&Value; 4]>,
) -> Result<Option<Value>, NativeFunctionError> { ) -> Result<Option<Value>, NativeFunctionError> {
if arguments.len() != 1 { if arguments.len() != 1 {
return Err(NativeFunctionError::ExpectedArgumentCount { return Err(NativeFunctionError::ExpectedArgumentCount {

View File

@ -1,11 +1,14 @@
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use crate::{vm::Pointer, ConcreteValue, DustString, Value, ValueRef, Vm, VmError}; use crate::{vm::Pointer, ConcreteValue, DustString, Type, Value, Vm, VmError};
#[derive(Debug, PartialEq, PartialOrd)] #[derive(Debug, PartialEq, PartialOrd)]
pub enum AbstractValue { pub enum AbstractValue {
FunctionSelf, FunctionSelf,
List { item_pointers: Vec<Pointer> }, List {
item_type: Type,
item_pointers: Vec<Pointer>,
},
} }
impl AbstractValue { impl AbstractValue {
@ -13,10 +16,6 @@ impl AbstractValue {
Value::Abstract(self) Value::Abstract(self)
} }
pub fn to_value_ref(&self) -> ValueRef {
ValueRef::Abstract(self)
}
pub fn to_concrete_owned(&self, vm: &Vm) -> ConcreteValue { pub fn to_concrete_owned(&self, vm: &Vm) -> ConcreteValue {
match self { match self {
AbstractValue::FunctionSelf => ConcreteValue::function(vm.chunk().clone()), AbstractValue::FunctionSelf => ConcreteValue::function(vm.chunk().clone()),
@ -26,7 +25,7 @@ impl AbstractValue {
for pointer in item_pointers { for pointer in item_pointers {
let item_option = vm.follow_pointer_allow_empty(*pointer); let item_option = vm.follow_pointer_allow_empty(*pointer);
let item = match item_option { let item = match item_option {
Some(value_ref) => value_ref.into_concrete_owned(vm), Some(value) => value.clone().into_concrete_owned(vm),
None => continue, None => continue,
}; };
@ -65,6 +64,13 @@ impl AbstractValue {
Ok(display) Ok(display)
} }
pub fn r#type(&self) -> Type {
match self {
AbstractValue::FunctionSelf => Type::SelfChunk,
AbstractValue::List { item_type, .. } => Type::List(Box::new(item_type.clone())),
}
}
} }
impl Clone for AbstractValue { impl Clone for AbstractValue {
@ -74,8 +80,10 @@ impl Clone for AbstractValue {
match self { match self {
AbstractValue::FunctionSelf => AbstractValue::FunctionSelf, AbstractValue::FunctionSelf => AbstractValue::FunctionSelf,
AbstractValue::List { AbstractValue::List {
item_type: r#type,
item_pointers: items, item_pointers: items,
} => AbstractValue::List { } => AbstractValue::List {
item_type: r#type.clone(),
item_pointers: items.clone(), item_pointers: items.clone(),
}, },
} }

View File

@ -3,7 +3,7 @@ use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use crate::{Chunk, Type, Value, ValueError, ValueRef}; use crate::{Chunk, Type, Value, ValueError};
use super::RangeValue; use super::RangeValue;
@ -27,10 +27,6 @@ impl ConcreteValue {
Value::Concrete(self) Value::Concrete(self)
} }
pub fn to_value_ref(&self) -> ValueRef {
ValueRef::Concrete(self)
}
pub fn function(chunk: Chunk) -> Self { pub fn function(chunk: Chunk) -> Self {
ConcreteValue::Function(Box::new(chunk)) ConcreteValue::Function(Box::new(chunk))
} }

View File

@ -6,25 +6,20 @@ mod range_value;
pub use abstract_value::AbstractValue; pub use abstract_value::AbstractValue;
pub use concrete_value::{ConcreteValue, DustString}; pub use concrete_value::{ConcreteValue, DustString};
pub use range_value::RangeValue; pub use range_value::RangeValue;
use serde::{Deserialize, Serialize};
use std::fmt::{self, Debug, Display, Formatter}; use std::fmt::{self, Debug, Display, Formatter};
use crate::{Vm, VmError}; use crate::{Type, Vm, VmError};
#[derive(Clone, Debug, PartialEq, PartialOrd)] #[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub enum Value { pub enum Value {
#[serde(skip)]
Abstract(AbstractValue), Abstract(AbstractValue),
Concrete(ConcreteValue), Concrete(ConcreteValue),
} }
impl Value { impl Value {
pub fn to_ref(&self) -> ValueRef {
match self {
Value::Abstract(abstract_value) => ValueRef::Abstract(abstract_value),
Value::Concrete(concrete_value) => ValueRef::Concrete(concrete_value),
}
}
pub fn into_concrete_owned(self, vm: &Vm) -> ConcreteValue { pub fn into_concrete_owned(self, vm: &Vm) -> 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),
@ -39,58 +34,24 @@ impl Value {
None None
} }
} }
}
impl Display for Value { pub fn r#type(&self) -> Type {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self { match self {
Value::Abstract(abstract_value) => write!(f, "{}", abstract_value), Value::Abstract(abstract_value) => abstract_value.r#type(),
Value::Concrete(concrete_value) => write!(f, "{}", concrete_value), Value::Concrete(concrete_value) => concrete_value.r#type(),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub enum ValueRef<'a> {
Abstract(&'a AbstractValue),
Concrete(&'a ConcreteValue),
}
impl ValueRef<'_> {
pub fn to_owned(&self) -> Value {
match self {
ValueRef::Abstract(abstract_value) => Value::Abstract((*abstract_value).clone()),
ValueRef::Concrete(concrete_value) => Value::Concrete((*concrete_value).clone()),
} }
} }
pub fn into_concrete_owned(self, vm: &Vm) -> ConcreteValue { pub fn add(&self, other: &Value) -> Result<Value, ValueError> {
match self {
ValueRef::Abstract(abstract_value) => abstract_value.to_concrete_owned(vm),
ValueRef::Concrete(concrete_value) => concrete_value.clone(),
}
}
pub fn display(&self, vm: &Vm) -> Result<DustString, VmError> {
match self {
ValueRef::Abstract(abstract_value) => abstract_value.to_dust_string(vm),
ValueRef::Concrete(concrete_value) => Ok(concrete_value.to_dust_string()),
}
}
#[inline(always)]
pub fn add(&self, other: ValueRef) -> Result<Value, ValueError> {
match (self, other) { match (self, other) {
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => { (Value::Concrete(left), Value::Concrete(right)) => left.add(right).map(Value::Concrete),
left.add(right).map(Value::Concrete)
}
_ => Err(ValueError::CannotAdd(self.to_owned(), other.to_owned())), _ => Err(ValueError::CannotAdd(self.to_owned(), other.to_owned())),
} }
} }
pub fn subtract(&self, other: ValueRef) -> Result<Value, ValueError> { pub fn subtract(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) { match (self, other) {
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => { (Value::Concrete(left), Value::Concrete(right)) => {
left.subtract(right).map(Value::Concrete) left.subtract(right).map(Value::Concrete)
} }
_ => Err(ValueError::CannotSubtract( _ => Err(ValueError::CannotSubtract(
@ -100,9 +61,9 @@ impl ValueRef<'_> {
} }
} }
pub fn multiply(&self, other: ValueRef) -> Result<Value, ValueError> { pub fn multiply(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) { match (self, other) {
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => { (Value::Concrete(left), Value::Concrete(right)) => {
left.multiply(right).map(Value::Concrete) left.multiply(right).map(Value::Concrete)
} }
_ => Err(ValueError::CannotMultiply( _ => Err(ValueError::CannotMultiply(
@ -112,18 +73,18 @@ impl ValueRef<'_> {
} }
} }
pub fn divide(&self, other: ValueRef) -> Result<Value, ValueError> { pub fn divide(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) { match (self, other) {
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => { (Value::Concrete(left), Value::Concrete(right)) => {
left.divide(right).map(Value::Concrete) left.divide(right).map(Value::Concrete)
} }
_ => Err(ValueError::CannotDivide(self.to_owned(), other.to_owned())), _ => Err(ValueError::CannotDivide(self.to_owned(), other.to_owned())),
} }
} }
pub fn modulo(&self, other: ValueRef) -> Result<Value, ValueError> { pub fn modulo(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) { match (self, other) {
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => { (Value::Concrete(left), Value::Concrete(right)) => {
left.modulo(right).map(Value::Concrete) left.modulo(right).map(Value::Concrete)
} }
_ => Err(ValueError::CannotModulo(self.to_owned(), other.to_owned())), _ => Err(ValueError::CannotModulo(self.to_owned(), other.to_owned())),
@ -132,51 +93,58 @@ impl ValueRef<'_> {
pub fn negate(&self) -> Result<Value, ValueError> { pub fn negate(&self) -> Result<Value, ValueError> {
match self { match self {
ValueRef::Concrete(concrete_value) => concrete_value.negate().map(Value::Concrete), Value::Concrete(concrete_value) => concrete_value.negate().map(Value::Concrete),
_ => Err(ValueError::CannotNegate(self.to_owned())), _ => Err(ValueError::CannotNegate(self.to_owned())),
} }
} }
pub fn not(&self) -> Result<Value, ValueError> { pub fn not(&self) -> Result<Value, ValueError> {
match self { match self {
ValueRef::Concrete(concrete_value) => concrete_value.not().map(Value::Concrete), Value::Concrete(concrete_value) => concrete_value.not().map(Value::Concrete),
_ => Err(ValueError::CannotNot(self.to_owned())), _ => Err(ValueError::CannotNot(self.to_owned())),
} }
} }
pub fn equal(&self, other: ValueRef) -> Result<Value, ValueError> { pub fn equal(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) { match (self, other) {
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => { (Value::Concrete(left), Value::Concrete(right)) => {
left.equal(right).map(Value::Concrete) left.equal(right).map(Value::Concrete)
} }
_ => Err(ValueError::CannotCompare(self.to_owned(), other.to_owned())), _ => Err(ValueError::CannotCompare(self.to_owned(), other.to_owned())),
} }
} }
pub fn less(&self, other: ValueRef) -> Result<Value, ValueError> { pub fn less(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) { match (self, other) {
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => { (Value::Concrete(left), Value::Concrete(right)) => {
left.less_than(right).map(Value::Concrete) left.less_than(right).map(Value::Concrete)
} }
_ => Err(ValueError::CannotCompare(self.to_owned(), other.to_owned())), _ => Err(ValueError::CannotCompare(self.to_owned(), other.to_owned())),
} }
} }
pub fn less_equal(&self, other: ValueRef) -> Result<Value, ValueError> { pub fn less_equal(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) { match (self, other) {
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => { (Value::Concrete(left), Value::Concrete(right)) => {
left.less_than_or_equal(right).map(Value::Concrete) left.less_than_or_equal(right).map(Value::Concrete)
} }
_ => Err(ValueError::CannotCompare(self.to_owned(), other.to_owned())), _ => Err(ValueError::CannotCompare(self.to_owned(), other.to_owned())),
} }
} }
pub fn display(&self, vm: &Vm) -> Result<DustString, VmError> {
match self {
Value::Abstract(abstract_value) => abstract_value.to_dust_string(vm),
Value::Concrete(concrete_value) => Ok(concrete_value.to_dust_string()),
}
}
} }
impl Display for ValueRef<'_> { impl Display for Value {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self { match self {
ValueRef::Abstract(abstract_value) => write!(f, "{}", abstract_value), Value::Abstract(abstract_value) => write!(f, "{}", abstract_value),
ValueRef::Concrete(concrete_value) => write!(f, "{}", concrete_value), Value::Concrete(concrete_value) => write!(f, "{}", concrete_value),
} }
} }
} }

View File

@ -4,6 +4,7 @@ mod runners;
use std::{ use std::{
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
io, iter, io, iter,
rc::Rc,
}; };
use runners::Runner; use runners::Runner;
@ -11,10 +12,10 @@ use smallvec::SmallVec;
use crate::{ use crate::{
compile, instruction::*, AbstractValue, AnnotatedError, Chunk, ConcreteValue, DustError, compile, instruction::*, AbstractValue, AnnotatedError, Chunk, ConcreteValue, DustError,
NativeFunctionError, Span, Value, ValueError, ValueRef, NativeFunctionError, Span, Value, ValueError,
}; };
pub fn run(source: &str) -> Result<Option<ConcreteValue>, 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(source, &chunk, None, None);
@ -35,7 +36,7 @@ pub struct Vm<'a> {
ip: usize, ip: usize,
last_assigned_register: Option<u8>, last_assigned_register: Option<u8>,
source: &'a str, source: &'a str,
return_value: Option<ConcreteValue>, return_value: Option<Value>,
} }
impl<'a> Vm<'a> { impl<'a> Vm<'a> {
@ -85,26 +86,31 @@ impl<'a> Vm<'a> {
position position
} }
pub fn run(mut self) -> Option<ConcreteValue> { pub fn run(mut self) -> Option<Value> {
while self.ip < self.runners.len() && self.return_value.is_none() { while self.ip < self.runners.len() && self.return_value.is_none() {
let runner = self.runners[self.ip]; self.execute_next_runner();
runner.run(&mut self);
} }
self.return_value self.return_value
} }
pub(crate) fn follow_pointer(&self, pointer: Pointer) -> ValueRef { pub fn execute_next_runner(&mut self) {
assert!(
self.ip < self.runners.len(),
"Runtime Error: IP out of bounds"
);
let runner = self.runners[self.ip];
runner.run(self);
}
pub(crate) fn follow_pointer(&self, pointer: Pointer) -> &Value {
log::trace!("Follow pointer {pointer}"); log::trace!("Follow pointer {pointer}");
match pointer { match pointer {
Pointer::Stack(register_index) => self.open_register(register_index), Pointer::Stack(register_index) => self.open_register(register_index),
Pointer::Constant(constant_index) => { Pointer::Constant(constant_index) => self.get_constant(constant_index),
let constant = self.get_constant(constant_index);
ValueRef::Concrete(constant)
}
Pointer::ParentStack(register_index) => { Pointer::ParentStack(register_index) => {
assert!(self.parent.is_some(), "Vm Error: Expected parent"); assert!(self.parent.is_some(), "Vm Error: Expected parent");
@ -113,15 +119,12 @@ impl<'a> Vm<'a> {
Pointer::ParentConstant(constant_index) => { Pointer::ParentConstant(constant_index) => {
assert!(self.parent.is_some(), "Vm Error: Expected parent"); assert!(self.parent.is_some(), "Vm Error: Expected parent");
self.parent self.parent.unwrap().get_constant(constant_index)
.unwrap()
.get_constant(constant_index)
.to_value_ref()
} }
} }
} }
pub(crate) fn follow_pointer_allow_empty(&self, pointer: Pointer) -> Option<ValueRef> { pub(crate) fn follow_pointer_allow_empty(&self, pointer: Pointer) -> Option<&Value> {
log::trace!("Follow pointer {pointer}"); log::trace!("Follow pointer {pointer}");
match pointer { match pointer {
@ -129,7 +132,7 @@ impl<'a> Vm<'a> {
Pointer::Constant(constant_index) => { Pointer::Constant(constant_index) => {
let constant = self.get_constant(constant_index); let constant = self.get_constant(constant_index);
Some(ValueRef::Concrete(constant)) Some(constant)
} }
Pointer::ParentStack(register_index) => { Pointer::ParentStack(register_index) => {
assert!(self.parent.is_some(), "Vm Error: Expected parent"); assert!(self.parent.is_some(), "Vm Error: Expected parent");
@ -141,18 +144,14 @@ impl<'a> Vm<'a> {
Pointer::ParentConstant(constant_index) => { Pointer::ParentConstant(constant_index) => {
assert!(self.parent.is_some(), "Vm Error: Expected parent"); assert!(self.parent.is_some(), "Vm Error: Expected parent");
let constant = self let constant = self.parent.unwrap().get_constant(constant_index);
.parent
.unwrap()
.get_constant(constant_index)
.to_value_ref();
Some(constant) Some(constant)
} }
} }
} }
fn open_register(&self, register_index: u8) -> ValueRef { fn open_register(&self, register_index: u8) -> &Value {
log::trace!("Open register R{register_index}"); log::trace!("Open register R{register_index}");
let register_index = register_index as usize; let register_index = register_index as usize;
@ -165,13 +164,13 @@ impl<'a> Vm<'a> {
let register = &self.stack[register_index]; let register = &self.stack[register_index];
match register { match register {
Register::Value(value) => value.to_ref(), Register::Value(value) => value,
Register::Pointer(pointer) => self.follow_pointer(*pointer), Register::Pointer(pointer) => self.follow_pointer(*pointer),
Register::Empty => panic!("VM Error: Register {register_index} is empty"), Register::Empty => panic!("VM Error: Register {register_index} is empty"),
} }
} }
fn open_register_allow_empty(&self, register_index: u8) -> Option<ValueRef> { fn open_register_allow_empty(&self, register_index: u8) -> Option<&Value> {
log::trace!("Open register R{register_index}"); log::trace!("Open register R{register_index}");
let register_index = register_index as usize; let register_index = register_index as usize;
@ -184,7 +183,7 @@ impl<'a> Vm<'a> {
let register = &self.stack[register_index]; let register = &self.stack[register_index];
match register { match register {
Register::Value(value) => Some(value.to_ref()), Register::Value(value) => Some(value),
Register::Pointer(pointer) => Some(self.follow_pointer(*pointer)), Register::Pointer(pointer) => Some(self.follow_pointer(*pointer)),
Register::Empty => None, Register::Empty => None,
} }
@ -209,9 +208,9 @@ impl<'a> Vm<'a> {
} }
/// 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) -> ValueRef { fn get_argument(&self, index: u8, is_constant: bool) -> &Value {
if is_constant { if is_constant {
self.get_constant(index).to_value_ref() self.get_constant(index)
} else { } else {
self.open_register(index) self.open_register(index)
} }
@ -229,7 +228,7 @@ impl<'a> Vm<'a> {
self.stack[to_register] = register; self.stack[to_register] = register;
} }
fn get_constant(&self, constant_index: u8) -> &ConcreteValue { fn get_constant(&self, constant_index: u8) -> &Value {
let constant_index = constant_index as usize; let constant_index = constant_index as usize;
let constants = self.chunk.constants(); let constants = self.chunk.constants();

View File

@ -1,6 +1,8 @@
use std::{borrow::BorrowMut, cell::RefCell, rc::Rc};
use smallvec::SmallVec; use smallvec::SmallVec;
use crate::{AbstractValue, ConcreteValue, NativeFunction, Value, ValueRef}; use crate::{AbstractValue, ConcreteValue, NativeFunction, Type, Value};
use super::{Instruction, InstructionData, Pointer, Register, Vm}; use super::{Instruction, InstructionData, Pointer, Register, Vm};
@ -56,8 +58,7 @@ pub const RUNNER_LOGIC_TABLE: [RunnerLogic; 24] = [
r#return, r#return,
]; ];
#[allow(clippy::needless_lifetimes)] pub fn r#move(vm: &mut Vm, instruction_data: InstructionData) {
pub fn r#move<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { b, c, .. } = instruction_data; let InstructionData { b, c, .. } = instruction_data;
let from_register_has_value = vm let from_register_has_value = vm
.stack .stack
@ -71,9 +72,7 @@ pub fn r#move<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.ip += 1; vm.ip += 1;
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -93,9 +92,7 @@ pub fn close<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.ip += 1; vm.ip += 1;
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -112,9 +109,7 @@ pub fn load_boolean<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionDat
vm.ip += 1; vm.ip += 1;
} }
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -130,20 +125,29 @@ pub fn load_constant<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionDa
vm.ip += 1; vm.ip += 1;
} }
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
pub fn load_list<'b, 'c>(vm: &'b mut Vm<'c>, 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::new(); let mut item_pointers = Vec::with_capacity((a - b) as usize);
let stack = vm.stack.as_slice(); let stack = vm.stack.as_slice();
let mut item_type = Type::Any;
for register_index in b..a { for register_index in b..a {
if let Register::Empty = stack[register_index as usize] { match &stack[register_index as usize] {
continue; Register::Empty => continue,
Register::Value(value) => {
if item_type == Type::Any {
item_type = value.r#type();
}
}
Register::Pointer(pointer) => {
if item_type == Type::Any {
item_type = vm.follow_pointer(*pointer).r#type();
}
}
} }
let pointer = Pointer::Stack(register_index); let pointer = Pointer::Stack(register_index);
@ -151,16 +155,18 @@ 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 { item_pointers }.to_value(); let list_value = AbstractValue::List {
item_type,
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);
vm.ip += 1; vm.ip += 1;
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -172,9 +178,7 @@ pub fn load_self<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData)
vm.ip += 1; vm.ip += 1;
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -187,9 +191,7 @@ pub fn get_local<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData)
vm.ip += 1; vm.ip += 1;
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -202,9 +204,7 @@ pub fn set_local<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData)
vm.ip += 1; vm.ip += 1;
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -220,7 +220,7 @@ pub fn add<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let left = vm.get_argument(b, b_is_constant); let left = vm.get_argument(b, b_is_constant);
let right = vm.get_argument(c, c_is_constant); let right = vm.get_argument(c, c_is_constant);
let sum = match (left, right) { let sum = match (left, right) {
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => match (left, right) { (Value::Concrete(left), Value::Concrete(right)) => match (left, right) {
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => { (ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
ConcreteValue::Integer(left + right).to_value() ConcreteValue::Integer(left + right).to_value()
} }
@ -234,9 +234,7 @@ pub fn add<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.ip += 1; vm.ip += 1;
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -252,7 +250,7 @@ pub fn subtract<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let left = vm.get_argument(b, b_is_constant); let left = vm.get_argument(b, b_is_constant);
let right = vm.get_argument(c, c_is_constant); let right = vm.get_argument(c, c_is_constant);
let difference = match (left, right) { let difference = match (left, right) {
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => match (left, right) { (Value::Concrete(left), Value::Concrete(right)) => match (left, right) {
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => { (ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
ConcreteValue::Integer(left - right).to_value() ConcreteValue::Integer(left - right).to_value()
} }
@ -266,9 +264,7 @@ pub fn subtract<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.ip += 1; vm.ip += 1;
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -284,7 +280,7 @@ pub fn multiply<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let left = vm.get_argument(b, b_is_constant); let left = vm.get_argument(b, b_is_constant);
let right = vm.get_argument(c, c_is_constant); let right = vm.get_argument(c, c_is_constant);
let product = match (left, right) { let product = match (left, right) {
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => match (left, right) { (Value::Concrete(left), Value::Concrete(right)) => match (left, right) {
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => { (ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
ConcreteValue::Integer(left * right).to_value() ConcreteValue::Integer(left * right).to_value()
} }
@ -298,9 +294,7 @@ pub fn multiply<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.ip += 1; vm.ip += 1;
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -316,7 +310,7 @@ pub fn divide<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let left = vm.get_argument(b, b_is_constant); let left = vm.get_argument(b, b_is_constant);
let right = vm.get_argument(c, c_is_constant); let right = vm.get_argument(c, c_is_constant);
let quotient = match (left, right) { let quotient = match (left, right) {
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => match (left, right) { (Value::Concrete(left), Value::Concrete(right)) => match (left, right) {
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => { (ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
ConcreteValue::Integer(left / right).to_value() ConcreteValue::Integer(left / right).to_value()
} }
@ -330,9 +324,7 @@ pub fn divide<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.ip += 1; vm.ip += 1;
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -348,7 +340,7 @@ pub fn modulo<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let left = vm.get_argument(b, b_is_constant); let left = vm.get_argument(b, b_is_constant);
let right = vm.get_argument(c, c_is_constant); let right = vm.get_argument(c, c_is_constant);
let remainder = match (left, right) { let remainder = match (left, right) {
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => match (left, right) { (Value::Concrete(left), Value::Concrete(right)) => match (left, right) {
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => { (ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
ConcreteValue::Integer(left % right).to_value() ConcreteValue::Integer(left % right).to_value()
} }
@ -362,9 +354,7 @@ pub fn modulo<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.ip += 1; vm.ip += 1;
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -376,7 +366,7 @@ pub fn test<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
.. ..
} = instruction_data; } = instruction_data;
let value = vm.get_argument(b, b_is_constant); let value = vm.get_argument(b, b_is_constant);
let boolean = if let ValueRef::Concrete(ConcreteValue::Boolean(boolean)) = value { let boolean = if let Value::Concrete(ConcreteValue::Boolean(boolean)) = value {
*boolean *boolean
} else { } else {
panic!( panic!(
@ -392,9 +382,7 @@ pub fn test<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.ip += 1; vm.ip += 1;
} }
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -407,7 +395,7 @@ pub fn test_set<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
.. ..
} = instruction_data; } = instruction_data;
let value = vm.get_argument(b, b_is_constant); let value = vm.get_argument(b, b_is_constant);
let boolean = if let ValueRef::Concrete(ConcreteValue::Boolean(boolean)) = value { let boolean = if let Value::Concrete(ConcreteValue::Boolean(boolean)) = value {
*boolean *boolean
} else { } else {
panic!( panic!(
@ -432,9 +420,7 @@ pub fn test_set<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.ip += 1; vm.ip += 1;
} }
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -457,13 +443,10 @@ pub fn equal<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.ip += 1; vm.ip += 1;
} }
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] pub fn less(vm: &mut Vm, instruction_data: InstructionData) {
pub fn less<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let InstructionData { let InstructionData {
b, b,
c, c,
@ -482,9 +465,7 @@ pub fn less<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.ip += 1; vm.ip += 1;
} }
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -507,9 +488,7 @@ pub fn less_equal<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData)
vm.ip += 1; vm.ip += 1;
} }
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -522,12 +501,12 @@ pub fn negate<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
} = instruction_data; } = instruction_data;
let argument = vm.get_argument(b, b_is_constant); let argument = vm.get_argument(b, b_is_constant);
let negated = match argument { let negated = match argument {
ValueRef::Concrete(value) => match value { Value::Concrete(value) => match value {
ConcreteValue::Float(float) => ConcreteValue::Float(-float), ConcreteValue::Float(float) => ConcreteValue::Float(-float),
ConcreteValue::Integer(integer) => ConcreteValue::Integer(-integer), ConcreteValue::Integer(integer) => ConcreteValue::Integer(-integer),
_ => panic!("Value Error: Cannot negate value"), _ => panic!("Value Error: Cannot negate value"),
}, },
ValueRef::Abstract(_) => panic!("VM Error: Cannot negate value"), Value::Abstract(_) => panic!("VM Error: Cannot negate value"),
}; };
let register = Register::Value(Value::Concrete(negated)); let register = Register::Value(Value::Concrete(negated));
@ -535,9 +514,7 @@ pub fn negate<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.ip += 1; vm.ip += 1;
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -550,7 +527,7 @@ pub fn not<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
} = instruction_data; } = instruction_data;
let argument = vm.get_argument(b, b_is_constant); let argument = vm.get_argument(b, b_is_constant);
let not = match argument { let not = match argument {
ValueRef::Concrete(ConcreteValue::Boolean(boolean)) => ConcreteValue::Boolean(!boolean), Value::Concrete(ConcreteValue::Boolean(boolean)) => ConcreteValue::Boolean(!boolean),
_ => panic!("VM Error: Expected boolean value for NOT operation"), _ => panic!("VM Error: Expected boolean value for NOT operation"),
}; };
let register = Register::Value(Value::Concrete(not)); let register = Register::Value(Value::Concrete(not));
@ -559,9 +536,7 @@ pub fn not<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
vm.ip += 1; vm.ip += 1;
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -576,9 +551,7 @@ pub fn jump<'c>(vm: &mut Vm<'c>, instruction_data: InstructionData) {
vm.ip -= offset vm.ip -= offset
} }
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -591,9 +564,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 ValueRef::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(vm.source, chunk, Some(vm), None)
} else if let ValueRef::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.source, vm.chunk, Some(vm), Some(vm.runners.clone()))
} else { } else {
panic!("VM Error: Expected function") panic!("VM Error: Expected function")
@ -620,16 +593,14 @@ pub fn call<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
let return_value = function_vm.run(); let return_value = function_vm.run();
if let Some(concrete_value) = return_value { if let Some(concrete_value) = return_value {
let register = Register::Value(concrete_value.to_value()); let register = Register::Value(concrete_value);
vm.set_register(a, register); vm.set_register(a, register);
} }
vm.ip += 1; vm.ip += 1;
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -637,12 +608,12 @@ 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;
let mut arguments: SmallVec<[ValueRef; 4]> = SmallVec::new(); let mut arguments: SmallVec<[&Value; 4]> = SmallVec::new();
for register_index in argument_range { for register_index in argument_range {
let register = &vm.stack[register_index]; let register = &vm.stack[register_index];
let value = match register { let value = match register {
Register::Value(value) => value.to_ref(), Register::Value(value) => value,
Register::Pointer(pointer) => { Register::Pointer(pointer) => {
let value_option = vm.follow_pointer_allow_empty(*pointer); let value_option = vm.follow_pointer_allow_empty(*pointer);
@ -668,9 +639,7 @@ pub fn call_native<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData
vm.ip += 1; vm.ip += 1;
let next = vm.runners[vm.ip]; vm.execute_next_runner();
next.run(vm);
} }
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
@ -682,7 +651,7 @@ pub fn r#return<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
} }
if let Some(register_index) = &vm.last_assigned_register { if let Some(register_index) = &vm.last_assigned_register {
let return_value = vm.open_register(*register_index).into_concrete_owned(vm); let return_value = vm.open_register(*register_index).clone();
vm.return_value = Some(return_value); vm.return_value = Some(return_value);
} else { } else {