let rec print_mexpr e =
  let rec print t = function
      CTTMexpComma( e1, e2 ) ->
        "("^(print_mexpr e1)^", "^(print_mexpr e2)^") : "^(print_c_type t)
    | CTTMexpAddress( lhs, flist ) ->
        "&("^(print_mexpr_lvalue lhs flist)^") : "^(print_c_type t)
    | CTTMexpRead( lhs, flist ) ->
        "READ("^(print_mexpr_lvalue lhs flist)^") : "^(print_c_type t)
    | CTTMexpWrite( lhs, flist, None, e2 ) ->
        "WRITE("^(print_mexpr_lvalue lhs flist)^") = "^(print_mexpr e2)^" : "^(print_c_type t)
    | CTTMexpWrite( lhs, flist, Some(o,Some t), e2 ) ->
        "WRITE("^(print_mexpr_lvalue lhs flist)^") "
        ^(print_binary_operator o)^"= ("^(print_c_type t)^")"^(print_mexpr e2)^") : "^(print_c_type t)
    | CTTMexpWrite( lhs, flist, Some(o,None), e2 ) ->
        "WRITE("^(print_mexpr_lvalue lhs flist)^") "
        ^(print_binary_operator o)^"= "^(print_mexpr e2)^") : "^(print_c_type t)
    | CTTMexpConditional( e1, e2, e3 ) ->
        "("^(print_mexpr e1)^" ? "^(print_mexpr e2)^" : "^(print_mexpr e3)^") : "^(print_c_type t)
    | CTTMexpBinExpr( o, e1, e2 ) ->
        "("^(print_mexpr e1)^" "^(print_binary_operator o)^" "^(print_mexpr e2)^") : "^(print_c_type t)
    | CTTMexpCoerce( t, e ) -> 
        "("^(print_c_type t)^")"^(print_mexpr e)
    | CTTMexpUnaryExpr( o, e ) ->
        "("^(print_unary_operator o)^" "^(print_mexpr e)^") : "^(print_c_type t)
    | CTTMexpInvoke( e, l ) ->
        let rec continue = function
            [] -> ""
          | [e] -> print_mexpr e
          | e::l -> (print_mexpr e)^", "^(continue l)
        in
        let lhs = match e with
          CTTMlvPtr(e) -> "(*"^(print_mexpr e)^")"
        | CTTMlvVar(id,t) -> id ^ " : " ^ (print_c_type t)
        | _ -> assert false
        in
        lhs^"("^(continue l)^")"^" : "^(print_c_type t)
    | CTTMexpConstant c ->
        (print_c_constants c)^" : "^(print_c_type t)
  and print_mexpr_lvalue lhs flist = 
    let rec print_lhs lhs =
      match lhs with
        CTTMlvPtr(e) -> "(*"^(print_mexpr e)^")"
      | CTTMlvVar(id,t) -> id ^ " : " ^ (print_c_type t)
      | CTTMlvInvoke(e, l, t) ->
          let rec continue = function
              [] -> ""
            | [e] -> print_mexpr e
            | e::l -> (print_mexpr e)^", "^(continue l)
          in
          (print_lhs e)^"("^(continue l)^")"^" : "^(print_c_type t)
    in
    let rec continue = function
        [] -> ""
      | [f,t] -> "." ^ f ^ " : "^(print_c_type t)
      | (f,t)::l -> ".(" ^ f ^ " : "^(print_c_type t) ^ ")" ^ continue l
    in
    (print_lhs lhs) ^ (continue flist)
  in
  print e.mexpr_type e.mexpr_t