Simplify errors and make them fancier

This commit is contained in:
Jeff 2024-02-16 19:57:24 -05:00
parent fd33f330f7
commit 1094a5662c
6 changed files with 139 additions and 127 deletions

View File

@ -91,7 +91,9 @@ impl AbstractTree for Index {
Ok(Value::string(item.to_string()))
}
_ => Err(RuntimeError::ExpectedCollection { actual: value }),
_ => Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedCollection { actual: value },
)),
}
}
}

View File

@ -7,7 +7,10 @@ use std::fmt::{self, Display, Formatter};
use rand::{random, thread_rng, Rng};
use serde::{Deserialize, Serialize};
use crate::{error::RuntimeError, Context, EnumInstance, Format, Identifier, Type, Value};
use crate::{
error::{RuntimeError, ValidationError},
Context, EnumInstance, Format, Identifier, Type, Value,
};
use self::{fs::Fs, json::Json, str::StrFunction};
@ -128,9 +131,11 @@ impl Callable for BuiltInFunction {
} else if let Ok(str) = value.as_string() {
str.chars().count()
} else {
return Err(RuntimeError::ExpectedCollection {
actual: value.clone(),
});
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedCollection {
actual: value.clone(),
},
));
};
Ok(Value::Integer(length as i64))

View File

