2024-02-25 18:49:26 +00:00
|
|
|
use std::sync::PoisonError;
|
|
|
|
|
2024-03-07 03:15:35 +00:00
|
|
|
use ariadne::{Color, Label, Report, ReportKind};
|
2024-03-16 19:01:45 +00:00
|
|
|
use chumsky::{prelude::Rich, span::Span};
|
2024-02-25 18:49:26 +00:00
|
|
|
|
2024-03-06 22:32:31 +00:00
|
|
|
use crate::{
|
|
|
|
abstract_tree::{Identifier, Type},
|
|
|
|
lexer::Token,
|
|
|
|
};
|
2024-02-25 18:49:26 +00:00
|
|
|
|
|
|
|
#[derive(Debug, PartialEq)]
|
2024-03-06 20:36:58 +00:00
|
|
|
pub enum Error {
|
2024-03-06 22:32:31 +00:00
|
|
|
Parse {
|
|
|
|
expected: String,
|
2024-03-16 19:01:45 +00:00
|
|
|
span: (usize, usize),
|
2024-03-06 22:32:31 +00:00
|
|
|
},
|
|
|
|
Lex {
|
|
|
|
expected: String,
|
2024-03-16 19:01:45 +00:00
|
|
|
span: (usize, usize),
|
2024-03-06 22:32:31 +00:00
|
|
|
},
|
2024-02-25 18:49:26 +00:00
|
|
|
Runtime(RuntimeError),
|
2024-03-17 04:49:01 +00:00
|
|
|
Validation(ValidationError),
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
|
|
|
|
2024-03-07 03:15:35 +00:00
|
|
|
impl Error {
|
|
|
|
pub fn report(&self) -> Report {
|
|
|
|
match self {
|
2024-03-16 19:01:45 +00:00
|
|
|
Error::Parse { expected, span } => {
|
|
|
|
let message = match expected.as_str() {
|
|
|
|
"" => "Invalid character.".to_string(),
|
|
|
|
expected => format!("Expected {expected}."),
|
|
|
|
};
|
|
|
|
|
|
|
|
Report::build(ReportKind::Custom("Lexing Error", Color::White), (), span.0)
|
|
|
|
.with_label(Label::new(span.0..span.1).with_message(message))
|
|
|
|
.finish()
|
|
|
|
}
|
2024-03-07 03:15:35 +00:00
|
|
|
Error::Lex { expected, span } => {
|
2024-03-16 19:01:45 +00:00
|
|
|
let message = match expected.as_str() {
|
|
|
|
"" => "Invalid character.".to_string(),
|
|
|
|
expected => format!("Expected {expected}."),
|
2024-03-07 03:15:35 +00:00
|
|
|
};
|
|
|
|
|
2024-03-16 19:01:45 +00:00
|
|
|
Report::build(ReportKind::Custom("Lexing Error", Color::White), (), span.0)
|
|
|
|
.with_label(Label::new(span.0..span.1).with_message(message))
|
|
|
|
.finish()
|
2024-03-07 03:15:35 +00:00
|
|
|
}
|
|
|
|
Error::Runtime(_) => todo!(),
|
2024-03-17 04:49:01 +00:00
|
|
|
Error::Validation(validation_error) => {
|
|
|
|
let mut report =
|
|
|
|
Report::build(ReportKind::Custom("Validation Error", Color::White), (), 0);
|
|
|
|
|
|
|
|
match validation_error {
|
2024-03-07 03:15:35 +00:00
|
|
|
ValidationError::ExpectedBoolean => {
|
2024-03-17 04:49:01 +00:00
|
|
|
report =
|
|
|
|
report.with_label(Label::new(0..0).with_message("Expected boolean."));
|
2024-03-07 03:15:35 +00:00
|
|
|
}
|
2024-03-07 11:33:54 +00:00
|
|
|
ValidationError::ExpectedIntegerOrFloat => {
|
|
|
|
report = report.with_label(
|
2024-03-17 04:49:01 +00:00
|
|
|
Label::new(0..0).with_message("Expected integer or float."),
|
2024-03-07 11:33:54 +00:00
|
|
|
);
|
|
|
|
}
|
2024-03-07 03:15:35 +00:00
|
|
|
ValidationError::RwLockPoison(_) => todo!(),
|
2024-03-17 04:49:01 +00:00
|
|
|
ValidationError::TypeCheck {
|
|
|
|
conflict,
|
|
|
|
actual_position,
|
|
|
|
expected_position: expected_postion,
|
|
|
|
} => {
|
|
|
|
let TypeConflict { actual, expected } = conflict;
|
|
|
|
|
|
|
|
report = report.with_labels([
|
|
|
|
Label::new(expected_postion.0..expected_postion.1)
|
|
|
|
.with_message(format!("Type {expected} established here.")),
|
|
|
|
Label::new(actual_position.0..actual_position.1)
|
|
|
|
.with_message(format!("Got type {actual} here.")),
|
|
|
|
]);
|
2024-03-07 03:15:35 +00:00
|
|
|
}
|
|
|
|
ValidationError::VariableNotFound(identifier) => {
|
|
|
|
report = report
|
2024-03-17 04:49:01 +00:00
|
|
|
.with_label(Label::new(0..0).with_message(format!(
|
2024-03-07 03:15:35 +00:00
|
|
|
"The variable {identifier} does not exist."
|
|
|
|
)));
|
|
|
|
}
|
2024-03-07 17:29:07 +00:00
|
|
|
ValidationError::CannotIndex(_) => todo!(),
|
|
|
|
ValidationError::CannotIndexWith(_, _) => todo!(),
|
2024-03-08 17:24:11 +00:00
|
|
|
ValidationError::InterpreterExpectedReturn => todo!(),
|
2024-03-09 13:10:54 +00:00
|
|
|
ValidationError::ExpectedFunction => todo!(),
|
|
|
|
ValidationError::ExpectedValue => todo!(),
|
2024-03-07 03:15:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
report.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-06 20:36:58 +00:00
|
|
|
impl From<Rich<'_, char>> for Error {
|
|
|
|
fn from(error: Rich<'_, char>) -> Self {
|
|
|
|
Error::Lex {
|
|
|
|
expected: error.expected().map(|error| error.to_string()).collect(),
|
2024-03-16 19:01:45 +00:00
|
|
|
span: (error.span().start(), error.span().end()),
|
2024-03-06 20:36:58 +00:00
|
|
|
}
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-06 20:36:58 +00:00
|
|
|
impl<'src> From<Rich<'_, Token<'src>>> for Error {
|
|
|
|
fn from(error: Rich<'_, Token<'src>>) -> Self {
|
|
|
|
Error::Parse {
|
|
|
|
expected: error.expected().map(|error| error.to_string()).collect(),
|
2024-03-16 19:01:45 +00:00
|
|
|
span: (error.span().start(), error.span().end()),
|
2024-03-06 20:36:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<RuntimeError> for Error {
|
2024-02-25 18:49:26 +00:00
|
|
|
fn from(error: RuntimeError) -> Self {
|
|
|
|
Error::Runtime(error)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
pub enum RuntimeError {
|
|
|
|
RwLockPoison(RwLockPoisonError),
|
2024-02-29 02:04:38 +00:00
|
|
|
ValidationFailure(ValidationError),
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<RwLockPoisonError> for RuntimeError {
|
|
|
|
fn from(error: RwLockPoisonError) -> Self {
|
|
|
|
RuntimeError::RwLockPoison(error)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-29 02:04:38 +00:00
|
|
|
impl From<ValidationError> for RuntimeError {
|
|
|
|
fn from(error: ValidationError) -> Self {
|
|
|
|
RuntimeError::ValidationFailure(error)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
pub enum ValidationError {
|
2024-03-07 17:29:07 +00:00
|
|
|
CannotIndex(Type),
|
|
|
|
CannotIndexWith(Type, Type),
|
2024-02-29 02:04:38 +00:00
|
|
|
ExpectedBoolean,
|
2024-03-09 13:10:54 +00:00
|
|
|
ExpectedFunction,
|
2024-03-07 11:33:54 +00:00
|
|
|
ExpectedIntegerOrFloat,
|
2024-03-09 13:10:54 +00:00
|
|
|
ExpectedValue,
|
2024-03-08 17:24:11 +00:00
|
|
|
InterpreterExpectedReturn,
|
2024-03-06 17:15:03 +00:00
|
|
|
RwLockPoison(RwLockPoisonError),
|
2024-03-17 04:49:01 +00:00
|
|
|
TypeCheck {
|
|
|
|
/// The mismatch that caused the error.
|
|
|
|
conflict: TypeConflict,
|
|
|
|
|
|
|
|
/// The position of the item that gave the "actual" type.
|
|
|
|
actual_position: (usize, usize),
|
|
|
|
|
|
|
|
/// The position of the item that gave the "expected" type.
|
|
|
|
expected_position: (usize, usize),
|
|
|
|
},
|
2024-03-06 22:32:31 +00:00
|
|
|
VariableNotFound(Identifier),
|
2024-02-29 02:04:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<RwLockPoisonError> for ValidationError {
|
|
|
|
fn from(error: RwLockPoisonError) -> Self {
|
|
|
|
ValidationError::RwLockPoison(error)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-25 18:49:26 +00:00
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
pub struct RwLockPoisonError;
|
|
|
|
|
|
|
|
impl<T> From<PoisonError<T>> for RwLockPoisonError {
|
|
|
|
fn from(_: PoisonError<T>) -> Self {
|
|
|
|
RwLockPoisonError
|
|
|
|
}
|
|
|
|
}
|
2024-03-06 17:15:03 +00:00
|
|
|
|
|
|
|
#[derive(Debug, PartialEq)]
|
2024-03-17 04:49:01 +00:00
|
|
|
pub struct TypeConflict {
|
2024-03-06 17:15:03 +00:00
|
|
|
pub actual: Type,
|
|
|
|
pub expected: Type,
|
|
|
|
}
|