mirror of https://github.com/rm-dr/daisy
Added basic math error checking
parent
eb101439d9
commit
a90c00c18d
|
@ -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; }
|
||||
|
|
21
src/main.rs
21
src/main.rs
|
@ -94,11 +94,12 @@ 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 {
|
||||
match g {
|
||||
Ok(Token::Number(v)) => {
|
||||
write!(
|
||||
stdout, "\r\n {}{}={} {v}{}\r\n\n",
|
||||
style::Bold,
|
||||
|
@ -106,7 +107,19 @@ fn main() -> Result<(), std::io::Error> {
|
|||
style::Reset,
|
||||
color::Fg(color::Reset)
|
||||
)?;
|
||||
} else { panic!(); }
|
||||
},
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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!(); }
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue