let positiveCallOrRet clause =
let positive = ref None in
let isFalse = ref false in
let computePositive=
List.fold_left
(fun treated term ->
match term with
| PCall (s) as t ->
begin match !positive with
| None ->
positive:= Some(t) ;
t::treated
| Some(PCall (a)) ->
(* Two positives on two different functions *)
if (String.compare a s)<>0 then isFalse:=true;
(* Already present. Removed from list *)
treated
| Some(PReturn (_)) ->
(* Two positives on two different function or Call and Ret on the same function. Always False *)
isFalse:=true;
[]
| Some(PCallOrReturn (a)) ->
(* Two positives on two different functions *)
if (String.compare a s)<>0 then isFalse:=true;
(* More specific information *)
positive:= Some(t) ;
t::(removeTerm (PCallOrReturn (a)) treated)
| _ -> assert false (* This Variable has to contain only positive call, ret or call/ret conditions *)
end
| PReturn (s) as t ->
begin match !positive with
| None ->
positive:= Some(t) ;
t::treated
| Some(PReturn (a)) ->
(* Two positives on two different functions *)
if (String.compare a s)<>0 then isFalse:=true;
(* Already present. Removed from list *)
treated
| Some(PCall (_)) ->
(* Two positives on two different function or Call and Ret on the same function. Always False *)
isFalse:=true;
[]
| Some(PCallOrReturn (a)) ->
(* Two positives on two different functions *)
if (String.compare a s)<>0 then isFalse:=true;
(* More specific information *)
positive:= Some(t) ;
t::(removeTerm (PCallOrReturn (a)) treated)
| _ -> assert false (* This Variable has to contain only positive call, ret or call/ret conditions *)
end
| PCallOrReturn(s) as t ->
begin match !positive with
| None ->
positive:= Some(t) ;
t::treated
| Some(PReturn (a)) ->
(* Two positives on two different functions *)
if (String.compare a s)<>0 then isFalse:=true;
(* More specific information already present *)
treated
| Some(PCall (a)) ->
(* Two positives on two different functions *)
if (String.compare a s)<>0 then isFalse:=true;
(* More specific information already present *)
treated
| Some(PCallOrReturn (a)) ->
(* Two positives on two different functions *)
if (String.compare a s)<>0 then isFalse:=true;
(* Already present. Removed from list *)
treated
| _ -> assert false (* This Variable has to contain only positive call, ret or call/ret conditions *)
end
| _ as t -> t::treated
)
[]
clause
in
(* Step 2 : Remove negatives not enough expressive *)
if !isFalse then
[]
else
let res =
match !positive with
| None -> computePositive
| Some(PCall(name)) ->
List.fold_left
(fun treated term ->
match term with
| PNot(PCall (s)) ->
(* Two opposite information *)
if (String.compare name s)=0 then isFalse:=true;
(* Positive information more specific than negative one *)
treated
| PNot(PReturn (_)) ->
(* Positive information more specific than negative one *)
treated
| PNot(PCallOrReturn (s)) ->
(* Two opposite information *)
if (String.compare name s)=0 then isFalse:=true;
(* Positive information more specific than negative one *)
treated
| _ as t -> t::treated
)
[]
computePositive
| Some(PReturn (name))->
List.fold_left
(fun treated term ->
match term with
| PNot(PCall (_)) ->
(* Positive information more specific than negative one *)
treated
| PNot(PReturn (s)) ->
(* Two opposite information *)
if (String.compare name s)=0 then isFalse:=true;
(* Positive information more specific than negative one *)
treated
| PNot(PCallOrReturn (s)) ->
(* Two opposite information *)
if (String.compare name s)=0 then isFalse:=true;
(* Positive information more specific than negative one *)
treated
| _ as t -> t::treated
)
[]
computePositive
| Some(PCallOrReturn (name)) ->
List.fold_left
(fun treated term ->
match term with
| PNot(PCall (s)) ->
if (String.compare name s)=0 then
(PReturn(s))::(removeTerm (PCallOrReturn (name)) treated)
else
(* Positive information more specific than negative one *)
treated
| PNot(PReturn (s)) ->
if (String.compare name s)=0 then
(PCall(s))::(removeTerm (PCallOrReturn (name)) treated)
else
(* Positive information more specific than negative one *)
treated
| PNot(PCallOrReturn (s)) ->
(* Two opposite information *)
if (String.compare name s)=0 then isFalse:=true;
(* Positive information more specific than negative one *)
treated
| _ as t -> t::treated
)
[]
computePositive
| _ -> assert false (* This Variable has to contain only positive call, ret or call/ret conditions *)
in
if !isFalse then
[]
else
res