diff --git a/bench/bench b/bench/bench
index cc13b8f801006c1efb9a5af683ffad269816da3a..bb195033d8115dc21a6516bbeed924338651384c 100755
--- a/bench/bench
+++ b/bench/bench
@@ -298,16 +298,8 @@ list_stuff () {
 
 test_mlw_printer () {
     python3 -m sexpdata || return
-    bench/test_mlw_printer "bench/valid/booleans.mlw" || exit 1
-    bench/test_mlw_printer "bench/valid/complex_arg_1.mlw" || exit 1
-    bench/test_mlw_printer "bench/valid/complex_arg_2.mlw" || exit 1
-    bench/test_mlw_printer "bench/valid/division.mlw" || exit 1
-    bench/test_mlw_printer "bench/valid/exns.mlw" || exit 1
-    bench/test_mlw_printer "bench/valid/oldify.mlw" || exit 1
-    bench/test_mlw_printer "bench/valid/recfun.mlw" || exit 1
-    bench/test_mlw_printer "bench/valid/see.mlw" || exit 1
-    bench/test_mlw_printer "bench/valid/type_invariant.mlw" || exit 1
-    bench/test_mlw_printer "bench/valid/wpcalls.mlw" || exit 1
+    bench/test_mlw_printer bench/valid/*.mlw
+    bench/test_mlw_printer bench/typing/good/*.mlw
 }
 
 echo "=== Checking stdlib ==="
diff --git a/bench/test_mlw_printer b/bench/test_mlw_printer
index 5ce98c58af5268092f7bfa6dfa5f3ca9f533fb74..8de3ced9fbd5fc6e89e0e39a0991fd810d808264 100755
--- a/bench/test_mlw_printer
+++ b/bench/test_mlw_printer
@@ -53,11 +53,14 @@ def trace(path, sexp, sexp1):
 
 def test(filename):
     sexp0 = read(filename)
-    sexp1 = print_and_read(filename)
     try:
+        sexp1 = print_and_read(filename)
         assert_equal([], sexp0, sexp1)
         print("OK:", filename)
         return True
+    except AssertionError:
+        print("CANT REPARSE:", filename)
+        return False
     except NotEqual as e:
         print("FAILED:", filename)
         # sexpdata.dump(trace(e.path, sexp0, e.sexp1), sys.stdout)
diff --git a/examples/use_api/oracles/test-api-mlw_tree.stdout b/examples/use_api/oracles/test-api-mlw_tree.stdout
index 7ec9008988aabe5360d67c2126ee263c22cf2f0c..656d6f7e6cc17a8312666a816b763d4fcd5d91ae 100644
--- a/examples/use_api/oracles/test-api-mlw_tree.stdout
+++ b/examples/use_api/oracles/test-api-mlw_tree.stdout
@@ -8,9 +8,9 @@ module M2
   use  int.Int
   
   let f (x : int)
-    requires {(x = 6)}
-    ensures { (result = 42) } =
-    (Int.(*) x 7)
+    requires { x = 6 }
+    ensures { result = 42 } =
+    Int.(*) x 7
 end
 
 module M3
@@ -18,8 +18,8 @@ module M3
   use  ref.Ref
   
   let f (_ : ())
-    ensures { (Int.(>=) result 0) } =
-    (let x = (Ref.ref 42) in Ref.(!) x)
+    ensures { Int.(>=) result 0 } =
+    let x = Ref.ref 42 in Ref.(!) x
 end
 
 module M4
@@ -27,9 +27,9 @@ module M4
   use  array.Array
   
   let f (a : Array.array int)
-    requires {(Int.(>=) (Array.length a) 1)}
+    requires { Int.(>=) (Array.length a) 1 }
     returns { _ -> (Array.([]) a 0) = 42 } =
-    (Array.([]<-) a 0 42)
+    Array.([]<-) a 0 42
 end
 Tasks are:
 Task 1: theory Task
diff --git a/src/parser/mlw_printer.ml b/src/parser/mlw_printer.ml
index 9349e23de46995ba645b72f181fd4cb5960a0901..ef1b2387c29555b2c891672d4c314f10e00bbc38 100644
--- a/src/parser/mlw_printer.ml
+++ b/src/parser/mlw_printer.ml
@@ -49,7 +49,7 @@ let next_pos =
     incr counter;
     Loc.user_position "" !counter 0 0
 
-let todo fmt str =
+let todo fmt _str =
   fprintf fmt "__todo__"
 (* fprintf fmt "<NOT IMPLEMENTED: %s>" str *)
 
@@ -78,14 +78,19 @@ let pp_bool ?true_ ?false_ fmt = function
   | true -> pp_opt (fun fmt f -> fprintf fmt f) fmt true_
   | false -> pp_opt (fun fmt f -> fprintf fmt f) fmt false_
 
-let pp_closed is_closed pp fmt x =
-  if is_closed x
-  then pp fmt x
-  else fprintf fmt "(%a)" pp x
+(* let pp_scoped fmt begin_ (f: ('a, formatter, unit) format) end_ : 'a =
+ *   pp_open_box fmt 0;
+ *   pp_open_hvbox fmt 2;
+ *   fprintf fmt begin_;
+ *   kfprintf (fun fmt ->
+ *       pp_close_box fmt ();
+ *       fprintf fmt end_;
+ *       pp_close_box fmt ())
+ *     fmt f *)
 
 let expr_closed e = match e.expr_desc with
-  | Eref | Etrue | Efalse | Econst _ | Eident _ | Etuple _ | Erecord _
-  | Eabsurd | Escope _ | Eidapp (_, []) | Ecast _ | Einfix _ | Einnfix _ ->
+  | Eref | Etrue | Efalse | Econst _ | Eident _ | Etuple _ | Erecord _ | Efor _ | Ewhile _
+  | Eassert _ | Eabsurd | Escope _ | Eidapp (_, []) | Ecast _ | Einfix _ | Einnfix _ ->
       true
   | _ -> marker e.expr_loc <> None
 
@@ -105,6 +110,11 @@ let pty_closed t = match t with
       true
   | _ -> false
 
+let pp_closed is_closed pp fmt x =
+  if is_closed x
+  then pp fmt x
+  else fprintf fmt "@[<hv 1>(%a)@]" pp x
+
 let pp_id fmt id =
   pp_maybe_marker fmt id.id_loc;
   let open Ident in
@@ -221,7 +231,7 @@ let pp_update pp fmt x fs =
 let rec pp_pty =
   let raw fmt = function
     | PTtyvar id ->
-        pp_id fmt id
+        fprintf fmt "'%a" pp_id id
     | PTtyapp (qid, []) ->
         pp_qualid fmt qid
     | PTtyapp (qid, ptys) ->
@@ -245,16 +255,16 @@ let rec pp_pty =
 let pp_opt_pty = pp_opt ~prefix:" : " pp_pty.marked
 
 let pp_ghost fmt ghost =
-  if ghost then pp_print_string fmt " ghost"
+  if ghost then pp_print_string fmt "ghost "
 
 let pp_mutable fmt mutable_ =
-  if mutable_ then pp_print_string fmt " mutable"
+  if mutable_ then pp_print_string fmt "mutable "
 
 let pp_kind ~unary fmt = function
   | Expr.RKnone -> ()
-  | Expr.RKfunc -> pp_print_string fmt (if unary then " constant" else " func")
-  | Expr.RKpred -> pp_print_string fmt " predicate"
-  | Expr.RKlemma -> pp_print_string fmt " lemma"
+  | Expr.RKfunc -> pp_print_string fmt (if unary then "constant " else "func ")
+  | Expr.RKpred -> pp_print_string fmt "predicate "
+  | Expr.RKlemma -> pp_print_string fmt "lemma "
   | Expr.RKlocal -> todo fmt "RKlocal"
 
 let pp_binder fmt (loc, opt_id, ghost, opt_pty) =
@@ -271,25 +281,29 @@ let pp_binders fmt =
   pp_print_opt_list ~prefix:" " pp_binder fmt
 
 let pp_comma_binder fmt (loc, opt_id, ghost, opt_pty) =
-  let ghost = if ghost then "ghost " else "" in
-  fprintf fmt "%a%s%a%a" pp_maybe_marker loc ghost (pp_opt ~def:"_" pp_id) opt_id
+  fprintf fmt "%a%a%a%a" pp_maybe_marker loc pp_ghost ghost (pp_opt ~def:"_" pp_id) opt_id
     (pp_opt ~prefix:" : " pp_pty.marked) opt_pty
 
 let pp_comma_binders fmt =
   pp_print_opt_list ~prefix:" " ~sep:", " pp_comma_binder fmt
 
 let pp_param fmt (loc, opt_id, ghost, pty) =
-  pp_binder fmt (loc, opt_id, ghost, Some pty)
+  if ghost || opt_id <> None then
+    fprintf fmt "%a(%a%a: %a)" pp_maybe_marker loc
+      pp_ghost ghost (pp_opt ~prefix:" " pp_id) opt_id
+      pp_pty.marked pty
+  else
+    fprintf fmt "%a%a" pp_maybe_marker loc pp_pty.closed pty
 
 let pp_params fmt =
   pp_print_opt_list ~prefix:" " pp_param fmt
 
 let pp_if pp fmt x1 x2 x3 =
-  fprintf fmt "@[@[<hv 2>if %a@]@ @[<hv 2>then %a@]@ @[<hv 2>else %a@]@]"
-    pp.marked x1 pp.marked x2 pp.marked x3
+  fprintf fmt "@[<v>@[<hv 2>if %a then@ %a@]@ @[<hv 2>else@ %a@]@]"
+    pp.closed x1 pp.closed x2 pp.closed x3
 
 let pp_cast pp fmt x pty =
-  fprintf fmt "(%a : %a)" pp.marked x pp_pty.marked pty
+  fprintf fmt "@[<hv 1>(%a :@ %a)@]" pp.marked x pp_pty.marked pty
 
 let pp_attr pp fmt attr x =
   match attr with
@@ -310,7 +324,7 @@ let pp_exn fmt (id, pty, mask) =
   fprintf fmt "@[<h>exception %a%t%t@]" pp_id id pp_mask pp_pty
 
 let pp_let pp fmt (id, ghost, kind, x) =
-  fprintf fmt "@[<hv 2>let%a%a %a =@ %a@]" pp_ghost ghost
+  fprintf fmt "@[<hv 2>let %a%a%a =@ %a@]" pp_ghost ghost
     (pp_kind ~unary:true) kind pp_id id pp.marked x
 
 let remove_attr s t = match t.term_desc with
@@ -353,10 +367,10 @@ let pp_match pp pp_pattern fmt x cases xcases =
   let pp_exn_branch fmt (qid, p_opt, x) =
     fprintf fmt "@[<hv 2>%a%a -> %a@]" pp_qualid qid
       (pp_opt ~prefix:" " pp_pattern.marked) p_opt pp.marked x in
-  fprintf fmt "@[@[<hv 2>match@ %a@]@ @[<hv 2>with@ | %a%a@]@ end@]"
+  fprintf fmt "@[<v>@[<hv 2>match %a with@]%a%a@ end@]"
     pp.marked x
-    (pp_print_list ~pp_sep:(pp_sep "@ | ") pp_reg_branch) cases
-    (pp_print_list ~pp_sep:(pp_sep "@ | exception ") pp_exn_branch) xcases
+    (pp_print_opt_list ~prefix:"@ | " ~sep:"@ | " pp_reg_branch) cases
+    (pp_print_opt_list ~prefix:"@ | exception " ~sep:"@ | exception " pp_exn_branch) xcases
 
 let rec pp_fun pp fmt (binders, opt_pty, pat, mask, spec, e) =
   if pat.pat_desc <> Pwild then
@@ -373,7 +387,7 @@ and pp_let_fun pp fmt (id, ghost, kind, (binders, opt_pty, pat, mask, spec, x))
   else if mask <> Ity.MaskVisible then
     todo fmt "let fun with ghost return"
   else
-    fprintf fmt "@[<hv 2>let%a%a %a%a%a%a =@ %a@]"
+    fprintf fmt "@[<v 2>let %a%a%a%a%a%a =@ %a@]"
       pp_ghost ghost (pp_kind ~unary:false) kind
       pp_id id pp_binders binders pp_opt_pty opt_pty pp_spec spec pp.marked x
 
@@ -385,8 +399,10 @@ and pp_let_any fmt (id, ghost, kind, (params, kind', opt_pty, pat, mask, spec))
   else if kind' <> Expr.RKnone then
     todo fmt "let fun with result not kind none"
   else
-    fprintf fmt "@[<hv 2>val%a%a %a%a%a%a@]" pp_ghost ghost (pp_kind ~unary:true) kind
-      pp_id id pp_params params pp_opt_pty opt_pty pp_spec spec
+    let pp_partial = pp_bool ~true_:"partial " ~false_:"" in
+    fprintf fmt "@[<v 2>val %a%a%a%a%a%a%a@]" pp_ghost ghost pp_partial spec.sp_partial
+      (pp_kind ~unary:true) kind pp_id id pp_params params pp_opt_pty opt_pty
+      pp_spec {spec with sp_partial=false} (* [sic!] *)
 
 and pp_fundef fmt (id, ghost, kind, binders, pty_opt, pat, mask, spec, e) =
   if pat.pat_desc <> Pwild then
@@ -394,175 +410,162 @@ and pp_fundef fmt (id, ghost, kind, binders, pty_opt, pat, mask, spec, e) =
   else if mask <> Ity.MaskVisible then
     todo fmt "fun def with ghost return"
   else
-    fprintf fmt "@[<hv 2>%a%a%a%a%a%a =@ %a@]"
+    fprintf fmt "%a%a%a%a%a%a =@ %a"
       pp_ghost ghost (pp_kind ~unary:false) kind
       pp_id id
-      (pp_print_opt_list ~prefix:" " pp_binder) binders
+      pp_binders binders
       pp_opt_pty pty_opt
       pp_spec spec
       pp_expr.marked e
 
-and pp_variants fmt =
-  let pp_variant fmt (t, qid_opt) =
-    fprintf fmt "@ @[<hv 2>variant {@ %a%a }@]" pp_term.marked t
-      (pp_opt ~prefix:" with " pp_qualid) qid_opt in
-  pp_print_opt_list ~prefix:"" ~sep:("@ ") ~suffix:"@ " pp_variant fmt
-
-and pp_invariants fmt =
-  let pp_invariant fmt t =
-    fprintf fmt "@ @[<hv 2>invariant {@ %a }@]" pp_term.marked
-      (remove_attr "hyp_name:LoopInvariant" t) in
-  pp_print_opt_list ~prefix:"" ~sep:"@ " ~suffix:"@ " pp_invariant fmt
-
 and pp_expr =
   let raw fmt e =
-  match e.expr_desc with
-  | Eref ->
-      pp_print_string fmt "ref"
-  | Etrue ->
-      pp_true fmt ()
-  | Efalse ->
-      pp_false fmt ()
-  | Econst c ->
-      pp_const fmt c
-  | Eident id ->
-      pp_ident fmt id
-  | Easref qid ->
-      pp_asref fmt qid
-  | Eidapp (qid, es) ->
-      pp_idapp pp_expr fmt qid es
-  | Eapply (e1, e2) ->
-      pp_apply pp_expr fmt e1 e2
-  | Einfix (e1, op, e2) ->
-      pp_infix pp_expr fmt e1 op e2
-  | Einnfix (e1, op, e2) ->
-      pp_innfix pp_expr fmt e1 op e2;
-  | Elet (id, ghost, kind, {expr_desc=Efun (binders, pty_opt, pat, mask, spec, e1)}, e2) ->
-      if pat.pat_desc <> Pwild then
-        todo fmt "let with named return"
-      else
+    match e.expr_desc with
+    | Eref ->
+        pp_print_string fmt "ref"
+    | Etrue ->
+        pp_true fmt ()
+    | Efalse ->
+        pp_false fmt ()
+    | Econst c ->
+        pp_const fmt c
+    | Eident id ->
+        pp_ident fmt id
+    | Easref qid ->
+        pp_asref fmt qid
+    | Eidapp (qid, es) ->
+        pp_idapp pp_expr fmt qid es
+    | Eapply (e1, e2) ->
+        pp_apply pp_expr fmt e1 e2
+    | Einfix (e1, op, e2) ->
+        pp_infix pp_expr fmt e1 op e2
+    | Einnfix (e1, op, e2) ->
+        pp_innfix pp_expr fmt e1 op e2;
+    | Elet (id, ghost, kind, {expr_desc=Efun (binders, pty_opt, pat, mask, spec, e1)}, e2) ->
+        if pat.pat_desc <> Pwild then
+          todo fmt "let with named return"
+        else
+          fprintf fmt "@[<v>%a in@ %a@]"
+            (pp_let_fun pp_expr) (id, ghost, kind, (binders, pty_opt, pat, mask, spec, e1))
+            pp_expr.marked e2
+    | Elet (id, ghost, kind, {expr_desc=Eany (params, kind', pty_opt, pat, mask, spec)}, e2) ->
         fprintf fmt "@[<v>%a in@ %a@]"
-          (pp_let_fun pp_expr) (id, ghost, kind, (binders, pty_opt, pat, mask, spec, e1))
+          pp_let_any (id, ghost, kind, (params, kind', pty_opt, pat, mask, spec))
           pp_expr.marked e2
-  | Elet (id, ghost, kind, {expr_desc=Eany (params, kind', pty_opt, pat, mask, spec)}, e2) ->
-      fprintf fmt "@[<v>%a in@ %a@]"
-        pp_let_any (id, ghost, kind, (params, kind', pty_opt, pat, mask, spec))
-        pp_expr.marked e2
-  | Elet (id, ghost, kind, e1, e2) ->
-      fprintf fmt "@[<hv>@[<hv 2>%a@] in@ %a@]" (pp_let pp_expr) (id, ghost, kind, e1)
-        pp_expr.marked e2
-  | Erec (defs, e) ->
-      let pp_fundefs = pp_print_list ~pp_sep:(pp_sep "@ and ") pp_fundef in
-      fprintf fmt "@[<v>let rec %a in@ %a@]" pp_fundefs defs pp_expr.marked e
-  | Efun ([], None, {pat_desc=Pwild}, Ity.MaskVisible, spec, {expr_desc=Etuple []}) ->
-      fprintf fmt "@[<v>@[<v 2>begin%a@]@ end@]" pp_spec spec
-  | Efun ([], None, {pat_desc=Pwild}, Ity.MaskVisible, spec, e) ->
-      fprintf fmt "@[<v>@[<v 2>begin%a@ %a@]@ end@]" pp_spec spec pp_expr.marked e
-  | Efun (binders, opt_pty, pat, mask, spec, e) ->
-      pp_fun pp_expr fmt (binders, opt_pty, pat, mask, spec, e)
-  | Eany ([], _kind, Some pty, _pat, _mask, spec) ->
-      fprintf fmt "@[<hv 2>any %a%a@]" pp_pty.marked pty pp_spec spec
-  | Eany _ ->
-      todo fmt "Eany _"
-  | Etuple es ->
-      pp_tuple pp_expr fmt es
-  | Erecord fs ->
-      pp_record pp_expr fmt fs
-  | Eupdate (e, fs) ->
-      pp_update pp_expr fmt e fs
-  | Eassign [e1, None, e2] ->
-      fprintf fmt "@[<hv 2>%a <-@ %a@]" pp_expr.closed e1 pp_expr.closed e2
-  | Eassign [e1, Some qid, e2] ->
-      fprintf fmt "@[<hv 2>%a.%a <-@ %a@]" pp_expr.closed e1 pp_qualid qid pp_expr.closed e2
-  | Eassign _ ->
-      todo fmt "Eassign _"
-  | Esequence _ ->
-      let rec flatten e = match e.expr_desc with
-        | Esequence (e1, e2) -> e1 :: flatten e2
-        | _ -> [e] in
-      fprintf fmt "@[<v 1>(%a)@]"
-        (pp_print_list ~pp_sep:(pp_sep ";@ ") pp_expr.closed)
-        (flatten e)
-  | Eif (e1, e2, e3) ->
-      pp_if pp_expr fmt e1 e2 e3
-  | Ewhile (e1, invs, vars, e2) ->
-    fprintf fmt "@[<v>@[<hv 2>while@ %a@] do@,  @[<hv>%a%a%a@]@,done@]"
-      pp_expr.marked e1 pp_variants vars pp_invariants invs pp_expr.marked e2
-  | Eand (e1, e2) ->
-      fprintf fmt "@[@[<hv 2>%a@]@ @[<hv 2> &&@ %a@]@]" pp_expr.closed e1 pp_expr.closed e2
-  | Eor (e1, e2) ->
-      fprintf fmt "@[@[<hv 2>%a@]@ @[<hv 2> ||@ %a@]@]" pp_expr.closed e1 pp_expr.closed e2
-  | Enot e ->
-      pp_not pp_expr fmt e
-  | Ematch (e, [], xcases) ->
-      let pp_xcase fmt (qid, opt_pat, e) =
-        fprintf fmt "%a%a ->@ %a" pp_qualid qid
-          (pp_opt ~prefix:" " pp_pattern.marked) opt_pat pp_expr.marked e in
-      let pp_xcases = pp_print_list ~pp_sep:(pp_sep "@ | ") pp_xcase in
-      fprintf fmt "@[<hv>@[<hv 2>try@ %a@]@ @[<hv 2>with@ %a@]@ end@]"
-        pp_expr.marked e pp_xcases xcases
-  | Ematch (e, cases, xcases) ->
-      pp_match pp_expr pp_pattern fmt e cases xcases
-  | Eabsurd ->
-      pp_print_string fmt "absurd"
-  | Epure t ->
-      fprintf fmt "@[@[<hv 2>pure {@ %a@] }@]" pp_term.marked t
-  | Eidpur qid ->
-      fprintf fmt "@[<h>{ %a }@]" pp_qualid qid
-  | Eraise (Qident {id_str="'Return"|"'Break"|"'Continue" as str; id_loc}, opt_arg) ->
-      let keyword = match str with
-        | "'Return" -> "return"
-        | "'Break" -> "break"
-        | "'Continue" -> "continue"
-        | _ -> assert false in
-      fprintf fmt "@[hv 2%a%s%a@]" pp_maybe_marker id_loc keyword
-        (pp_opt ~prefix:" " pp_expr.closed) opt_arg
-  | Eraise (qid, opt_arg) ->
-      fprintf fmt "raise %a%a" pp_qualid qid (pp_opt ~prefix:" " pp_expr.closed) opt_arg
-  | Eexn (id, pty, mask, e) ->
-      fprintf fmt "@[%a in@ %a@]" pp_exn (id, pty, mask) pp_expr.marked e
-  | Eoptexn ({id_str="'Return"|"'Break"|"'Continue"; id_loc}, _mask, e)
-    when marker id_loc = None ->
-      (* Syntactic sugar *)
-      pp_expr.marked fmt e
-  | Eoptexn (id, mask, e) ->
-      if mask <> Ity.MaskVisible then
-        todo fmt "local excption with mask not visible"
-      else
-        fprintf fmt "@[<v>exception %a in@ %a@]" pp_id id pp_expr.marked e
-  | Efor (id, start, dir, end_, invs, body) ->
-      let dir = match dir with Expr.To -> "to" | Expr.DownTo -> "downto" in
-      fprintf fmt "@[@[<v 2>for %a = %a %s %a do@ %a%a@]@ done@]"
-        pp_id id pp_expr.marked start dir pp_expr.marked end_
-        pp_invariants invs pp_expr.marked body
-  | Eassert (Expr.Assert, {
-      term_desc=Tattr (ATstr {Ident.attr_string="hyp_name:Assert"}, t)}) ->
-      fprintf fmt "@[<hv 2>assert {@ %a }@]" pp_term.marked t
-  | Eassert (Expr.Assume, {
-      term_desc=Tattr (ATstr {Ident.attr_string="hyp_name:Assume"}, t)}) ->
-      fprintf fmt "@[<hv 2>assume {@ %a }@]" pp_term.marked t
-  | Eassert (Expr.Check, {
-      term_desc=Tattr (ATstr {Ident.attr_string="hyp_name:Check"}, t)}) ->
-      fprintf fmt "@[<hv 2>check {@ %a }@]" pp_term.marked t
-  | Eassert (kind, t) ->
-      let kind = match kind with
-        | Expr.Assert -> "assert"
-        | Expr.Assume -> "assume"
-        | Expr.Check -> "check" in
-      fprintf fmt "@[<hv 2>%s {@ %a }@]" kind pp_term.marked t
-  | Escope (qid, e) ->
-      pp_scope pp_expr fmt qid e
-  | Elabel (id, e) ->
-      fprintf fmt "@[<hv 2>label %a in@ %a@]" pp_id id pp_expr.marked e
-  | Ecast (e, pty) ->
-      pp_cast pp_expr fmt e pty
-  | Eghost e ->
-      fprintf fmt "ghost %a" pp_expr.closed e
-  | Eattr (attr, e) ->
-      let expr_closed = function
-        | {expr_desc=Eattr _} -> true
-        | e -> expr_closed e in
-      pp_attr (pp_closed expr_closed pp_expr.marked) fmt attr e in
+    | Elet (id, ghost, kind, e1, e2) ->
+        fprintf fmt "@[<hv>@[<v 2>%a@] in@ %a@]" (pp_let pp_expr) (id, ghost, kind, e1)
+          pp_expr.marked e2
+    | Erec (defs, e) ->
+        let pp_fundefs = pp_print_list ~pp_sep:(pp_sep "@]@ @[<hv 2>with ") pp_fundef in
+        fprintf fmt "@[<v>@[<v 2>let rec %a in@]@ %a@]" pp_fundefs defs pp_expr.marked e
+    | Efun ([], None, {pat_desc=Pwild}, Ity.MaskVisible, spec, {expr_desc=Etuple []}) ->
+        fprintf fmt "@[<v>@[<v 2>begin%a@]@ end@]" pp_spec spec
+    | Efun ([], None, {pat_desc=Pwild}, Ity.MaskVisible, spec, e) ->
+        fprintf fmt "@[<v>@[<v 2>begin%a@ %a@]@ end@]" pp_spec spec pp_expr.marked e
+    | Efun (binders, opt_pty, pat, mask, spec, e) ->
+        pp_fun pp_expr fmt (binders, opt_pty, pat, mask, spec, e)
+    | Eany ([], _kind, Some pty, _pat, _mask, spec) ->
+        fprintf fmt "@[<hv 2>any %a%a@]" pp_pty.marked pty pp_spec spec
+    | Eany _ ->
+        todo fmt "Eany _"
+    | Etuple es ->
+        pp_tuple pp_expr fmt es
+    | Erecord fs ->
+        pp_record pp_expr fmt fs
+    | Eupdate (e, fs) ->
+        pp_update pp_expr fmt e fs
+    | Eassign [e1, None, e2] ->
+        fprintf fmt "@[<hv 2>%a <-@ %a@]" pp_expr.closed e1 pp_expr.closed e2
+    | Eassign [e1, Some qid, e2] ->
+        fprintf fmt "@[<hv 2>%a.%a <-@ %a@]" pp_expr.closed e1 pp_qualid qid pp_expr.closed e2
+    | Eassign _ ->
+        todo fmt "Eassign _"
+    | Esequence _ ->
+        let rec flatten e = match e.expr_desc with
+          | Esequence (e1, e2) -> e1 :: flatten e2
+          | _ -> [e] in
+        pp_print_list ~pp_sep:(pp_sep ";@ ") pp_expr.closed fmt
+          (flatten e)
+    | Eif (e1, e2, e3) ->
+        pp_if pp_expr fmt e1 e2 e3
+    | Ewhile (e1, invs, vars, e2) ->
+        fprintf fmt "@[<v>@[<v 2>while %a do%a%a@ %a@]@ done@]"
+          pp_expr.marked e1 pp_variants vars pp_invariants invs pp_expr.marked e2
+    | Eand (e1, e2) ->
+        fprintf fmt "@[@[<hv 2>%a@]@ @[<hv 2> &&@ %a@]@]" pp_expr.closed e1 pp_expr.closed e2
+    | Eor (e1, e2) ->
+        fprintf fmt "@[@[<hv 2>%a@]@ @[<hv 2> ||@ %a@]@]" pp_expr.closed e1 pp_expr.closed e2
+    | Enot e ->
+        pp_not pp_expr fmt e
+    | Ematch (e, [], xcases) ->
+        let pp_xcase fmt (qid, opt_pat, e) =
+          fprintf fmt "%a%a ->@ %a" pp_qualid qid
+            (pp_opt ~prefix:" " pp_pattern.marked) opt_pat pp_expr.marked e in
+        let pp_xcases = pp_print_list ~pp_sep:(pp_sep "@ | ") pp_xcase in
+        fprintf fmt "@[<hv>@[<hv 2>try@ %a@]@ @[<hv 2>with@ %a@]@ end@]"
+          pp_expr.marked e pp_xcases xcases
+    | Ematch (e, cases, xcases) ->
+        pp_match pp_expr pp_pattern fmt e cases xcases
+    | Eabsurd ->
+        pp_print_string fmt "absurd"
+    | Epure t ->
+        fprintf fmt "@[@[<hv 2>pure {@ %a@] }@]" pp_term.marked t
+    | Eidpur qid ->
+        fprintf fmt "@[<h>{ %a }@]" pp_qualid qid
+    | Eraise (Qident {id_str="'Return"|"'Break"|"'Continue" as str; id_loc}, opt_arg) ->
+        let keyword = match str with
+          | "'Return" -> "return"
+          | "'Break" -> "break"
+          | "'Continue" -> "continue"
+          | _ -> assert false in
+        fprintf fmt "@[hv 2%a%s%a@]" pp_maybe_marker id_loc keyword
+          (pp_opt ~prefix:" " pp_expr.closed) opt_arg
+    | Eraise (qid, opt_arg) ->
+        fprintf fmt "raise %a%a" pp_qualid qid (pp_opt ~prefix:" " pp_expr.closed) opt_arg
+    | Eexn (id, pty, mask, e) ->
+        fprintf fmt "@[%a in@ %a@]" pp_exn (id, pty, mask) pp_expr.marked e
+    | Eoptexn ({id_str="'Return"|"'Break"|"'Continue"; id_loc}, _mask, e)
+      when marker id_loc = None ->
+        (* Syntactic sugar *)
+        pp_expr.marked fmt e
+    | Eoptexn (id, mask, e) ->
+        if mask <> Ity.MaskVisible then
+          todo fmt "local excption with mask not visible"
+        else
+          fprintf fmt "@[<v>exception %a in@ %a@]" pp_id id pp_expr.marked e
+    | Efor (id, start, dir, end_, invs, body) ->
+        let dir = match dir with Expr.To -> "to" | Expr.DownTo -> "downto" in
+        fprintf fmt "@[<v>@[<v 2>for %a = %a %s %a do%a@ %a@]@ done@]"
+          pp_id id pp_expr.marked start dir pp_expr.marked end_
+          pp_invariants invs pp_expr.marked body
+    | Eassert (Expr.Assert, {
+        term_desc=Tattr (ATstr {Ident.attr_string="hyp_name:Assert"}, t)}) ->
+        fprintf fmt "@[<hv 2>assert {@ %a }@]" pp_term.marked t
+    | Eassert (Expr.Assume, {
+        term_desc=Tattr (ATstr {Ident.attr_string="hyp_name:Assume"}, t)}) ->
+        fprintf fmt "@[<hv 2>assume {@ %a }@]" pp_term.marked t
+    | Eassert (Expr.Check, {
+        term_desc=Tattr (ATstr {Ident.attr_string="hyp_name:Check"}, t)}) ->
+        fprintf fmt "@[<hv 2>check {@ %a }@]" pp_term.marked t
+    | Eassert (kind, t) ->
+        let kind = match kind with
+          | Expr.Assert -> "assert"
+          | Expr.Assume -> "assume"
+          | Expr.Check -> "check" in
+        fprintf fmt "@[<hv 2>%s {@ %a }@]" kind pp_term.marked t
+    | Escope (qid, e) ->
+        pp_scope pp_expr fmt qid e
+    | Elabel (id, e) ->
+        fprintf fmt "@[<hv 2>label %a in@ %a@]" pp_id id pp_expr.marked e
+    | Ecast (e, pty) ->
+        pp_cast pp_expr fmt e pty
+    | Eghost e ->
+        fprintf fmt "ghost %a" pp_expr.closed e
+    | Eattr (attr, e) ->
+        let expr_closed = function
+          | {expr_desc=Eattr _} -> true
+          | e -> expr_closed e in
+        pp_attr (pp_closed expr_closed pp_expr.marked) fmt attr e in
   let marked fmt e = pp_maybe_marked (fun e -> e.expr_loc) raw fmt e in
   let closed fmt = pp_closed expr_closed marked fmt in
   { marked; closed }
@@ -643,6 +646,19 @@ and pp_term =
   let closed fmt = pp_closed term_closed marked fmt in
   { closed; marked }
 
+and pp_variants fmt =
+  let pp_variant fmt (t, qid_opt) =
+    fprintf fmt "@[<hv 2>variant {@ %a%a@] }"
+      pp_term.marked t
+      (pp_opt ~prefix:" with " pp_qualid) qid_opt in
+  pp_print_opt_list ~prefix:"@ " ~sep:"@ " pp_variant fmt
+
+and pp_invariants fmt =
+  let pp_invariant fmt t =
+    fprintf fmt "@[<hv 2>invariant {@ %a@] }" pp_term.marked
+      (remove_attr "hyp_name:LoopInvariant" t) in
+  pp_print_opt_list ~prefix:"@ " ~sep:"@ " pp_invariant fmt
+
 and pp_spec fmt s =
   let pp_post fmt = function
     | loc, [{pat_desc=Pvar {id_str="result"; id_loc}}, t] when marker id_loc = None ->
@@ -663,13 +679,13 @@ and pp_spec fmt s =
       (pp_print_list ~pp_sep:(pp_sep "@ | ") pp_exn_case) exn_cases in
   let pp_alias fmt (t1, t2) =
     fprintf fmt "%a with %a" pp_term.marked t1 pp_term.marked t2 in
-  pp_print_opt_list ~prefix:"@ reads {" ~suffix:"}" ~sep:", " pp_qualid fmt s.sp_reads;
-  pp_print_opt_list ~prefix:"@ requires {" ~suffix:"}" pp_term.marked fmt
+  pp_print_opt_list ~prefix:"@ @[<hv 2>reads { " ~suffix:"@] }" ~sep:",@ " pp_qualid fmt s.sp_reads;
+  pp_print_opt_list ~prefix:"@ @[<hv 2>requires { " ~suffix:"@] }" pp_term.marked fmt
     (List.map (remove_attr "hyp_name:Requires") s.sp_pre);
-  pp_print_opt_list ~prefix:"@ writes {" ~suffix:"}" pp_term.marked fmt s.sp_writes;
+  pp_print_opt_list ~prefix:"@ @[<hv 2>writes { " ~suffix:"@] }" pp_term.marked fmt s.sp_writes;
   pp_print_list pp_post fmt s.sp_post;
-  pp_print_opt_list ~prefix:"@ " ~sep:"@ " pp_xpost fmt s.sp_xpost;
-  pp_print_opt_list ~prefix:"@ alias { " ~sep:",@ " ~suffix:"}" pp_alias fmt s.sp_alias;
+  pp_print_opt_list ~prefix:"@ " ~sep:"@," pp_xpost fmt s.sp_xpost;
+  pp_print_opt_list ~prefix:"@ @[<hv 2>alias { " ~sep:",@," ~suffix:"@] }" pp_alias fmt s.sp_alias;
   pp_variants fmt s.sp_variant;
   pp_bool ~true_:"@ diverges" fmt s.sp_diverge;
   pp_bool ~true_:"@ partial" fmt s.sp_partial;
@@ -690,7 +706,7 @@ and pp_pattern =
     | Ptuple ps ->
         pp_tuple pp_pattern fmt ps
     | Pas (p, id, ghost) ->
-        fprintf fmt "@[<hv 2>%a@] as@ %a%a" pp_pattern.marked p pp_id id pp_ghost ghost
+        fprintf fmt "@[<hv 2>%a@] as@ %a%a" pp_pattern.marked p pp_ghost ghost pp_id id
     | Por (p1, p2) ->
         fprintf fmt "%a | %a" pp_pattern.marked p1 pp_pattern.marked p2
     | Pcast (p, pty) ->
@@ -714,35 +730,32 @@ and pp_type_decl fmt d =
     | TDrecord fs ->
         let vis = match d.td_vis with
           | Public -> ""
-          | Private -> " private"
-          | Abstract -> " abstract" in
+          | Private -> "private "
+          | Abstract -> "abstract " in
         let pp_field fmt f =
-          fprintf fmt "%a%a%a%a : %a" pp_maybe_marker f.f_loc
+          fprintf fmt "@[<hv 2>%a%a%a%a :@ %a@]" pp_maybe_marker f.f_loc
             pp_mutable f.f_mutable pp_ghost f.f_ghost
             pp_id f.f_ident pp_pty.marked f.f_pty in
-        let pp_fields = pp_print_list ~pp_sep:(pp_sep " ;@,") pp_field in
-        fprintf fmt " =%s %a{@,@[<v 2>  %a@]@,}%a" vis
+        let pp_fields = pp_print_list ~pp_sep:(pp_sep ";@ ") pp_field in
+        fprintf fmt "@[<hv 2> = %s%a{@ %a@ }@]%a" vis
           pp_mutable d.td_mut pp_fields fs pp_invariants d.td_inv
     | TDalgebraic variants ->
         let pp_variant fmt (loc, id, params) =
           fprintf fmt "%a%a%a" pp_maybe_marker loc pp_id id
-            (pp_print_opt_list ~prefix:" " pp_param) params in
+            pp_params params in
         fprintf fmt " = @,@[<v 2>  | %a@]"
           (pp_print_list ~pp_sep:(pp_sep "@,| ") pp_variant) variants
     | TDrange (i1, i2) ->
         fprintf fmt " = <range %s %s>" (BigInt.to_string i1) (BigInt.to_string i2)
     | TDfloat (i1, i2) ->
         fprintf fmt " = <float %d %d>" i1 i2 in
-  let pp_wit fmt = function
-    | [] -> ()
-    | wits ->
-        fprintf fmt "@,by { %a }" (pp_fields pp_expr) wits in
   fprintf fmt "%a%a%a%a%a"
     pp_maybe_marker d.td_loc
     pp_id d.td_ident
-    (pp_print_opt_list ~prefix:" " pp_id) d.td_params
+    (pp_print_opt_list ~prefix:" '" pp_id) d.td_params
     pp_def d.td_def
-    pp_wit d.td_wit
+    (pp_print_opt_list ~prefix:"@ @[<hv 2>by {@ " ~sep:";@ " ~suffix:"@] }"
+       (pp_field pp_expr)) d.td_wit
 
 and pp_ind_decl fmt d =
   let pp_ind_decl_case fmt (loc, id, t) =
@@ -762,29 +775,29 @@ and pp_logic_decl fmt d =
 
 and pp_decl fmt = function
   | Dtype decls ->
-      let pp_type_decls = pp_print_list ~pp_sep:(pp_sep "@,with ") pp_type_decl in
-      fprintf fmt "@[<v>type %a@]" pp_type_decls decls
+      let pp_type_decls = pp_print_list ~pp_sep:(pp_sep "@]@ @[<v 2>with ") pp_type_decl in
+      fprintf fmt "@[<v 2>type %a@]" pp_type_decls decls
   | Dlogic decls when List.for_all (fun d -> d.ld_type = None) decls ->
       let pp_logic_decls =
-        pp_print_list ~pp_sep:(pp_sep "@]@,@[<hv 2>with ") pp_logic_decl in
-      fprintf fmt "@[<v>@[<hv 2>predicate %a@]@]" pp_logic_decls decls
+        pp_print_list ~pp_sep:(pp_sep "@]@ @[<hv 2>with ") pp_logic_decl in
+      fprintf fmt "@[<hv 2>predicate %a@]" pp_logic_decls decls
   | Dlogic decls when List.for_all (fun d -> d.ld_type <> None) decls ->
-      let pp_logic_decls = pp_print_list ~pp_sep:(pp_sep "@,with ") pp_logic_decl in
-      fprintf fmt "@[<v>function %a@]" pp_logic_decls decls
+      let pp_logic_decls = pp_print_list ~pp_sep:(pp_sep "@]@ @[<hv 2>with ") pp_logic_decl in
+      fprintf fmt "@[<hv 2>function %a@]" pp_logic_decls decls
   | Dlogic _ ->
       todo fmt "Dlogic _"
   | Dind (sign, decls) ->
       let keyword = match sign with
         | Decl.Ind -> "inductive"
         | Decl.Coind -> "coinductive" in
-      let pp_ind_decls = pp_print_list ~pp_sep:(pp_sep " with ") pp_ind_decl in
-      fprintf fmt "%s %a" keyword pp_ind_decls decls
+      let pp_ind_decls = pp_print_list ~pp_sep:(pp_sep "@]@ @[<hv 2>with ") pp_ind_decl in
+      fprintf fmt "@[<hv 2>%s %a@]" keyword pp_ind_decls decls
   | Dprop (kind, id, t) ->
       let keyword = match kind with
         | Decl.Plemma -> "lemma"
         | Decl.Paxiom -> "axiom"
         | Decl.Pgoal -> "goal" in
-      fprintf fmt "%s %a: %a" keyword pp_id id pp_term.marked t
+      fprintf fmt "@[<hv 2>%s %a:@ %a@]" keyword pp_id id pp_term.marked t
   | Dlet (id, ghost, kind, {expr_desc=Efun (binders, pty_opt, pat, mask, spec, e)}) ->
       pp_let_fun pp_expr fmt (id, ghost, kind, (binders, pty_opt, pat, mask, spec, e))
   | Dlet (id, ghost, kind, {expr_desc=Eany (params, kind', pty_opt, pat, mask, spec)}) ->
@@ -792,8 +805,8 @@ and pp_decl fmt = function
   | Dlet (id, ghost, kind, e) ->
       pp_let pp_expr fmt (id, ghost, kind, e)
   | Drec defs ->
-      let pp_fundefs = pp_print_list ~pp_sep:(pp_sep " and ") pp_fundef in
-      fprintf fmt "let rec %a" pp_fundefs defs
+      let pp_fundefs = pp_print_list ~pp_sep:(pp_sep "@]@ @[<hv 2>with ") pp_fundef in
+      fprintf fmt "@[<v>@[<v 2>let rec %a@]@]" pp_fundefs defs
   | Dexn (id, pty, mask) ->
       fprintf fmt "%a" pp_exn (id, pty, mask)
   | Dmeta (ident, args) ->
@@ -830,7 +843,7 @@ and pp_decl fmt = function
       fprintf fmt "import %a" pp_qualid qid
   | Dscope (loc, export, id, decls) ->
       let pp_export fmt = if export then pp_print_string fmt " export" in
-      fprintf fmt "@[<v 2>@[<v 2>%ascope%t %a =@,%a@]@,end]@"
+      fprintf fmt "@[<v 2>@[<v 2>%ascope%t %a =@ %a@]@ end]@"
         pp_maybe_marker loc pp_export pp_id id pp_decls decls
 
 and pp_decls fmt decls =
@@ -854,6 +867,6 @@ let pp_mlw_file fmt = function
       pp_decls fmt decls
   | Modules modules ->
       let pp_module fmt (id, decls) =
-        fprintf fmt "@[<v 2>module %a@,%a@]@,end" pp_id id pp_decls decls in
-      let pp_modules = pp_print_list ~pp_sep:(pp_sep "@,@,") pp_module in
+        fprintf fmt "@[<v 2>module %a@ %a@]@ end" pp_id id pp_decls decls in
+      let pp_modules = pp_print_list ~pp_sep:(pp_sep "@\n@\n") pp_module in
       fprintf fmt "@[<v>%a@]" pp_modules modules