let mk_mu m lval =
let do_indir f_obj1 sh f_mu_of_mu2 =
let f_obj2 = fun obj0 -> match sh with
| None -> F.data_of_term (indir m (f_obj1 obj0))
| Some i -> F.data_of_term (indir m (F.shift_pointer (f_obj1 obj0) i))
in
let f_mu_of_mu3 = fun obj0 mu3 ->
let mu2 = F.term_of_data (F.mk_mu_sh_indir (f_obj1 obj0) sh mu3) in
f_mu_of_mu2 obj0 (Some mu2)
in f_obj2, f_mu_of_mu3
in
let rec addr_loc l = match l with
| F.D1var (Some (vi, Clabels.Here),_) -> cvar m vi
| F.D1proj (l, ch) -> F.shift_epath (addr_loc l) ch
| F.D1indir l -> l
| _ -> unsupported "take address of unknown location: %a" pp_loc l
in
let rec mk_mu_rec lval = match lval with
| F.D1null -> unsupported "assignment to NULL pointer !"
| F.D1addr (v,_) -> v, (fun obj -> obj), (fun _obj mu -> mu)
| F.D1depl (lv, d2) ->
let v, f_obj1, f_mu_of_mu2 = mk_mu_rec lv in
let f_obj2 = fun obj0 -> F.data_of_term (F.proj (f_obj1 obj0) d2) in
let f_mu_of_mu3 = fun obj0 mu3 ->
let mu2 = F.term_of_data (F.mk_mu (f_obj1 obj0) d2 mu3) in
f_mu_of_mu2 obj0 (Some mu2)
in
v, f_obj2, f_mu_of_mu3
| F.D1indir (lv) ->
let v, f_obj1, f_mu_of_mu2 = mk_mu_rec lv in
let f_obj2, f_mu_of_mu3 = do_indir f_obj1 None f_mu_of_mu2 in
v, f_obj2, f_mu_of_mu3
| F.D1var (Some (v, Clabels.Here),_) ->
let f_obj1 obj0 = obj0 in
let f_mu_of_mu2 _o mu = mu in
let f_obj2, f_mu_of_mu3 = do_indir f_obj1 None f_mu_of_mu2 in
v, f_obj2, f_mu_of_mu3
| F.D1proj (lv, ch) ->
let lv_depl = F.shift_epath (addr_loc lv) ch in
let v, f_obj1, f_mu_of_mu2 = mk_mu_rec lv_depl in
let f_obj2, f_mu_of_mu3 = do_indir f_obj1 None f_mu_of_mu2 in
v, f_obj2, f_mu_of_mu3
| F.D1shift (lv, i) ->
let p = addr_loc lv in
let v, f_obj1, f_mu_of_mu2 = mk_mu_rec p in
let f_obj2, f_mu_of_mu3 = do_indir f_obj1 (Some i) f_mu_of_mu2 in
v, f_obj2, f_mu_of_mu3
| _ -> unsupported "assignment to unknown location: %a" pp_loc lval
in mk_mu_rec lval