let rec print_expr e =
let print t = function
CTTexpComma( e1, e2 ) ->
"("^(print_expr e1)^", "^(print_expr e2)^") : "^(print_c_type t)
| CTTexpAssign( e1, e2 ) ->
"("^(print_expr e1)^" = "^(print_expr e2)^") : "^(print_c_type t)
| CTTexpBinAssign( o, e1, None, e2 ) ->
"("^(print_expr e1)^" "^(print_binary_operator o)^"= "^(print_expr e2)^") : "^(print_c_type t)
| CTTexpBinAssign( o, e1, Some t2, e2 ) ->
"("^(print_expr e1)^" "^(print_binary_operator o)^"= ("^(print_c_type t2)^")"^(print_expr e2)^") : "^(print_c_type t)
| CTTexpConditional( e1, e2, e3 ) ->
"("^(print_expr e1)^" ? "^(print_expr e2)^" : "^(print_expr e3)^") : "^(print_c_type t)
| CTTexpBinExpr( o, e1, e2 ) ->
"("^(print_expr e1)^" "^(print_binary_operator o)^" "^(print_expr e2)^") : "^(print_c_type t)
| CTTexpCoerce( t, e ) ->
"("^(print_c_type t)^")"^(print_expr e)
| CTTexpUnaryExpr( o, e ) ->
"("^(print_unary_operator o)^" "^(print_expr e)^") : "^(print_c_type t)
| CTTexpAddress e -> "&"^(print_expr e)^" : "^(print_c_type t)
| CTTexpPtrDeref e -> "*"^(print_expr e)^" : "^(print_c_type t)
| CTTexpInvoke( e, l ) ->
let rec continue = function
[] -> ""
| [e] -> print_expr e
| e::l -> (print_expr e)^", "^(continue l)
in
(print_expr e)^"("^(continue l)^")"^" : "^(print_c_type t)
| CTTexpField( e, s ) ->
(print_expr e)^"."^s^" : "^(print_c_type t)
| CTTexpConstant c ->
(print_c_constants c)^" : "^(print_c_type t)
| CTTexpVar s ->
s^" : "^(print_c_type t)
in
print e.expr_type e.expr_t