let subst_havoc (m:mem) = function
| F.Aloc(_,(Path p| PRef p | PRpar(p,_)))
when p.p_off=[] ->
let x = get_funvar m p.p_arity p.p_root false in
let v = L.fresh (F.basename_of_var x) (F.kind_of_var x) in
[F.Fresh v;F.Update(x,fun _ -> F.var v)]
| F.Aloc(_, (ARpar(p,_)| ARef p)) when p.p_off=[] ->
let x = get_funvar m p.p_arity p.p_root true in
let v = L.fresh (F.basename_of_var x) (F.kind_of_var x) in
[F.Fresh v;F.Update(x,fun _ -> F.var v)]
| F.Aloc(_,(Path p| PRef p | PRpar(p,_))) ->
let x = get_funvar m p.p_arity p.p_root false in
let v =
match p.p_type with
| None -> Wp_parameters.fatal "[subst_havoc] pure logic var"
| Some ty ->
L.fresh "v" (Model (tau_of_object ty))
in
let newterm (sigma : (F.var * F.var) list ) : F.abstract =
F.wrap ( update_offset
(fun _ -> F.var v)
(L.apply sigma (F.var x)) p.p_off )
in
[F.Fresh v;F.Update(x,newterm)]
| F.Aloc(_, (ARpar(p,_)| ARef p)) ->
let x = get_funvar m p.p_arity p.p_root true in
let v =
match p.p_type with
| None -> Wp_parameters.fatal "[subst_havoc] of pure logic var"
| Some ty -> L.fresh "v" (Model (tau_of_object ty))
in
let newterm (sigma : (F.var * F.var) list ) : F.abstract =
F.wrap ( update_offset
(fun _ -> F.var v)
(L.apply sigma (F.var x)) p.p_off )
in
[F.Fresh v;F.Update(x,newterm)]
| F.Arange(_,(Path p| PRef p | PRpar(p,_)),rg) ->
let x = get_funvar m p.p_arity p.p_root false in
let upd_range rg = fun array ->
F.wrap (F.set_range_index (F.unwrap array) rg)
in
let newterm (sigma :(F.var * F.var) list ) : F.abstract =
F.wrap (update_offset (upd_range rg) (L.apply sigma (F.var x))
p.p_off)
in
[F.Update(x,newterm)]
| F.Arange(_, (ARpar(p,_)| ARef p),rg) ->
let x = get_funvar m p.p_arity p.p_root true in
let upd_range rg = fun array ->
F.wrap (F.set_range_index (F.unwrap array) rg)
in
let newterm (sigma :(F.var * F.var) list ) : F.abstract =
F.wrap (update_offset (upd_range rg) (L.apply sigma (F.var x))
p.p_off)
in
[F.Update(x,newterm)]
| F.Aloc(te,Mloc l) ->
M.subst_havoc m.mem (F.Aloc(te,l))
| F.Arange(te,Mloc l,rg) ->
M.subst_havoc m.mem (F.Arange(te,l,rg))