1
0

Optimize with more SmallVecs

This commit is contained in:
Jeff 2024-12-04 13:31:02 -05:00
parent e5742f6294
commit 1c3c30ac21
20 changed files with 316 additions and 246 deletions

View File

@ -16,8 +16,8 @@ use log::{Level, LevelFilter};
struct Cli {
/// Log level, overrides the DUST_LOG environment variable
///
/// Possible values: trace, debug, info, warn, error
#[arg(short, long, global = true, value_name = "LOG_LEVEL")]
/// Possible values: trace, debug, info, warn, error, off
#[arg(short, long, value_name = "LOG_LEVEL")]
log: Option<LevelFilter>,
#[command(flatten)]
@ -28,7 +28,7 @@ struct Cli {
}
#[derive(Args)]
#[group(required = true, multiple = false)]
#[group(multiple = false)]
struct ModeFlags {
/// Run the source code (default)
#[arg(short, long)]
@ -106,24 +106,6 @@ fn main() {
read_to_string(path).expect("Failed to read file")
};
if mode.run {
let run_result = run(&source);
match run_result {
Ok(Some(value)) => {
if !mode.no_output {
println!("{}", value)
}
}
Ok(None) => {}
Err(error) => {
eprintln!("{}", error.report());
}
}
return;
}
if mode.disassemble {
let chunk = match compile(&source) {
Ok(chunk) => chunk,
@ -157,6 +139,20 @@ fn main() {
write_token_list(&tokens, mode.style, &mut stdout)
}
let run_result = run(&source);
match run_result {
Ok(Some(value)) => {
if !mode.no_output {
println!("{}", value)
}
}
Ok(None) => {}
Err(error) => {
eprintln!("{}", error.report());
}
}
}
#[cfg(test)]

View File

@ -20,7 +20,8 @@ pub struct Chunk {
name: Option<String>,
r#type: FunctionType,
instructions: SmallVec<[(Instruction, Span); 32]>,
instructions: SmallVec<[Instruction; 32]>,
positions: SmallVec<[Span; 32]>,
constants: SmallVec<[ConcreteValue; 16]>,
locals: SmallVec<[Local; 8]>,
}
@ -30,12 +31,13 @@ impl Chunk {
Self {
name,
instructions: SmallVec::new(),
positions: SmallVec::new(),
constants: SmallVec::new(),
locals: SmallVec::new(),
r#type: FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::None),
return_type: Type::None,
},
}
}
@ -43,16 +45,18 @@ impl Chunk {
pub fn with_data(
name: Option<String>,
r#type: FunctionType,
instructions: Vec<(Instruction, Span)>,
constants: Vec<ConcreteValue>,
locals: Vec<Local>,
instructions: SmallVec<[Instruction; 32]>,
positions: SmallVec<[Span; 32]>,
constants: SmallVec<[ConcreteValue; 16]>,
locals: SmallVec<[Local; 8]>,
) -> Self {
Self {
name,
r#type,
instructions: instructions.into(),
constants: constants.into(),
locals: locals.into(),
instructions,
positions,
constants,
locals,
}
}
@ -76,10 +80,14 @@ impl Chunk {
&self.constants
}
pub fn instructions(&self) -> &SmallVec<[(Instruction, Span); 32]> {
pub fn instructions(&self) -> &SmallVec<[Instruction; 32]> {
&self.instructions
}
pub fn positions(&self) -> &SmallVec<[Span; 32]> {
&self.positions
}
pub fn locals(&self) -> &SmallVec<[Local; 8]> {
&self.locals
}
@ -88,7 +96,7 @@ impl Chunk {
self.instructions()
.iter()
.rev()
.find_map(|(instruction, _)| {
.find_map(|instruction| {
if instruction.yields_value() {
Some(instruction.a() as usize + 1)
} else {

View File

@ -8,10 +8,10 @@ use std::{
fmt::{self, Display, Formatter},
mem::replace,
num::{ParseFloatError, ParseIntError},
vec,
};
use colored::Colorize;
use smallvec::{smallvec, SmallVec};
use crate::{
instruction::{
@ -36,12 +36,11 @@ use crate::{
/// ```
pub fn compile(source: &str) -> Result<Chunk, DustError> {
let lexer = Lexer::new(source);
let mut compiler =
Compiler::new(lexer).map_err(|error| DustError::Compile { error, source })?;
let mut compiler = Compiler::new(lexer).map_err(|error| DustError::compile(error, source))?;
compiler
.compile()
.map_err(|error| DustError::Compile { error, source })?;
.map_err(|error| DustError::compile(error, source))?;
let chunk = compiler.finish(None, None);
@ -54,9 +53,9 @@ pub fn compile(source: &str) -> Result<Chunk, DustError> {
#[derive(Debug)]
pub struct Compiler<'src> {
self_name: Option<DustString>,
instructions: Vec<(Instruction, Type, Span)>,
constants: Vec<ConcreteValue>,
locals: Vec<Local>,
instructions: SmallVec<[(Instruction, Type, Span); 32]>,
constants: SmallVec<[ConcreteValue; 16]>,
locals: SmallVec<[Local; 8]>,
lexer: Lexer<'src>,
@ -83,9 +82,9 @@ impl<'src> Compiler<'src> {
Ok(Compiler {
self_name: None,
instructions: Vec::new(),
constants: Vec::new(),
locals: Vec::new(),
instructions: SmallVec::new(),
constants: SmallVec::new(),
locals: SmallVec::new(),
lexer,
current_token,
current_position,
@ -100,26 +99,27 @@ impl<'src> Compiler<'src> {
pub fn finish(
self,
type_parameters: Option<Vec<u16>>,
value_parameters: Option<Vec<(u16, Type)>>,
type_parameters: Option<SmallVec<[u16; 4]>>,
value_parameters: Option<SmallVec<[(u16, Type); 4]>>,
) -> Chunk {
log::info!("End chunk");
let r#type = FunctionType {
type_parameters,
value_parameters,
return_type: Box::new(self.return_type.unwrap_or(Type::None)),
return_type: self.return_type.unwrap_or(Type::None),
};
let instructions = self
let (instructions, positions) = self
.instructions
.into_iter()
.map(|(i, _, s)| (i, s))
.collect();
.map(|(instruction, _, position)| (instruction, position))
.unzip();
Chunk::with_data(
self.self_name,
r#type,
instructions,
positions,
self.constants,
self.locals,
)
@ -1301,7 +1301,7 @@ impl<'src> Compiler<'src> {
let end = self.previous_position.1;
let destination = self.next_register();
let argument_count = destination - start_register;
let return_type = *function.r#type().return_type;
let return_type = function.r#type().return_type;
let call_native = Instruction::from(CallNative {
destination: Destination::Register(destination),
function,
@ -1453,7 +1453,7 @@ impl<'src> Compiler<'src> {
function_compiler.expect(Token::LeftParenthesis)?;
let mut value_parameters: Option<Vec<(u16, Type)>> = None;
let mut value_parameters: Option<SmallVec<[(u16, Type); 4]>> = None;
while !function_compiler.allow(Token::RightParenthesis)? {
let is_mutable = function_compiler.allow(Token::Mut)?;
@ -1488,7 +1488,7 @@ impl<'src> Compiler<'src> {
if let Some(value_parameters) = value_parameters.as_mut() {
value_parameters.push((identifier_index, r#type));
} else {
value_parameters = Some(vec![(identifier_index, r#type)]);
value_parameters = Some(smallvec![(identifier_index, r#type)]);
};
function_compiler.minimum_register += 1;
@ -1504,12 +1504,12 @@ impl<'src> Compiler<'src> {
function_compiler.advance()?;
Box::new(r#type)
r#type
} else {
Box::new(Type::None)
Type::None
};
function_compiler.return_type = Some((*return_type).clone());
function_compiler.return_type = Some((return_type).clone());
function_compiler.expect(Token::LeftBrace)?;
function_compiler.compile()?;
@ -1536,7 +1536,7 @@ impl<'src> Compiler<'src> {
if let Some((identifier, position)) = identifier_info {
let (local_index, _) = self.declare_local(
identifier,
Type::Function(function_type.clone()),
Type::function(function_type.clone()),
false,
self.current_scope,
);
@ -1553,7 +1553,7 @@ impl<'src> Compiler<'src> {
self.emit_instruction(
load_constant,
Type::Function(function_type),
Type::function(function_type),
Span(function_start, function_end),
);
self.emit_instruction(define_local, Type::None, position);
@ -1566,7 +1566,7 @@ impl<'src> Compiler<'src> {
self.emit_instruction(
load_constant,
Type::Function(function_type),
Type::function(function_type),
Span(function_start, function_end),
);
}
@ -1598,7 +1598,7 @@ impl<'src> Compiler<'src> {
})?;
let register_type = self.get_register_type(function.index())?;
let function_return_type = match register_type {
Type::Function(function_type) => *function_type.return_type,
Type::Function(function_type) => function_type.return_type,
Type::SelfChunk => self.return_type.clone().unwrap_or(Type::None),
_ => {
return Err(CompileError::ExpectedFunction {
@ -1610,12 +1610,8 @@ impl<'src> Compiler<'src> {
};
let start = self.current_position.0;
println!("{} {}", self.previous_token, self.current_token);
self.advance()?;
println!("{} {}", self.previous_token, self.current_token);
let mut argument_count = 0;
while !self.allow(Token::RightParenthesis)? {

View File

@ -209,7 +209,13 @@ impl<'a> Disassembler<'a> {
self.push_header(line);
}
for (index, (instruction, position)) in self.chunk.instructions().iter().enumerate() {
for (index, (instruction, position)) in self
.chunk
.instructions()
.iter()
.zip(self.chunk.positions().iter())
.enumerate()
{
let position = position.to_string();
let operation = instruction.operation().to_string();
let info = instruction.disassembly_info();

View File

@ -1,7 +1,10 @@
//! Top-level Dust errors with source code annotations.
use std::fmt::{self, Display, Formatter};
use annotate_snippets::{Level, Renderer, Snippet};
use crate::{vm::VmError, CompileError, Span};
use crate::{CompileError, Span, VmError};
/// A top-level error that can occur during the execution of Dust code.
///
@ -19,43 +22,60 @@ pub enum DustError<'src> {
}
impl<'src> DustError<'src> {
pub fn report(&self) -> String {
pub fn compile(error: CompileError, source: &'src str) -> Self {
DustError::Compile { error, source }
}
pub fn runtime(error: VmError, source: &'src str) -> Self {
DustError::Runtime { error, source }
}
pub fn create_report(&self) -> String {
let (position, title, description, details) = self.error_data();
let label = format!("{}: {}", title, description);
let details = details.unwrap_or_else(|| "While parsing this code".to_string());
let message = Level::Error.title(&label).snippet(
Snippet::source(self.source())
.fold(false)
.annotation(Level::Error.span(position.0..position.1).label(&details)),
);
let mut report = String::new();
let renderer = Renderer::styled();
match self {
DustError::Runtime { error, source } => {
let position = error.position();
let label = format!("{}: {}", VmError::title(), error.description());
let details = error
.details()
.unwrap_or_else(|| "While running this code".to_string());
let message = Level::Error.title(&label).snippet(
Snippet::source(source)
.fold(false)
.annotation(Level::Error.span(position.0..position.1).label(&details)),
);
report.push_str(&renderer.render(message).to_string());
}
DustError::Compile { error, source } => {
let position = error.position();
let label = format!("{}: {}", CompileError::title(), error.description());
let details = error
.details()
.unwrap_or_else(|| "While parsing this code".to_string());
let message = Level::Error.title(&label).snippet(
Snippet::source(source)
.fold(false)
.annotation(Level::Error.span(position.0..position.1).label(&details)),
);
report.push_str(&renderer.render(message).to_string());
}
}
report.push_str(&renderer.render(message).to_string());
report
}
fn error_data(&self) -> (Span, &str, &str, Option<String>) {
match self {
Self::Compile { error, .. } => (
error.position(),
CompileError::title(),
error.description(),
error.details(),
),
Self::Runtime { error, .. } => (
error.position(),
VmError::title(),
error.description(),
error.details(),
),
}
}
fn source(&self) -> &str {
match self {
Self::Compile { source, .. } => source,
Self::Runtime { source, .. } => source,
}
}
}
impl Display for DustError<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.create_report())
}
}
pub trait AnnotatedError {

View File

@ -35,10 +35,9 @@ pub fn lex(source: &str) -> Result<Vec<(Token, Span)>, DustError> {
let mut tokens = Vec::new();
loop {
let (token, span) = lexer.next_token().map_err(|error| DustError::Compile {
error: CompileError::Lex(error),
source,
})?;
let (token, span) = lexer
.next_token()
.map_err(|error| DustError::compile(CompileError::Lex(error), source))?;
tokens.push((token, span));

View File

@ -11,6 +11,7 @@ use std::{
};
use serde::{Deserialize, Serialize};
use smallvec::smallvec;
use crate::{AnnotatedError, FunctionType, Instruction, Span, Type, Value, Vm, VmError};
@ -68,7 +69,7 @@ macro_rules! define_native_function {
pub fn returns_value(&self) -> bool {
match self {
$(
NativeFunction::$name => *$type.return_type != Type::None,
NativeFunction::$name => $type.return_type != Type::None,
)*
}
}
@ -131,7 +132,7 @@ define_native_function! {
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::None)
return_type: Type::None
},
logic::panic
),
@ -147,8 +148,8 @@ define_native_function! {
"to_string",
FunctionType {
type_parameters: None,
value_parameters: Some(vec![(0, Type::Any)]),
return_type: Box::new(Type::String)
value_parameters: Some(smallvec![(0, Type::Any)]),
return_type: Type::String
},
logic::to_string
),
@ -209,7 +210,7 @@ define_native_function! {
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::String)
return_type: Type::String
},
logic::read_line
),
@ -224,8 +225,8 @@ define_native_function! {
"write",
FunctionType {
type_parameters: None,
value_parameters: Some(vec![(0, Type::String)]),
return_type: Box::new(Type::None)
value_parameters: Some(smallvec![(0, Type::String)]),
return_type: Type::None
},
logic::write
),
@ -236,8 +237,8 @@ define_native_function! {
"write_line",
FunctionType {
type_parameters: None,
value_parameters: Some(vec![(0, Type::String)]),
return_type: Box::new(Type::None)
value_parameters: Some(smallvec![(0, Type::String)]),
return_type: Type::None
},
logic::write_line
)

View File

@ -1,5 +1,7 @@
//! Tools used by the compiler to optimize a chunk's bytecode.
use smallvec::SmallVec;
use crate::{instruction::SetLocal, Instruction, Operation, Span, Type};
fn get_last_operations<const COUNT: usize>(
@ -83,7 +85,7 @@ pub fn optimize_control_flow(instructions: &mut [(Instruction, Type, Span)]) {
/// The instructions must be in the following order:
/// - `Add`, `Subtract`, `Multiply`, `Divide` or `Modulo`
/// - `SetLocal`
pub fn optimize_set_local(instructions: &mut Vec<(Instruction, Type, Span)>) {
pub fn optimize_set_local(instructions: &mut SmallVec<[(Instruction, Type, Span); 32]>) {
if !matches!(
get_last_operations(instructions),
Some([

View File

@ -6,6 +6,7 @@ use std::{
};
use serde::{Deserialize, Serialize};
use smallvec::SmallVec;
/// Description of a kind of value.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
@ -16,7 +17,7 @@ pub enum Type {
Character,
Enum(EnumType),
Float,
Function(FunctionType),
Function(Box<FunctionType>),
Generic {
identifier_index: u8,
concrete_type: Option<Box<Type>>,
@ -24,7 +25,7 @@ pub enum Type {
Integer,
List(Box<Type>),
Map {
pairs: HashMap<u8, Type>,
pairs: Box<SmallVec<[(u8, Type); 8]>>,
},
None,
Range {
@ -34,11 +35,19 @@ pub enum Type {
String,
Struct(StructType),
Tuple {
fields: Option<Vec<Type>>,
fields: Option<Box<SmallVec<[Type; 4]>>>,
},
}
impl Type {
pub fn function(function_type: FunctionType) -> Self {
Type::Function(Box::new(function_type))
}
pub fn list(element_type: Type) -> Self {
Type::List(Box::new(element_type))
}
/// Returns a concrete type, either the type itself or the concrete type of a generic type.
pub fn concrete_type(&self) -> &Type {
if let Type::Generic {
@ -107,18 +116,18 @@ impl Type {
return Ok(());
}
(
Type::Function(FunctionType {
(Type::Function(left_function_type), Type::Function(right_function_type)) => {
let FunctionType {
type_parameters: left_type_parameters,
value_parameters: left_value_parameters,
return_type: left_return,
}),
Type::Function(FunctionType {
} = left_function_type.as_ref();
let FunctionType {
type_parameters: right_type_parameters,
value_parameters: right_value_parameters,
return_type: right_return,
}),
) => {
} = right_function_type.as_ref();
if left_return != right_return
|| left_type_parameters != right_type_parameters
|| left_value_parameters != right_value_parameters
@ -269,9 +278,23 @@ impl Ord for Type {
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct FunctionType {
pub type_parameters: Option<Vec<u16>>,
pub value_parameters: Option<Vec<(u16, Type)>>,
pub return_type: Box<Type>,
pub type_parameters: Option<SmallVec<[u16; 4]>>,
pub value_parameters: Option<SmallVec<[(u16, Type); 4]>>,
pub return_type: Type,
}
impl FunctionType {
pub fn new<T: Into<SmallVec<[u16; 4]>>, U: Into<SmallVec<[(u16, Type); 4]>>>(
type_parameters: Option<T>,
value_parameters: Option<U>,
return_type: Type,
) -> Self {
FunctionType {
type_parameters: type_parameters.map(|into_types| into_types.into()),
value_parameters: value_parameters.map(|into_values| into_values.into()),
return_type,
}
}
}
impl Display for FunctionType {
@ -306,7 +329,7 @@ impl Display for FunctionType {
write!(f, ")")?;
if *self.return_type != Type::None {
if self.return_type != Type::None {
write!(f, " -> {}", self.return_type)?;
}

View File

@ -57,7 +57,7 @@ impl ConcreteValue {
ConcreteValue::Byte(_) => Type::Byte,
ConcreteValue::Character(_) => Type::Character,
ConcreteValue::Float(_) => Type::Float,
ConcreteValue::Function(chunk) => Type::Function(chunk.r#type().clone()),
ConcreteValue::Function(chunk) => Type::function(chunk.r#type().clone()),
ConcreteValue::Integer(_) => Type::Integer,
ConcreteValue::List(list) => {
let item_type = list.first().map_or(Type::Any, |item| item.r#type());

View File

@ -14,10 +14,9 @@ use crate::{
pub fn run(source: &str) -> Result<Option<ConcreteValue>, DustError> {
let chunk = compile(source)?;
let mut vm = Vm::new(&chunk, None);
let mut vm = Vm::new(source, &chunk, None);
vm.run()
.map_err(|error| DustError::Runtime { error, source })
vm.run().map_err(|error| DustError::runtime(error, source))
}
/// Dust virtual machine.
@ -25,18 +24,19 @@ pub fn run(source: &str) -> Result<Option<ConcreteValue>, DustError> {
/// See the [module-level documentation](index.html) for more information.
#[derive(Debug)]
pub struct Vm<'a> {
chunk: &'a Chunk,
stack: SmallVec<[Register; 64]>,
chunk: &'a Chunk,
parent: Option<&'a Vm<'a>>,
local_definitions: SmallVec<[Option<u16>; 16]>,
ip: usize,
last_assigned_register: Option<u16>,
current_position: Span,
source: &'a str,
}
impl<'a> Vm<'a> {
pub fn new(chunk: &'a Chunk, parent: Option<&'a Vm<'a>>) -> Self {
pub fn new(source: &'a str, chunk: &'a Chunk, parent: Option<&'a Vm<'a>>) -> Self {
Self {
chunk,
stack: smallvec![Register::Empty; chunk.stack_size()],
@ -44,7 +44,7 @@ impl<'a> Vm<'a> {
local_definitions: smallvec![None; chunk.locals().len()],
ip: 0,
last_assigned_register: None,
current_position: Span(0, 0),
source,
}
}
@ -53,7 +53,7 @@ impl<'a> Vm<'a> {
}
pub fn current_position(&self) -> Span {
self.current_position
self.chunk.positions()[self.ip.saturating_sub(1)]
}
pub fn run(&mut self) -> Result<Option<ConcreteValue>, VmError> {
@ -63,7 +63,7 @@ impl<'a> Vm<'a> {
log::info!(
"{} | {} | {} | {}",
self.ip - 1,
self.current_position,
self.current_position(),
instruction.operation(),
instruction.disassembly_info()
);
@ -86,7 +86,7 @@ impl<'a> Vm<'a> {
if self.stack.len() < to as usize {
return Err(VmError::StackUnderflow {
position: self.current_position,
position: self.current_position(),
});
}
@ -173,7 +173,7 @@ impl<'a> Vm<'a> {
let local_register = self.local_definitions[local_index as usize].ok_or(
VmError::UndefinedLocal {
local_index,
position: self.current_position,
position: self.current_position(),
},
)?;
let register = Register::Pointer(Pointer::Stack(local_register));
@ -199,7 +199,17 @@ impl<'a> Vm<'a> {
let right = self.get_argument(right)?;
let sum_result = left.add(right);
assert!(sum_result.is_ok(), "VM Error: {}", sum_result.unwrap_err());
assert!(
sum_result.is_ok(),
"VM Error: {}",
DustError::runtime(
VmError::Value {
error: sum_result.unwrap_err(),
position: self.current_position()
},
self.source
)
);
let sum = sum_result.unwrap();
@ -216,7 +226,7 @@ impl<'a> Vm<'a> {
let right = self.get_argument(right)?;
let difference = left.subtract(right).map_err(|error| VmError::Value {
error,
position: self.current_position,
position: self.current_position(),
})?;
self.set_register(register_index, Register::Value(difference))?;
@ -232,7 +242,7 @@ impl<'a> Vm<'a> {
let right = self.get_argument(right)?;
let product = left.multiply(right).map_err(|error| VmError::Value {
error,
position: self.current_position,
position: self.current_position(),
})?;
self.set_register(register_index, Register::Value(product))?;
@ -248,7 +258,7 @@ impl<'a> Vm<'a> {
let right = self.get_argument(right)?;
let quotient = left.divide(right).map_err(|error| VmError::Value {
error,
position: self.current_position,
position: self.current_position(),
})?;
self.set_register(register_index, Register::Value(quotient))?;
@ -264,7 +274,7 @@ impl<'a> Vm<'a> {
let right = self.get_argument(right)?;
let remainder = left.modulo(right).map_err(|error| VmError::Value {
error,
position: self.current_position,
position: self.current_position(),
})?;
self.set_register(register_index, Register::Value(remainder))?;
@ -281,7 +291,7 @@ impl<'a> Vm<'a> {
} else {
return Err(VmError::ExpectedBoolean {
found: value.to_owned(),
position: self.current_position,
position: self.current_position(),
});
};
@ -303,7 +313,7 @@ impl<'a> Vm<'a> {
} else {
return Err(VmError::ExpectedBoolean {
found: value.to_owned(),
position: self.current_position,
position: self.current_position(),
});
};
@ -316,7 +326,7 @@ impl<'a> Vm<'a> {
let register_index = self.local_definitions[local_index as usize]
.ok_or(VmError::UndefinedLocal {
local_index,
position: self.current_position,
position: self.current_position(),
})?;
Pointer::Stack(register_index)
@ -334,7 +344,7 @@ impl<'a> Vm<'a> {
let right = self.get_argument(right)?;
let equal_result = left.equal(right).map_err(|error| VmError::Value {
error,
position: self.current_position,
position: self.current_position(),
})?;
let is_equal =
if let Value::Concrete(ConcreteValue::Boolean(boolean)) = equal_result {
@ -342,7 +352,7 @@ impl<'a> Vm<'a> {
} else {
return Err(VmError::ExpectedBoolean {
found: equal_result,
position: self.current_position,
position: self.current_position(),
});
};
@ -360,7 +370,7 @@ impl<'a> Vm<'a> {
less_result.is_ok(),
"VM Error: {}\nPosition: {}",
less_result.unwrap_err(),
self.current_position
self.current_position()
);
let less_than_value = less_result.unwrap();
@ -369,7 +379,7 @@ impl<'a> Vm<'a> {
assert!(
less_than_boolean.is_some(),
"VM Error: Expected a boolean\nPosition: {}",
self.current_position
self.current_position()
);
let is_less_than = less_than_boolean.unwrap();
@ -386,7 +396,7 @@ impl<'a> Vm<'a> {
left.less_than_or_equal(right)
.map_err(|error| VmError::Value {
error,
position: self.current_position,
position: self.current_position(),
})?;
let is_less_than_or_equal =
if let Value::Concrete(ConcreteValue::Boolean(boolean)) =
@ -396,7 +406,7 @@ impl<'a> Vm<'a> {
} else {
return Err(VmError::ExpectedBoolean {
found: less_or_equal_result,
position: self.current_position,
position: self.current_position(),
});
};
@ -412,7 +422,7 @@ impl<'a> Vm<'a> {
let value = self.get_argument(argument)?;
let negated = value.negate().map_err(|error| VmError::Value {
error,
position: self.current_position,
position: self.current_position(),
})?;
let register_index = self.get_destination(destination)?;
let register = Register::Value(negated);
@ -427,7 +437,7 @@ impl<'a> Vm<'a> {
let value = self.get_argument(argument)?;
let not = value.not().map_err(|error| VmError::Value {
error,
position: self.current_position,
position: self.current_position(),
})?;
let register_index = self.get_destination(destination)?;
let register = Register::Value(not);
@ -458,10 +468,10 @@ impl<'a> Vm<'a> {
} else {
return Err(VmError::ExpectedFunction {
found: function.to_concrete_owned(self)?,
position: self.current_position,
position: self.current_position(),
});
};
let mut function_vm = Vm::new(chunk, Some(self));
let mut function_vm = Vm::new(self.source, chunk, Some(self));
let first_argument_index = register_index - argument_count;
for (argument_index, argument_register_index) in
@ -515,7 +525,7 @@ impl<'a> Vm<'a> {
Ok(Some(return_value))
} else {
Err(VmError::StackUnderflow {
position: self.current_position,
position: self.current_position(),
})
};
}
@ -536,7 +546,7 @@ impl<'a> Vm<'a> {
.parent
.as_ref()
.ok_or_else(|| VmError::ExpectedParent {
position: self.current_position,
position: self.current_position(),
})?;
parent.open_register(register_index)
@ -546,7 +556,7 @@ impl<'a> Vm<'a> {
.parent
.as_ref()
.ok_or_else(|| VmError::ExpectedParent {
position: self.current_position,
position: self.current_position(),
})?;
let constant = parent.get_constant(constant_index);
@ -572,7 +582,7 @@ impl<'a> Vm<'a> {
Register::Pointer(pointer) => self.follow_pointer(*pointer),
Register::Empty => Err(VmError::EmptyRegister {
index: register_index,
position: self.current_position,
position: self.current_position(),
}),
}
}
@ -587,7 +597,7 @@ impl<'a> Vm<'a> {
.get(register_index)
.ok_or_else(|| VmError::RegisterIndexOutOfBounds {
index: register_index,
position: self.current_position,
position: self.current_position(),
})?;
log::trace!("Open R{register_index} to {register}");
@ -685,7 +695,7 @@ impl<'a> Vm<'a> {
self.local_definitions[local_index].ok_or_else(|| VmError::UndefinedLocal {
local_index: local_index as u16,
position: self.current_position,
position: self.current_position(),
})
}
@ -693,12 +703,21 @@ impl<'a> Vm<'a> {
fn read(&mut self) -> Instruction {
let instructions = self.chunk.instructions();
assert!(self.ip < instructions.len(), "VM Error: IP out of bounds");
assert!(
self.ip < instructions.len(),
"{}",
DustError::runtime(
VmError::InstructionIndexOutOfBounds {
index: self.ip,
position: self.current_position()
},
self.source,
)
);
let (instruction, position) = instructions[self.ip];
let instruction = instructions[self.ip];
self.ip += 1;
self.current_position = position;
instruction
}

View File

@ -6,7 +6,7 @@ fn add_assign_expects_mutable_variable() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::ExpectedMutableVariable {
found: Token::Integer("1").to_owned(),
position: Span(0, 1)
@ -22,7 +22,7 @@ fn divide_assign_expects_mutable_variable() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::ExpectedMutableVariable {
found: Token::Integer("1").to_owned(),
position: Span(0, 1)
@ -38,7 +38,7 @@ fn multiply_assign_expects_mutable_variable() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::ExpectedMutableVariable {
found: Token::Integer("1").to_owned(),
position: Span(0, 1)
@ -54,7 +54,7 @@ fn subtract_assign_expects_mutable_variable() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::ExpectedMutableVariable {
found: Token::Integer("1").to_owned(),
position: Span(0, 1)
@ -70,7 +70,7 @@ fn modulo_assign_expects_mutable_variable() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::ExpectedMutableVariable {
found: Token::Integer("1").to_owned(),
position: Span(0, 1)

View File

@ -6,7 +6,7 @@ fn add_boolean_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddType {
argument_type: Type::Boolean,
position: Span(0, 4)
@ -22,7 +22,7 @@ fn add_boolean_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddType {
argument_type: Type::Boolean,
position: Span(4, 8)
@ -38,7 +38,7 @@ fn add_function_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddType {
argument_type: Type::Function(FunctionType {
type_parameters: None,
@ -58,7 +58,7 @@ fn add_function_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddType {
argument_type: Type::Function(FunctionType {
type_parameters: None,
@ -78,7 +78,7 @@ fn add_list_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddType {
argument_type: Type::List(Box::new(Type::Integer)),
position: Span(0, 6)
@ -94,7 +94,7 @@ fn add_list_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddType {
argument_type: Type::List(Box::new(Type::Integer)),
position: Span(4, 10)
@ -121,7 +121,7 @@ fn add_byte_and_character() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::Byte,
right_type: Type::Character,
@ -138,7 +138,7 @@ fn add_byte_and_integer() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::Byte,
right_type: Type::Integer,
@ -155,7 +155,7 @@ fn add_byte_and_string() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::Byte,
right_type: Type::String,
@ -172,7 +172,7 @@ fn add_character_and_byte() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::Character,
right_type: Type::Byte,
@ -189,7 +189,7 @@ fn add_character_and_float() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::Character,
right_type: Type::Float,
@ -206,7 +206,7 @@ fn add_character_and_integer() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::Character,
right_type: Type::Integer,
@ -223,7 +223,7 @@ fn add_float_and_byte() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::Float,
right_type: Type::Byte,
@ -240,7 +240,7 @@ fn add_float_and_character() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::Float,
right_type: Type::Character,
@ -257,7 +257,7 @@ fn add_float_and_integer() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::Float,
right_type: Type::Integer,
@ -274,7 +274,7 @@ fn add_float_and_string() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::Float,
right_type: Type::String,
@ -291,7 +291,7 @@ fn add_integer_and_byte() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::Integer,
right_type: Type::Byte,
@ -308,7 +308,7 @@ fn add_integer_and_character() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::Integer,
right_type: Type::Character,
@ -325,7 +325,7 @@ fn add_integer_and_float() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::Integer,
right_type: Type::Float,
@ -342,7 +342,7 @@ fn add_integer_and_string() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::Integer,
right_type: Type::String,
@ -359,7 +359,7 @@ fn add_string_and_byte() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::String,
right_type: Type::Byte,
@ -376,7 +376,7 @@ fn add_string_and_float() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::String,
right_type: Type::Float,
@ -393,7 +393,7 @@ fn add_string_and_integer() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotAddArguments {
left_type: Type::String,
right_type: Type::Integer,

View File

@ -6,7 +6,7 @@ fn divide_boolean_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotDivideType {
argument_type: Type::Boolean,
position: Span(0, 4)
@ -22,7 +22,7 @@ fn divide_boolean_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotDivideType {
argument_type: Type::Boolean,
position: Span(4, 8)
@ -38,7 +38,7 @@ fn divide_character_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotDivideType {
argument_type: Type::Character,
position: Span(0, 3)
@ -54,7 +54,7 @@ fn divide_character_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotDivideType {
argument_type: Type::Character,
position: Span(4, 7)
@ -70,7 +70,7 @@ fn divide_float_and_character() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotDivideType {
argument_type: Type::Character,
position: Span(6, 9)
@ -86,7 +86,7 @@ fn divide_float_and_integer() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotDivideArguments {
left_type: Type::Float,
right_type: Type::Integer,
@ -103,7 +103,7 @@ fn divide_function_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotDivideType {
argument_type: Type::Function(FunctionType {
type_parameters: None,
@ -123,7 +123,7 @@ fn divide_function_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotDivideType {
argument_type: Type::Function(FunctionType {
type_parameters: None,
@ -143,7 +143,7 @@ fn divide_integer_and_float() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotDivideArguments {
left_type: Type::Integer,
right_type: Type::Float,
@ -160,7 +160,7 @@ fn divide_list_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotDivideType {
argument_type: Type::List(Box::new(Type::Integer)),
position: Span(0, 6)
@ -176,7 +176,7 @@ fn divide_list_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotDivideType {
argument_type: Type::List(Box::new(Type::Integer)),
position: Span(4, 10)
@ -202,7 +202,7 @@ fn divide_string_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotDivideType {
argument_type: Type::String,
position: Span(0, 7)
@ -218,7 +218,7 @@ fn divide_string_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotDivideType {
argument_type: Type::String,
position: Span(4, 11)

View File

@ -6,7 +6,7 @@ fn modulo_boolean_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotModuloType {
argument_type: Type::Boolean,
position: Span(0, 4)
@ -22,7 +22,7 @@ fn modulo_boolean_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotModuloType {
argument_type: Type::Boolean,
position: Span(4, 8)
@ -38,7 +38,7 @@ fn modulo_character_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotModuloType {
argument_type: Type::Character,
position: Span(0, 3)
@ -54,7 +54,7 @@ fn modulo_character_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotModuloType {
argument_type: Type::Character,
position: Span(4, 7)
@ -70,7 +70,7 @@ fn modulo_float_and_character() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotModuloType {
argument_type: Type::Character,
position: Span(6, 9)
@ -86,7 +86,7 @@ fn modulo_float_and_integer() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotModuloArguments {
left_type: Type::Float,
right_type: Type::Integer,
@ -103,7 +103,7 @@ fn modulo_function_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotModuloType {
argument_type: Type::Function(FunctionType {
type_parameters: None,
@ -123,7 +123,7 @@ fn modulo_function_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotModuloType {
argument_type: Type::Function(FunctionType {
type_parameters: None,
@ -143,7 +143,7 @@ fn modulo_integer_and_float() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotModuloArguments {
left_type: Type::Integer,
right_type: Type::Float,
@ -160,7 +160,7 @@ fn modulo_list_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotModuloType {
argument_type: Type::List(Box::new(Type::Integer)),
position: Span(0, 6)
@ -176,7 +176,7 @@ fn modulo_list_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotModuloType {
argument_type: Type::List(Box::new(Type::Integer)),
position: Span(4, 10)
@ -202,7 +202,7 @@ fn modulo_string_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotModuloType {
argument_type: Type::String,
position: Span(0, 7)
@ -218,7 +218,7 @@ fn modulo_string_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotModuloType {
argument_type: Type::String,
position: Span(4, 11)

View File

@ -6,7 +6,7 @@ fn multiply_boolean_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotMultiplyType {
argument_type: Type::Boolean,
position: Span(0, 4)
@ -22,7 +22,7 @@ fn multiply_boolean_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotMultiplyType {
argument_type: Type::Boolean,
position: Span(4, 8)
@ -38,7 +38,7 @@ fn multiply_character_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotMultiplyType {
argument_type: Type::Character,
position: Span(0, 3)
@ -54,7 +54,7 @@ fn multiply_character_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotMultiplyType {
argument_type: Type::Character,
position: Span(4, 7)
@ -70,7 +70,7 @@ fn multiply_float_and_character() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotMultiplyType {
argument_type: Type::Character,
position: Span(6, 9)
@ -86,7 +86,7 @@ fn multiply_float_and_integer() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotMultiplyArguments {
left_type: Type::Float,
right_type: Type::Integer,
@ -103,7 +103,7 @@ fn multiply_function_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotMultiplyType {
argument_type: Type::Function(FunctionType {
type_parameters: None,
@ -123,7 +123,7 @@ fn multiply_function_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotMultiplyType {
argument_type: Type::Function(FunctionType {
type_parameters: None,
@ -143,7 +143,7 @@ fn multiply_integer_and_float() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotMultiplyArguments {
left_type: Type::Integer,
right_type: Type::Float,
@ -160,7 +160,7 @@ fn multiply_list_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotMultiplyType {
argument_type: Type::List(Box::new(Type::Integer)),
position: Span(0, 6)
@ -176,7 +176,7 @@ fn multiply_list_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotMultiplyType {
argument_type: Type::List(Box::new(Type::Integer)),
position: Span(4, 10)
@ -202,7 +202,7 @@ fn multiply_string_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotMultiplyType {
argument_type: Type::String,
position: Span(0, 7)
@ -218,7 +218,7 @@ fn multiply_string_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotMultiplyType {
argument_type: Type::String,
position: Span(4, 11)

View File

@ -6,7 +6,7 @@ fn subtract_boolean_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotSubtractType {
argument_type: Type::Boolean,
position: Span(0, 4)
@ -22,7 +22,7 @@ fn subtract_boolean_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotSubtractType {
argument_type: Type::Boolean,
position: Span(4, 8)
@ -38,7 +38,7 @@ fn subtract_character_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotSubtractType {
argument_type: Type::Character,
position: Span(0, 3)
@ -54,7 +54,7 @@ fn subtract_character_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotSubtractType {
argument_type: Type::Character,
position: Span(4, 7)
@ -70,7 +70,7 @@ fn subtract_float_and_character() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotSubtractType {
argument_type: Type::Character,
position: Span(6, 9)
@ -86,7 +86,7 @@ fn subtract_float_and_integer() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotSubtractArguments {
left_type: Type::Float,
right_type: Type::Integer,
@ -103,7 +103,7 @@ fn subtract_function_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotSubtractType {
argument_type: Type::Function(FunctionType {
type_parameters: None,
@ -123,7 +123,7 @@ fn subtract_function_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotSubtractType {
argument_type: Type::Function(FunctionType {
type_parameters: None,
@ -143,7 +143,7 @@ fn subtract_integer_and_float() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotSubtractArguments {
left_type: Type::Integer,
right_type: Type::Float,
@ -160,7 +160,7 @@ fn subtract_list_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotSubtractType {
argument_type: Type::List(Box::new(Type::Integer)),
position: Span(0, 6)
@ -176,7 +176,7 @@ fn subtract_list_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotSubtractType {
argument_type: Type::List(Box::new(Type::Integer)),
position: Span(4, 10)
@ -202,7 +202,7 @@ fn subtract_string_left() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotSubtractType {
argument_type: Type::String,
position: Span(0, 7)
@ -218,7 +218,7 @@ fn subtract_string_right() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::CannotSubtractType {
argument_type: Type::String,
position: Span(4, 11)

View File

@ -38,7 +38,7 @@ fn panic() {
assert_eq!(
run(source),
Err(DustError::Runtime {
Err(CreateReport::Runtime {
error: VmError::NativeFunction(NativeFunctionError::Panic {
message: Some("Goodbye world! 42".to_string()),
position: Span(0, 27)

View File

@ -205,7 +205,7 @@ fn disallow_access_to_child_scope() {
assert_eq!(
run(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::VariableOutOfScope {
identifier: "x".to_string(),
position: Span(52, 53),
@ -230,7 +230,7 @@ fn disallow_access_to_child_scope_nested() {
assert_eq!(
run(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::VariableOutOfScope {
identifier: "x".to_string(),
position: Span(78, 79),
@ -255,7 +255,7 @@ fn disallow_access_to_sibling_scope() {
assert_eq!(
run(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::VariableOutOfScope {
identifier: "x".to_string(),
variable_scope: Scope::new(1, 1),
@ -282,7 +282,7 @@ fn disallow_access_to_sibling_scope_nested() {
assert_eq!(
run(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::VariableOutOfScope {
identifier: "x".to_string(),
variable_scope: Scope::new(2, 2),

View File

@ -35,7 +35,7 @@ fn let_statement_expects_identifier() {
assert_eq!(
compile(source),
Err(DustError::Compile {
Err(CreateReport::Compile {
error: CompileError::ExpectedToken {
expected: TokenKind::Identifier,
found: Token::Integer("1").to_owned(),