let rec reduce_expression e =
let loc = e.expr_pr.ctt_loc in
let reduce = function
CTTexpComma( e1, e2 ) ->
begin
match e1.expr_t with
CTTexpConstant _ -> e2
| _ -> e
end
| CTTexpConditional( e1, e2, e3 ) ->
begin
match e1.expr_t with
CTTexpConstant (CTTconstInteger n) ->
if n = zero_big_int then e3 else e2
| CTTexpConstant (CTTconstFloat n) ->
if n = 0.0 then e3 else e2
| CTTexpConstant _ -> e2
| _ -> e
end
| CTTexpBinExpr( operator, e1, e2 ) ->
begin
match e1.expr_t, e2.expr_t with
CTTexpConstant (CTTconstInteger n1), CTTexpConstant (CTTconstInteger n2) ->
{ e with expr_t = compute_const_ii operator n1 n2 }
| CTTexpConstant (CTTconstInteger n1), CTTexpConstant (CTTconstFloat n2) ->
{ e with expr_t = compute_const_fi operator n2 n1 }
| CTTexpConstant (CTTconstFloat n1), CTTexpConstant (CTTconstInteger n2) ->
{ e with expr_t = compute_const_fi operator n1 n2 }
| CTTexpConstant (CTTconstFloat n1), CTTexpConstant (CTTconstFloat n2) ->
{ e with expr_t = compute_const_ff operator n1 n2 }
| _ -> e
end
| CTTexpCoerce( t, e1 ) ->
let numeric = function
Tbuiltin _ -> true | _ -> false
in
let is_int = function
Tbuiltin Tfloat -> false | Tbuiltin Tdouble -> false
| Tbuiltin Tlongdouble -> false
| _ -> true
in
if numeric t.ct_ty then
match e1.expr_t, is_int t.ct_ty with
CTTexpConstant (CTTconstInteger n), true ->
let n = coerce_int_constant n t in
make_expr (CTTexpConstant (CTTconstInteger n)) t ~loc
| CTTexpConstant (CTTconstInteger n), false ->
make_expr (CTTexpConstant (CTTconstFloat (float_of_big_int n))) t ~loc
| CTTexpConstant (CTTconstFloat n), true ->
make_expr (CTTexpConstant (CTTconstInteger (big_int_of_float n))) t ~loc
| CTTexpConstant (CTTconstFloat _), false ->
{ e with expr_type = t }
| _ -> e
else
e
| CTTexpUnaryExpr( operator, e1 ) ->
begin
match e1.expr_t with
CTTexpConstant(CTTconstInteger n) ->
begin
match operator with
UnaryPlus -> e1
| UnaryMinus -> { e with expr_t =
CTTexpConstant(CTTconstInteger (minus_big_int n)) }
| LogNot ->
let n =
if n = zero_big_int then unit_big_int else zero_big_int
in
{ e with expr_t = CTTexpConstant(CTTconstInteger n) }
| IntNot ->
{ e with expr_t =
CTTexpConstant(CTTconstInteger
(minus_big_int (add_int_big_int 1 n))) }
end
| CTTexpConstant(CTTconstFloat n) ->
begin
match operator with
UnaryPlus -> e1
| UnaryMinus -> { e with expr_t = CTTexpConstant(CTTconstFloat (-. n)) }
| LogNot -> assert false
| IntNot -> assert false
end
| _ -> e
end
| CTTexpConstant _ -> e
| _ -> e
in
reduce e.expr_t