Improved evaluator errors

pull/2/head
Mark 2023-04-10 18:53:35 -07:00
parent 0134bc5c12
commit ad3ae83c66
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
5 changed files with 40 additions and 19 deletions

View File

@ -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,

View File

@ -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<Token>) -> Result<Token, ()> {
pub fn apply(&self, args: &VecDeque<Token>) -> Result<Token, EvalError> {
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 {

View File

@ -5,3 +5,8 @@ mod token;
pub use crate::tokens::token::Token;
pub use crate::tokens::function::Function;
pub use crate::tokens::operator::Operator;
pub enum EvalError {
BadMath,
IncompatibleUnit
}

View File

@ -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<Token>) -> Result<Token, ()> {
pub fn apply(&self, args: &VecDeque<Token>) -> Result<Token, EvalError> {
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();

View File

@ -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<Token, ()> {
pub fn eval(&self) -> Result<Token, EvalError> {
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<Token, ()> {
pub fn evaluate(&self) -> Result<Token, EvalError> {
let mut g = self.clone();
let mut coords: Vec<usize> = Vec::with_capacity(16);
coords.push(0);