diff --git a/src/evaluate.rs b/src/evaluate.rs index 06f3c16..5a0590e 100644 --- a/src/evaluate.rs +++ b/src/evaluate.rs @@ -30,7 +30,7 @@ pub fn evaluate( let p = get_at_coords(&mut g, &coords); - let e = p.eval(); + let e = p.eval()?; *p = e; if coords.len() == 0 { break 'outer; } diff --git a/src/main.rs b/src/main.rs index a4e2a26..db85657 100644 --- a/src/main.rs +++ b/src/main.rs @@ -94,19 +94,32 @@ fn main() -> Result<(), std::io::Error> { Ok(g) => { #[cfg(debug_assertions)] RawTerminal::suspend_raw_mode(&stdout)?; - let g = evaluate::evaluate(g).unwrap(); + let g = evaluate::evaluate(g); #[cfg(debug_assertions)] RawTerminal::activate_raw_mode(&stdout)?; - if let Token::Number(v) = g { - write!( - stdout, "\r\n {}{}={} {v}{}\r\n\n", - style::Bold, - color::Fg(color::Green), - style::Reset, - color::Fg(color::Reset) - )?; - } else { panic!(); } + match g { + Ok(Token::Number(v)) => { + write!( + stdout, "\r\n {}{}={} {v}{}\r\n\n", + style::Bold, + color::Fg(color::Green), + style::Reset, + color::Fg(color::Reset) + )?; + }, + + Err(_) => { + write!( + stdout, "\r\n {}{}Mathematical Error: {}Failed to evaluate expression.is{}\r\n\n", + style::Bold, + color::Fg(color::Red), + style::Reset, + color::Fg(color::Reset), + )?; + } + _ => panic!() + } }, // Show parse error @@ -164,7 +177,7 @@ mod tests { let s = String::from(s); let g = parser::parse(&s).unwrap(); let g = evaluate::evaluate(g).unwrap(); - let n = g.eval(); + let n = g.eval().unwrap(); let tokens::Token::Number(v) = n else {panic!()}; assert_eq!(v, r); } diff --git a/src/tokens.rs b/src/tokens.rs index 271b999..a31868c 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -25,12 +25,12 @@ impl Token { } #[inline(always)] - pub fn eval(&self) -> Token { - match self { + pub fn eval(&self) -> Result { + Ok(match self { Token::Number(v) => { Token::Number(*v) }, Token::Constant(v,_) => { Token::Number(*v) }, - Token::Operator(o,v) => { o.apply(v) } - } + Token::Operator(o,v) => { o.apply(v)? } + }) } // Temporary solution @@ -162,7 +162,7 @@ impl Operator { } impl Operator{ - pub fn apply(&self, args: &VecDeque) -> Token { + pub fn apply(&self, args: &VecDeque) -> Result { match self { Operator::ImplicitMultiply | Operator::Sqrt | @@ -175,7 +175,7 @@ impl Operator{ let args = args[0].as_number(); if let Token::Number(v) = args { - Token::Number(-v) + return Ok(Token::Number(-v)); } else { panic!(); } }, @@ -184,7 +184,8 @@ impl Operator{ let args = args[0].as_number(); if let Token::Number(v) = args { - Token::Number(1f64/v) + if v == 0f64 { return Err(()); } + return Ok(Token::Number(1f64/v)); } else { panic!(); } }, @@ -198,7 +199,7 @@ impl Operator{ panic!(); } } - Token::Number(sum) + return Ok(Token::Number(sum)); }, Operator::Multiply => { @@ -211,7 +212,7 @@ impl Operator{ panic!(); } } - Token::Number(prod) + return Ok(Token::Number(prod)); }, Operator::Modulo => { @@ -221,7 +222,11 @@ impl Operator{ if let Token::Number(va) = a { if let Token::Number(vb) = b { - Token::Number(va%vb) + if vb <= 1f64 { return Err(()); } + if va.fract() != 0f64 { return Err(()); } + if vb.fract() != 0f64 { return Err(()); } + + return Ok(Token::Number(va%vb)); } else { panic!(); } } else { panic!(); } }, @@ -233,13 +238,32 @@ impl Operator{ if let Token::Number(va) = a { if let Token::Number(vb) = b { - Token::Number(va.powf(vb)) + let p = va.powf(vb); + if p.is_nan() {return Err(());} + return Ok(Token::Number(p)); } else { panic!(); } } else { panic!(); } }, - Operator::Factorial => { todo!() }, - } + Operator::Factorial => { + if args.len() != 1 {panic!()}; + let args = args[0].as_number(); + + if let Token::Number(v) = args { + if v.fract() != 0f64 { return Err(()); } + if v >= 100f64 { return Err(()); } + + let mut prod = 1f64; + let mut u = v; + while u > 0f64 { + prod *= u; + u -= 1f64; + } + + return Ok(Token::Number(prod)); + } else { panic!(); } + }, + }; } } \ No newline at end of file