let positiveCallOrRet clause =
let positive = ref None in
let isFalse = ref false in
let computePositive=
List.fold_left
(fun treated term ->
match term with
| PFuncParam (_,s,_) as t ->
begin match !positive with
| None ->
positive:= Some(t) ;
t::treated
| Some(PFuncParam (_,a,_)) ->
if (String.compare a s)<>0 then isFalse:=true;
treated
| Some(PReturn (_))
| Some(PFuncReturn (_,_)) ->
isFalse:=true;
[]
| Some(PCallOrReturn (a)) ->
if (String.compare a s)<>0 then isFalse:=true;
(* More specific information found in t *)
positive:= Some(t) ;
t::(removeTerm (PCallOrReturn (a)) treated)
| Some(PCall (a)) ->
if (String.compare a s)<>0 then isFalse:=true;
(* More specific information found in t *)
positive:= Some(t) ;
t::(removeTerm (PCall (a)) treated)
| _ -> assert false (* This Variable has to contain only positive call,
ret or call/ret conditions *)
end
| PCall(s) as t->
begin match !positive with
| None ->
positive:= Some(t) ;
t::treated
| Some(PCall (a))
| Some(PFuncParam (_,a,_)) ->
if (String.compare a s)<>0 then isFalse:=true;
treated
| Some(PReturn (_))
| Some(PFuncReturn (_,_)) ->
isFalse:=true;
[]
| Some(PCallOrReturn (a)) ->
if (String.compare a s)<>0 then isFalse:=true;
positive:= Some(t) ;
t::(removeTerm (PCallOrReturn (a)) treated)
| _ -> assert false (* This Variable has to contain only positive call,
ret or call/ret conditions *)
end
| PFuncReturn (_,s) as t ->
begin match !positive with
| None ->
positive:= Some(t) ;
t::treated
| Some(PFuncReturn (_,a)) ->
if (String.compare a s)<>0 then isFalse:=true;
treated
| Some(PCall (_))
| Some(PFuncParam (_,_,_)) ->
isFalse:=true;
[]
| Some(PReturn (a)) ->
(* Two positives on two different functions *)
if (String.compare a s)<>0 then isFalse:=true;
(* More specific information *)
positive:= Some(t) ;
t::(removeTerm (PReturn (a)) treated)
| 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))
| Some(PFuncReturn (_,a)) ->
if (String.compare a s)<>0 then isFalse:=true;
treated
| Some(PCall (_))
| Some(PFuncParam (_,_,_)) ->
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))
| Some(PFuncReturn (_,a))
| Some(PCall (a))
| Some(PFuncParam (_,a,_))
| Some(PCallOrReturn (a)) ->
(* Two positives on two different functions *)
if (String.compare a s)<>0 then isFalse:=true;
(* More specific information already present *)
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))
| Some(PFuncParam(_,name,_)) ->
List.fold_left
(fun treated term ->
match term with
| PNot(PCall (s))
| PNot(PFuncParam (_,s,_))
| PNot(PCallOrReturn (s)) ->
(* Two opposite information *)
if (String.compare name s)=0 then isFalse:=true;
(* Positive information more specific than negative one *)
treated
| PNot(PReturn (_))
| PNot(PFuncReturn (_,_)) ->
(* Positive information more specific than negative one *)
treated
| _ as t -> t::treated
)
[]
computePositive
| Some(PReturn (name))
| Some(PFuncReturn (_,name)) ->
List.fold_left
(fun treated term ->
match term with
| PNot(PCall (_))
| PNot(PFuncParam (_,_,_)) ->
(* Positive information more specific than negative one *)
treated
| PNot(PReturn (s))
| PNot(PCallOrReturn (s))
| PNot(PFuncReturn (_,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))
| PNot(PFuncParam (_,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))
| PNot(PFuncReturn (_,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