anchor.diff:    in
     snd (List.fold_left fold_fun init xs)
   
  +(* [separate_map_with_comments_kw prefix sep f xs extract_range] is the same  *)
  +(* as separate_map_with_comments but the keyword is also passed as an         *)
  +(* argument to f, resulting in                                                *)
  +(*                                                                            *)
  +(*   (f prefix xs[0]) *)
  +(*   comments[0] *)
  +(*   f spe xs[1]) *)
  +(*   comments[1] *)
  +(*   ... *)
  +(*   (f sep xs[n]) *)
  +let separate_map_with_comments_kw prefix sep f xs extract_range =
  +  let fold_fun (last_line, doc) x =
  +    let r = extract_range x in
  +    let doc = place_comments_until_pos 1 last_line (start_of_range r) doc in
  +    line_of_pos (end_of_range r), doc ^^ f sep x
  +  in
  +  let x, xs = List.hd xs, List.tl xs in
  +  let init =
  +    line_of_pos (end_of_range (extract_range x)), f prefix x
  +  in
  +  snd (List.fold_left fold_fun init xs)
  +
   
   (* ****************************************************************************)
   (*                                                                            *)
  
positive.code:   | Val (lid, t) ->
        (str "val" ^^ space ^^ p_lident lid ^^ space ^^ colon) ^/+^ p_typ false false t
    | TopLevelLet (_, lbs) ->
        separate_map hardline (fun lb -> group (str "let" ^/^ p_letlhs lb)) lbs
    | _ ->
        empty
  
  
negative.code:   (* TODO : Should we allow tagging individual constructor with a comment ? *)
    optional p_fsdoc doc_opt ^^ default_or_map uid_doc (fun t -> (group (uid_doc ^^ space ^^ sep)) ^/+^ p_typ false false t) t_opt
  
  and p_letlhs kw (pat, _) =
    (* TODO : this should be refined when head is an applicative pattern (function definition) *)
    let pat, ascr_doc =
      match pat.pat with
      | PatAscribed (pat, (t, None)) -> pat, group (colon ^^ space ^^ p_tmArrow p_tmNoEq t)
      | PatAscribed (pat, (t, Some tac)) -> pat, group (colon ^^ space ^^ p_tmArrow p_tmNoEq t) ^^ group (str "by" ^^ space ^^ p_atomicTerm tac)
      | _ -> pat, empty
    in
    match pat.pat with
    | PatApp ({pat=PatVar (x, _)}, pats) ->
        (* has binders *)
        prefix2_nonempty (prefix2 (group (kw ^/^ p_lident x)) (flow_map break1 p_atomicPattern pats)) ascr_doc
    | _ ->
        (* doesn't have binders *)
        group (group (kw ^/^ p_tuplePattern pat) ^^ ascr_doc)
  
  and p_letbinding kw (pat, e) =
    let doc_pat = p_letlhs kw (pat, e) in
    let doc_expr = p_term false false e in
    ifflat (doc_pat ^/^ equals ^/^ doc_expr) (doc_pat ^^ space ^^ group (equals ^^ jump2 doc_expr))
  
  (* ****************************************************************************)
  (*                                                                            *)
  