-
Erwan Jahier authored
More precisely, transforms equations of the form y = x when Toto(c); into x when Toto_c ; Toto_c=Toto(c);
Erwan Jahier authoredMore precisely, transforms equations of the form y = x when Toto(c); into x when Toto_c ; Toto_c=Toto(c);
l2lWhenOnId.ml 5.61 KiB
(** Time-stamp: <modified the 01/06/2016 (at 17:34) by Erwan Jahier> *)
open Lxm
open Lic
open AstPredef
let dbg = (Lv6Verbose.get_flag "woi")
(********************************************************************************)
(** The functions below accumulate
(1) the assertions
(2) the new equations
(3) the fresh variables
*)
type acc =
Lic.var_info list (* new local vars *)
* Lic.eq_info srcflagged list (* equations *)
* Lic.val_exp srcflagged list (* assertions *)
let new_var = FreshName.var_info
let new_var str type_eff clock_eff =
let id = Lv6Id.of_string (FreshName.local_var str) in
let var =
{
var_name_eff = id;
var_nature_eff = AstCore.VarLocal;
var_number_eff = -1;
var_type_eff = type_eff;
var_clock_eff = id,clock_eff;
} in
var
(********************************************************************************)
(* The one that perform the real work, namely:
- invent a fresh var name NV
- replace 'when Idle(st)' by 'when NV'
- generate the equation defining NV (NV=(Idle=st);)
*)
let (gen_ident : Lxm.t -> Lv6Id.long -> Lv6Id.t -> type_ -> Lic.clock -> acc ->
Lic.by_pos_op srcflagged * acc ) =
fun lxm cc cv ct clk (vl,eql,al) -> (* On(Idle, st, enum_t) *)
let nv_base = (snd cc) ^ "_" ^ cv in
let nv = new_var nv_base Bool_type_eff clk in
let ve1 = {
ve_typ = [ct];
ve_clk = [clk];
ve_core = CallByPosLic(Lxm.flagit (Lic.CONST_REF cc) lxm,[])
}
in
let ve2 = {
ve_typ = [ct];
ve_clk = [clk];
ve_core = CallByPosLic(Lxm.flagit (Lic.VAR_REF cv) lxm,[])
}
in
let ve = (* Idle=st *){
ve_typ = [Bool_type_eff];
ve_clk = [clk];
ve_core =
CallByPosLic({it=Lic.PREDEF_CALL({it=(("Lustre","eq"),[]);src=lxm});src=lxm},
[ve1;ve2])
}
in
let new_eq = (* NV=(Idle=st) *) {src=lxm;it=[LeftVarLic (nv, lxm)], ve} in
let true_cc = "Lustre","true" in
let op = WHEN (On((true_cc, nv.var_name_eff, Bool_type_eff),clk)) in
Lxm.flagit op lxm, (nv::vl,new_eq::eql,al)
(********************************************************************************)
(* All the remaining are admnistrative functions *)
let rec (do_eq : LicPrg.t -> Lic.eq_info srcflagged -> acc -> acc) =
fun licprg { src = lxm_eq ; it = (left_list, ve) } acc ->
let ve, (nv,neqs,nass) = do_val_exp licprg ve acc in
nv, { src = lxm_eq ; it = (left_list, ve) }::neqs, nass
and (do_val_exp: LicPrg.t -> val_exp -> acc -> val_exp * acc) =
fun licprg ve acc ->
let ve_core, acc =
match ve.ve_core with
| Merge(ce,cl) -> (
let cl,acc =
List.fold_left
(fun (ncl,acc) (c, ve) ->
let ve, acc = do_val_exp licprg ve acc in
((c, ve)::ncl), acc
)
([],acc)
cl
in
Merge(ce,cl),acc
)
| CallByNameLic(op, fl) -> (
let fl,acc = List.fold_left
(fun (nfl,acc) (id,ve) ->
let nf, acc = do_val_exp licprg ve acc in
((id,nf)::nfl), acc
)
([],acc)
fl
in
CallByNameLic(op, fl), acc
)
| CallByPosLic (op, vel) -> (
let vel, acc = List.fold_left
(fun (vel,acc) ve ->
let ve, acc = do_val_exp licprg ve acc in
(ve::vel), acc
)
([],acc)
(List.rev vel)
in
match op.it with
| WHEN (On((_,_,Bool_type_eff),_)) -> (* nothing to do in this case *)
CallByPosLic(op, vel), acc
| WHEN (On((cc,cv,ct),clk)) ->
let op, acc = gen_ident op.src cc cv ct clk acc in
CallByPosLic(op, vel), acc
| _ -> CallByPosLic(op, vel), acc
)
in
{ ve with ve_core = ve_core },acc
and (do_val_exp_flag: LicPrg.t -> val_exp srcflagged -> acc ->
val_exp srcflagged * acc) =
fun licprg ve_f acc ->
let ve, acc = do_val_exp licprg ve_f.it acc in
{ ve_f with it = ve }, acc
and (do_node : LicPrg.t -> Lic.node_exp -> Lic.node_exp) =
fun licprg n ->
match n.def_eff with
| ExternLic | MetaOpLic | AbstractLic _ -> n
| BodyLic b ->
let acc = List.fold_left
(fun acc eq -> do_eq licprg eq acc)
([],[],[])
(List.rev b.eqs_eff)
in
let acc = List.fold_left
(fun acc ve ->
let ve,(nv,neq,nass) = do_val_exp_flag licprg ve acc in
(nv,neq,ve::nass)
)
acc
b.asserts_eff
in
let (nv,neqs,nass) = acc in
let nlocs = match n.loclist_eff with
| None -> nv (* SNO, but eats no bread *)
| Some v -> List.rev_append nv v
in
{ n with
def_eff = BodyLic {
eqs_eff = neqs;
asserts_eff = nass;
};
loclist_eff = Some nlocs;
}
(* exported *)
let rec (doit : LicPrg.t -> LicPrg.t) =
fun inprg ->
let outprg = LicPrg.empty in
(** types and constants do not change *)
let outprg = LicPrg.fold_types LicPrg.add_type inprg outprg in
let outprg = LicPrg.fold_consts LicPrg.add_const inprg outprg in
(** transform nodes *)
let rec (doit_node : Lic.node_key -> Lic.node_exp -> LicPrg.t -> LicPrg.t) =
fun nk ne outprg ->
Lv6Verbose.exe ~flag:dbg (fun() -> Printf.printf "#DBG: L2lWhenOnId '%s'\n"
(Lic.string_of_node_key nk));
let ne = do_node inprg ne in
LicPrg.add_node nk ne outprg
in
let outprg = LicPrg.fold_nodes doit_node inprg outprg in
outprg