Optimize with more SmallVecs
This commit is contained in:
parent
e5742f6294
commit
1c3c30ac21
@ -16,8 +16,8 @@ use log::{Level, LevelFilter};
|
|||||||
struct Cli {
|
struct Cli {
|
||||||
/// Log level, overrides the DUST_LOG environment variable
|
/// Log level, overrides the DUST_LOG environment variable
|
||||||
///
|
///
|
||||||
/// Possible values: trace, debug, info, warn, error
|
/// Possible values: trace, debug, info, warn, error, off
|
||||||
#[arg(short, long, global = true, value_name = "LOG_LEVEL")]
|
#[arg(short, long, value_name = "LOG_LEVEL")]
|
||||||
log: Option<LevelFilter>,
|
log: Option<LevelFilter>,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
@ -28,7 +28,7 @@ struct Cli {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
#[group(required = true, multiple = false)]
|
#[group(multiple = false)]
|
||||||
struct ModeFlags {
|
struct ModeFlags {
|
||||||
/// Run the source code (default)
|
/// Run the source code (default)
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
@ -106,24 +106,6 @@ fn main() {
|
|||||||
read_to_string(path).expect("Failed to read file")
|
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 {
|
if mode.disassemble {
|
||||||
let chunk = match compile(&source) {
|
let chunk = match compile(&source) {
|
||||||
Ok(chunk) => chunk,
|
Ok(chunk) => chunk,
|
||||||
@ -157,6 +139,20 @@ fn main() {
|
|||||||
|
|
||||||
write_token_list(&tokens, mode.style, &mut stdout)
|
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)]
|
#[cfg(test)]
|
||||||
|
@ -20,7 +20,8 @@ pub struct Chunk {
|
|||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
r#type: FunctionType,
|
r#type: FunctionType,
|
||||||
|
|
||||||
instructions: SmallVec<[(Instruction, Span); 32]>,
|
instructions: SmallVec<[Instruction; 32]>,
|
||||||
|
positions: SmallVec<[Span; 32]>,
|
||||||
constants: SmallVec<[ConcreteValue; 16]>,
|
constants: SmallVec<[ConcreteValue; 16]>,
|
||||||
locals: SmallVec<[Local; 8]>,
|
locals: SmallVec<[Local; 8]>,
|
||||||
}
|
}
|
||||||
@ -30,12 +31,13 @@ impl Chunk {
|
|||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
instructions: SmallVec::new(),
|
instructions: SmallVec::new(),
|
||||||
|
positions: SmallVec::new(),
|
||||||
constants: SmallVec::new(),
|
constants: SmallVec::new(),
|
||||||
locals: SmallVec::new(),
|
locals: SmallVec::new(),
|
||||||
r#type: FunctionType {
|
r#type: FunctionType {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
value_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(
|
pub fn with_data(
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
r#type: FunctionType,
|
r#type: FunctionType,
|
||||||
instructions: Vec<(Instruction, Span)>,
|
instructions: SmallVec<[Instruction; 32]>,
|
||||||
constants: Vec<ConcreteValue>,
|
positions: SmallVec<[Span; 32]>,
|
||||||
locals: Vec<Local>,
|
constants: SmallVec<[ConcreteValue; 16]>,
|
||||||
|
locals: SmallVec<[Local; 8]>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
r#type,
|
r#type,
|
||||||
instructions: instructions.into(),
|
instructions,
|
||||||
constants: constants.into(),
|
positions,
|
||||||
locals: locals.into(),
|
constants,
|
||||||
|
locals,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,10 +80,14 @@ impl Chunk {
|
|||||||
&self.constants
|
&self.constants
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn instructions(&self) -> &SmallVec<[(Instruction, Span); 32]> {
|
pub fn instructions(&self) -> &SmallVec<[Instruction; 32]> {
|
||||||
&self.instructions
|
&self.instructions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn positions(&self) -> &SmallVec<[Span; 32]> {
|
||||||
|
&self.positions
|
||||||
|
}
|
||||||
|
|
||||||
pub fn locals(&self) -> &SmallVec<[Local; 8]> {
|
pub fn locals(&self) -> &SmallVec<[Local; 8]> {
|
||||||
&self.locals
|
&self.locals
|
||||||
}
|
}
|
||||||
@ -88,7 +96,7 @@ impl Chunk {
|
|||||||
self.instructions()
|
self.instructions()
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|(instruction, _)| {
|
.find_map(|instruction| {
|
||||||
if instruction.yields_value() {
|
if instruction.yields_value() {
|
||||||
Some(instruction.a() as usize + 1)
|
Some(instruction.a() as usize + 1)
|
||||||
} else {
|
} else {
|
||||||
|
@ -8,10 +8,10 @@ use std::{
|
|||||||
fmt::{self, Display, Formatter},
|
fmt::{self, Display, Formatter},
|
||||||
mem::replace,
|
mem::replace,
|
||||||
num::{ParseFloatError, ParseIntError},
|
num::{ParseFloatError, ParseIntError},
|
||||||
vec,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
instruction::{
|
instruction::{
|
||||||
@ -36,12 +36,11 @@ use crate::{
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn compile(source: &str) -> Result<Chunk, DustError> {
|
pub fn compile(source: &str) -> Result<Chunk, DustError> {
|
||||||
let lexer = Lexer::new(source);
|
let lexer = Lexer::new(source);
|
||||||
let mut compiler =
|
let mut compiler = Compiler::new(lexer).map_err(|error| DustError::compile(error, source))?;
|
||||||
Compiler::new(lexer).map_err(|error| DustError::Compile { error, source })?;
|
|
||||||
|
|
||||||
compiler
|
compiler
|
||||||
.compile()
|
.compile()
|
||||||
.map_err(|error| DustError::Compile { error, source })?;
|
.map_err(|error| DustError::compile(error, source))?;
|
||||||
|
|
||||||
let chunk = compiler.finish(None, None);
|
let chunk = compiler.finish(None, None);
|
||||||
|
|
||||||
@ -54,9 +53,9 @@ pub fn compile(source: &str) -> Result<Chunk, DustError> {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Compiler<'src> {
|
pub struct Compiler<'src> {
|
||||||
self_name: Option<DustString>,
|
self_name: Option<DustString>,
|
||||||
instructions: Vec<(Instruction, Type, Span)>,
|
instructions: SmallVec<[(Instruction, Type, Span); 32]>,
|
||||||
constants: Vec<ConcreteValue>,
|
constants: SmallVec<[ConcreteValue; 16]>,
|
||||||
locals: Vec<Local>,
|
locals: SmallVec<[Local; 8]>,
|
||||||
|
|
||||||
lexer: Lexer<'src>,
|
lexer: Lexer<'src>,
|
||||||
|
|
||||||
@ -83,9 +82,9 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
Ok(Compiler {
|
Ok(Compiler {
|
||||||
self_name: None,
|
self_name: None,
|
||||||
instructions: Vec::new(),
|
instructions: SmallVec::new(),
|
||||||
constants: Vec::new(),
|
constants: SmallVec::new(),
|
||||||
locals: Vec::new(),
|
locals: SmallVec::new(),
|
||||||
lexer,
|
lexer,
|
||||||
current_token,
|
current_token,
|
||||||
current_position,
|
current_position,
|
||||||
@ -100,26 +99,27 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
pub fn finish(
|
pub fn finish(
|
||||||
self,
|
self,
|
||||||
type_parameters: Option<Vec<u16>>,
|
type_parameters: Option<SmallVec<[u16; 4]>>,
|
||||||
value_parameters: Option<Vec<(u16, Type)>>,
|
value_parameters: Option<SmallVec<[(u16, Type); 4]>>,
|
||||||
) -> Chunk {
|
) -> Chunk {
|
||||||
log::info!("End chunk");
|
log::info!("End chunk");
|
||||||
|
|
||||||
let r#type = FunctionType {
|
let r#type = FunctionType {
|
||||||
type_parameters,
|
type_parameters,
|
||||||
value_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
|
.instructions
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(i, _, s)| (i, s))
|
.map(|(instruction, _, position)| (instruction, position))
|
||||||
.collect();
|
.unzip();
|
||||||
|
|
||||||
Chunk::with_data(
|
Chunk::with_data(
|
||||||
self.self_name,
|
self.self_name,
|
||||||
r#type,
|
r#type,
|
||||||
instructions,
|
instructions,
|
||||||
|
positions,
|
||||||
self.constants,
|
self.constants,
|
||||||
self.locals,
|
self.locals,
|
||||||
)
|
)
|
||||||
@ -1301,7 +1301,7 @@ impl<'src> Compiler<'src> {
|
|||||||
let end = self.previous_position.1;
|
let end = self.previous_position.1;
|
||||||
let destination = self.next_register();
|
let destination = self.next_register();
|
||||||
let argument_count = destination - start_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 {
|
let call_native = Instruction::from(CallNative {
|
||||||
destination: Destination::Register(destination),
|
destination: Destination::Register(destination),
|
||||||
function,
|
function,
|
||||||
@ -1453,7 +1453,7 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
function_compiler.expect(Token::LeftParenthesis)?;
|
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)? {
|
while !function_compiler.allow(Token::RightParenthesis)? {
|
||||||
let is_mutable = function_compiler.allow(Token::Mut)?;
|
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() {
|
if let Some(value_parameters) = value_parameters.as_mut() {
|
||||||
value_parameters.push((identifier_index, r#type));
|
value_parameters.push((identifier_index, r#type));
|
||||||
} else {
|
} else {
|
||||||
value_parameters = Some(vec![(identifier_index, r#type)]);
|
value_parameters = Some(smallvec![(identifier_index, r#type)]);
|
||||||
};
|
};
|
||||||
|
|
||||||
function_compiler.minimum_register += 1;
|
function_compiler.minimum_register += 1;
|
||||||
@ -1504,12 +1504,12 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
function_compiler.advance()?;
|
function_compiler.advance()?;
|
||||||
|
|
||||||
Box::new(r#type)
|
r#type
|
||||||
} else {
|
} 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.expect(Token::LeftBrace)?;
|
||||||
function_compiler.compile()?;
|
function_compiler.compile()?;
|
||||||
@ -1536,7 +1536,7 @@ impl<'src> Compiler<'src> {
|
|||||||
if let Some((identifier, position)) = identifier_info {
|
if let Some((identifier, position)) = identifier_info {
|
||||||
let (local_index, _) = self.declare_local(
|
let (local_index, _) = self.declare_local(
|
||||||
identifier,
|
identifier,
|
||||||
Type::Function(function_type.clone()),
|
Type::function(function_type.clone()),
|
||||||
false,
|
false,
|
||||||
self.current_scope,
|
self.current_scope,
|
||||||
);
|
);
|
||||||
@ -1553,7 +1553,7 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
self.emit_instruction(
|
self.emit_instruction(
|
||||||
load_constant,
|
load_constant,
|
||||||
Type::Function(function_type),
|
Type::function(function_type),
|
||||||
Span(function_start, function_end),
|
Span(function_start, function_end),
|
||||||
);
|
);
|
||||||
self.emit_instruction(define_local, Type::None, position);
|
self.emit_instruction(define_local, Type::None, position);
|
||||||
@ -1566,7 +1566,7 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
self.emit_instruction(
|
self.emit_instruction(
|
||||||
load_constant,
|
load_constant,
|
||||||
Type::Function(function_type),
|
Type::function(function_type),
|
||||||
Span(function_start, function_end),
|
Span(function_start, function_end),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1598,7 +1598,7 @@ impl<'src> Compiler<'src> {
|
|||||||
})?;
|
})?;
|
||||||
let register_type = self.get_register_type(function.index())?;
|
let register_type = self.get_register_type(function.index())?;
|
||||||
let function_return_type = match register_type {
|
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),
|
Type::SelfChunk => self.return_type.clone().unwrap_or(Type::None),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(CompileError::ExpectedFunction {
|
return Err(CompileError::ExpectedFunction {
|
||||||
@ -1610,12 +1610,8 @@ impl<'src> Compiler<'src> {
|
|||||||
};
|
};
|
||||||
let start = self.current_position.0;
|
let start = self.current_position.0;
|
||||||
|
|
||||||
println!("{} {}", self.previous_token, self.current_token);
|
|
||||||
|
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
|
|
||||||
println!("{} {}", self.previous_token, self.current_token);
|
|
||||||
|
|
||||||
let mut argument_count = 0;
|
let mut argument_count = 0;
|
||||||
|
|
||||||
while !self.allow(Token::RightParenthesis)? {
|
while !self.allow(Token::RightParenthesis)? {
|
||||||
|
@ -209,7 +209,13 @@ impl<'a> Disassembler<'a> {
|
|||||||
self.push_header(line);
|
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 position = position.to_string();
|
||||||
let operation = instruction.operation().to_string();
|
let operation = instruction.operation().to_string();
|
||||||
let info = instruction.disassembly_info();
|
let info = instruction.disassembly_info();
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
//! Top-level Dust errors with source code annotations.
|
//! Top-level Dust errors with source code annotations.
|
||||||
|
|
||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use annotate_snippets::{Level, Renderer, Snippet};
|
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.
|
/// 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> {
|
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 mut report = String::new();
|
||||||
let renderer = Renderer::styled();
|
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());
|
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
|
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 {
|
pub trait AnnotatedError {
|
||||||
|
@ -35,10 +35,9 @@ pub fn lex(source: &str) -> Result<Vec<(Token, Span)>, DustError> {
|
|||||||
let mut tokens = Vec::new();
|
let mut tokens = Vec::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (token, span) = lexer.next_token().map_err(|error| DustError::Compile {
|
let (token, span) = lexer
|
||||||
error: CompileError::Lex(error),
|
.next_token()
|
||||||
source,
|
.map_err(|error| DustError::compile(CompileError::Lex(error), source))?;
|
||||||
})?;
|
|
||||||
|
|
||||||
tokens.push((token, span));
|
tokens.push((token, span));
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use smallvec::smallvec;
|
||||||
|
|
||||||
use crate::{AnnotatedError, FunctionType, Instruction, Span, Type, Value, Vm, VmError};
|
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 {
|
pub fn returns_value(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
$(
|
$(
|
||||||
NativeFunction::$name => *$type.return_type != Type::None,
|
NativeFunction::$name => $type.return_type != Type::None,
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,7 +132,7 @@ define_native_function! {
|
|||||||
FunctionType {
|
FunctionType {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
value_parameters: None,
|
value_parameters: None,
|
||||||
return_type: Box::new(Type::None)
|
return_type: Type::None
|
||||||
},
|
},
|
||||||
logic::panic
|
logic::panic
|
||||||
),
|
),
|
||||||
@ -147,8 +148,8 @@ define_native_function! {
|
|||||||
"to_string",
|
"to_string",
|
||||||
FunctionType {
|
FunctionType {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
value_parameters: Some(vec![(0, Type::Any)]),
|
value_parameters: Some(smallvec![(0, Type::Any)]),
|
||||||
return_type: Box::new(Type::String)
|
return_type: Type::String
|
||||||
},
|
},
|
||||||
logic::to_string
|
logic::to_string
|
||||||
),
|
),
|
||||||
@ -209,7 +210,7 @@ define_native_function! {
|
|||||||
FunctionType {
|
FunctionType {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
value_parameters: None,
|
value_parameters: None,
|
||||||
return_type: Box::new(Type::String)
|
return_type: Type::String
|
||||||
},
|
},
|
||||||
logic::read_line
|
logic::read_line
|
||||||
),
|
),
|
||||||
@ -224,8 +225,8 @@ define_native_function! {
|
|||||||
"write",
|
"write",
|
||||||
FunctionType {
|
FunctionType {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
value_parameters: Some(vec![(0, Type::String)]),
|
value_parameters: Some(smallvec![(0, Type::String)]),
|
||||||
return_type: Box::new(Type::None)
|
return_type: Type::None
|
||||||
},
|
},
|
||||||
logic::write
|
logic::write
|
||||||
),
|
),
|
||||||
@ -236,8 +237,8 @@ define_native_function! {
|
|||||||
"write_line",
|
"write_line",
|
||||||
FunctionType {
|
FunctionType {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
value_parameters: Some(vec![(0, Type::String)]),
|
value_parameters: Some(smallvec![(0, Type::String)]),
|
||||||
return_type: Box::new(Type::None)
|
return_type: Type::None
|
||||||
},
|
},
|
||||||
logic::write_line
|
logic::write_line
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
//! Tools used by the compiler to optimize a chunk's bytecode.
|
//! Tools used by the compiler to optimize a chunk's bytecode.
|
||||||
|
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::{instruction::SetLocal, Instruction, Operation, Span, Type};
|
use crate::{instruction::SetLocal, Instruction, Operation, Span, Type};
|
||||||
|
|
||||||
fn get_last_operations<const COUNT: usize>(
|
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:
|
/// The instructions must be in the following order:
|
||||||
/// - `Add`, `Subtract`, `Multiply`, `Divide` or `Modulo`
|
/// - `Add`, `Subtract`, `Multiply`, `Divide` or `Modulo`
|
||||||
/// - `SetLocal`
|
/// - `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!(
|
if !matches!(
|
||||||
get_last_operations(instructions),
|
get_last_operations(instructions),
|
||||||
Some([
|
Some([
|
||||||
|
@ -6,6 +6,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
/// Description of a kind of value.
|
/// Description of a kind of value.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
@ -16,7 +17,7 @@ pub enum Type {
|
|||||||
Character,
|
Character,
|
||||||
Enum(EnumType),
|
Enum(EnumType),
|
||||||
Float,
|
Float,
|
||||||
Function(FunctionType),
|
Function(Box<FunctionType>),
|
||||||
Generic {
|
Generic {
|
||||||
identifier_index: u8,
|
identifier_index: u8,
|
||||||
concrete_type: Option<Box<Type>>,
|
concrete_type: Option<Box<Type>>,
|
||||||
@ -24,7 +25,7 @@ pub enum Type {
|
|||||||
Integer,
|
Integer,
|
||||||
List(Box<Type>),
|
List(Box<Type>),
|
||||||
Map {
|
Map {
|
||||||
pairs: HashMap<u8, Type>,
|
pairs: Box<SmallVec<[(u8, Type); 8]>>,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
Range {
|
Range {
|
||||||
@ -34,11 +35,19 @@ pub enum Type {
|
|||||||
String,
|
String,
|
||||||
Struct(StructType),
|
Struct(StructType),
|
||||||
Tuple {
|
Tuple {
|
||||||
fields: Option<Vec<Type>>,
|
fields: Option<Box<SmallVec<[Type; 4]>>>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Type {
|
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.
|
/// Returns a concrete type, either the type itself or the concrete type of a generic type.
|
||||||
pub fn concrete_type(&self) -> &Type {
|
pub fn concrete_type(&self) -> &Type {
|
||||||
if let Type::Generic {
|
if let Type::Generic {
|
||||||
@ -107,18 +116,18 @@ impl Type {
|
|||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
(
|
(Type::Function(left_function_type), Type::Function(right_function_type)) => {
|
||||||
Type::Function(FunctionType {
|
let FunctionType {
|
||||||
type_parameters: left_type_parameters,
|
type_parameters: left_type_parameters,
|
||||||
value_parameters: left_value_parameters,
|
value_parameters: left_value_parameters,
|
||||||
return_type: left_return,
|
return_type: left_return,
|
||||||
}),
|
} = left_function_type.as_ref();
|
||||||
Type::Function(FunctionType {
|
let FunctionType {
|
||||||
type_parameters: right_type_parameters,
|
type_parameters: right_type_parameters,
|
||||||
value_parameters: right_value_parameters,
|
value_parameters: right_value_parameters,
|
||||||
return_type: right_return,
|
return_type: right_return,
|
||||||
}),
|
} = right_function_type.as_ref();
|
||||||
) => {
|
|
||||||
if left_return != right_return
|
if left_return != right_return
|
||||||
|| left_type_parameters != right_type_parameters
|
|| left_type_parameters != right_type_parameters
|
||||||
|| left_value_parameters != right_value_parameters
|
|| left_value_parameters != right_value_parameters
|
||||||
@ -269,9 +278,23 @@ impl Ord for Type {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct FunctionType {
|
pub struct FunctionType {
|
||||||
pub type_parameters: Option<Vec<u16>>,
|
pub type_parameters: Option<SmallVec<[u16; 4]>>,
|
||||||
pub value_parameters: Option<Vec<(u16, Type)>>,
|
pub value_parameters: Option<SmallVec<[(u16, Type); 4]>>,
|
||||||
pub return_type: Box<Type>,
|
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 {
|
impl Display for FunctionType {
|
||||||
@ -306,7 +329,7 @@ impl Display for FunctionType {
|
|||||||
|
|
||||||
write!(f, ")")?;
|
write!(f, ")")?;
|
||||||
|
|
||||||
if *self.return_type != Type::None {
|
if self.return_type != Type::None {
|
||||||
write!(f, " -> {}", self.return_type)?;
|
write!(f, " -> {}", self.return_type)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ impl ConcreteValue {
|
|||||||
ConcreteValue::Byte(_) => Type::Byte,
|
ConcreteValue::Byte(_) => Type::Byte,
|
||||||
ConcreteValue::Character(_) => Type::Character,
|
ConcreteValue::Character(_) => Type::Character,
|
||||||
ConcreteValue::Float(_) => Type::Float,
|
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::Integer(_) => Type::Integer,
|
||||||
ConcreteValue::List(list) => {
|
ConcreteValue::List(list) => {
|
||||||
let item_type = list.first().map_or(Type::Any, |item| item.r#type());
|
let item_type = list.first().map_or(Type::Any, |item| item.r#type());
|
||||||
|
@ -14,10 +14,9 @@ use crate::{
|
|||||||
|
|
||||||
pub fn run(source: &str) -> Result<Option<ConcreteValue>, DustError> {
|
pub fn run(source: &str) -> Result<Option<ConcreteValue>, DustError> {
|
||||||
let chunk = compile(source)?;
|
let chunk = compile(source)?;
|
||||||
let mut vm = Vm::new(&chunk, None);
|
let mut vm = Vm::new(source, &chunk, None);
|
||||||
|
|
||||||
vm.run()
|
vm.run().map_err(|error| DustError::runtime(error, source))
|
||||||
.map_err(|error| DustError::Runtime { error, source })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dust virtual machine.
|
/// 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.
|
/// See the [module-level documentation](index.html) for more information.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Vm<'a> {
|
pub struct Vm<'a> {
|
||||||
chunk: &'a Chunk,
|
|
||||||
stack: SmallVec<[Register; 64]>,
|
stack: SmallVec<[Register; 64]>,
|
||||||
|
|
||||||
|
chunk: &'a Chunk,
|
||||||
parent: Option<&'a Vm<'a>>,
|
parent: Option<&'a Vm<'a>>,
|
||||||
local_definitions: SmallVec<[Option<u16>; 16]>,
|
local_definitions: SmallVec<[Option<u16>; 16]>,
|
||||||
|
|
||||||
ip: usize,
|
ip: usize,
|
||||||
last_assigned_register: Option<u16>,
|
last_assigned_register: Option<u16>,
|
||||||
current_position: Span,
|
source: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Vm<'a> {
|
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 {
|
Self {
|
||||||
chunk,
|
chunk,
|
||||||
stack: smallvec![Register::Empty; chunk.stack_size()],
|
stack: smallvec![Register::Empty; chunk.stack_size()],
|
||||||
@ -44,7 +44,7 @@ impl<'a> Vm<'a> {
|
|||||||
local_definitions: smallvec![None; chunk.locals().len()],
|
local_definitions: smallvec![None; chunk.locals().len()],
|
||||||
ip: 0,
|
ip: 0,
|
||||||
last_assigned_register: None,
|
last_assigned_register: None,
|
||||||
current_position: Span(0, 0),
|
source,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ impl<'a> Vm<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_position(&self) -> Span {
|
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> {
|
pub fn run(&mut self) -> Result<Option<ConcreteValue>, VmError> {
|
||||||
@ -63,7 +63,7 @@ impl<'a> Vm<'a> {
|
|||||||
log::info!(
|
log::info!(
|
||||||
"{} | {} | {} | {}",
|
"{} | {} | {} | {}",
|
||||||
self.ip - 1,
|
self.ip - 1,
|
||||||
self.current_position,
|
self.current_position(),
|
||||||
instruction.operation(),
|
instruction.operation(),
|
||||||
instruction.disassembly_info()
|
instruction.disassembly_info()
|
||||||
);
|
);
|
||||||
@ -86,7 +86,7 @@ impl<'a> Vm<'a> {
|
|||||||
|
|
||||||
if self.stack.len() < to as usize {
|
if self.stack.len() < to as usize {
|
||||||
return Err(VmError::StackUnderflow {
|
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(
|
let local_register = self.local_definitions[local_index as usize].ok_or(
|
||||||
VmError::UndefinedLocal {
|
VmError::UndefinedLocal {
|
||||||
local_index,
|
local_index,
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
let register = Register::Pointer(Pointer::Stack(local_register));
|
let register = Register::Pointer(Pointer::Stack(local_register));
|
||||||
@ -199,7 +199,17 @@ impl<'a> Vm<'a> {
|
|||||||
let right = self.get_argument(right)?;
|
let right = self.get_argument(right)?;
|
||||||
let sum_result = left.add(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();
|
let sum = sum_result.unwrap();
|
||||||
|
|
||||||
@ -216,7 +226,7 @@ impl<'a> Vm<'a> {
|
|||||||
let right = self.get_argument(right)?;
|
let right = self.get_argument(right)?;
|
||||||
let difference = left.subtract(right).map_err(|error| VmError::Value {
|
let difference = left.subtract(right).map_err(|error| VmError::Value {
|
||||||
error,
|
error,
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.set_register(register_index, Register::Value(difference))?;
|
self.set_register(register_index, Register::Value(difference))?;
|
||||||
@ -232,7 +242,7 @@ impl<'a> Vm<'a> {
|
|||||||
let right = self.get_argument(right)?;
|
let right = self.get_argument(right)?;
|
||||||
let product = left.multiply(right).map_err(|error| VmError::Value {
|
let product = left.multiply(right).map_err(|error| VmError::Value {
|
||||||
error,
|
error,
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.set_register(register_index, Register::Value(product))?;
|
self.set_register(register_index, Register::Value(product))?;
|
||||||
@ -248,7 +258,7 @@ impl<'a> Vm<'a> {
|
|||||||
let right = self.get_argument(right)?;
|
let right = self.get_argument(right)?;
|
||||||
let quotient = left.divide(right).map_err(|error| VmError::Value {
|
let quotient = left.divide(right).map_err(|error| VmError::Value {
|
||||||
error,
|
error,
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.set_register(register_index, Register::Value(quotient))?;
|
self.set_register(register_index, Register::Value(quotient))?;
|
||||||
@ -264,7 +274,7 @@ impl<'a> Vm<'a> {
|
|||||||
let right = self.get_argument(right)?;
|
let right = self.get_argument(right)?;
|
||||||
let remainder = left.modulo(right).map_err(|error| VmError::Value {
|
let remainder = left.modulo(right).map_err(|error| VmError::Value {
|
||||||
error,
|
error,
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.set_register(register_index, Register::Value(remainder))?;
|
self.set_register(register_index, Register::Value(remainder))?;
|
||||||
@ -281,7 +291,7 @@ impl<'a> Vm<'a> {
|
|||||||
} else {
|
} else {
|
||||||
return Err(VmError::ExpectedBoolean {
|
return Err(VmError::ExpectedBoolean {
|
||||||
found: value.to_owned(),
|
found: value.to_owned(),
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -303,7 +313,7 @@ impl<'a> Vm<'a> {
|
|||||||
} else {
|
} else {
|
||||||
return Err(VmError::ExpectedBoolean {
|
return Err(VmError::ExpectedBoolean {
|
||||||
found: value.to_owned(),
|
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]
|
let register_index = self.local_definitions[local_index as usize]
|
||||||
.ok_or(VmError::UndefinedLocal {
|
.ok_or(VmError::UndefinedLocal {
|
||||||
local_index,
|
local_index,
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Pointer::Stack(register_index)
|
Pointer::Stack(register_index)
|
||||||
@ -334,7 +344,7 @@ impl<'a> Vm<'a> {
|
|||||||
let right = self.get_argument(right)?;
|
let right = self.get_argument(right)?;
|
||||||
let equal_result = left.equal(right).map_err(|error| VmError::Value {
|
let equal_result = left.equal(right).map_err(|error| VmError::Value {
|
||||||
error,
|
error,
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
})?;
|
})?;
|
||||||
let is_equal =
|
let is_equal =
|
||||||
if let Value::Concrete(ConcreteValue::Boolean(boolean)) = equal_result {
|
if let Value::Concrete(ConcreteValue::Boolean(boolean)) = equal_result {
|
||||||
@ -342,7 +352,7 @@ impl<'a> Vm<'a> {
|
|||||||
} else {
|
} else {
|
||||||
return Err(VmError::ExpectedBoolean {
|
return Err(VmError::ExpectedBoolean {
|
||||||
found: equal_result,
|
found: equal_result,
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -360,7 +370,7 @@ impl<'a> Vm<'a> {
|
|||||||
less_result.is_ok(),
|
less_result.is_ok(),
|
||||||
"VM Error: {}\nPosition: {}",
|
"VM Error: {}\nPosition: {}",
|
||||||
less_result.unwrap_err(),
|
less_result.unwrap_err(),
|
||||||
self.current_position
|
self.current_position()
|
||||||
);
|
);
|
||||||
|
|
||||||
let less_than_value = less_result.unwrap();
|
let less_than_value = less_result.unwrap();
|
||||||
@ -369,7 +379,7 @@ impl<'a> Vm<'a> {
|
|||||||
assert!(
|
assert!(
|
||||||
less_than_boolean.is_some(),
|
less_than_boolean.is_some(),
|
||||||
"VM Error: Expected a boolean\nPosition: {}",
|
"VM Error: Expected a boolean\nPosition: {}",
|
||||||
self.current_position
|
self.current_position()
|
||||||
);
|
);
|
||||||
|
|
||||||
let is_less_than = less_than_boolean.unwrap();
|
let is_less_than = less_than_boolean.unwrap();
|
||||||
@ -386,7 +396,7 @@ impl<'a> Vm<'a> {
|
|||||||
left.less_than_or_equal(right)
|
left.less_than_or_equal(right)
|
||||||
.map_err(|error| VmError::Value {
|
.map_err(|error| VmError::Value {
|
||||||
error,
|
error,
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
})?;
|
})?;
|
||||||
let is_less_than_or_equal =
|
let is_less_than_or_equal =
|
||||||
if let Value::Concrete(ConcreteValue::Boolean(boolean)) =
|
if let Value::Concrete(ConcreteValue::Boolean(boolean)) =
|
||||||
@ -396,7 +406,7 @@ impl<'a> Vm<'a> {
|
|||||||
} else {
|
} else {
|
||||||
return Err(VmError::ExpectedBoolean {
|
return Err(VmError::ExpectedBoolean {
|
||||||
found: less_or_equal_result,
|
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 value = self.get_argument(argument)?;
|
||||||
let negated = value.negate().map_err(|error| VmError::Value {
|
let negated = value.negate().map_err(|error| VmError::Value {
|
||||||
error,
|
error,
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
})?;
|
})?;
|
||||||
let register_index = self.get_destination(destination)?;
|
let register_index = self.get_destination(destination)?;
|
||||||
let register = Register::Value(negated);
|
let register = Register::Value(negated);
|
||||||
@ -427,7 +437,7 @@ impl<'a> Vm<'a> {
|
|||||||
let value = self.get_argument(argument)?;
|
let value = self.get_argument(argument)?;
|
||||||
let not = value.not().map_err(|error| VmError::Value {
|
let not = value.not().map_err(|error| VmError::Value {
|
||||||
error,
|
error,
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
})?;
|
})?;
|
||||||
let register_index = self.get_destination(destination)?;
|
let register_index = self.get_destination(destination)?;
|
||||||
let register = Register::Value(not);
|
let register = Register::Value(not);
|
||||||
@ -458,10 +468,10 @@ impl<'a> Vm<'a> {
|
|||||||
} else {
|
} else {
|
||||||
return Err(VmError::ExpectedFunction {
|
return Err(VmError::ExpectedFunction {
|
||||||
found: function.to_concrete_owned(self)?,
|
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;
|
let first_argument_index = register_index - argument_count;
|
||||||
|
|
||||||
for (argument_index, argument_register_index) in
|
for (argument_index, argument_register_index) in
|
||||||
@ -515,7 +525,7 @@ impl<'a> Vm<'a> {
|
|||||||
Ok(Some(return_value))
|
Ok(Some(return_value))
|
||||||
} else {
|
} else {
|
||||||
Err(VmError::StackUnderflow {
|
Err(VmError::StackUnderflow {
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -536,7 +546,7 @@ impl<'a> Vm<'a> {
|
|||||||
.parent
|
.parent
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or_else(|| VmError::ExpectedParent {
|
.ok_or_else(|| VmError::ExpectedParent {
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
parent.open_register(register_index)
|
parent.open_register(register_index)
|
||||||
@ -546,7 +556,7 @@ impl<'a> Vm<'a> {
|
|||||||
.parent
|
.parent
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or_else(|| VmError::ExpectedParent {
|
.ok_or_else(|| VmError::ExpectedParent {
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
})?;
|
})?;
|
||||||
let constant = parent.get_constant(constant_index);
|
let constant = parent.get_constant(constant_index);
|
||||||
|
|
||||||
@ -572,7 +582,7 @@ impl<'a> Vm<'a> {
|
|||||||
Register::Pointer(pointer) => self.follow_pointer(*pointer),
|
Register::Pointer(pointer) => self.follow_pointer(*pointer),
|
||||||
Register::Empty => Err(VmError::EmptyRegister {
|
Register::Empty => Err(VmError::EmptyRegister {
|
||||||
index: register_index,
|
index: register_index,
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -587,7 +597,7 @@ impl<'a> Vm<'a> {
|
|||||||
.get(register_index)
|
.get(register_index)
|
||||||
.ok_or_else(|| VmError::RegisterIndexOutOfBounds {
|
.ok_or_else(|| VmError::RegisterIndexOutOfBounds {
|
||||||
index: register_index,
|
index: register_index,
|
||||||
position: self.current_position,
|
position: self.current_position(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
log::trace!("Open R{register_index} to {register}");
|
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 {
|
self.local_definitions[local_index].ok_or_else(|| VmError::UndefinedLocal {
|
||||||
local_index: local_index as u16,
|
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 {
|
fn read(&mut self) -> Instruction {
|
||||||
let instructions = self.chunk.instructions();
|
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.ip += 1;
|
||||||
self.current_position = position;
|
|
||||||
|
|
||||||
instruction
|
instruction
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ fn add_assign_expects_mutable_variable() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::ExpectedMutableVariable {
|
error: CompileError::ExpectedMutableVariable {
|
||||||
found: Token::Integer("1").to_owned(),
|
found: Token::Integer("1").to_owned(),
|
||||||
position: Span(0, 1)
|
position: Span(0, 1)
|
||||||
@ -22,7 +22,7 @@ fn divide_assign_expects_mutable_variable() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::ExpectedMutableVariable {
|
error: CompileError::ExpectedMutableVariable {
|
||||||
found: Token::Integer("1").to_owned(),
|
found: Token::Integer("1").to_owned(),
|
||||||
position: Span(0, 1)
|
position: Span(0, 1)
|
||||||
@ -38,7 +38,7 @@ fn multiply_assign_expects_mutable_variable() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::ExpectedMutableVariable {
|
error: CompileError::ExpectedMutableVariable {
|
||||||
found: Token::Integer("1").to_owned(),
|
found: Token::Integer("1").to_owned(),
|
||||||
position: Span(0, 1)
|
position: Span(0, 1)
|
||||||
@ -54,7 +54,7 @@ fn subtract_assign_expects_mutable_variable() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::ExpectedMutableVariable {
|
error: CompileError::ExpectedMutableVariable {
|
||||||
found: Token::Integer("1").to_owned(),
|
found: Token::Integer("1").to_owned(),
|
||||||
position: Span(0, 1)
|
position: Span(0, 1)
|
||||||
@ -70,7 +70,7 @@ fn modulo_assign_expects_mutable_variable() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::ExpectedMutableVariable {
|
error: CompileError::ExpectedMutableVariable {
|
||||||
found: Token::Integer("1").to_owned(),
|
found: Token::Integer("1").to_owned(),
|
||||||
position: Span(0, 1)
|
position: Span(0, 1)
|
||||||
|
@ -6,7 +6,7 @@ fn add_boolean_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddType {
|
error: CompileError::CannotAddType {
|
||||||
argument_type: Type::Boolean,
|
argument_type: Type::Boolean,
|
||||||
position: Span(0, 4)
|
position: Span(0, 4)
|
||||||
@ -22,7 +22,7 @@ fn add_boolean_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddType {
|
error: CompileError::CannotAddType {
|
||||||
argument_type: Type::Boolean,
|
argument_type: Type::Boolean,
|
||||||
position: Span(4, 8)
|
position: Span(4, 8)
|
||||||
@ -38,7 +38,7 @@ fn add_function_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddType {
|
error: CompileError::CannotAddType {
|
||||||
argument_type: Type::Function(FunctionType {
|
argument_type: Type::Function(FunctionType {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
@ -58,7 +58,7 @@ fn add_function_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddType {
|
error: CompileError::CannotAddType {
|
||||||
argument_type: Type::Function(FunctionType {
|
argument_type: Type::Function(FunctionType {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
@ -78,7 +78,7 @@ fn add_list_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddType {
|
error: CompileError::CannotAddType {
|
||||||
argument_type: Type::List(Box::new(Type::Integer)),
|
argument_type: Type::List(Box::new(Type::Integer)),
|
||||||
position: Span(0, 6)
|
position: Span(0, 6)
|
||||||
@ -94,7 +94,7 @@ fn add_list_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddType {
|
error: CompileError::CannotAddType {
|
||||||
argument_type: Type::List(Box::new(Type::Integer)),
|
argument_type: Type::List(Box::new(Type::Integer)),
|
||||||
position: Span(4, 10)
|
position: Span(4, 10)
|
||||||
@ -121,7 +121,7 @@ fn add_byte_and_character() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::Byte,
|
left_type: Type::Byte,
|
||||||
right_type: Type::Character,
|
right_type: Type::Character,
|
||||||
@ -138,7 +138,7 @@ fn add_byte_and_integer() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::Byte,
|
left_type: Type::Byte,
|
||||||
right_type: Type::Integer,
|
right_type: Type::Integer,
|
||||||
@ -155,7 +155,7 @@ fn add_byte_and_string() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::Byte,
|
left_type: Type::Byte,
|
||||||
right_type: Type::String,
|
right_type: Type::String,
|
||||||
@ -172,7 +172,7 @@ fn add_character_and_byte() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::Character,
|
left_type: Type::Character,
|
||||||
right_type: Type::Byte,
|
right_type: Type::Byte,
|
||||||
@ -189,7 +189,7 @@ fn add_character_and_float() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::Character,
|
left_type: Type::Character,
|
||||||
right_type: Type::Float,
|
right_type: Type::Float,
|
||||||
@ -206,7 +206,7 @@ fn add_character_and_integer() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::Character,
|
left_type: Type::Character,
|
||||||
right_type: Type::Integer,
|
right_type: Type::Integer,
|
||||||
@ -223,7 +223,7 @@ fn add_float_and_byte() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::Float,
|
left_type: Type::Float,
|
||||||
right_type: Type::Byte,
|
right_type: Type::Byte,
|
||||||
@ -240,7 +240,7 @@ fn add_float_and_character() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::Float,
|
left_type: Type::Float,
|
||||||
right_type: Type::Character,
|
right_type: Type::Character,
|
||||||
@ -257,7 +257,7 @@ fn add_float_and_integer() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::Float,
|
left_type: Type::Float,
|
||||||
right_type: Type::Integer,
|
right_type: Type::Integer,
|
||||||
@ -274,7 +274,7 @@ fn add_float_and_string() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::Float,
|
left_type: Type::Float,
|
||||||
right_type: Type::String,
|
right_type: Type::String,
|
||||||
@ -291,7 +291,7 @@ fn add_integer_and_byte() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::Integer,
|
left_type: Type::Integer,
|
||||||
right_type: Type::Byte,
|
right_type: Type::Byte,
|
||||||
@ -308,7 +308,7 @@ fn add_integer_and_character() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::Integer,
|
left_type: Type::Integer,
|
||||||
right_type: Type::Character,
|
right_type: Type::Character,
|
||||||
@ -325,7 +325,7 @@ fn add_integer_and_float() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::Integer,
|
left_type: Type::Integer,
|
||||||
right_type: Type::Float,
|
right_type: Type::Float,
|
||||||
@ -342,7 +342,7 @@ fn add_integer_and_string() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::Integer,
|
left_type: Type::Integer,
|
||||||
right_type: Type::String,
|
right_type: Type::String,
|
||||||
@ -359,7 +359,7 @@ fn add_string_and_byte() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::String,
|
left_type: Type::String,
|
||||||
right_type: Type::Byte,
|
right_type: Type::Byte,
|
||||||
@ -376,7 +376,7 @@ fn add_string_and_float() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::String,
|
left_type: Type::String,
|
||||||
right_type: Type::Float,
|
right_type: Type::Float,
|
||||||
@ -393,7 +393,7 @@ fn add_string_and_integer() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotAddArguments {
|
error: CompileError::CannotAddArguments {
|
||||||
left_type: Type::String,
|
left_type: Type::String,
|
||||||
right_type: Type::Integer,
|
right_type: Type::Integer,
|
||||||
|
@ -6,7 +6,7 @@ fn divide_boolean_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotDivideType {
|
error: CompileError::CannotDivideType {
|
||||||
argument_type: Type::Boolean,
|
argument_type: Type::Boolean,
|
||||||
position: Span(0, 4)
|
position: Span(0, 4)
|
||||||
@ -22,7 +22,7 @@ fn divide_boolean_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotDivideType {
|
error: CompileError::CannotDivideType {
|
||||||
argument_type: Type::Boolean,
|
argument_type: Type::Boolean,
|
||||||
position: Span(4, 8)
|
position: Span(4, 8)
|
||||||
@ -38,7 +38,7 @@ fn divide_character_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotDivideType {
|
error: CompileError::CannotDivideType {
|
||||||
argument_type: Type::Character,
|
argument_type: Type::Character,
|
||||||
position: Span(0, 3)
|
position: Span(0, 3)
|
||||||
@ -54,7 +54,7 @@ fn divide_character_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotDivideType {
|
error: CompileError::CannotDivideType {
|
||||||
argument_type: Type::Character,
|
argument_type: Type::Character,
|
||||||
position: Span(4, 7)
|
position: Span(4, 7)
|
||||||
@ -70,7 +70,7 @@ fn divide_float_and_character() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotDivideType {
|
error: CompileError::CannotDivideType {
|
||||||
argument_type: Type::Character,
|
argument_type: Type::Character,
|
||||||
position: Span(6, 9)
|
position: Span(6, 9)
|
||||||
@ -86,7 +86,7 @@ fn divide_float_and_integer() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotDivideArguments {
|
error: CompileError::CannotDivideArguments {
|
||||||
left_type: Type::Float,
|
left_type: Type::Float,
|
||||||
right_type: Type::Integer,
|
right_type: Type::Integer,
|
||||||
@ -103,7 +103,7 @@ fn divide_function_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotDivideType {
|
error: CompileError::CannotDivideType {
|
||||||
argument_type: Type::Function(FunctionType {
|
argument_type: Type::Function(FunctionType {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
@ -123,7 +123,7 @@ fn divide_function_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotDivideType {
|
error: CompileError::CannotDivideType {
|
||||||
argument_type: Type::Function(FunctionType {
|
argument_type: Type::Function(FunctionType {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
@ -143,7 +143,7 @@ fn divide_integer_and_float() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotDivideArguments {
|
error: CompileError::CannotDivideArguments {
|
||||||
left_type: Type::Integer,
|
left_type: Type::Integer,
|
||||||
right_type: Type::Float,
|
right_type: Type::Float,
|
||||||
@ -160,7 +160,7 @@ fn divide_list_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotDivideType {
|
error: CompileError::CannotDivideType {
|
||||||
argument_type: Type::List(Box::new(Type::Integer)),
|
argument_type: Type::List(Box::new(Type::Integer)),
|
||||||
position: Span(0, 6)
|
position: Span(0, 6)
|
||||||
@ -176,7 +176,7 @@ fn divide_list_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotDivideType {
|
error: CompileError::CannotDivideType {
|
||||||
argument_type: Type::List(Box::new(Type::Integer)),
|
argument_type: Type::List(Box::new(Type::Integer)),
|
||||||
position: Span(4, 10)
|
position: Span(4, 10)
|
||||||
@ -202,7 +202,7 @@ fn divide_string_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotDivideType {
|
error: CompileError::CannotDivideType {
|
||||||
argument_type: Type::String,
|
argument_type: Type::String,
|
||||||
position: Span(0, 7)
|
position: Span(0, 7)
|
||||||
@ -218,7 +218,7 @@ fn divide_string_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotDivideType {
|
error: CompileError::CannotDivideType {
|
||||||
argument_type: Type::String,
|
argument_type: Type::String,
|
||||||
position: Span(4, 11)
|
position: Span(4, 11)
|
||||||
|
@ -6,7 +6,7 @@ fn modulo_boolean_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotModuloType {
|
error: CompileError::CannotModuloType {
|
||||||
argument_type: Type::Boolean,
|
argument_type: Type::Boolean,
|
||||||
position: Span(0, 4)
|
position: Span(0, 4)
|
||||||
@ -22,7 +22,7 @@ fn modulo_boolean_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotModuloType {
|
error: CompileError::CannotModuloType {
|
||||||
argument_type: Type::Boolean,
|
argument_type: Type::Boolean,
|
||||||
position: Span(4, 8)
|
position: Span(4, 8)
|
||||||
@ -38,7 +38,7 @@ fn modulo_character_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotModuloType {
|
error: CompileError::CannotModuloType {
|
||||||
argument_type: Type::Character,
|
argument_type: Type::Character,
|
||||||
position: Span(0, 3)
|
position: Span(0, 3)
|
||||||
@ -54,7 +54,7 @@ fn modulo_character_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotModuloType {
|
error: CompileError::CannotModuloType {
|
||||||
argument_type: Type::Character,
|
argument_type: Type::Character,
|
||||||
position: Span(4, 7)
|
position: Span(4, 7)
|
||||||
@ -70,7 +70,7 @@ fn modulo_float_and_character() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotModuloType {
|
error: CompileError::CannotModuloType {
|
||||||
argument_type: Type::Character,
|
argument_type: Type::Character,
|
||||||
position: Span(6, 9)
|
position: Span(6, 9)
|
||||||
@ -86,7 +86,7 @@ fn modulo_float_and_integer() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotModuloArguments {
|
error: CompileError::CannotModuloArguments {
|
||||||
left_type: Type::Float,
|
left_type: Type::Float,
|
||||||
right_type: Type::Integer,
|
right_type: Type::Integer,
|
||||||
@ -103,7 +103,7 @@ fn modulo_function_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotModuloType {
|
error: CompileError::CannotModuloType {
|
||||||
argument_type: Type::Function(FunctionType {
|
argument_type: Type::Function(FunctionType {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
@ -123,7 +123,7 @@ fn modulo_function_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotModuloType {
|
error: CompileError::CannotModuloType {
|
||||||
argument_type: Type::Function(FunctionType {
|
argument_type: Type::Function(FunctionType {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
@ -143,7 +143,7 @@ fn modulo_integer_and_float() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotModuloArguments {
|
error: CompileError::CannotModuloArguments {
|
||||||
left_type: Type::Integer,
|
left_type: Type::Integer,
|
||||||
right_type: Type::Float,
|
right_type: Type::Float,
|
||||||
@ -160,7 +160,7 @@ fn modulo_list_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotModuloType {
|
error: CompileError::CannotModuloType {
|
||||||
argument_type: Type::List(Box::new(Type::Integer)),
|
argument_type: Type::List(Box::new(Type::Integer)),
|
||||||
position: Span(0, 6)
|
position: Span(0, 6)
|
||||||
@ -176,7 +176,7 @@ fn modulo_list_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotModuloType {
|
error: CompileError::CannotModuloType {
|
||||||
argument_type: Type::List(Box::new(Type::Integer)),
|
argument_type: Type::List(Box::new(Type::Integer)),
|
||||||
position: Span(4, 10)
|
position: Span(4, 10)
|
||||||
@ -202,7 +202,7 @@ fn modulo_string_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotModuloType {
|
error: CompileError::CannotModuloType {
|
||||||
argument_type: Type::String,
|
argument_type: Type::String,
|
||||||
position: Span(0, 7)
|
position: Span(0, 7)
|
||||||
@ -218,7 +218,7 @@ fn modulo_string_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotModuloType {
|
error: CompileError::CannotModuloType {
|
||||||
argument_type: Type::String,
|
argument_type: Type::String,
|
||||||
position: Span(4, 11)
|
position: Span(4, 11)
|
||||||
|
@ -6,7 +6,7 @@ fn multiply_boolean_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotMultiplyType {
|
error: CompileError::CannotMultiplyType {
|
||||||
argument_type: Type::Boolean,
|
argument_type: Type::Boolean,
|
||||||
position: Span(0, 4)
|
position: Span(0, 4)
|
||||||
@ -22,7 +22,7 @@ fn multiply_boolean_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotMultiplyType {
|
error: CompileError::CannotMultiplyType {
|
||||||
argument_type: Type::Boolean,
|
argument_type: Type::Boolean,
|
||||||
position: Span(4, 8)
|
position: Span(4, 8)
|
||||||
@ -38,7 +38,7 @@ fn multiply_character_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotMultiplyType {
|
error: CompileError::CannotMultiplyType {
|
||||||
argument_type: Type::Character,
|
argument_type: Type::Character,
|
||||||
position: Span(0, 3)
|
position: Span(0, 3)
|
||||||
@ -54,7 +54,7 @@ fn multiply_character_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotMultiplyType {
|
error: CompileError::CannotMultiplyType {
|
||||||
argument_type: Type::Character,
|
argument_type: Type::Character,
|
||||||
position: Span(4, 7)
|
position: Span(4, 7)
|
||||||
@ -70,7 +70,7 @@ fn multiply_float_and_character() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotMultiplyType {
|
error: CompileError::CannotMultiplyType {
|
||||||
argument_type: Type::Character,
|
argument_type: Type::Character,
|
||||||
position: Span(6, 9)
|
position: Span(6, 9)
|
||||||
@ -86,7 +86,7 @@ fn multiply_float_and_integer() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotMultiplyArguments {
|
error: CompileError::CannotMultiplyArguments {
|
||||||
left_type: Type::Float,
|
left_type: Type::Float,
|
||||||
right_type: Type::Integer,
|
right_type: Type::Integer,
|
||||||
@ -103,7 +103,7 @@ fn multiply_function_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotMultiplyType {
|
error: CompileError::CannotMultiplyType {
|
||||||
argument_type: Type::Function(FunctionType {
|
argument_type: Type::Function(FunctionType {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
@ -123,7 +123,7 @@ fn multiply_function_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotMultiplyType {
|
error: CompileError::CannotMultiplyType {
|
||||||
argument_type: Type::Function(FunctionType {
|
argument_type: Type::Function(FunctionType {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
@ -143,7 +143,7 @@ fn multiply_integer_and_float() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotMultiplyArguments {
|
error: CompileError::CannotMultiplyArguments {
|
||||||
left_type: Type::Integer,
|
left_type: Type::Integer,
|
||||||
right_type: Type::Float,
|
right_type: Type::Float,
|
||||||
@ -160,7 +160,7 @@ fn multiply_list_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotMultiplyType {
|
error: CompileError::CannotMultiplyType {
|
||||||
argument_type: Type::List(Box::new(Type::Integer)),
|
argument_type: Type::List(Box::new(Type::Integer)),
|
||||||
position: Span(0, 6)
|
position: Span(0, 6)
|
||||||
@ -176,7 +176,7 @@ fn multiply_list_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotMultiplyType {
|
error: CompileError::CannotMultiplyType {
|
||||||
argument_type: Type::List(Box::new(Type::Integer)),
|
argument_type: Type::List(Box::new(Type::Integer)),
|
||||||
position: Span(4, 10)
|
position: Span(4, 10)
|
||||||
@ -202,7 +202,7 @@ fn multiply_string_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotMultiplyType {
|
error: CompileError::CannotMultiplyType {
|
||||||
argument_type: Type::String,
|
argument_type: Type::String,
|
||||||
position: Span(0, 7)
|
position: Span(0, 7)
|
||||||
@ -218,7 +218,7 @@ fn multiply_string_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotMultiplyType {
|
error: CompileError::CannotMultiplyType {
|
||||||
argument_type: Type::String,
|
argument_type: Type::String,
|
||||||
position: Span(4, 11)
|
position: Span(4, 11)
|
||||||
|
@ -6,7 +6,7 @@ fn subtract_boolean_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotSubtractType {
|
error: CompileError::CannotSubtractType {
|
||||||
argument_type: Type::Boolean,
|
argument_type: Type::Boolean,
|
||||||
position: Span(0, 4)
|
position: Span(0, 4)
|
||||||
@ -22,7 +22,7 @@ fn subtract_boolean_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotSubtractType {
|
error: CompileError::CannotSubtractType {
|
||||||
argument_type: Type::Boolean,
|
argument_type: Type::Boolean,
|
||||||
position: Span(4, 8)
|
position: Span(4, 8)
|
||||||
@ -38,7 +38,7 @@ fn subtract_character_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotSubtractType {
|
error: CompileError::CannotSubtractType {
|
||||||
argument_type: Type::Character,
|
argument_type: Type::Character,
|
||||||
position: Span(0, 3)
|
position: Span(0, 3)
|
||||||
@ -54,7 +54,7 @@ fn subtract_character_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotSubtractType {
|
error: CompileError::CannotSubtractType {
|
||||||
argument_type: Type::Character,
|
argument_type: Type::Character,
|
||||||
position: Span(4, 7)
|
position: Span(4, 7)
|
||||||
@ -70,7 +70,7 @@ fn subtract_float_and_character() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotSubtractType {
|
error: CompileError::CannotSubtractType {
|
||||||
argument_type: Type::Character,
|
argument_type: Type::Character,
|
||||||
position: Span(6, 9)
|
position: Span(6, 9)
|
||||||
@ -86,7 +86,7 @@ fn subtract_float_and_integer() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotSubtractArguments {
|
error: CompileError::CannotSubtractArguments {
|
||||||
left_type: Type::Float,
|
left_type: Type::Float,
|
||||||
right_type: Type::Integer,
|
right_type: Type::Integer,
|
||||||
@ -103,7 +103,7 @@ fn subtract_function_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotSubtractType {
|
error: CompileError::CannotSubtractType {
|
||||||
argument_type: Type::Function(FunctionType {
|
argument_type: Type::Function(FunctionType {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
@ -123,7 +123,7 @@ fn subtract_function_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotSubtractType {
|
error: CompileError::CannotSubtractType {
|
||||||
argument_type: Type::Function(FunctionType {
|
argument_type: Type::Function(FunctionType {
|
||||||
type_parameters: None,
|
type_parameters: None,
|
||||||
@ -143,7 +143,7 @@ fn subtract_integer_and_float() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotSubtractArguments {
|
error: CompileError::CannotSubtractArguments {
|
||||||
left_type: Type::Integer,
|
left_type: Type::Integer,
|
||||||
right_type: Type::Float,
|
right_type: Type::Float,
|
||||||
@ -160,7 +160,7 @@ fn subtract_list_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotSubtractType {
|
error: CompileError::CannotSubtractType {
|
||||||
argument_type: Type::List(Box::new(Type::Integer)),
|
argument_type: Type::List(Box::new(Type::Integer)),
|
||||||
position: Span(0, 6)
|
position: Span(0, 6)
|
||||||
@ -176,7 +176,7 @@ fn subtract_list_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotSubtractType {
|
error: CompileError::CannotSubtractType {
|
||||||
argument_type: Type::List(Box::new(Type::Integer)),
|
argument_type: Type::List(Box::new(Type::Integer)),
|
||||||
position: Span(4, 10)
|
position: Span(4, 10)
|
||||||
@ -202,7 +202,7 @@ fn subtract_string_left() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotSubtractType {
|
error: CompileError::CannotSubtractType {
|
||||||
argument_type: Type::String,
|
argument_type: Type::String,
|
||||||
position: Span(0, 7)
|
position: Span(0, 7)
|
||||||
@ -218,7 +218,7 @@ fn subtract_string_right() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::CannotSubtractType {
|
error: CompileError::CannotSubtractType {
|
||||||
argument_type: Type::String,
|
argument_type: Type::String,
|
||||||
position: Span(4, 11)
|
position: Span(4, 11)
|
||||||
|
@ -38,7 +38,7 @@ fn panic() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
run(source),
|
run(source),
|
||||||
Err(DustError::Runtime {
|
Err(CreateReport::Runtime {
|
||||||
error: VmError::NativeFunction(NativeFunctionError::Panic {
|
error: VmError::NativeFunction(NativeFunctionError::Panic {
|
||||||
message: Some("Goodbye world! 42".to_string()),
|
message: Some("Goodbye world! 42".to_string()),
|
||||||
position: Span(0, 27)
|
position: Span(0, 27)
|
||||||
|
@ -205,7 +205,7 @@ fn disallow_access_to_child_scope() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
run(source),
|
run(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::VariableOutOfScope {
|
error: CompileError::VariableOutOfScope {
|
||||||
identifier: "x".to_string(),
|
identifier: "x".to_string(),
|
||||||
position: Span(52, 53),
|
position: Span(52, 53),
|
||||||
@ -230,7 +230,7 @@ fn disallow_access_to_child_scope_nested() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
run(source),
|
run(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::VariableOutOfScope {
|
error: CompileError::VariableOutOfScope {
|
||||||
identifier: "x".to_string(),
|
identifier: "x".to_string(),
|
||||||
position: Span(78, 79),
|
position: Span(78, 79),
|
||||||
@ -255,7 +255,7 @@ fn disallow_access_to_sibling_scope() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
run(source),
|
run(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::VariableOutOfScope {
|
error: CompileError::VariableOutOfScope {
|
||||||
identifier: "x".to_string(),
|
identifier: "x".to_string(),
|
||||||
variable_scope: Scope::new(1, 1),
|
variable_scope: Scope::new(1, 1),
|
||||||
@ -282,7 +282,7 @@ fn disallow_access_to_sibling_scope_nested() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
run(source),
|
run(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::VariableOutOfScope {
|
error: CompileError::VariableOutOfScope {
|
||||||
identifier: "x".to_string(),
|
identifier: "x".to_string(),
|
||||||
variable_scope: Scope::new(2, 2),
|
variable_scope: Scope::new(2, 2),
|
||||||
|
@ -35,7 +35,7 @@ fn let_statement_expects_identifier() {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compile(source),
|
compile(source),
|
||||||
Err(DustError::Compile {
|
Err(CreateReport::Compile {
|
||||||
error: CompileError::ExpectedToken {
|
error: CompileError::ExpectedToken {
|
||||||
expected: TokenKind::Identifier,
|
expected: TokenKind::Identifier,
|
||||||
found: Token::Integer("1").to_owned(),
|
found: Token::Integer("1").to_owned(),
|
||||||
|
Loading…
Reference in New Issue
Block a user