Skip to content
Snippets Groups Projects
l2lWhenOnId.ml 9.46 KiB
Newer Older
(** Time-stamp: <modified the 29/08/2019 (at 16:07) by Erwan Jahier> *)

open Lxm
open Lic
 
let dbg =  (Lv6Verbose.get_flag "woi")

(********************************************************************************)
(** The functions below accumulate 
   (2) the new equations 
   (3) the fresh variables
   (4) the table mapping enumerated clocks to new boolean clock
type clock_tbl = ((Lv6Id.long * Lv6Id.t), Lic.var_info) Hashtbl.t (* use Map.t ? *)
type acc = 
      Lic.var_info list           (* new local vars *)
    * Lic.eq_info srcflagged list (* equations *)
    * Lic.val_exp srcflagged list (* assertions *)
let new_var (cc,cv) type_eff clock_eff clk_tbl = 
   try Hashtbl.find clk_tbl (cc,cv), true
   with Not_found ->
     let str = (snd cc) ^ "_" ^ cv in
     let str2 = (snd cc) ^ "(" ^ cv ^")" in
     let id = Lv6Id.of_string (FreshName.local_var (str)) in 
     Lv6Verbose.exe
       ~flag:dbg
       (fun() -> Printf.printf
                   "L2lWhenOnId: '%s' not found; create %s\n" str2 id);
     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
     Hashtbl.add clk_tbl (cc,cv) var;

(********************************************************************************)
(* The one that performs the real work, namely:
- if it hasn't been created yet
   - invent a fresh var name NV, 
   - generate the equation defining NV (NV=(Idle=st);)
*)
let (gen_ident : Lxm.t -> Lv6Id.long -> Lv6Id.t -> type_ -> Lic.clock -> acc -> 
                  var_info * acc ) =
   fun lxm cc cv ct clk (vl,eql,al,tbl) -> (* On(Idle, st, enum_t)  *)
   let nv, already_done = new_var (cc,cv) Bool_type_eff clk tbl in
     let ve1 = {
       ve_typ = [ct];
       ve_clk = [clk]; 
       ve_core = CallByPosLic(Lxm.flagit (Lic.CONST_REF cc) lxm,[]);
       ve_src = lxm
     }
     in
     let ve2 = {
       ve_typ = [ct];
       ve_clk = [clk]; 
       ve_core = CallByPosLic(Lxm.flagit (Lic.VAR_REF cv) lxm,[]);
       ve_src = 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}, 
     }
     in
     if already_done then
       nv, (vl,eql,al,tbl)
     else
       let new_eq = (* NV=(Idle=st) *) {src=lxm;it=[LeftVarLic (nv, lxm)], ve} in
       nv,  (nv::vl,new_eq::eql,al,tbl)
        
(********************************************************************************)
let rec update_clock : Lxm.t -> acc -> clock -> clock * acc = 
  fun lxm acc clk ->
  match clk with
  | BaseLic | ClockVar _ -> clk, acc
  | On((cc,cv,ct),sclk) ->
     let sclk, acc = update_clock lxm acc sclk in
     let (_,_,_,clk_tbl) = acc in
     try 
       let nv = Hashtbl.find clk_tbl (cc,cv) in
       On((("Lustre","true"),nv.var_name_eff, Bool_type_eff), sclk), acc
     with Not_found ->
       if cc = ("Lustre","true") || cc = ("Lustre","false") then 
         On((cc,cv,ct),sclk), acc
       else
         let nv, acc = gen_ident lxm cc cv ct sclk acc in
         On((("Lustre","true"),nv.var_name_eff, Bool_type_eff), sclk), acc
let update_clock_list : Lxm.t -> clock list * acc -> clock -> clock list * acc =
  fun lxm (res,acc) clk ->
  let clk, acc = update_clock lxm acc clk in
  clk::res, acc

                                                                         
