From c6675e87ba80145ac2ed9342e7f5f459c0a909e0 Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 13 Oct 2023 12:26:44 -0400 Subject: [PATCH] Update error variants --- src/abstract_tree/function_call.rs | 3 +- src/abstract_tree/tool.rs | 43 ++++- src/error.rs | 273 ++--------------------------- src/value/mod.rs | 62 ++++--- src/value/variable_map.rs | 12 +- 5 files changed, 99 insertions(+), 294 deletions(-) diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index f4acf2d..5b51257 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -34,7 +34,8 @@ impl AbstractTree for FunctionCall { "assert_equal" => Tool::AssertEqual, "output" => Tool::Output, "read" => Tool::Read, - _ => panic!(""), + "help" => Tool::Help, + _ => panic!("Tool name not recognized."), }; FunctionName::Tool(tool) diff --git a/src/abstract_tree/tool.rs b/src/abstract_tree/tool.rs index e7d8ea3..3b8a5c0 100644 --- a/src/abstract_tree/tool.rs +++ b/src/abstract_tree/tool.rs @@ -2,7 +2,7 @@ use std::fs::read_to_string; use serde::{Deserialize, Serialize}; -use crate::{Error, Result, Value}; +use crate::{Error, Result, Table, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub enum Tool { @@ -10,6 +10,7 @@ pub enum Tool { AssertEqual, Output, Read, + Help, } impl Tool { @@ -27,10 +28,7 @@ impl Tool { if values[0].as_boolean()? { Value::Empty } else { - return Err(Error::AssertEqualFailed { - expected: Value::Boolean(true), - actual: values[0].clone(), - }); + return Err(Error::AssertFailed); } } Tool::AssertEqual => { @@ -77,6 +75,41 @@ impl Tool { Value::String(file_contents) } + Tool::Help => { + if values.len() > 1 { + return Err(Error::ExpectedToolArgumentAmount { + tool_name: "help", + expected: 1, + actual: values.len(), + }); + } + + let mut help_table = + Table::new(vec!["name".to_string(), "description".to_string()]); + + help_table.insert(vec![ + Value::String("help".to_string()), + Value::String("List available tools.".to_string()), + ])?; + help_table.insert(vec![ + Value::String("assert".to_string()), + Value::String("Panic if an expression is false.".to_string()), + ])?; + help_table.insert(vec![ + Value::String("assert_equal".to_string()), + Value::String("Panic if two values are not equal.".to_string()), + ])?; + help_table.insert(vec![ + Value::String("output".to_string()), + Value::String("Emit a value to stdout.".to_string()), + ])?; + help_table.insert(vec![ + Value::String("read".to_string()), + Value::String("Get a file's content.".to_string()), + ])?; + + Value::Table(help_table) + } }; Ok(value) diff --git a/src/error.rs b/src/error.rs index 61d1694..da10d53 100644 --- a/src/error.rs +++ b/src/error.rs @@ -3,14 +3,13 @@ //! To deal with errors from dependencies, either create a new error variant //! or use the MacroFailure variant if the error can only occur inside a macro. -use crate::{value::value_type::ValueType, value::Value, Identifier}; +use crate::{value::Value, Identifier}; use std::{fmt, io, time::SystemTimeError}; pub type Result = std::result::Result; #[derive(Clone, PartialEq)] -#[non_exhaustive] pub enum Error { UnexpectedSyntaxNode { expected: &'static str, @@ -19,8 +18,6 @@ pub enum Error { relevant_source: String, }, - ExpectedFieldName, - ExpectedChildNode { empty_node_sexp: String, }, @@ -116,113 +113,14 @@ pub enum Error { actual: Value, }, - /// Tried to append a child to a node such that the precedence of the child - /// is not higher. This error should never occur. If it does, please file a - /// bug report. - PrecedenceViolation, - /// A `VariableIdentifier` operation did not find its value in the context. VariableIdentifierNotFound(String), /// A `FunctionIdentifier` operation did not find its value in the context. FunctionIdentifierNotFound(Identifier), - /// A value has the wrong type. - /// Only use this if there is no other error that describes the expected and - /// provided types in more detail. - TypeError { - /// The expected types. - expected: &'static [ValueType], - /// The actual value. - actual: Value, - }, - - /// An operator is used with a wrong combination of types. - WrongTypeCombination { - /// The operator that whose evaluation caused the error. - expected: ValueType, - /// The types that were used in the operator causing it to fail. - actual: ValueType, - }, - - /// An opening brace without a matching closing brace was found. - UnmatchedLBrace, - - /// A closing brace without a matching opening brace was found. - UnmatchedRBrace, - - /// Left of an opening brace or right of a closing brace is a token that does not expect the brace next to it. - /// For example, writing `4(5)` would yield this error, as the `4` does not have any operands. - MissingOperatorOutsideOfBrace, - - /// An addition operation performed by Rust failed. - AdditionError { - /// The first argument of the addition. - augend: Value, - /// The second argument of the addition. - addend: Value, - }, - - /// A subtraction operation performed by Rust failed. - SubtractionError { - /// The first argument of the subtraction. - minuend: Value, - /// The second argument of the subtraction. - subtrahend: Value, - }, - - /// A negation operation performed by Rust failed. - NegationError { - /// The argument of the negation. - argument: Value, - }, - - /// A multiplication operation performed by Rust failed. - MultiplicationError { - /// The first argument of the multiplication. - multiplicand: Value, - /// The second argument of the multiplication. - multiplier: Value, - }, - - /// A division operation performed by Rust failed. - DivisionError { - /// The first argument of the division. - dividend: Value, - /// The second argument of the division. - divisor: Value, - }, - - /// A modulation operation performed by Rust failed. - ModulationError { - /// The first argument of the modulation. - dividend: Value, - /// The second argument of the modulation. - divisor: Value, - }, - - /// A regular expression could not be parsed - InvalidRegex { - /// The invalid regular expression - regex: String, - /// Failure message from the regex engine - message: String, - }, - - /// A modification was attempted on a `Context` that does not allow modifications. - ContextNotMutable, - - /// An escape sequence within a string literal is illegal. - IllegalEscapeSequence(String), - - /// This context does not allow enabling builtin functions. - BuiltinFunctionsCannotBeEnabled, - - /// This context does not allow disabling builtin functions. - BuiltinFunctionsCannotBeDisabled, - /// The function failed due to an external error. - MacroFailure(String), + ToolFailure(String), /// A custom error explained by its message. CustomMessage(String), @@ -230,129 +128,55 @@ pub enum Error { impl From for Error { fn from(value: csv::Error) -> Self { - Error::MacroFailure(value.to_string()) + Error::ToolFailure(value.to_string()) } } impl From for Error { fn from(value: json::Error) -> Self { - Error::MacroFailure(value.to_string()) + Error::ToolFailure(value.to_string()) } } impl From for Error { fn from(value: std::io::Error) -> Self { - Error::MacroFailure(value.to_string()) + Error::ToolFailure(value.to_string()) } } impl From for Error { fn from(value: git2::Error) -> Self { - Error::MacroFailure(value.to_string()) + Error::ToolFailure(value.to_string()) } } impl From for Error { fn from(value: reqwest::Error) -> Self { - Error::MacroFailure(value.to_string()) + Error::ToolFailure(value.to_string()) } } impl From for Error { fn from(value: serde_json::Error) -> Self { - Error::MacroFailure(value.to_string()) + Error::ToolFailure(value.to_string()) } } impl From for Error { fn from(value: SystemTimeError) -> Self { - Error::MacroFailure(value.to_string()) + Error::ToolFailure(value.to_string()) } } impl From for Error { fn from(value: trash::Error) -> Self { - Error::MacroFailure(value.to_string()) + Error::ToolFailure(value.to_string()) } } impl From for Error { fn from(value: toml::de::Error) -> Self { - Error::MacroFailure(value.to_string()) - } -} - -impl Error { - pub fn type_error(actual: Value, expected: &'static [ValueType]) -> Self { - Error::TypeError { actual, expected } - } - - pub fn expected_string(actual: Value) -> Self { - Error::ExpectedString { actual } - } - - pub fn expected_int(actual: Value) -> Self { - Error::ExpectedInt { actual } - } - - pub fn expected_float(actual: Value) -> Self { - Error::ExpectedFloat { actual } - } - - pub fn expected_number(actual: Value) -> Self { - Error::ExpectedNumber { actual } - } - - pub fn expected_number_or_string(actual: Value) -> Self { - Error::ExpectedNumberOrString { actual } - } - - pub fn expected_boolean(actual: Value) -> Self { - Error::ExpectedBoolean { actual } - } - - pub fn expected_list(actual: Value) -> Self { - Error::ExpectedList { actual } - } - - pub fn expected_fixed_len_list(expected_len: usize, actual: Value) -> Self { - Error::ExpectedFixedLenList { - expected_len, - actual, - } - } - - pub fn expected_empty(actual: Value) -> Self { - Error::ExpectedEmpty { actual } - } - - pub fn expected_map(actual: Value) -> Self { - Error::ExpectedMap { actual } - } - - pub fn expected_table(actual: Value) -> Self { - Error::ExpectedTable { actual } - } - - pub fn expected_function(actual: Value) -> Self { - Error::ExpectedFunction { actual } - } - - pub fn expected_collection(actual: Value) -> Self { - Error::ExpectedCollection { actual } - } - - /// Constructs `EvalexprError::InvalidRegex(regex)` - pub fn invalid_regex(regex: String, message: String) -> Self { - Error::InvalidRegex { regex, message } - } -} - -/// Returns `Ok(())` if the given value is a string or a numeric. -pub fn expect_number_or_string(actual: &Value) -> Result<()> { - match actual { - Value::String(_) | Value::Float(_) | Value::Integer(_) => Ok(()), - _ => Err(Error::expected_number_or_string(actual.clone())), + Error::ToolFailure(value.to_string()) } } @@ -438,10 +262,6 @@ impl fmt::Display for Error { actual ) } - PrecedenceViolation => write!( - f, - "Tried to append a node to another node with higher precedence." - ), VariableIdentifierNotFound(identifier) => write!( f, "Variable identifier is not bound to anything by context: {}.", @@ -452,75 +272,16 @@ impl fmt::Display for Error { "Function identifier is not bound to anything by context: {}.", identifier.inner() ), - TypeError { expected, actual } => { - write!( - f, - "Type Error. The value {actual} is not one of the following: {expected:?}.", - ) - } - UnmatchedLBrace => write!(f, "Found an unmatched opening parenthesis '('."), - UnmatchedRBrace => write!(f, "Found an unmatched closing parenthesis ')'."), - MissingOperatorOutsideOfBrace { .. } => write!( - f, - "Found an opening parenthesis that is preceded by something that does not take \ - any arguments on the right, or found a closing parenthesis that is succeeded by \ - something that does not take any arguments on the left." - ), - AdditionError { augend, addend } => write!(f, "Error adding {} + {}", augend, addend), - SubtractionError { - minuend, - subtrahend, - } => write!(f, "Error subtracting {} - {}", minuend, subtrahend), - NegationError { argument } => write!(f, "Error negating -{}", argument), - MultiplicationError { - multiplicand, - multiplier, - } => write!(f, "Error multiplying {} * {}", multiplicand, multiplier), - DivisionError { dividend, divisor } => { - write!(f, "Error dividing {} / {}", dividend, divisor) - } - ModulationError { dividend, divisor } => { - write!(f, "Error modulating {} % {}", dividend, divisor) - } - InvalidRegex { regex, message } => write!( - f, - "Regular expression {:?} is invalid: {:?}", - regex, message - ), - ContextNotMutable => write!(f, "Cannot manipulate context"), - BuiltinFunctionsCannotBeEnabled => { - write!(f, "This context does not allow enabling builtin functions") - } - BuiltinFunctionsCannotBeDisabled => { - write!(f, "This context does not allow disabling builtin functions") - } - IllegalEscapeSequence(string) => write!(f, "Illegal escape sequence: {}", string), - MacroFailure(message) => write!(f, "Function failure: {}", message), - CustomMessage(message) => write!(f, "Error: {}", message), - WrongColumnAmount { expected, actual } => write!( - f, - "Wrong number of columns for this table. Expected {expected}, found {actual}." - ), UnexpectedSyntaxNode { expected, actual, location, - relevant_source - } => write!( - f, - "Unexpected syntax at {location}. Expected {expected}, but found {actual}. {relevant_source}" - ), - ExpectedFieldName => write!( - f, - "Expected a field name for this node, but none was found." - ), - WrongTypeCombination { expected, actual } => write!( - f, - "Wrong type combination. Expected {expected}, found {actual}." - ), - ExpectedChildNode { empty_node_sexp } => { - write!(f, "Expected this node to have a child, {empty_node_sexp}.") - } + relevant_source, + } => todo!(), + ExpectedChildNode { empty_node_sexp } => todo!(), + WrongColumnAmount { expected, actual } => todo!(), + ToolFailure(_) => todo!(), + CustomMessage(_) => todo!(), } } } diff --git a/src/value/mod.rs b/src/value/mod.rs index 8aa515e..80e2115 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -92,7 +92,9 @@ impl Value { pub fn as_string(&self) -> Result<&String> { match self { Value::String(string) => Ok(string), - value => Err(Error::expected_string(value.clone())), + value => Err(Error::ExpectedString { + actual: value.clone(), + }), } } @@ -100,7 +102,9 @@ impl Value { pub fn as_int(&self) -> Result { match self { Value::Integer(i) => Ok(*i), - value => Err(Error::expected_int(value.clone())), + value => Err(Error::ExpectedInt { + actual: value.clone(), + }), } } @@ -108,7 +112,9 @@ impl Value { pub fn as_float(&self) -> Result { match self { Value::Float(f) => Ok(*f), - value => Err(Error::expected_float(value.clone())), + value => Err(Error::ExpectedFloat { + actual: value.clone(), + }), } } @@ -118,7 +124,9 @@ impl Value { match self { Value::Float(f) => Ok(*f), Value::Integer(i) => Ok(*i as f64), - value => Err(Error::expected_number(value.clone())), + value => Err(Error::ExpectedNumber { + actual: value.clone(), + }), } } @@ -126,7 +134,9 @@ impl Value { pub fn as_boolean(&self) -> Result { match self { Value::Boolean(boolean) => Ok(*boolean), - value => Err(Error::expected_boolean(value.clone())), + value => Err(Error::ExpectedBoolean { + actual: value.clone(), + }), } } @@ -134,7 +144,9 @@ impl Value { pub fn as_list(&self) -> Result<&Vec> { match self { Value::List(list) => Ok(list), - value => Err(Error::expected_list(value.clone())), + value => Err(Error::ExpectedList { + actual: value.clone(), + }), } } @@ -142,21 +154,9 @@ impl Value { pub fn into_inner_list(self) -> Result> { match self { Value::List(list) => Ok(list), - value => Err(Error::expected_list(value.clone())), - } - } - - /// Borrows the value stored in `self` as `Vec` or returns `Err` if `self` is not a `Value::Map` of the required length. - pub fn as_fixed_len_list(&self, len: usize) -> Result<&Vec> { - match self { - Value::List(tuple) => { - if tuple.len() == len { - Ok(tuple) - } else { - Err(Error::expected_fixed_len_list(len, self.clone())) - } - } - value => Err(Error::expected_list(value.clone())), + value => Err(Error::ExpectedList { + actual: value.clone(), + }), } } @@ -164,7 +164,9 @@ impl Value { pub fn as_map(&self) -> Result<&VariableMap> { match self { Value::Map(map) => Ok(map), - value => Err(Error::expected_map(value.clone())), + value => Err(Error::ExpectedMap { + actual: value.clone(), + }), } } @@ -172,7 +174,9 @@ impl Value { pub fn as_table(&self) -> Result<&Table> { match self { Value::Table(table) => Ok(table), - value => Err(Error::expected_table(value.clone())), + value => Err(Error::ExpectedTable { + actual: value.clone(), + }), } } @@ -181,7 +185,9 @@ impl Value { pub fn as_function(&self) -> Result<&Function> { match self { Value::Function(function) => Ok(function), - value => Err(Error::expected_function(value.clone())), + value => Err(Error::ExpectedFunction { + actual: value.clone(), + }), } } @@ -189,7 +195,9 @@ impl Value { pub fn as_empty(&self) -> Result<()> { match self { Value::Empty => Ok(()), - value => Err(Error::expected_empty(value.clone())), + value => Err(Error::ExpectedEmpty { + actual: value.clone(), + }), } } @@ -199,7 +207,9 @@ impl Value { Value::Table(table) => Ok(table.clone()), Value::List(list) => Ok(Table::from(list)), Value::Map(map) => Ok(Table::from(map)), - value => Err(Error::expected_table(value.clone())), + value => Err(Error::ExpectedTable { + actual: value.clone(), + }), } } } diff --git a/src/value/variable_map.rs b/src/value/variable_map.rs index d589c3d..47220db 100644 --- a/src/value/variable_map.rs +++ b/src/value/variable_map.rs @@ -41,9 +41,9 @@ impl VariableMap { let index = if let Ok(index) = next_identifier.parse::() { index } else { - return Err(Error::expected_int(Value::String( - next_identifier.to_string(), - ))); + return Err(Error::ExpectedInt { + actual: Value::String(next_identifier.to_string()), + }); }; Ok(list.get(index).cloned()) @@ -70,9 +70,9 @@ impl VariableMap { let index = if let Ok(index) = next_identifier.parse::() { index } else { - return Err(Error::expected_int(Value::String( - next_identifier.to_string(), - ))); + return Err(Error::ExpectedInt { + actual: Value::String(next_identifier.to_string()), + }); }; let mut missing_elements = index.saturating_sub(list.len()) + 1;