Add crude support for casts in constant expressions

Only casts to integral and float types are supported

Closes #1975
This commit is contained in:
Marijn Haverbeke
2012-03-14 18:04:03 +01:00
parent c988800cf5
commit de79caa97e
8 changed files with 129 additions and 73 deletions

View File

@@ -250,38 +250,36 @@ enum const_val {
}
// FIXME: issue #1417
fn eval_const_expr(e: @expr) -> const_val {
fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val {
import middle::ty;
fn fromb(b: bool) -> const_val { const_int(b as i64) }
alt e.node {
alt check e.node {
expr_unary(neg, inner) {
alt eval_const_expr(inner) {
alt check eval_const_expr(tcx, inner) {
const_float(f) { const_float(-f) }
const_int(i) { const_int(-i) }
const_uint(i) { const_uint(-i) }
_ { fail "eval_const_expr: bad neg argument"; }
}
}
expr_unary(not, inner) {
alt eval_const_expr(inner) {
alt check eval_const_expr(tcx, inner) {
const_int(i) { const_int(!i) }
const_uint(i) { const_uint(!i) }
_ { fail "eval_const_expr: bad not argument"; }
}
}
expr_binary(op, a, b) {
alt (eval_const_expr(a), eval_const_expr(b)) {
alt check (eval_const_expr(tcx, a), eval_const_expr(tcx, b)) {
(const_float(a), const_float(b)) {
alt op {
alt check op {
add { const_float(a + b) } subtract { const_float(a - b) }
mul { const_float(a * b) } div { const_float(a / b) }
rem { const_float(a % b) } eq { fromb(a == b) }
lt { fromb(a < b) } le { fromb(a <= b) } ne { fromb(a != b) }
ge { fromb(a >= b) } gt { fromb(a > b) }
_ { fail "eval_const_expr: can't apply this binop to floats"; }
}
}
(const_int(a), const_int(b)) {
alt op {
alt check op {
add { const_int(a + b) } subtract { const_int(a - b) }
mul { const_int(a * b) } div { const_int(a / b) }
rem { const_int(a % b) } and | bitand { const_int(a & b) }
@@ -291,11 +289,11 @@ fn eval_const_expr(e: @expr) -> const_val {
eq { fromb(a == b) } lt { fromb(a < b) }
le { fromb(a <= b) } ne { fromb(a != b) }
ge { fromb(a >= b) } gt { fromb(a > b) }
_ { fail "eval_const_expr: can't apply this binop to ints"; }
}
}
(const_uint(a), const_uint(b)) {
alt op {
alt check op {
add { const_uint(a + b) } subtract { const_uint(a - b) }
mul { const_uint(a * b) } div { const_uint(a / b) }
rem { const_uint(a % b) } and | bitand { const_uint(a & b) }
@@ -306,17 +304,38 @@ fn eval_const_expr(e: @expr) -> const_val {
eq { fromb(a == b) } lt { fromb(a < b) }
le { fromb(a <= b) } ne { fromb(a != b) }
ge { fromb(a >= b) } gt { fromb(a > b) }
_ { fail "eval_const_expr: can't apply this binop to uints"; }
}
}
_ { fail "eval_constr_expr: bad binary arguments"; }
}
}
expr_cast(base, _) {
let ety = ty::expr_ty(tcx, e);
let base = eval_const_expr(tcx, base);
alt check ty::get(ety).struct {
ty::ty_float(_) {
alt check base {
const_uint(u) { const_float(u as f64) }
const_int(i) { const_float(i as f64) }
const_float(_) { base }
}
}
ty::ty_uint(_) {
alt check base {
const_uint(_) { base }
const_int(i) { const_uint(i as u64) }
const_float(f) { const_uint(f as u64) }
}
}
ty::ty_int(_) | ty::ty_bool {
alt check base {
const_uint(u) { const_int(u as i64) }
const_int(_) { base }
const_float(f) { const_int(f as i64) }
}
}
}
}
expr_lit(lit) { lit_to_const(lit) }
// Precondition?
_ {
fail "eval_const_expr: non-constant expression";
}
}
}
@@ -375,11 +394,13 @@ fn compare_const_vals(a: const_val, b: const_val) -> int {
}
}
fn compare_lit_exprs(a: @expr, b: @expr) -> int {
compare_const_vals(eval_const_expr(a), eval_const_expr(b))
fn compare_lit_exprs(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> int {
compare_const_vals(eval_const_expr(tcx, a), eval_const_expr(tcx, b))
}
fn lit_expr_eq(a: @expr, b: @expr) -> bool { compare_lit_exprs(a, b) == 0 }
fn lit_expr_eq(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> bool {
compare_lit_exprs(tcx, a, b) == 0
}
fn lit_eq(a: @lit, b: @lit) -> bool {
compare_const_vals(lit_to_const(a), lit_to_const(b)) == 0