let rec do_data_rec do_data do_exp d =
  (* Format.printf "@[<v2>-> %a@," pp_data d; *)
  let do_path ch = do_path do_exp ch in
  let do_exp_opt e = match e with None -> None 
    | Some e -> Some (do_exp e)
  in
  let frec = do_data_rec do_data do_exp in
  let rec do_rec d = match d with (* poragate in sub-data and sub-exp *)
    | D1null | D1addr _ -> d
    | D1var _ -> d
    | D1base p -> D1base (frec p)
    | D1indir p -> data_of_term (indir_here (frec p))
    | D1proj (e, ch) -> (D1proj (frec e, do_path ch))
    | D1depl (e, ch) -> (D1depl (frec e, do_path ch))
    | D1shift (e, i) -> (D1shift (frec e, do_exp i))
    | D1mu (e, ch, x) -> (D1mu (frec e, do_path ch, (do_exp_opt x)))
    | D1muRange (e, x) -> (D1muRange (frec e, do_exp x))
    | D1muI (e, None, x) -> (D1muI (frec e, None, do_exp_opt x))
    | D1muI (e, Some i, x) -> (D1muI (frec e, Some (do_exp i), do_exp_opt x))
    | D1muIrange (e, x) -> (D1muIrange (frec e, do_exp x))
  in
  let d' = do_rec d in
  let d' = do_data d' in
  (* Format.printf "<- %a@]@," pp_data d; *)
    d'