method expr =
                  fun f e ->
                    let () = o#node f e Ast.loc_of_expr
                    in
                      match e with
                      | (Ast.ExLet (_, _, _, _) | Ast.ExLmd (_, _, _, _) as
                         e) when semi -> pp f "(%a)" o#reset#expr e
                      | (Ast.ExMat (_, _, _) | Ast.ExTry (_, _, _) |
                           Ast.ExFun (_, _)
                         as e) when pipe || semi ->
                          pp f "(%a)" o#reset#expr e
                      | Ast.ExApp (_, (Ast.ExId (_, (Ast.IdLid (_, "~-")))),
                          x) -> pp f "@[<2>-@ %a@]" o#dot_expr x
                      | Ast.ExApp (_, (Ast.ExId (_, (Ast.IdLid (_, "~-.")))),
                          x) -> pp f "@[<2>-.@ %a@]" o#dot_expr x
                      | Ast.ExApp (_,
                          (Ast.ExApp (_,
                             (Ast.ExId (_, (Ast.IdUid (_, "::")))), _)),
                          _) -> o#expr_list_cons false f e
                      | Ast.ExApp (_loc,
                          (Ast.ExApp (_, (Ast.ExId (_, (Ast.IdLid (_, n)))),
                             x)),
                          y) when is_infix n ->
                          pp f "@[<2>%a@ %s@ %a@]" o#apply_expr x n
                            o#apply_expr y
                      | Ast.ExApp (_, x, y) ->
                          let (a, al) = get_expr_args x [ y ]
                          in
                            if
                              (not curry_constr) &&
                                (Ast.is_expr_constructor a)
                            then
                              (match al with
                               | [ Ast.ExTup (_, _) ] ->
                                   pp f "@[<2>%a@ (%a)@]" o#apply_expr x
                                     o#expr y
                               | [ _ ] ->
                                   pp f "@[<2>%a@ %a@]" o#apply_expr x
                                     o#apply_expr y
                               | al ->
                                   pp f "@[<2>%a@ (%a)@]" o#apply_expr a
                                     (list o#under_pipe#apply_expr ",@ ") al)
                            else
                              pp f "@[<2>%a@]" (list o#apply_expr "@ ")
                                (a :: al)
                      | Ast.ExAss (_,
                          (Ast.ExAcc (_, e1,
                             (Ast.ExId (_, (Ast.IdLid (_, "val")))))),
                          e2) ->
                          pp f "@[<2>%a :=@ %a@]" o#dot_expr e1 o#expr e2
                      | Ast.ExAss (_, e1, e2) ->
                          pp f "@[<2>%a@ <-@ %a@]" o#dot_expr e1 o#expr e2
                      | Ast.ExFun (loc, (Ast.McNil _)) ->
                          pp f "@[<2>fun@ _@ ->@ %a@]" o#raise_match_failure
                            loc
                      | Ast.ExFun (_, (Ast.McArr (_, p, (Ast.ExNil _), e)))
                          when is_irrefut_patt p ->
                          pp f "@[<2>fun@ %a@]" o#patt_expr_fun_args
                            ((`patt p), e)
                      | Ast.ExFUN (_, i, e) ->
                          pp f "@[<2>fun@ %a@]" o#patt_expr_fun_args
                            ((`newtype i), e)
                      | Ast.ExFun (_, a) ->
                          pp f "@[<hv0>function%a@]" o#match_case a
                      | Ast.ExIfe (_, e1, e2, e3) ->
                          pp f
                            "@[<hv0>@[<2>if@ %a@]@ @[<2>then@ %a@]@ @[<2>else@ %a@]@]"
                            o#expr e1 o#under_semi#expr e2 o#under_semi#expr
                            e3
                      | Ast.ExLaz (_, e) ->
                          pp f "@[<2>lazy@ %a@]" o#simple_expr e
                      | Ast.ExLet (_, r, bi, e) ->
                          (match e with
                           | Ast.ExLet (_, _, _, _) ->
                               pp f "@[<0>@[<2>let %a%a in@]@ %a@]"
                                 o#rec_flag r o#binding bi o#reset_semi#expr
                                 e
                           | _ ->
                               pp f
                                 "@[<hv0>@[<2>let %a%a@]@ @[<hv2>in@ %a@]@]"
                                 o#rec_flag r o#binding bi o#reset_semi#expr
                                 e)
                      | Ast.ExOpI (_, i, e) ->
                          pp f "@[<2>let open %a@]@ @[<2>in@ %a@]" o#ident i
                            o#reset_semi#expr e
                      | Ast.ExMat (_, e, a) ->
                          pp f "@[<hv0>@[<hv0>@[<2>match %a@]@ with@]%a@]"
                            o#expr e o#match_case a
                      | Ast.ExTry (_, e, a) ->
                          pp f "@[<0>@[<hv2>try@ %a@]@ @[<0>with%a@]@]"
                            o#expr e o#match_case a
                      | Ast.ExAsf _ -> pp f "@[<2>assert@ false@]"
                      | Ast.ExAsr (_, e) ->
                          pp f "@[<2>assert@ %a@]" o#dot_expr e
                      | Ast.ExLmd (_, s, me, e) ->
                          pp f "@[<2>let module %a =@ %a@]@ @[<2>in@ %a@]"
                            o#var s o#module_expr me o#reset_semi#expr e
                      | Ast.ExObj (_, (Ast.PaNil _), cst) ->
                          pp f "@[<hv0>@[<hv2>object@ %a@]@ end@]"
                            o#class_str_item cst
                      | Ast.ExObj (_, (Ast.PaTyc (_, p, t)), cst) ->
                          pp f
                            "@[<hv0>@[<hv2>object @[<1>(%a :@ %a)@]@ %a@]@ end@]"
                            o#patt p o#ctyp t o#class_str_item cst
                      | Ast.ExObj (_, p, cst) ->
                          pp f
                            "@[<hv0>@[<hv2>object @[<2>(%a)@]@ %a@]@ end@]"
                            o#patt p o#class_str_item cst
                      | e -> o#apply_expr f e