forked from AbleScript/ablescript
Fix panic on arithmetic error
Divide by zero and add, subtract, or multiply with overflow are all caught now and reported as an ArithmeticError, rather than causing the interpreter to panic.
This commit is contained in:
parent
acfd81ead2
commit
07195d4cf6
|
@ -110,21 +110,42 @@ impl ExecEnv {
|
||||||
use Expr::*;
|
use Expr::*;
|
||||||
use Value::*;
|
use Value::*;
|
||||||
|
|
||||||
// NOTE(Alex): This is quite nasty, and should probably be
|
// NOTE(Alex): This is really quite horrible. I think the only
|
||||||
// re-done using macros or something.
|
// real way to clean it up would be to re-engineer the AST's
|
||||||
|
// representation to be more hierarchical: rather than having
|
||||||
|
// e.g. "Expr::Add" and "Expr::Subtract" each with a "left"
|
||||||
|
// and "right" struct member, have something like
|
||||||
|
// "Expr::Binary { oper: BinOp, left: Box<Expr>, right:
|
||||||
|
// Box<Expr> }". That way we could factor out a whole bunch of
|
||||||
|
// common code here.
|
||||||
|
//
|
||||||
|
// That work should probably wait for Ondra's new parser to
|
||||||
|
// come in, however.
|
||||||
Ok(match expr {
|
Ok(match expr {
|
||||||
Add { left, right } => {
|
Add { left, right } => Int(i32::try_from(self.eval_expr(left)?)?
|
||||||
Int(i32::try_from(self.eval_expr(left)?)? + i32::try_from(self.eval_expr(right)?)?)
|
.checked_add(i32::try_from(self.eval_expr(right)?)?)
|
||||||
}
|
.ok_or(Error {
|
||||||
Subtract { left, right } => {
|
kind: ErrorKind::ArithmeticError,
|
||||||
Int(i32::try_from(self.eval_expr(left)?)? - i32::try_from(self.eval_expr(right)?)?)
|
position: 0..0,
|
||||||
}
|
})?),
|
||||||
Multiply { left, right } => {
|
Subtract { left, right } => Int(i32::try_from(self.eval_expr(left)?)?
|
||||||
Int(i32::try_from(self.eval_expr(left)?)? * i32::try_from(self.eval_expr(right)?)?)
|
.checked_sub(i32::try_from(self.eval_expr(right)?)?)
|
||||||
}
|
.ok_or(Error {
|
||||||
Divide { left, right } => {
|
kind: ErrorKind::ArithmeticError,
|
||||||
Int(i32::try_from(self.eval_expr(left)?)? / i32::try_from(self.eval_expr(right)?)?)
|
position: 0..0,
|
||||||
}
|
})?),
|
||||||
|
Multiply { left, right } => Int(i32::try_from(self.eval_expr(left)?)?
|
||||||
|
.checked_mul(i32::try_from(self.eval_expr(right)?)?)
|
||||||
|
.ok_or(Error {
|
||||||
|
kind: ErrorKind::ArithmeticError,
|
||||||
|
position: 0..0,
|
||||||
|
})?),
|
||||||
|
Divide { left, right } => Int(i32::try_from(self.eval_expr(left)?)?
|
||||||
|
.checked_div(i32::try_from(self.eval_expr(right)?)?)
|
||||||
|
.ok_or(Error {
|
||||||
|
kind: ErrorKind::ArithmeticError,
|
||||||
|
position: 0..0,
|
||||||
|
})?),
|
||||||
Lt { left, right } => {
|
Lt { left, right } => {
|
||||||
Bool(i32::try_from(self.eval_expr(left)?)? < i32::try_from(self.eval_expr(right)?)?)
|
Bool(i32::try_from(self.eval_expr(left)?)? < i32::try_from(self.eval_expr(right)?)?)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue