From ad3ae83c66959e4f54db485fc1629e757163ae0e Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 10 Apr 2023 18:53:35 -0700 Subject: [PATCH] Improved evaluator errors --- src/entry/unix/unix.rs | 15 +++++++++++++-- src/tokens/function.rs | 5 +++-- src/tokens/mod.rs | 7 ++++++- src/tokens/operator.rs | 26 ++++++++++++++------------ src/tokens/token.rs | 6 ++++-- 5 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/entry/unix/unix.rs b/src/entry/unix/unix.rs index 94ab461..a276bc8 100644 --- a/src/entry/unix/unix.rs +++ b/src/entry/unix/unix.rs @@ -11,6 +11,7 @@ use termion::{ style, }; +use crate::tokens::EvalError; use super::promptbuffer::PromptBuffer; use crate::parser; @@ -103,9 +104,19 @@ pub fn main() -> Result<(), std::io::Error> { )?; }, - Err(_) => { + Err(EvalError::BadMath) => { write!( - stdout, "\n {}{}Mathematical Error: {}Failed to evaluate expression.{}\r\n\n", + stdout, "\n {}{}Mathematical Error: {}Failed to evaluate expression{}\r\n\n", + style::Bold, + color::Fg(color::Red), + style::Reset, + color::Fg(color::Reset), + )?; + }, + + Err(EvalError::IncompatibleUnit) => { + write!( + stdout, "\n {}{}Evaluation Error: {}Incompatible units{}\r\n\n", style::Bold, color::Fg(color::Red), style::Reset, diff --git a/src/tokens/function.rs b/src/tokens/function.rs index b958c46..d0d2000 100644 --- a/src/tokens/function.rs +++ b/src/tokens/function.rs @@ -1,6 +1,7 @@ use std::collections::VecDeque; use crate::tokens::Token; +use crate::tokens::EvalError; use crate::tokens::Operator; #[derive(Debug)] @@ -65,13 +66,13 @@ impl Function { } } - pub fn apply(&self, args: &VecDeque) -> Result { + pub fn apply(&self, args: &VecDeque) -> Result { if args.len() != 1 {panic!()}; let a = args[0].as_number(); let Token::Number(q) = a else {panic!()}; if !q.unitless() { - return Err(()); + return Err(EvalError::IncompatibleUnit); } match self { diff --git a/src/tokens/mod.rs b/src/tokens/mod.rs index 82ac2d1..65c21c3 100644 --- a/src/tokens/mod.rs +++ b/src/tokens/mod.rs @@ -4,4 +4,9 @@ mod token; pub use crate::tokens::token::Token; pub use crate::tokens::function::Function; -pub use crate::tokens::operator::Operator; \ No newline at end of file +pub use crate::tokens::operator::Operator; + +pub enum EvalError { + BadMath, + IncompatibleUnit +} \ No newline at end of file diff --git a/src/tokens/operator.rs b/src/tokens/operator.rs index 6488cd8..4ee34a9 100644 --- a/src/tokens/operator.rs +++ b/src/tokens/operator.rs @@ -3,8 +3,10 @@ use std::cmp::Ordering; use crate::tokens::Token; use crate::tokens::Function; +use crate::tokens::EvalError; use crate::quantity::Quantity; + /// Operator types, in order of increasing priority. #[derive(Debug)] #[derive(Clone)] @@ -331,7 +333,7 @@ impl Operator { } impl Operator{ - pub fn apply(&self, args: &VecDeque) -> Result { + pub fn apply(&self, args: &VecDeque) -> Result { match self { Operator::ImplicitMultiply | Operator::Sqrt | @@ -352,7 +354,7 @@ impl Operator{ let args = args[0].as_number(); if let Token::Number(v) = args { - if v.is_zero() { return Err(()); } + if v.is_zero() { return Err(EvalError::BadMath); } return Ok(Token::Number( Quantity::new_rational(1f64).unwrap()/v )); @@ -371,7 +373,7 @@ impl Operator{ if let Token::Number(v) = j { if sum.unit() != v.unit() { - return Err(()); + return Err(EvalError::IncompatibleUnit); } sum += v; @@ -406,12 +408,12 @@ impl Operator{ if let Token::Number(vb) = b { if !(va.unitless() && vb.unitless()) { - return Err(()); + return Err(EvalError::IncompatibleUnit); } - if vb <= Quantity::new_rational(1f64).unwrap() { return Err(()); } - if va.fract() != Quantity::new_rational(0f64).unwrap() { return Err(()); } - if vb.fract() != Quantity::new_rational(0f64).unwrap() { return Err(()); } + if vb <= Quantity::new_rational(1f64).unwrap() { return Err(EvalError::BadMath); } + if va.fract() != Quantity::new_rational(0f64).unwrap() { return Err(EvalError::BadMath); } + if vb.fract() != Quantity::new_rational(0f64).unwrap() { return Err(EvalError::BadMath); } return Ok(Token::Number(va%vb)); } else { panic!(); } @@ -427,11 +429,11 @@ impl Operator{ if let Token::Number(vb) = b { if va.unit() != vb.unit() { - return Err(()); + return Err(EvalError::IncompatibleUnit); } let p = va.pow(vb); - if p.is_nan() {return Err(());} + if p.is_nan() {return Err(EvalError::BadMath);} return Ok(Token::Number(p)); } else { panic!(); } } else { panic!(); } @@ -444,11 +446,11 @@ impl Operator{ if let Token::Number(v) = args { if !v.unitless() { - return Err(()); + return Err(EvalError::IncompatibleUnit); } - if !v.fract().is_zero() { return Err(()); } - if v > Quantity::new_rational(50_000f64).unwrap() { return Err(()); } + if !v.fract().is_zero() { return Err(EvalError::BadMath); } + if v > Quantity::new_rational(50_000f64).unwrap() { return Err(EvalError::IncompatibleUnit); } let mut prod = Quantity::new_rational(1f64).unwrap(); let mut u = v.clone(); diff --git a/src/tokens/token.rs b/src/tokens/token.rs index ff498ed..a2e86cf 100644 --- a/src/tokens/token.rs +++ b/src/tokens/token.rs @@ -1,8 +1,10 @@ use std::collections::VecDeque; +use crate::tokens::EvalError; use crate::tokens::Operator; use crate::quantity::Quantity; + /// Tokens represent logical objects in an expession. /// /// Tokens starting with `Pre*` are intermediate tokens, and @@ -60,7 +62,7 @@ impl Token { } #[inline(always)] - pub fn eval(&self) -> Result { + pub fn eval(&self) -> Result { Ok(match self { Token::Number(_) => { self.clone() }, Token::Constant(v,_) => { Token::Number(v.clone()) }, @@ -96,7 +98,7 @@ impl Token { } - pub fn evaluate(&self) -> Result { + pub fn evaluate(&self) -> Result { let mut g = self.clone(); let mut coords: Vec = Vec::with_capacity(16); coords.push(0);