let rec pred sigma = function
| Papp(f,ts) -> p_app f (List.map (term sigma) ts)
| Ptrue -> Ptrue
| Pfalse -> Pfalse
| Pif(e,p,q) -> p_if (term sigma e) (pred sigma p) (pred sigma q)
| Pand(p,q) -> p_and (pred sigma p) (pred sigma q)
| Por(p,q) -> p_or (pred sigma p) (pred sigma q)
| Piff(p,q) -> p_iff (pred sigma p) (pred sigma q)
| Pnot p -> p_not (pred sigma p)
| Pnamed(a,p) -> p_named a (pred sigma p)
| Pforall(x,p) -> let x,sigma = fresh sigma x in p_forall x (pred sigma p)
| Pexists(x,p) -> let x,sigma = fresh sigma x in p_exists x (pred sigma p)
| Plet(x,v,p) ->
let v = term sigma v in
if is_simple v && Wp_parameters.Simpl.get()
then
pred (bind x v sigma) p
else
let x,sigma = fresh sigma x in
p_let x v (pred sigma p)
| Pimplies(p,q) ->
match def p with
| Papp(("eq"|"eq_int"|"eq_real"),([Tvar x;e] | [e;Tvar x])) when Wp_parameters.Simpl.get() ->
let ve = term sigma e in
if is_simple ve then
let vx = alpha sigma x in
let q = pred (bind x ve sigma) q in
let p = redef p (Papp("eq",[vx;ve])) in
p_implies p q
else
let vx = alpha sigma x in
let q = pred sigma q in
let p = redef p (Papp("eq",[vx;ve])) in
p_implies p q
| _ ->
let p = pred sigma p in
let q = pred sigma q in
match def p with
| Papp("eq",([Tvar x;v] | [v;Tvar x]))
when is_simple v && Wp_parameters.Simpl.get() ->
let q = Fol.pred_replace (fun _ -> None) x v q in
p_implies p q
| _ -> p_implies p q