let rec reduce_by_predicate state positive p =
let result =
match positive,p.content with
| true,Ptrue | false,Pfalse -> state
| true,Pfalse | false,Ptrue -> Relations_type.Model.bottom
| true,Pand (p1,p2 ) | false,Por(p1,p2)->
reduce_by_predicate (reduce_by_predicate state positive p1) positive p2
| true,Por (p1,p2 ) | false,Pand (p1, p2) ->
Relations_type.Model.join
(reduce_by_predicate state positive p1)
(reduce_by_predicate state positive p2)
| _,Pnot p -> reduce_by_predicate state (not positive) p
| true,Piff (p1, p2) ->
let red1 =
reduce_by_predicate state true (Logic_const.pand (p1, p2))
in
let red2 =
reduce_by_predicate state false
(Logic_const.por (p1, p2))
in
Relations_type.Model.join red1 red2
| false,Piff (p1, p2) ->
reduce_by_predicate state true
(Logic_const.por
(Logic_const.pand (p1, Logic_const.pnot p2),
Logic_const.pand (Logic_const.pnot p1, p2)))
| _,Pxor(p1,p2) ->
reduce_by_predicate state (not positive) (Logic_const.piff(p1, p2))
| _,Prel (op,t1,t2) ->
begin try
let c1 = !Db.Properties.Interp.term_to_exp t1 in
let c2 = !Db.Properties.Interp.term_to_exp t2 in
let t = dummy_exp (BinOp(lop_to_cop op, c1, c2, intType)) in
let state =
eval_cond ~with_alarms:warn_raise_mode
state { positive = positive ; exp = t }
in
state
with
Invalid_argument "not an lvalue" -> state
| Reduce_to_bottom ->
Relations_type.Model.bottom
| Predicate_alarm -> state
end
| _,Pvalid tsets ->
begin try
let exps = !Db.Properties.Interp.loc_to_exp tsets in
List.fold_left
(fun state exp ->
reduce_by_valid_expr ~with_alarms:warn_raise_mode ~positive
exp state) state exps
with Invalid_argument "not an lvalue" -> state
| Predicate_alarm -> state
end
| true,Pimplies (_,_) -> state
| false,Pimplies (_,_) -> state
| _,Papp _ | _,Pold _ | _,Pat _ -> state
| _,Pexists (_varl, _p1) | _,Pforall (_varl, _p1) -> state
| _,Pfresh _
| _,Pvalid_range (_, _, _)| _,Pvalid_index (_, _)
| _,Plet (_, _, _) | _,Pif (_, _, _)
| _,Psubtype _
-> state
| _, Pseparated _ -> state
in
result