Continue VM optimizations
This commit is contained in:
parent
cd4fa6bef5
commit
ec5033a32f
@ -46,7 +46,7 @@ use std::{
|
||||
|
||||
use colored::{ColoredString, Colorize};
|
||||
|
||||
use crate::{value::ConcreteValue, Chunk, Local};
|
||||
use crate::{value::ConcreteValue, Chunk, Local, Value};
|
||||
|
||||
const INSTRUCTION_COLUMNS: [(&str, usize); 4] =
|
||||
[("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])?;
|
||||
|
||||
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 value_display = if is_function {
|
||||
"Function displayed below".to_string()
|
||||
@ -353,7 +353,7 @@ impl<'a, W: Write> Disassembler<'a, W> {
|
||||
|
||||
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
|
||||
.disassembler(self.writer)
|
||||
.style(self.style)
|
||||
|
@ -17,7 +17,7 @@ use std::io::Write;
|
||||
use serde::{Deserialize, Serialize};
|
||||
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.
|
||||
///
|
||||
@ -28,7 +28,7 @@ pub struct Chunk {
|
||||
r#type: FunctionType,
|
||||
|
||||
instructions: SmallVec<[(Instruction, Span); 32]>,
|
||||
constants: SmallVec<[ConcreteValue; 16]>,
|
||||
constants: SmallVec<[Value; 16]>,
|
||||
locals: SmallVec<[Local; 8]>,
|
||||
|
||||
stack_size: usize,
|
||||
@ -39,7 +39,7 @@ impl Chunk {
|
||||
name: Option<DustString>,
|
||||
r#type: FunctionType,
|
||||
instructions: SmallVec<[(Instruction, Span); 32]>,
|
||||
constants: SmallVec<[ConcreteValue; 16]>,
|
||||
constants: SmallVec<[Value; 16]>,
|
||||
locals: SmallVec<[Local; 8]>,
|
||||
stack_size: usize,
|
||||
) -> Self {
|
||||
@ -57,7 +57,7 @@ impl Chunk {
|
||||
name: Option<DustString>,
|
||||
r#type: FunctionType,
|
||||
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]>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
@ -82,7 +82,7 @@ impl Chunk {
|
||||
self.instructions.is_empty()
|
||||
}
|
||||
|
||||
pub fn constants(&self) -> &SmallVec<[ConcreteValue; 16]> {
|
||||
pub fn constants(&self) -> &SmallVec<[Value; 16]> {
|
||||
&self.constants
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ use crate::{
|
||||
Not, Return, SetLocal, Test,
|
||||
},
|
||||
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.
|
||||
@ -58,7 +58,7 @@ pub fn compile(source: &str) -> Result<Chunk, DustError> {
|
||||
pub struct Compiler<'src> {
|
||||
self_name: Option<DustString>,
|
||||
instructions: SmallVec<[(Instruction, Type, Span); 32]>,
|
||||
constants: SmallVec<[ConcreteValue; 16]>,
|
||||
constants: SmallVec<[Value; 16]>,
|
||||
locals: SmallVec<[(Local, Type); 8]>,
|
||||
stack_size: usize,
|
||||
|
||||
@ -203,11 +203,12 @@ impl<'src> Compiler<'src> {
|
||||
.rev()
|
||||
.find_map(|(index, (local, _))| {
|
||||
let constant = self.constants.get(local.identifier_index as usize)?;
|
||||
let identifier = if let ConcreteValue::String(identifier) = constant {
|
||||
identifier
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
let identifier =
|
||||
if let Value::Concrete(ConcreteValue::String(identifier)) = constant {
|
||||
identifier
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
|
||||
if identifier == identifier_text {
|
||||
Some(index as u8)
|
||||
@ -231,7 +232,7 @@ impl<'src> Compiler<'src> {
|
||||
) -> (u8, u8) {
|
||||
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 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
|
||||
.constants
|
||||
.iter()
|
||||
@ -405,7 +406,7 @@ impl<'src> Compiler<'src> {
|
||||
position: Span,
|
||||
) -> Result<(), CompileError> {
|
||||
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 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 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 destination = self.next_register();
|
||||
let function_type = FunctionType {
|
||||
|
@ -47,9 +47,7 @@ pub use crate::lexer::{lex, LexError, Lexer};
|
||||
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, ValueRef,
|
||||
};
|
||||
pub use crate::value::{AbstractValue, ConcreteValue, DustString, RangeValue, Value, ValueError};
|
||||
pub use crate::vm::{run, Vm, VmError};
|
||||
|
||||
use std::fmt::Display;
|
||||
|
@ -3,11 +3,11 @@ use std::panic;
|
||||
use annotate_snippets::{Level, Renderer, Snippet};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::{DustString, NativeFunctionError, Value, ValueRef, Vm};
|
||||
use crate::{DustString, NativeFunctionError, Value, Vm};
|
||||
|
||||
pub fn panic(
|
||||
vm: &Vm,
|
||||
arguments: SmallVec<[ValueRef; 4]>,
|
||||
arguments: SmallVec<[&Value; 4]>,
|
||||
) -> Result<Option<Value>, NativeFunctionError> {
|
||||
let mut message: Option<DustString> = None;
|
||||
|
||||
|
@ -2,12 +2,9 @@ use std::io::{stdin, stdout, Write};
|
||||
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::{ConcreteValue, NativeFunctionError, Value, ValueRef, Vm};
|
||||
use crate::{ConcreteValue, NativeFunctionError, Value, Vm};
|
||||
|
||||
pub fn read_line(
|
||||
vm: &Vm,
|
||||
_: SmallVec<[ValueRef; 4]>,
|
||||
) -> Result<Option<Value>, NativeFunctionError> {
|
||||
pub fn read_line(vm: &Vm, _: SmallVec<[&Value; 4]>) -> Result<Option<Value>, NativeFunctionError> {
|
||||
let mut buffer = String::new();
|
||||
|
||||
match stdin().read_line(&mut buffer) {
|
||||
@ -27,7 +24,7 @@ pub fn read_line(
|
||||
|
||||
pub fn write(
|
||||
vm: &Vm,
|
||||
arguments: SmallVec<[ValueRef; 4]>,
|
||||
arguments: SmallVec<[&Value; 4]>,
|
||||
) -> Result<Option<Value>, NativeFunctionError> {
|
||||
let mut stdout = stdout();
|
||||
|
||||
@ -50,7 +47,7 @@ pub fn write(
|
||||
|
||||
pub fn write_line(
|
||||
vm: &Vm,
|
||||
arguments: SmallVec<[ValueRef; 4]>,
|
||||
arguments: SmallVec<[&Value; 4]>,
|
||||
) -> Result<Option<Value>, NativeFunctionError> {
|
||||
let mut stdout = stdout();
|
||||
|
||||
|
@ -15,7 +15,7 @@ use std::{
|
||||
use serde::{Deserialize, Serialize};
|
||||
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 {
|
||||
($(($name:ident, $bytes:literal, $str:expr, $type:expr, $function:expr)),*) => {
|
||||
@ -33,7 +33,7 @@ macro_rules! define_native_function {
|
||||
pub fn call<'a>(
|
||||
&self,
|
||||
vm: &Vm<'a>,
|
||||
arguments: SmallVec<[ValueRef<'a>; 4]>,
|
||||
arguments: SmallVec<[&Value; 4]>,
|
||||
) -> Result<Option<Value>, NativeFunctionError> {
|
||||
match self {
|
||||
$(
|
||||
|
@ -1,10 +1,10 @@
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::{ConcreteValue, NativeFunctionError, Value, ValueRef, Vm};
|
||||
use crate::{ConcreteValue, NativeFunctionError, Value, Vm};
|
||||
|
||||
pub fn to_string(
|
||||
vm: &Vm,
|
||||
arguments: SmallVec<[ValueRef; 4]>,
|
||||
arguments: SmallVec<[&Value; 4]>,
|
||||
) -> Result<Option<Value>, NativeFunctionError> {
|
||||
if arguments.len() != 1 {
|
||||
return Err(NativeFunctionError::ExpectedArgumentCount {
|
||||
|
@ -1,11 +1,14 @@
|
||||
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)]
|
||||
pub enum AbstractValue {
|
||||
FunctionSelf,
|
||||
List { item_pointers: Vec<Pointer> },
|
||||
List {
|
||||
item_type: Type,
|
||||
item_pointers: Vec<Pointer>,
|
||||
},
|
||||
}
|
||||
|
||||
impl AbstractValue {
|
||||
@ -13,10 +16,6 @@ impl AbstractValue {
|
||||
Value::Abstract(self)
|
||||
}
|
||||
|
||||
pub fn to_value_ref(&self) -> ValueRef {
|
||||
ValueRef::Abstract(self)
|
||||
}
|
||||
|
||||
pub fn to_concrete_owned(&self, vm: &Vm) -> ConcreteValue {
|
||||
match self {
|
||||
AbstractValue::FunctionSelf => ConcreteValue::function(vm.chunk().clone()),
|
||||
@ -26,7 +25,7 @@ impl AbstractValue {
|
||||
for pointer in item_pointers {
|
||||
let item_option = vm.follow_pointer_allow_empty(*pointer);
|
||||
let item = match item_option {
|
||||
Some(value_ref) => value_ref.into_concrete_owned(vm),
|
||||
Some(value) => value.clone().into_concrete_owned(vm),
|
||||
None => continue,
|
||||
};
|
||||
|
||||
@ -65,6 +64,13 @@ impl AbstractValue {
|
||||
|
||||
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 {
|
||||
@ -74,8 +80,10 @@ impl Clone for AbstractValue {
|
||||
match self {
|
||||
AbstractValue::FunctionSelf => AbstractValue::FunctionSelf,
|
||||
AbstractValue::List {
|
||||
item_type: r#type,
|
||||
item_pointers: items,
|
||||
} => AbstractValue::List {
|
||||
item_type: r#type.clone(),
|
||||
item_pointers: items.clone(),
|
||||
},
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use std::fmt::{self, Display, Formatter};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smartstring::{LazyCompact, SmartString};
|
||||
|
||||
use crate::{Chunk, Type, Value, ValueError, ValueRef};
|
||||
use crate::{Chunk, Type, Value, ValueError};
|
||||
|
||||
use super::RangeValue;
|
||||
|
||||
@ -27,10 +27,6 @@ impl ConcreteValue {
|
||||
Value::Concrete(self)
|
||||
}
|
||||
|
||||
pub fn to_value_ref(&self) -> ValueRef {
|
||||
ValueRef::Concrete(self)
|
||||
}
|
||||
|
||||
pub fn function(chunk: Chunk) -> Self {
|
||||
ConcreteValue::Function(Box::new(chunk))
|
||||
}
|
||||
|
@ -6,25 +6,20 @@ mod range_value;
|
||||
pub use abstract_value::AbstractValue;
|
||||
pub use concrete_value::{ConcreteValue, DustString};
|
||||
pub use range_value::RangeValue;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
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 {
|
||||
#[serde(skip)]
|
||||
Abstract(AbstractValue),
|
||||
Concrete(ConcreteValue),
|
||||
}
|
||||
|
||||
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 {
|
||||
match self {
|
||||
Value::Abstract(abstract_value) => abstract_value.to_concrete_owned(vm),
|
||||
@ -39,58 +34,24 @@ impl Value {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Value {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
pub fn r#type(&self) -> Type {
|
||||
match self {
|
||||
Value::Abstract(abstract_value) => write!(f, "{}", abstract_value),
|
||||
Value::Concrete(concrete_value) => write!(f, "{}", concrete_value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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()),
|
||||
Value::Abstract(abstract_value) => abstract_value.r#type(),
|
||||
Value::Concrete(concrete_value) => concrete_value.r#type(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_concrete_owned(self, vm: &Vm) -> ConcreteValue {
|
||||
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> {
|
||||
pub fn add(&self, other: &Value) -> Result<Value, ValueError> {
|
||||
match (self, other) {
|
||||
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => {
|
||||
left.add(right).map(Value::Concrete)
|
||||
}
|
||||
(Value::Concrete(left), Value::Concrete(right)) => left.add(right).map(Value::Concrete),
|
||||
_ => 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) {
|
||||
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => {
|
||||
(Value::Concrete(left), Value::Concrete(right)) => {
|
||||
left.subtract(right).map(Value::Concrete)
|
||||
}
|
||||
_ => 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) {
|
||||
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => {
|
||||
(Value::Concrete(left), Value::Concrete(right)) => {
|
||||
left.multiply(right).map(Value::Concrete)
|
||||
}
|
||||
_ => 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) {
|
||||
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => {
|
||||
(Value::Concrete(left), Value::Concrete(right)) => {
|
||||
left.divide(right).map(Value::Concrete)
|
||||
}
|
||||
_ => 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) {
|
||||
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => {
|
||||
(Value::Concrete(left), Value::Concrete(right)) => {
|
||||
left.modulo(right).map(Value::Concrete)
|
||||
}
|
||||
_ => Err(ValueError::CannotModulo(self.to_owned(), other.to_owned())),
|
||||
@ -132,51 +93,58 @@ impl ValueRef<'_> {
|
||||
|
||||
pub fn negate(&self) -> Result<Value, ValueError> {
|
||||
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())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn not(&self) -> Result<Value, ValueError> {
|
||||
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())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn equal(&self, other: ValueRef) -> Result<Value, ValueError> {
|
||||
pub fn equal(&self, other: &Value) -> Result<Value, ValueError> {
|
||||
match (self, other) {
|
||||
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => {
|
||||
(Value::Concrete(left), Value::Concrete(right)) => {
|
||||
left.equal(right).map(Value::Concrete)
|
||||
}
|
||||
_ => 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) {
|
||||
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => {
|
||||
(Value::Concrete(left), Value::Concrete(right)) => {
|
||||
left.less_than(right).map(Value::Concrete)
|
||||
}
|
||||
_ => 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) {
|
||||
(ValueRef::Concrete(left), ValueRef::Concrete(right)) => {
|
||||
(Value::Concrete(left), Value::Concrete(right)) => {
|
||||
left.less_than_or_equal(right).map(Value::Concrete)
|
||||
}
|
||||
_ => 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 {
|
||||
match self {
|
||||
ValueRef::Abstract(abstract_value) => write!(f, "{}", abstract_value),
|
||||
ValueRef::Concrete(concrete_value) => write!(f, "{}", concrete_value),
|
||||
Value::Abstract(abstract_value) => write!(f, "{}", abstract_value),
|
||||
Value::Concrete(concrete_value) => write!(f, "{}", concrete_value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ mod runners;
|
||||
use std::{
|
||||
fmt::{self, Display, Formatter},
|
||||
io, iter,
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
use runners::Runner;
|
||||
@ -11,10 +12,10 @@ use smallvec::SmallVec;
|
||||
|
||||
use crate::{
|
||||
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 vm = Vm::new(source, &chunk, None, None);
|
||||
|
||||
@ -35,7 +36,7 @@ pub struct Vm<'a> {
|
||||
ip: usize,
|
||||
last_assigned_register: Option<u8>,
|
||||
source: &'a str,
|
||||
return_value: Option<ConcreteValue>,
|
||||
return_value: Option<Value>,
|
||||
}
|
||||
|
||||
impl<'a> Vm<'a> {
|
||||
@ -85,26 +86,31 @@ impl<'a> Vm<'a> {
|
||||
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() {
|
||||
let runner = self.runners[self.ip];
|
||||
|
||||
runner.run(&mut self);
|
||||
self.execute_next_runner();
|
||||
}
|
||||
|
||||
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}");
|
||||
|
||||
match pointer {
|
||||
Pointer::Stack(register_index) => self.open_register(register_index),
|
||||
Pointer::Constant(constant_index) => {
|
||||
let constant = self.get_constant(constant_index);
|
||||
|
||||
ValueRef::Concrete(constant)
|
||||
}
|
||||
Pointer::Constant(constant_index) => self.get_constant(constant_index),
|
||||
Pointer::ParentStack(register_index) => {
|
||||
assert!(self.parent.is_some(), "Vm Error: Expected parent");
|
||||
|
||||
@ -113,15 +119,12 @@ impl<'a> Vm<'a> {
|
||||
Pointer::ParentConstant(constant_index) => {
|
||||
assert!(self.parent.is_some(), "Vm Error: Expected parent");
|
||||
|
||||
self.parent
|
||||
.unwrap()
|
||||
.get_constant(constant_index)
|
||||
.to_value_ref()
|
||||
self.parent.unwrap().get_constant(constant_index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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}");
|
||||
|
||||
match pointer {
|
||||
@ -129,7 +132,7 @@ impl<'a> Vm<'a> {
|
||||
Pointer::Constant(constant_index) => {
|
||||
let constant = self.get_constant(constant_index);
|
||||
|
||||
Some(ValueRef::Concrete(constant))
|
||||
Some(constant)
|
||||
}
|
||||
Pointer::ParentStack(register_index) => {
|
||||
assert!(self.parent.is_some(), "Vm Error: Expected parent");
|
||||
@ -141,18 +144,14 @@ impl<'a> Vm<'a> {
|
||||
Pointer::ParentConstant(constant_index) => {
|
||||
assert!(self.parent.is_some(), "Vm Error: Expected parent");
|
||||
|
||||
let constant = self
|
||||
.parent
|
||||
.unwrap()
|
||||
.get_constant(constant_index)
|
||||
.to_value_ref();
|
||||
let constant = self.parent.unwrap().get_constant(constant_index);
|
||||
|
||||
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}");
|
||||
|
||||
let register_index = register_index as usize;
|
||||
@ -165,13 +164,13 @@ impl<'a> Vm<'a> {
|
||||
let register = &self.stack[register_index];
|
||||
|
||||
match register {
|
||||
Register::Value(value) => value.to_ref(),
|
||||
Register::Value(value) => value,
|
||||
Register::Pointer(pointer) => self.follow_pointer(*pointer),
|
||||
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}");
|
||||
|
||||
let register_index = register_index as usize;
|
||||
@ -184,7 +183,7 @@ impl<'a> Vm<'a> {
|
||||
let register = &self.stack[register_index];
|
||||
|
||||
match register {
|
||||
Register::Value(value) => Some(value.to_ref()),
|
||||
Register::Value(value) => Some(value),
|
||||
Register::Pointer(pointer) => Some(self.follow_pointer(*pointer)),
|
||||
Register::Empty => None,
|
||||
}
|
||||
@ -209,9 +208,9 @@ impl<'a> Vm<'a> {
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
self.get_constant(index).to_value_ref()
|
||||
self.get_constant(index)
|
||||
} else {
|
||||
self.open_register(index)
|
||||
}
|
||||
@ -229,7 +228,7 @@ impl<'a> Vm<'a> {
|
||||
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 constants = self.chunk.constants();
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
use std::{borrow::BorrowMut, cell::RefCell, rc::Rc};
|
||||
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::{AbstractValue, ConcreteValue, NativeFunction, Value, ValueRef};
|
||||
use crate::{AbstractValue, ConcreteValue, NativeFunction, Type, Value};
|
||||
|
||||
use super::{Instruction, InstructionData, Pointer, Register, Vm};
|
||||
|
||||
@ -56,8 +58,7 @@ pub const RUNNER_LOGIC_TABLE: [RunnerLogic; 24] = [
|
||||
r#return,
|
||||
];
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn r#move<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn r#move(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData { b, c, .. } = instruction_data;
|
||||
let from_register_has_value = vm
|
||||
.stack
|
||||
@ -71,9 +72,7 @@ pub fn r#move<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
|
||||
vm.ip += 1;
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
@ -93,9 +92,7 @@ pub fn close<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
|
||||
vm.ip += 1;
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[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;
|
||||
}
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[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;
|
||||
}
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn load_list<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
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 mut item_type = Type::Any;
|
||||
|
||||
for register_index in b..a {
|
||||
if let Register::Empty = stack[register_index as usize] {
|
||||
continue;
|
||||
match &stack[register_index as usize] {
|
||||
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);
|
||||
@ -151,16 +155,18 @@ pub fn load_list<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData)
|
||||
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);
|
||||
|
||||
vm.set_register(a, register);
|
||||
|
||||
vm.ip += 1;
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[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;
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[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;
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[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;
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[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 right = vm.get_argument(c, c_is_constant);
|
||||
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 + right).to_value()
|
||||
}
|
||||
@ -234,9 +234,7 @@ pub fn add<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
|
||||
vm.ip += 1;
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[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 right = vm.get_argument(c, c_is_constant);
|
||||
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 - right).to_value()
|
||||
}
|
||||
@ -266,9 +264,7 @@ pub fn subtract<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
|
||||
vm.ip += 1;
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[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 right = vm.get_argument(c, c_is_constant);
|
||||
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 * right).to_value()
|
||||
}
|
||||
@ -298,9 +294,7 @@ pub fn multiply<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
|
||||
vm.ip += 1;
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[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 right = vm.get_argument(c, c_is_constant);
|
||||
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 / right).to_value()
|
||||
}
|
||||
@ -330,9 +324,7 @@ pub fn divide<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
|
||||
vm.ip += 1;
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[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 right = vm.get_argument(c, c_is_constant);
|
||||
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 % right).to_value()
|
||||
}
|
||||
@ -362,9 +354,7 @@ pub fn modulo<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
|
||||
vm.ip += 1;
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
@ -376,7 +366,7 @@ pub fn test<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
..
|
||||
} = instruction_data;
|
||||
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
|
||||
} else {
|
||||
panic!(
|
||||
@ -392,9 +382,7 @@ pub fn test<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
vm.ip += 1;
|
||||
}
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
@ -407,7 +395,7 @@ pub fn test_set<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
..
|
||||
} = instruction_data;
|
||||
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
|
||||
} else {
|
||||
panic!(
|
||||
@ -432,9 +420,7 @@ pub fn test_set<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
vm.ip += 1;
|
||||
}
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
@ -457,13 +443,10 @@ pub fn equal<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
vm.ip += 1;
|
||||
}
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn less<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
pub fn less(vm: &mut Vm, instruction_data: InstructionData) {
|
||||
let InstructionData {
|
||||
b,
|
||||
c,
|
||||
@ -482,9 +465,7 @@ pub fn less<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
vm.ip += 1;
|
||||
}
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[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;
|
||||
}
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
@ -522,12 +501,12 @@ pub fn negate<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
} = instruction_data;
|
||||
let argument = vm.get_argument(b, b_is_constant);
|
||||
let negated = match argument {
|
||||
ValueRef::Concrete(value) => match value {
|
||||
Value::Concrete(value) => match value {
|
||||
ConcreteValue::Float(float) => ConcreteValue::Float(-float),
|
||||
ConcreteValue::Integer(integer) => ConcreteValue::Integer(-integer),
|
||||
_ => 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));
|
||||
|
||||
@ -535,9 +514,7 @@ pub fn negate<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
|
||||
vm.ip += 1;
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
@ -550,7 +527,7 @@ pub fn not<'b, 'c>(vm: &'b mut Vm<'c>, instruction_data: InstructionData) {
|
||||
} = instruction_data;
|
||||
let argument = vm.get_argument(b, b_is_constant);
|
||||
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"),
|
||||
};
|
||||
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;
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
@ -576,9 +551,7 @@ pub fn jump<'c>(vm: &mut Vm<'c>, instruction_data: InstructionData) {
|
||||
vm.ip -= offset
|
||||
}
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
@ -591,9 +564,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 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)
|
||||
} 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()))
|
||||
} else {
|
||||
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();
|
||||
|
||||
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.ip += 1;
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[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 first_argument_index = (a - c) 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 {
|
||||
let register = &vm.stack[register_index];
|
||||
let value = match register {
|
||||
Register::Value(value) => value.to_ref(),
|
||||
Register::Value(value) => value,
|
||||
Register::Pointer(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;
|
||||
|
||||
let next = vm.runners[vm.ip];
|
||||
|
||||
next.run(vm);
|
||||
vm.execute_next_runner();
|
||||
}
|
||||
|
||||
#[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 {
|
||||
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);
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user