Skip to content
Snippets Groups Projects
l2lAliasType.ml 3.56 KiB
(* Time-stamp: <modified the 18/12/2012 (at 10:10) by Erwan Jahier> *)

(**  
Source 2 source transformation :
- toutes les expressions de type sans NOM
  (donc uniquement des tableaux immédiats ?)
  sont traquées et remplacées par un alias
*)

open Lic


let doit (inp : LicPrg.t) : LicPrg.t =
   (* n.b. on fait un minumum d'effet de bord pour
      pas avoir trop d'acummulateur ... *)
  let atab = Hashtbl.create 10 in
  let res = ref inp in

   (** UTILE : nommage des alias d'array *)
  let array_ident ty sz =
    let tid = Lic.ident_of_type ty in
    let sfx = Printf.sprintf "%s_%d" (snd tid) sz in
    let id = LicPrg.fresh_type_id !res (fst tid) sfx in
    id 
  in

   (** UTILE : cherche/crée un alias de type *)
  let rec alias_type te =
    match te with
      | Array_type_eff (ty, sz) -> (
        let ty = alias_type ty in
        let te = Array_type_eff (ty, sz) in
        try
          let ref_te = Hashtbl.find atab te in
            (*
              Verbose.printf "--> alias_type %s = %s ^ %d FOUND : %s\n"
              (LicDump.string_of_type_eff te)
              (LicDump.string_of_type_eff ty)
              sz
              (LicDump.string_of_type_eff ref_te);
            *)
          ref_te
        with Not_found -> (
          let id = array_ident ty sz in
          let ref_te = Abstract_type_eff (id, te) in
          res := LicPrg.add_type id ref_te !res;
          Hashtbl.add atab te ref_te; 
            (*
              Verbose.printf "--> alias_type %s = %s ^ %d NOT FOUND, gives: %s\n"
              (LicDump.string_of_type_eff te)
              (LicDump.string_of_type_eff ty)
              sz
              (LicDump.string_of_type_eff ref_te);
            *)
          ref_te 
        )
      ) | _ -> te
  in

   (** TRAITE LES TYPES *)
  let do_type k te =
    let te' = match te with
      | Array_type_eff (tel, sz) ->
        let tel' = alias_type tel in
        Array_type_eff (tel', sz)  
      | Struct_type_eff (id, fields) -> 
        let do_field (id, (tf, co)) =
          (id, (alias_type tf, co)) 
        in
        Struct_type_eff (id, List.map do_field fields)
      | _ -> te
    in
    if (te = te') then () 
    else
      res := LicPrg.add_type k te' !res 
  in
  LicPrg.iter_types do_type inp;

   (** TRAITE LES CONSTANTES *)
  let do_const k ec =
    let ec' = match ec with
      | Extern_const_eff (i, te) ->
        let te' = alias_type te in
        Extern_const_eff (i, te')
      | Abstract_const_eff (i, te, c, b) ->
        let te' = alias_type te in
        Abstract_const_eff (i, te', c, b)
      | Array_const_eff (cl, te) ->
        let te' = alias_type te in
        Array_const_eff (cl, te')
      | Bool_const_eff _
      | Int_const_eff _ 
      | Real_const_eff _
      | Enum_const_eff _ 
      | Struct_const_eff _
      | Tuple_const_eff _ -> ec
    in
    if (ec = ec') then ()
    else 
         (* n.b. add=replace *)
      res := LicPrg.add_const k ec' !res 
  in 
  LicPrg.iter_consts do_const inp ;

   (** TRAITE LES NOEUDS *)
  let do_node k en =
      (* n.b. les Lic.type_ apparraissent uniquement dans les var infos *)
    let do_var vi =
      let ty = alias_type vi.var_type_eff in
      {vi with var_type_eff = ty}
    in
    let en' = { en with
      inlist_eff = (List.map do_var en.inlist_eff);
      outlist_eff = (List.map do_var en.outlist_eff);
      loclist_eff = (
        match en.loclist_eff with
          | Some vl -> Some (List.map do_var vl)
          | None -> None
      )
    } in
      (* on fait pas dans la dentelle, on remplace ... *)
    res := LicPrg.add_node k en' !res
  in
  LicPrg.iter_nodes do_node inp;
  !res