-
Erwan Jahier authored
Ditto for Misc and Compile
Erwan Jahier authoredDitto for Misc and Compile
l2lRmPoly.ml 7.48 KiB
(* Time-stamp: <modified the 14/01/2016 (at 10:41) by Erwan Jahier> *)
(*
Source 2 source transformation :
élimine polymorphisme et surcharge
*)
open Lxm
open Lic
let dbg = (Lv6Verbose.get_flag "poly")
let (is_predef_overloaded : Lic.node_key -> bool) =
fun nk ->
match fst nk with
| ("Lustre",("times"|"slash"|"uminus"|"minus"|"plus"|"lt"|"lte"|"gt"|"gte")) -> true
| _ -> false
(** utile : on ne traite que les poly non externe *)
let node_is_poly ne =
(Lic.node_is_poly ne) && not (Lic.node_is_extern ne)
let types_of_operands ops =
match ops with vl ->
List.flatten (List.map Lic.type_of_val_exp vl)
(* transforme un type match en pseudo-arg statique
plus homogene ... *)
let static_args_of_matches matches =
List.map (fun (tv, te) ->
let tid = Lic.string_of_type_var tv in
TypeStaticArgLic (tid, te)
) matches
(* tranform "plus" into "iplus", etc. *)
let (instanciate_node_key: Lic.type_matches -> Lic.node_key -> Lic.node_key) =
fun tmatches nk ->
if is_predef_overloaded nk then (
let ((m,n),sargs) = nk in
try if List.assoc AnyNum tmatches = Int_type_eff then
("Lustre","i"^n),sargs
else
("Lustre","r"^n),sargs
with Not_found -> nk
) else
nk
let rec doit (inprg : LicPrg.t) : LicPrg.t =
(* n.b. on fait un minumum d'effet de bord pour
pas avoir trop d'acummulateur ... *)
let res = ref LicPrg.empty in
(** TRAITE LES TYPES *)
let do_type k (te:Lic.type_) =
res := LicPrg.add_type k te !res
in
LicPrg.iter_types do_type inprg;
(** TRAITE LES CONSTANTES *)
let do_const k (ec: Lic.const) =
res := LicPrg.add_const k ec !res
in
LicPrg.iter_consts do_const inprg ;
(** TRAITE LES NOEUDS : *)
let rec do_node k (ne:Lic.node_exp) = (
if node_is_poly ne then
(* pour les noeuds *NON* polymorphes/surchagés, on fait rien du tout.
pour les noeuds Lustre polymorphe (if, eq, neq) non plus.
*)
Lv6Verbose.exe ~flag:dbg (fun() -> Printf.printf
"### Warning: no code generated for polymorphic/overloaded node '%s'\n"
(Lic.string_of_node_key ne.node_key_eff))
else
let def' = match ne.def_eff with
| MetaOpLic
| ExternLic -> ne.def_eff
| AbstractLic _ -> assert false
| BodyLic nb -> BodyLic (do_body [] nb)
in
res := LicPrg.add_node k { ne with def_eff = def'} !res
)
(** TRAITEMENT DES BODY *)
and do_body (m: Lic.type_matches) (nb: Lic.node_body) : Lic.node_body =
(* parcours les expressions du body
à la recherche d'appel de noeuds poly *)
let do_assert a = Lxm.flagit (do_exp m a.it) a.src
and do_eq eq =
Lxm.flagit (List.map (do_left m) (fst eq.it),
do_exp m (snd eq.it))
eq.src
in
{
asserts_eff = List.map do_assert nb.asserts_eff;
eqs_eff = List.map do_eq nb.eqs_eff;
}
and do_left (m: Lic.type_matches) (l: Lic.left) : Lic.left =
let rec aux l =
match l with
| LeftVarLic (var_info, lxm) -> LeftVarLic(do_var_info m var_info, lxm)
| LeftFieldLic(left, id, t) -> LeftFieldLic(aux left, id, Lic.subst_matches m t)
| LeftArrayLic(left, int, t) -> LeftArrayLic(aux left, int, Lic.subst_matches m t)
| LeftSliceLic(left, si, t) -> LeftSliceLic(aux left, si, Lic.subst_matches m t)
in
aux l
and do_var_info (m: Lic.type_matches) (vi:Lic.var_info) : Lic.var_info =
{ vi with var_type_eff = Lic.subst_matches m vi.var_type_eff }
(* TRAITEMENT DES EXP : on passe en parametre un Lic.type_matches *)
and do_exp (m: Lic.type_matches) (e: Lic.val_exp) : Lic.val_exp =
let typ' = Lic.apply_type_matches m e.ve_typ in
let core' = match e.ve_core with
| CallByPosLic (posop, ops) -> (
let ops' = (List.map (do_exp m) ops) in
match posop.it with
| PREDEF_CALL (pop) -> CallByPosLic (posop, ops')
| CALL nk ->
let ne =
match LicPrg.find_node inprg nk.it with
| Some n -> n
| None -> assert false
in
let nk' = if is_predef_overloaded nk.it then
(Lxm.flagit (instanciate_node_key m nk.it) nk.src)
else if node_is_poly ne
then (
Lv6Verbose.exe ~flag:dbg (fun () ->
Printf.fprintf stderr "#DBG: CALL poly node %s\n" (Lxm.details posop.src));
let intypes = types_of_operands ops' in
let (inpars, _) = Lic.profile_of_node_exp ne in
let tmatches = UnifyType.is_matched inpars intypes in
{it=solve_poly tmatches nk.it ne; src=nk.src}
)
else nk
in
let posop' = Lxm.flagit (CALL nk') posop.src in
CallByPosLic (posop', ops')
| x ->
(* dans tout les autre cas, raf ? *)
CallByPosLic (posop, ops')
)
| CallByNameLic (namop, idops) ->
let idops' = List.map (fun (id, ve) -> (id, (do_exp m) ve)) idops in
CallByNameLic (namop, idops')
| Merge (ce,cl) ->
let cl = List.map (fun (id, ve) -> (id, (do_exp m) ve)) cl in
Merge (ce, cl)
in
{ e with ve_core = core'; ve_typ = typ' }
(* TRAITEMENT DES PARAMS STATIQUES *)
and do_static_arg (m: Lic.type_matches) (a: Lic.static_arg) : Lic.static_arg =
match a with
| ConstStaticArgLic (id, cst) -> a
| TypeStaticArgLic (id, ty) -> a
| NodeStaticArgLic (id, nk) -> (
match nk with
| (("Lustre",_),[]) -> NodeStaticArgLic (id, instanciate_node_key m nk)
| _ ->
let ne =
match LicPrg.find_node inprg nk with
| Some n -> n
| None -> assert false
in
let nk' = solve_poly m nk ne in
NodeStaticArgLic (id, nk')
)
(** Gros du boulot :
soit un noeud poly, soit un profil attendu,
fabrique s'il n'existe pas déjà, un noeud non poly adéquat ...
*)
and solve_poly (tmatches: Lic.type_matches) (nk: Lic.node_key) (ne: Lic.node_exp)
: Lic.node_key =
Lv6Verbose.exe ~flag:dbg (fun () ->
Printf.printf
"#DBG: L2lRmPoly.solve_poly nk='%s'\n# prof=%s'\n# matches='%s'\n"
(Lic.string_of_node_key nk)
(Lic.string_of_type_profile (Lic.profile_of_node_exp ne))
(Lic.string_of_type_matches tmatches)
);
let do_var vi =
let nt = Lic.subst_matches tmatches vi.var_type_eff in
assert(not (Lic.type_is_poly nt));
{ vi with var_type_eff = nt }
in
let (nid, sargs) = nk in
(* nouvelle clé unique = ancienne + tmatches *)
(* let sargs' = sargs@(static_args_of_matches tmatches) in *)
let sargs' = (List.map (do_static_arg tmatches) sargs)
@(static_args_of_matches tmatches)
in
let nk' = (nid, sargs') in
let def' = match ne.def_eff with
| ExternLic
| AbstractLic _ -> assert false
| MetaOpLic -> MetaOpLic
| BodyLic nb -> BodyLic(do_body tmatches nb)
in
let ne' = {
node_key_eff = nk';
inlist_eff = List.map do_var ne.inlist_eff;
outlist_eff = List.map do_var ne.outlist_eff;
loclist_eff = (match ne.loclist_eff with
| None -> None
| Some vl -> Some (List.map do_var vl)
);
def_eff = def';
has_mem_eff = ne.has_mem_eff;
is_safe_eff = ne.is_safe_eff;
lxm = ne.lxm;
} in
res := LicPrg.add_node nk' ne' !res;
nk'
in
(*LET's GO *)
LicPrg.iter_nodes do_node inprg;
!res