@ -7,6 +7,7 @@ pub(crate) mod rw_lock_error;
mod syntax_error;
mod validation_error;
use colored::Colorize;
pub use runtime_error::RuntimeError;
pub use syntax_error::SyntaxError;
pub use validation_error::ValidationError;
@ -35,9 +36,25 @@ impl Error {
/// used to create this error.
pub fn create_report(&self, source: &str) -> String {
match self {
Error::Syntax(syntax_error) => syntax_error.create_report(source),
Error::Syntax(syntax_error) => {
let report = syntax_error.create_report(source);
format!(
"{}\n{}\n{report}",
"Syntax Error".bold().yellow().underline(),
"Dust does not recognize this syntax.".dimmed()
)
}
Error::Validation(_) => todo!(),
Error::Runtime(runtime_error) => runtime_error.create_report(source),
Error::Runtime(runtime_error) => {
let report = runtime_error.create_report(source);
format!(
"{}\n{}\n{report}",
"Runtime Error".bold().red().underline(),
"This error occured while the program was running.".dimmed()
)
}
Error::ParserCancelled => todo!(),
Error::Language(_) => todo!(),
}

View File

@ -46,71 +46,6 @@ pub enum RuntimeError {
Toml(toml::de::Error),
ExpectedString {
actual: Value,
},
ExpectedInteger {
actual: Value,
},
ExpectedFloat {
actual: Value,
},
/// An integer, floating point or value was expected.
ExpectedNumber {
actual: Value,
},
/// An integer, floating point or string value was expected.
ExpectedNumberOrString {
actual: Value,
},
ExpectedBoolean {
actual: Value,
},
ExpectedList {
actual: Value,
},
ExpectedMinLengthList {
minimum_len: usize,
actual_len: usize,
},
ExpectedFixedLenList {
expected_len: usize,
actual: Value,
},
ExpectedNone {
actual: Value,
},
ExpectedMap {
actual: Value,
},
ExpectedTable {
actual: Value,
},
ExpectedFunction {
actual: Value,
},
ExpectedOption {
actual: Value,
},
/// A string, list, map or table value was expected.
ExpectedCollection {
actual: Value,
},
/// Failed to read or write a map.
///
/// See the [MapError] docs for more info.
@ -140,17 +75,14 @@ impl RuntimeError {
vec![(
0..source.len(),
format!("\"assert_equal\" failed. {} != {}", expected, actual),
(200, 100, 100),
(200, 0, 0),
)]
}
RuntimeError::AssertFailed { assertion } => todo!(),
RuntimeError::ConversionImpossible { from, to, position } => vec![(
position.start_byte..position.end_byte,
format!(
"Impossible conversion. {}",
format!("Cannot convert from {from} to {to}.").dimmed()
),
(255, 100, 100),
format!("Cannot convert from {from} to {to}."),
(255, 64, 112),
)],
RuntimeError::Csv(_) => todo!(),
RuntimeError::Io(_) => todo!(),
@ -158,27 +90,6 @@ impl RuntimeError {
RuntimeError::Json(_) => todo!(),
RuntimeError::SystemTime(_) => todo!(),
RuntimeError::Toml(_) => todo!(),
RuntimeError::ExpectedString { actual } => todo!(),
RuntimeError::ExpectedInteger { actual } => todo!(),
RuntimeError::ExpectedFloat { actual } => todo!(),
RuntimeError::ExpectedNumber { actual } => todo!(),
RuntimeError::ExpectedNumberOrString { actual } => todo!(),
RuntimeError::ExpectedBoolean { actual } => todo!(),
RuntimeError::ExpectedList { actual } => todo!(),
RuntimeError::ExpectedMinLengthList {
minimum_len,
actual_len,
} => todo!(),
RuntimeError::ExpectedFixedLenList {
expected_len,
actual,
} => todo!(),
RuntimeError::ExpectedNone { actual } => todo!(),
RuntimeError::ExpectedMap { actual } => todo!(),
RuntimeError::ExpectedTable { actual } => todo!(),
RuntimeError::ExpectedFunction { actual } => todo!(),
RuntimeError::ExpectedOption { actual } => todo!(),
RuntimeError::ExpectedCollection { actual } => todo!(),
RuntimeError::RwLock(_) => todo!(),
RuntimeError::ParseFloat(_) => todo!(),
RuntimeError::Utf8(_) => todo!(),

View File

@ -9,16 +9,28 @@ use super::rw_lock_error::RwLockError;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum ValidationError {
/// Two value are incompatible for addition.
CannotAdd { left: Value, right: Value },
CannotAdd {
left: Value,
right: Value,
},
/// Two value are incompatible for subtraction.
CannotSubtract { left: Value, right: Value },
CannotSubtract {
left: Value,
right: Value,
},
/// Two value are incompatible for multiplication.
CannotMultiply { left: Value, right: Value },
CannotMultiply {
left: Value,
right: Value,
},
/// Two value are incompatible for dividing.
CannotDivide { left: Value, right: Value },
CannotDivide {
left: Value,
right: Value,
},
/// The attempted conversion is impossible.
ConversionImpossible {
@ -26,6 +38,59 @@ pub enum ValidationError {
target_type: Type,
},
ExpectedString {
actual: Value,
},
ExpectedInteger {
actual: Value,
},
ExpectedFloat {
actual: Value,
},
/// An integer, floating point or value was expected.
ExpectedNumber {
actual: Value,
},
/// An integer, floating point or string value was expected.
ExpectedNumberOrString {
actual: Value,
},
ExpectedBoolean {
actual: Value,
},
ExpectedList {
actual: Value,
},
ExpectedMinLengthList {
minimum_len: usize,
actual_len: usize,
},
ExpectedFixedLenList {
expected_len: usize,
actual: Value,
},
ExpectedMap {
actual: Value,
},
ExpectedFunction {
actual: Value,
},
/// A string, list, map or table value was expected.
ExpectedCollection {
actual: Value,
},
/// A built-in function was called with the wrong amount of arguments.
ExpectedBuiltInFunctionArgumentAmount {
function_name: String,
@ -70,10 +135,14 @@ pub enum ValidationError {
TypeDefinitionNotFound(Identifier),
/// Failed to find an enum definition with this key.
ExpectedEnumDefintion { actual: TypeDefinition },
ExpectedEnumDefintion {
actual: TypeDefinition,
},
/// Failed to find a struct definition with this key.
ExpectedStructDefintion { actual: TypeDefinition },
ExpectedStructDefintion {
actual: TypeDefinition,
},
}
impl ValidationError {

View File

@ -156,10 +156,10 @@ impl Value {
/// Borrows the value stored in `self` as `&String`, or returns `Err` if
/// `self` is not a `Value::String`.
pub fn as_string(&self) -> Result<&String, RuntimeError> {
pub fn as_string(&self) -> Result<&String, ValidationError> {
match self {
Value::String(string) => Ok(string),
value => Err(RuntimeError::ExpectedString {
value => Err(ValidationError::ExpectedString {
actual: value.clone(),
}),
}
@ -167,10 +167,10 @@ impl Value {
/// Copies the value stored in `self` as `i64`, or returns `Err` if `self`
/// is not a `Value::Int`
pub fn as_integer(&self) -> Result<i64, RuntimeError> {
pub fn as_integer(&self) -> Result<i64, ValidationError> {
match self {
Value::Integer(i) => Ok(*i),
value => Err(RuntimeError::ExpectedInteger {
value => Err(ValidationError::ExpectedInteger {
actual: value.clone(),
}),
}
@ -178,10 +178,10 @@ impl Value {
/// Copies the value stored in `self` as `f64`, or returns `Err` if `self`
/// is not a `Primitive::Float`.
pub fn as_float(&self) -> Result<f64, RuntimeError> {
pub fn as_float(&self) -> Result<f64, ValidationError> {
match self {
Value::Float(f) => Ok(*f),
value => Err(RuntimeError::ExpectedFloat {
value => Err(ValidationError::ExpectedFloat {
actual: value.clone(),
}),
}
@ -192,11 +192,11 @@ impl Value {
///
/// Note that this method silently converts `i64` to `f64`, if `self` is
/// a `Value::Int`.
pub fn as_number(&self) -> Result<f64, RuntimeError> {
pub fn as_number(&self) -> Result<f64, ValidationError> {
match self {
Value::Float(f) => Ok(*f),
Value::Integer(i) => Ok(*i as f64),
value => Err(RuntimeError::ExpectedNumber {
value => Err(ValidationError::ExpectedNumber {
actual: value.clone(),
}),
}
@ -204,10 +204,10 @@ impl Value {
/// Copies the value stored in `self` as `bool`, or returns `Err` if `self`
/// is not a `Primitive::Boolean`.
pub fn as_boolean(&self) -> Result<bool, RuntimeError> {
pub fn as_boolean(&self) -> Result<bool, ValidationError> {
match self {
Value::Boolean(boolean) => Ok(*boolean),
value => Err(RuntimeError::ExpectedBoolean {
value => Err(ValidationError::ExpectedBoolean {
actual: value.clone(),
}),
}
@ -215,10 +215,10 @@ impl Value {
/// Borrows the value stored in `self` as `Vec<Value>`, or returns `Err` if
/// `self` is not a `Value::List`.
pub fn as_list(&self) -> Result<&List, RuntimeError> {
pub fn as_list(&self) -> Result<&List, ValidationError> {
match self {
Value::List(list) => Ok(list),
value => Err(RuntimeError::ExpectedList {
value => Err(ValidationError::ExpectedList {
actual: value.clone(),
}),
}
@ -226,10 +226,10 @@ impl Value {
/// Takes ownership of the value stored in `self` as `Vec<Value>`, or
/// returns `Err` if `self` is not a `Value::List`.
pub fn into_inner_list(self) -> Result<List, RuntimeError> {
pub fn into_inner_list(self) -> Result<List, ValidationError> {
match self {
Value::List(list) => Ok(list),
value => Err(RuntimeError::ExpectedList {
value => Err(ValidationError::ExpectedList {
actual: value.clone(),
}),
}
@ -237,10 +237,10 @@ impl Value {
/// Borrows the value stored in `self` as `Vec<Value>`, or returns `Err` if
/// `self` is not a `Value::Map`.
pub fn as_map(&self) -> Result<&Map, RuntimeError> {
pub fn as_map(&self) -> Result<&Map, ValidationError> {
match self {
Value::Map(map) => Ok(map),
value => Err(RuntimeError::ExpectedMap {
value => Err(ValidationError::ExpectedMap {
actual: value.clone(),
}),
}
@ -248,10 +248,10 @@ impl Value {
/// Borrows the value stored in `self` as `Function`, or returns `Err` if
/// `self` is not a `Value::Function`.
pub fn as_function(&self) -> Result<&Function, RuntimeError> {
pub fn as_function(&self) -> Result<&Function, ValidationError> {
match self {
Value::Function(function) => Ok(function),
value => Err(RuntimeError::ExpectedFunction {
value => Err(ValidationError::ExpectedFunction {
actual: value.clone(),
}),
}
@ -506,7 +506,9 @@ impl TryFrom<Value> for String {
if let Value::String(string) = value {
Ok(string)
} else {
Err(RuntimeError::ExpectedString { actual: value })
Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedString { actual: value },
))
}
}
}
@ -518,7 +520,9 @@ impl TryFrom<Value> for f64 {
if let Value::Float(value) = value {
Ok(value)
} else {
Err(RuntimeError::ExpectedFloat { actual: value })
Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedFloat { actual: value },
))
}
}
}
@ -530,7 +534,9 @@ impl TryFrom<Value> for i64 {
if let Value::Integer(value) = value {
Ok(value)
} else {
Err(RuntimeError::ExpectedInteger { actual: value })
Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedInteger { actual: value },
))
}
}
}
@ -542,7 +548,9 @@ impl TryFrom<Value> for bool {
if let Value::Boolean(value) = value {
Ok(value)
} else {
Err(RuntimeError::ExpectedBoolean { actual: value })
Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedBoolean { actual: value },
))
}
}
}