diff --git a/src/consts.rs b/src/consts.rs index c069539a0774..5056cc27a543 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -320,7 +320,7 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { /// create `Some(Vec![..])` of all constants, unless there is any /// non-constant part - fn multi + Sized>(&mut self, vec: &[E]) -> + fn multi + Sized>(&mut self, vec: &[E]) -> Option> { vec.iter().map(|elem| self.expr(elem)) .collect::>() @@ -388,9 +388,8 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { match (l, r) { (ConstantByte(l8), ConstantByte(r8)) => if r8 > l8 { None } else { Some(ConstantByte(l8 - r8)) }, - (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { - let (ln, rn) = (is_negative(lty), is_negative(rty)); - match (ln, rn) { + (ConstantInt(l64, lty), ConstantInt(r64, rty)) => + match (is_negative(lty), is_negative(rty)) { (false, false) => sub_int(l64, lty, r64, rty, r64 > l64), (true, true) => sub_int(l64, lty, r64, rty, l64 > r64), (true, false) => unify_int_type(lty, rty, Minus) @@ -399,12 +398,11 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { (false, true) => unify_int_type(lty, rty, Plus) .and_then(|ty| l64.checked_add(r64).map( |v| ConstantInt(v, ty))), - } - }, + }, _ => None, }), - //BiMul, - //BiDiv, + BiMul => self.divmul(left, right, u64::checked_mul), + BiDiv => self.divmul(left, right, u64::checked_div), //BiRem, BiAnd => self.short_circuit(left, right, false), BiOr => self.short_circuit(left, right, true), @@ -425,6 +423,20 @@ impl<'c, 'cc> ConstEvalContext<'c, 'cc> { } } + fn divmul(&mut self, left: &Expr, right: &Expr, f: F) + -> Option where F: Fn(u64, u64) -> Option { + self.binop_apply(left, right, |l, r| + match (l, r) { + (ConstantInt(l64, lty), ConstantInt(r64, rty)) => { + f(l64, r64).and_then(|value| + unify_int_type(lty, rty, if is_negative(lty) == + is_negative(rty) { Plus } else { Minus }) + .map(|ty| ConstantInt(value, ty))) + }, + _ => None, + }) + } + fn bitop(&mut self, left: &Expr, right: &Expr, f: F) -> Option where F: Fn(u64, u64) -> u64 { self.binop_apply(left, right, |l, r| match (l, r) { diff --git a/tests/consts.rs b/tests/consts.rs index bcc5aa4c30a5..55270cc6b515 100755 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -40,6 +40,8 @@ fn check(expect: Constant, expr: &Expr) { const TRUE : Constant = ConstantBool(true); const FALSE : Constant = ConstantBool(false); const ZERO : Constant = ConstantInt(0, UnsuffixedIntLit(Plus)); +const ONE : Constant = ConstantInt(1, UnsuffixedIntLit(Plus)); +const TWO : Constant = ConstantInt(2, UnsuffixedIntLit(Plus)); #[test] fn test_lit() { @@ -56,10 +58,17 @@ fn test_ops() { check(FALSE, &binop(BiAnd, lit(LitBool(false)), lit(LitBool(true)))); let litzero = lit(LitInt(0, UnsuffixedIntLit(Plus))); + let litone = lit(LitInt(1, UnsuffixedIntLit(Plus))); check(TRUE, &binop(BiEq, litzero.clone(), litzero.clone())); check(TRUE, &binop(BiGe, litzero.clone(), litzero.clone())); check(TRUE, &binop(BiLe, litzero.clone(), litzero.clone())); check(FALSE, &binop(BiNe, litzero.clone(), litzero.clone())); check(FALSE, &binop(BiGt, litzero.clone(), litzero.clone())); check(FALSE, &binop(BiLt, litzero.clone(), litzero.clone())); + + check(ZERO, &binop(BiAdd, litzero.clone(), litzero.clone())); + check(TWO, &binop(BiAdd, litone.clone(), litone.clone())); + check(ONE, &binop(BiSub, litone.clone(), litzero.clone())); + check(ONE, &binop(BiMul, litone.clone(), litone.clone())); + check(ONE, &binop(BiDiv, litone.clone(), litone.clone())); }