diff --git a/src/expr/syntax_tree.rs b/src/expr/syntax_tree.rs index f705feedd..ac11fbcc3 100644 --- a/src/expr/syntax_tree.rs +++ b/src/expr/syntax_tree.rs @@ -85,18 +85,25 @@ impl ASTNode { ASTNode::Node { ref op_type, .. } => match self.operand_values() { Err(reason) => Err(reason), Ok(operand_values) => match op_type.as_ref() { - "+" => infix_operator_two_ints(|a: i64, b: i64| Ok(a + b), &operand_values), - "-" => infix_operator_two_ints(|a: i64, b: i64| Ok(a - b), &operand_values), - "*" => infix_operator_two_ints(|a: i64, b: i64| Ok(a * b), &operand_values), - "/" => infix_operator_two_ints( - |a: i64, b: i64| { + "+" => infix_operator_two_ints(|a: i64, b: i64| { + checked_binop(|| a.checked_add(b), "+") + }, &operand_values + ), + "-" => infix_operator_two_ints(|a: i64, b: i64| { + checked_binop(|| a.checked_sub(b), "-") + }, &operand_values + ), + "*" => infix_operator_two_ints(|a: i64, b: i64| { + checked_binop(|| a.checked_mul(b), "*") + }, &operand_values + ), + "/" => infix_operator_two_ints(|a: i64, b: i64| { if b == 0 { Err("division by zero".to_owned()) } else { - Ok(a / b) + checked_binop(|| a.checked_div(b), "/") } - }, - &operand_values, + }, &operand_values ), "%" => infix_operator_two_ints( |a: i64, b: i64| { @@ -108,7 +115,6 @@ impl ASTNode { }, &operand_values, ), - "=" => infix_operator_two_ints_or_two_strings( |a: i64, b: i64| Ok(bool_as_int(a == b)), |a: &String, b: &String| Ok(bool_as_string(a == b)), @@ -384,6 +390,13 @@ fn move_till_match_paren( } } +fn checked_binop Option, T>(cb: F, op: &str) -> Result { + match cb() { + Some(v) => Ok(v), + None => Err(format!("{}: Numerical result out of range", op)), + } +} + fn infix_operator_two_ints(f: F, values: &Vec) -> Result where F: Fn(i64, i64) -> Result, diff --git a/tests/test_expr.rs b/tests/test_expr.rs index 6119f4232..eae4274c9 100644 --- a/tests/test_expr.rs +++ b/tests/test_expr.rs @@ -12,6 +12,17 @@ fn test_simple_arithmetic() { new_ucmd!().args(&["4", "/", "2"]).run().stdout_is("2\n"); } +#[test] +fn test_complex_arithmetic() { + let run = new_ucmd!().args(&["9223372036854775807", "+", "9223372036854775807"]).run(); + run.stdout_is(""); + run.stderr_is("expr: error: +: Numerical result out of range"); + + let run = new_ucmd!().args(&["9", "/", "0"]).run(); + run.stdout_is(""); + run.stderr_is("expr: error: division by zero"); +} + #[test] fn test_parenthesis() { new_ucmd!().args(&["(", "1", "+", "1", ")", "*", "2"]).run().stdout_is("4\n");