let rec pp_data fmt l =
  match l with
    | D1null -> Format.fprintf fmt "<null>"
    | D1base l -> Format.fprintf fmt "base(%a)" pp_data l
    | D1addr (v,_) -> Format.fprintf fmt "@@%s" v.vname (* (Fol.Var.var_name v) *)
    | D1var (Some (vi,l), fv) -> Format.fprintf fmt "%a(%s@@%a)"
        pp_var fv vi.vname Clabels.pretty l
    | D1var (_, v) -> Format.fprintf fmt "%a" pp_var v
    | D1depl (x, ch) ->
        Format.fprintf fmt "%a+%a" pp_data x pp_epath ch
    | D1proj (x, ch) ->
        Format.fprintf fmt "%a%a" pp_data x pp_epath ch
    | D1shift (p, i) ->
        Format.fprintf fmt "(%a#(%a))" pp_data p pp_term i
    | D1indir (p) -> Format.fprintf fmt "*(%a)"  pp_data p
    | D1mu (l, ch, x) -> Format.fprintf fmt "mu(%a, %a -> %a)"
        pp_data l pp_epath ch pp_term_opt x
    | D1muRange (l, ch) -> Format.fprintf fmt "muX(%a, %a -> _)"
        pp_data l pp_term ch
    | D1muI (l, None, x) -> Format.fprintf fmt "mu(%a, * -> %a)"
        pp_data l pp_term_opt x
    | D1muI (l, Some i, x) -> Format.fprintf fmt "mu(%a, #(%a),* -> %a)"
        pp_data l pp_term i pp_term_opt x
    | D1muIrange (l, i) -> Format.fprintf fmt "muX(%a, #(%a),* -> _)"
        pp_data l pp_term i 

and pp_epath fmt = function
  | Pfield f -> Format.fprintf fmt ".%s" f.fname
  | Pidx i -> Format.fprintf fmt "(%a)" pp_term i

and pp_term fmt e = Fol_pretty.fpretty_term pp_term pp_data fmt e

and pp_term_opt fmt e = match e with None -> Format.fprintf fmt "_"
  | Some e -> pp_term fmt e