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 p = get_at_coords(&mut g, &coords);
|
||||||
let e = p.eval();
|
let e = p.eval()?;
|
||||||
*p = e;
|
*p = e;
|
||||||
|
|
||||||
if coords.len() == 0 { break 'outer; }
|
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) => {
|
Ok(g) => {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
RawTerminal::suspend_raw_mode(&stdout)?;
|
RawTerminal::suspend_raw_mode(&stdout)?;
|
||||||
let g = evaluate::evaluate(g).unwrap();
|
let g = evaluate::evaluate(g);
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
RawTerminal::activate_raw_mode(&stdout)?;
|
RawTerminal::activate_raw_mode(&stdout)?;
|
||||||
|
|
||||||
if let Token::Number(v) = g {
|
match g {
|
||||||
|
Ok(Token::Number(v)) => {
|
||||||
write!(
|
write!(
|
||||||
stdout, "\r\n {}{}={} {v}{}\r\n\n",
|
stdout, "\r\n {}{}={} {v}{}\r\n\n",
|
||||||
style::Bold,
|
style::Bold,
|
||||||
|
@ -106,7 +107,19 @@ fn main() -> Result<(), std::io::Error> {
|
||||||
style::Reset,
|
style::Reset,
|
||||||
color::Fg(color::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
|
// Show parse error
|
||||||
|
@ -164,7 +177,7 @@ mod tests {
|
||||||
let s = String::from(s);
|
let s = String::from(s);
|
||||||
let g = parser::parse(&s).unwrap();
|
let g = parser::parse(&s).unwrap();
|
||||||
let g = evaluate::evaluate(g).unwrap();
|
let g = evaluate::evaluate(g).unwrap();
|
||||||
let n = g.eval();
|
let n = g.eval().unwrap();
|
||||||
let tokens::Token::Number(v) = n else {panic!()};
|
let tokens::Token::Number(v) = n else {panic!()};
|
||||||
assert_eq!(v, r);
|
assert_eq!(v, r);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,12 @@ impl Token {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn eval(&self) -> Token {
|
pub fn eval(&self) -> Result<Token, ()> {
|
||||||
match self {
|
Ok(match self {
|
||||||
Token::Number(v) => { Token::Number(*v) },
|
Token::Number(v) => { Token::Number(*v) },
|
||||||
Token::Constant(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
|
// Temporary solution
|
||||||
|
@ -162,7 +162,7 @@ impl Operator {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Operator{
|
impl Operator{
|
||||||
pub fn apply(&self, args: &VecDeque<Token>) -> Token {
|
pub fn apply(&self, args: &VecDeque<Token>) -> Result<Token, ()> {
|
||||||
match self {
|
match self {
|
||||||
Operator::ImplicitMultiply |
|
Operator::ImplicitMultiply |
|
||||||
Operator::Sqrt |
|
Operator::Sqrt |
|
||||||
|
@ -175,7 +175,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 {
|
||||||
Token::Number(-v)
|
return Ok(Token::Number(-v));
|
||||||
} else { panic!(); }
|
} else { panic!(); }
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -184,7 +184,8 @@ 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 {
|
||||||
Token::Number(1f64/v)
|
if v == 0f64 { return Err(()); }
|
||||||
|
return Ok(Token::Number(1f64/v));
|
||||||
} else { panic!(); }
|
} else { panic!(); }
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -198,7 +199,7 @@ impl Operator{
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Token::Number(sum)
|
return Ok(Token::Number(sum));
|
||||||
},
|
},
|
||||||
|
|
||||||
Operator::Multiply => {
|
Operator::Multiply => {
|
||||||
|
@ -211,7 +212,7 @@ impl Operator{
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Token::Number(prod)
|
return Ok(Token::Number(prod));
|
||||||
},
|
},
|
||||||
|
|
||||||
Operator::Modulo => {
|
Operator::Modulo => {
|
||||||
|
@ -221,7 +222,11 @@ impl Operator{
|
||||||
|
|
||||||
if let Token::Number(va) = a {
|
if let Token::Number(va) = a {
|
||||||
if let Token::Number(vb) = b {
|
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!(); }
|
||||||
} else { panic!(); }
|
} else { panic!(); }
|
||||||
},
|
},
|
||||||
|
@ -233,13 +238,32 @@ impl Operator{
|
||||||
|
|
||||||
if let Token::Number(va) = a {
|
if let Token::Number(va) = a {
|
||||||
if let Token::Number(vb) = b {
|
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!(); }
|
||||||
} 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