Simplify errors and make them fancier
This commit is contained in:
parent
fd33f330f7
commit
1094a5662c
@ -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 },
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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!(),
|
||||
}
|
||||
|
@ -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!(),
|
||||
|
@ -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 {
|
||||
|
@ -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 },
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user