let synch_upd_linear (state_l,trans_l) func status loc caller sid =
(* WARNING ! Notice that the order of these operations is very important.
Step 1 has to be done after the Step 0 and before the steps 2 and 3.
Step 4 has to be done after the Step 3.
*)
(* Step 0 : define new value of current operation and its status *)
let inst_curop_upd =
Set(
Cil.var (get_varinfo curOp),
new_exp (Const(func_to_cenum (func))),
loc
)
in
let inst_curopstatus_upd =
Set(
Cil.var (get_varinfo curOpStatus),
new_exp (Const(op_status_to_cenum status)),
loc
)
in
(* Step 0 : computing active states, according to result from AI *)
(* let computedIsOldActiveSt= if status=Promelaast.Return then get_pre_return func else get_pre_call func in
let nbOldActiveStates=Array.fold_left (fun old b -> if b then old+1 else old) 0 computedIsActiveSt in*)
(* TODO : caller et sid sont des options. Donc il faut les extraire avec un map seulement si status = call.
Il faut donc, autant que possible factoriser ce test une unique fois.
*)
(* Getting crossable transitions and active states from spec. *)
let allowedActiveSt,allowedCrossableTr,computedIsOldActiveSt=
if status=Promelaast.Call then
begin
(* Case of call *)
let activeSt,crossedTr = get_func_pre ~securised:true func in
let caller,sid =
match caller,sid with
| Some(c),Some(i) -> c,i
| _ -> assert false
in
let oldSt = (fst (Data_for_ltl.get_func_pre_call caller sid)) (*Si call alors on capture l'etat atteignable avec l'appel*)
in
(activeSt,crossedTr,oldSt)
end
else
begin
(* Case of return *)
let activeSt,crossedTr = pre_flattening (get_func_post_bycase ~securised:true func) in
let oldSt = Array.make(getNumberOfStates()) false in
List.iter
(fun tr -> if crossedTr.(tr.numt) then oldSt.(tr.start.nums) <- true)
trans_l ;
(activeSt,crossedTr,oldSt)
end
in
(* (* Deducting allowed old active states. During this computation, the number of old active state is also computed. *)
let computedIsOldActiveSt =
if status=Promelaast.Call
then fst (Data_for_ltl.get_func_pre_call caller sid) (*Si call alors capture l'etat atteignable avec l'appel*)
else Array.make(getNumberOfStates()) false in (* Sinon : return est unique dans la fonction. Les etats anciennement actifs sont les origines des transitions. On construit OldActive a partir des transitions. *)
(*let computedIsOldActiveSt = if status=Promelaast.Return then get_pre_return func else get_pre_call func in*)
if status=Promelaast.Return then
List.iter
(fun tr ->
if (allowedCrossableTr.(tr.numt)) && not (computedIsOldActiveSt.(tr.start.nums)) then
computedIsOldActiveSt.(tr.start.nums) <- true
)
trans_l ;
*)
(* Step 1 : update of Old states *)
(* This generation use allowed states wrt spec, and simplify cases with a single old active state *)
let step_one_inst =
List.fold_left
(fun inst_l st ->
let rightPart =
if(computedIsOldActiveSt.(st.nums)) then
new_exp (Lval(mk_int_offseted_array_lval curState st.nums))
else
(mk_int_exp 0)
in
((Cil_types.Set(
(mk_int_offseted_array_lval curStateOld st.nums),
rightPart,
loc
))::inst_l)
)
(inst_curopstatus_upd::[inst_curop_upd])
state_l
in
(* Step 2 : Computation of crossable transitions *)
(* Only crossable transitions wrt spec are considered. *)
let computedIsCrossTr= Array.make(getNumberOfTransitions()) false in
(*let nbTransitions = ref 0 in *)
let step_two_inst =
List.fold_left
(fun inst_l tr ->
let (b,r) = (upd_one_trans tr func status loc allowedCrossableTr computedIsOldActiveSt) in
(Array.set computedIsCrossTr tr.numt b;
(*(if b then nbTransitions:=!nbTransitions+1);*)
r::inst_l
)
)
step_one_inst
trans_l
in
(* Step 3 : Computation of reachable states *)
let step_three_inst =
List.fold_left
(fun inst_l st -> (upd_one_state trans_l st.nums loc computedIsCrossTr (*!nbTransitions*) allowedActiveSt)::inst_l)
step_two_inst
state_l
in
step_three_inst