let update_var_info : Lxm.t -> acc -> var_info -> var_info * acc = 
  fun lxm acc vi ->
  let (id, clk) = vi.var_clock_eff in
  let clk, acc = update_clock lxm acc clk in
  Lv6Verbose.exe
    ~flag:dbg
    (fun() -> Printf.printf
                "#DBG: L2lWhenOnId;  update_var_info %s\n" id);
  { vi with var_clock_eff = id, clk }, acc

let update_var_info_list : Lxm.t -> var_info list * acc -> var_info ->
                           var_info list * acc = 
  fun lxm (res,acc) vi ->
  let vi, acc = update_var_info lxm acc vi in
  vi::res, acc

 let rec update_left : acc -> left -> left * acc = 
   fun acc l -> 
   match l with
   | LeftVarLic(vi,lxm) ->
      let vi, acc = update_var_info lxm acc vi in
      LeftVarLic(vi,lxm), acc
   | LeftFieldLic(l,id,t) -> 
      let l, acc = update_left acc l in
      LeftFieldLic(l,id,t),acc
   | LeftArrayLic(l,i,t) -> 
      let l, acc = update_left acc l in
      LeftArrayLic(l,i,t), acc
   | LeftSliceLic(l,si,t) -> 
      let l, acc = update_left acc l in
      LeftSliceLic(l,si,t), acc

 let update_left_list : left list * acc -> left -> left list * acc = 
   fun (ll,acc) l -> 
   let l, acc = update_left acc l in
   l::ll, acc
(********************************************************************************)
(* 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,tbl) = do_val_exp licprg ve acc in
    let left_list,_acc = List.fold_left update_left_list ([],acc) left_list in
    let left_list = List.rev left_list in
    nv, { src = lxm_eq ; it = (left_list, ve) }::neqs, nass,tbl
      
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
          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((cc,cv,Bool_type_eff),clk)) -> (* nothing to do in this case *)
             let clk, acc = update_clock op.src acc clk in              
             let new_op = WHEN (On((cc, cv, Bool_type_eff),clk)) in
             let op = Lxm.flagit new_op op.src in
             CallByPosLic(op, vel), acc
          | WHEN (On((cc,cv,ct),clk)) ->
             let clk, acc = update_clock op.src acc clk in              
             let nv, acc = gen_ident op.src cc cv ct clk acc in
             let true_cc = "Lustre","true" in
             let new_op = WHEN (On((true_cc, nv.var_name_eff, Bool_type_eff),clk)) in
             let op = Lxm.flagit new_op op.src in
    in
    let lxm = lxm_of_val_exp ve in
    let ve_clk, acc = List.fold_left (update_clock_list lxm) ([],acc) ve.ve_clk in
      { ve with
        ve_core = ve_core;
        ve_clk  = List.rev ve_clk;
      },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 -> 
  let tbl = Hashtbl.create 0 in
      | ExternLic | MetaOpLic | AbstractLic _ -> n,acc
      | BodyLic b ->
        let acc = List.fold_left 
                    (fun acc eq -> do_eq licprg eq acc)
                    acc
                    (List.rev b.eqs_eff)
        in
        let acc = List.fold_left 
          (fun acc ve -> 
            let ve,(nv,neq,nass,tbl) = do_val_exp_flag licprg ve acc in
            (nv,neq,ve::nass,tbl)
        let uvi = update_var_info_list n.lxm in
        let inlist_eff,acc  = List.fold_left uvi ([],acc) n.inlist_eff in
        let outlist_eff,acc = List.fold_left uvi ([],acc) n.outlist_eff in
        let locs = match n.loclist_eff with Some x -> x | None -> [] in
        let loclist_eff,acc = List.fold_left uvi ([],acc) locs in        
        let (nv,neqs,nass,_tbl) = acc in
        let nlocs = List.rev_append nv loclist_eff in
          def_eff = BodyLic { eqs_eff = neqs; asserts_eff = nass };
          inlist_eff  = List.rev inlist_eff;
          outlist_eff = List.rev outlist_eff;
  let n,_acc = aux licprg n  ([],[],[],tbl) in
let (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 (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