mirror of https://github.com/rm-dr/daisy
Improved evaluator errors
parent
0134bc5c12
commit
ad3ae83c66
|
@ -11,6 +11,7 @@ use termion::{
|
||||||
style,
|
style,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::tokens::EvalError;
|
||||||
use super::promptbuffer::PromptBuffer;
|
use super::promptbuffer::PromptBuffer;
|
||||||
use crate::parser;
|
use crate::parser;
|
||||||
|
|
||||||
|
@ -103,9 +104,19 @@ pub fn main() -> Result<(), std::io::Error> {
|
||||||
)?;
|
)?;
|
||||||
},
|
},
|
||||||
|
|
||||||
Err(_) => {
|
Err(EvalError::BadMath) => {
|
||||||
write!(
|
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,
|
style::Bold,
|
||||||
color::Fg(color::Red),
|
color::Fg(color::Red),
|
||||||
style::Reset,
|
style::Reset,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use crate::tokens::Token;
|
use crate::tokens::Token;
|
||||||
|
use crate::tokens::EvalError;
|
||||||
use crate::tokens::Operator;
|
use crate::tokens::Operator;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[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!()};
|
if args.len() != 1 {panic!()};
|
||||||
let a = args[0].as_number();
|
let a = args[0].as_number();
|
||||||
let Token::Number(q) = a else {panic!()};
|
let Token::Number(q) = a else {panic!()};
|
||||||
|
|
||||||
if !q.unitless() {
|
if !q.unitless() {
|
||||||
return Err(());
|
return Err(EvalError::IncompatibleUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -5,3 +5,8 @@ mod token;
|
||||||
pub use crate::tokens::token::Token;
|
pub use crate::tokens::token::Token;
|
||||||
pub use crate::tokens::function::Function;
|
pub use crate::tokens::function::Function;
|
||||||
pub use crate::tokens::operator::Operator;
|
pub use crate::tokens::operator::Operator;
|
||||||
|
|
||||||
|
pub enum EvalError {
|
||||||
|
BadMath,
|
||||||
|
IncompatibleUnit
|
||||||
|
}
|
|
@ -3,8 +3,10 @@ use std::cmp::Ordering;
|
||||||
|
|
||||||
use crate::tokens::Token;
|
use crate::tokens::Token;
|
||||||
use crate::tokens::Function;
|
use crate::tokens::Function;
|
||||||
|
use crate::tokens::EvalError;
|
||||||
use crate::quantity::Quantity;
|
use crate::quantity::Quantity;
|
||||||
|
|
||||||
|
|
||||||
/// Operator types, in order of increasing priority.
|
/// Operator types, in order of increasing priority.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -331,7 +333,7 @@ impl Operator {
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
match self {
|
||||||
Operator::ImplicitMultiply |
|
Operator::ImplicitMultiply |
|
||||||
Operator::Sqrt |
|
Operator::Sqrt |
|
||||||
|
@ -352,7 +354,7 @@ impl Operator{
|
||||||
let args = args[0].as_number();
|
let args = args[0].as_number();
|
||||||
|
|
||||||
if let Token::Number(v) = args {
|
if let Token::Number(v) = args {
|
||||||
if v.is_zero() { return Err(()); }
|
if v.is_zero() { return Err(EvalError::BadMath); }
|
||||||
return Ok(Token::Number(
|
return Ok(Token::Number(
|
||||||
Quantity::new_rational(1f64).unwrap()/v
|
Quantity::new_rational(1f64).unwrap()/v
|
||||||
));
|
));
|
||||||
|
@ -371,7 +373,7 @@ impl Operator{
|
||||||
if let Token::Number(v) = j {
|
if let Token::Number(v) = j {
|
||||||
|
|
||||||
if sum.unit() != v.unit() {
|
if sum.unit() != v.unit() {
|
||||||
return Err(());
|
return Err(EvalError::IncompatibleUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
sum += v;
|
sum += v;
|
||||||
|
@ -406,12 +408,12 @@ impl Operator{
|
||||||
if let Token::Number(vb) = b {
|
if let Token::Number(vb) = b {
|
||||||
|
|
||||||
if !(va.unitless() && vb.unitless()) {
|
if !(va.unitless() && vb.unitless()) {
|
||||||
return Err(());
|
return Err(EvalError::IncompatibleUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if vb <= Quantity::new_rational(1f64).unwrap() { return Err(()); }
|
if vb <= Quantity::new_rational(1f64).unwrap() { return Err(EvalError::BadMath); }
|
||||||
if va.fract() != Quantity::new_rational(0f64).unwrap() { return Err(()); }
|
if va.fract() != Quantity::new_rational(0f64).unwrap() { return Err(EvalError::BadMath); }
|
||||||
if vb.fract() != Quantity::new_rational(0f64).unwrap() { return Err(()); }
|
if vb.fract() != Quantity::new_rational(0f64).unwrap() { return Err(EvalError::BadMath); }
|
||||||
|
|
||||||
return Ok(Token::Number(va%vb));
|
return Ok(Token::Number(va%vb));
|
||||||
} else { panic!(); }
|
} else { panic!(); }
|
||||||
|
@ -427,11 +429,11 @@ impl Operator{
|
||||||
if let Token::Number(vb) = b {
|
if let Token::Number(vb) = b {
|
||||||
|
|
||||||
if va.unit() != vb.unit() {
|
if va.unit() != vb.unit() {
|
||||||
return Err(());
|
return Err(EvalError::IncompatibleUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
let p = va.pow(vb);
|
let p = va.pow(vb);
|
||||||
if p.is_nan() {return Err(());}
|
if p.is_nan() {return Err(EvalError::BadMath);}
|
||||||
return Ok(Token::Number(p));
|
return Ok(Token::Number(p));
|
||||||
} else { panic!(); }
|
} else { panic!(); }
|
||||||
} else { panic!(); }
|
} else { panic!(); }
|
||||||
|
@ -444,11 +446,11 @@ impl Operator{
|
||||||
if let Token::Number(v) = args {
|
if let Token::Number(v) = args {
|
||||||
|
|
||||||
if !v.unitless() {
|
if !v.unitless() {
|
||||||
return Err(());
|
return Err(EvalError::IncompatibleUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !v.fract().is_zero() { return Err(()); }
|
if !v.fract().is_zero() { return Err(EvalError::BadMath); }
|
||||||
if v > Quantity::new_rational(50_000f64).unwrap() { return Err(()); }
|
if v > Quantity::new_rational(50_000f64).unwrap() { return Err(EvalError::IncompatibleUnit); }
|
||||||
|
|
||||||
let mut prod = Quantity::new_rational(1f64).unwrap();
|
let mut prod = Quantity::new_rational(1f64).unwrap();
|
||||||
let mut u = v.clone();
|
let mut u = v.clone();
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
use crate::tokens::EvalError;
|
||||||
use crate::tokens::Operator;
|
use crate::tokens::Operator;
|
||||||
use crate::quantity::Quantity;
|
use crate::quantity::Quantity;
|
||||||
|
|
||||||
|
|
||||||
/// Tokens represent logical objects in an expession.
|
/// Tokens represent logical objects in an expession.
|
||||||
///
|
///
|
||||||
/// Tokens starting with `Pre*` are intermediate tokens, and
|
/// Tokens starting with `Pre*` are intermediate tokens, and
|
||||||
|
@ -60,7 +62,7 @@ impl Token {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn eval(&self) -> Result<Token, ()> {
|
pub fn eval(&self) -> Result<Token, EvalError> {
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
Token::Number(_) => { self.clone() },
|
Token::Number(_) => { self.clone() },
|
||||||
Token::Constant(v,_) => { Token::Number(v.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 g = self.clone();
|
||||||
let mut coords: Vec<usize> = Vec::with_capacity(16);
|
let mut coords: Vec<usize> = Vec::with_capacity(16);
|
||||||
coords.push(0);
|
coords.push(0);
|
||||||
|
|
Loading…
Reference in New Issue