let get_read_addr with_direct p =
let do_var acc v = match Fol.lvar_of_variable v with
| Some lv when lv.lv_origin <> None ->
if with_direct then
(Wp_parameters.debug ~level:3
"get_read_addr : in '%s' base" lv.lv_name;
(M.mk_lvar_addr lv)::acc)
else
(Wp_parameters.debug ~level:3
"get_read_addr : ignore direct access to @@%s" lv.lv_name;
acc)
| Some lv ->
Wp_parameters.debug ~level:3
"get_read_addr : ignore logic variable %s" lv.lv_name;
acc
| None ->
Wp_parameters.debug ~level:3
"get_read_addr : ignore named variable %s" (Fol.var_name v);
acc
in
let rec do_data acc d = match d with
| E1addr _v -> acc
| E1proj (s, WpFol.Pfield f) ->
let add acc ps =
let pf = E1depl (ps, WpFol.Pfield f) in
(Fol.Tdata pf)::acc
in List.fold_left add acc (do_exp true [] s)
| E1proj (t, WpFol.Pidx i) ->
(match do_exp false [] i with
| [] ->
let add acc ps =
let pi = E1depl (ps, WpFol.Pidx i) in
(Fol.Tdata pi)::acc
in List.fold_left add acc (do_exp true [] t)
| _ -> raise (UnknownGuard (Fol.Tdata d, "index with data"))
)
| E1depl (ps, WpFol.Pfield _) -> do_exp true acc ps
| E1depl (pt, WpFol.Pidx _) -> do_exp true acc pt
| E1indir p -> let acc = match do_exp true [] p with
| [] -> acc
| accp -> p::(accp @ acc)
in acc
| E1shift (p, _) -> do_exp true acc p
| E1mu (s, WpFol.Pfield _f, x) ->
let acc = do_exp false acc x in
do_exp true acc s
| E1mu (t, WpFol.Pidx i, x) ->
let acc = do_exp false acc x in
let acc = do_exp false acc i in
do_exp true acc t
| E1muI (_p, _x) -> raise (UnknownGuard (Fol.Tdata d, "indirect mu"))
and do_exp in_data (acc : M.t_exp list) e : M.t_exp list = match e with
| Fol.Tdata d -> do_data acc d
| Fol.Tvar v -> do_var acc v
| _ when in_data -> raise (UnknownGuard (e, "exp in data"))
| _ -> Fol.fold_data_in_exp do_var do_data acc e
in
Fol.fold_exp_in_pred (do_exp false) [] p