Added basic math error checking

pull/2/head
Mark 2023-03-28 14:36:53 -07:00
parent eb101439d9
commit a90c00c18d
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
3 changed files with 62 additions and 25 deletions

View File

@ -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; }

View File

@ -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);
}

View File

@ -25,12 +25,12 @@ impl Token {
}
#[inline(always)]
pub fn eval(&self) -> Token {
match self {
pub fn eval(&self) -> Result<Token, ()> {
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>) -> Token {
pub fn apply(&self, args: &VecDeque<Token>) -> Result<Token, ()> {
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!(); }
},
};
}
}