From 43dc79f09a5f462c7cf0d8f2eb30b123ba63e7db Mon Sep 17 00:00:00 2001
From: Erwan Jahier <jahier@imag.fr>
Date: Thu, 20 Dec 2012 09:49:34 +0100
Subject: [PATCH] Plug back Meta operator Expansion.

---
 Makefile                |   2 +
 src/compile.ml          |   6 +-
 src/l2lExpandArrays.ml  |   8 +-
 src/l2lExpandMetaOp.ml  | 391 ++++++++++++++++++++++++++++++++++++++++
 src/l2lExpandMetaOp.mli |   6 +
 src/l2lRmPoly.ml        | 246 +++++++++++++------------
 src/lic.ml              |  78 ++++----
 src/licPrg.ml           |   6 +-
 src/licPrg.mli          |  11 +-
 src/uglyStuff.ml        |  16 +-
 10 files changed, 588 insertions(+), 182 deletions(-)
 create mode 100644 src/l2lExpandMetaOp.ml
 create mode 100644 src/l2lExpandMetaOp.mli

diff --git a/Makefile b/Makefile
index 1ae7f6aa..276090c4 100644
--- a/Makefile
+++ b/Makefile
@@ -92,6 +92,8 @@ SOURCES =  \
 	$(OBJDIR)/l2lExpandArrays.ml \
 	$(OBJDIR)/l2lExpandNodes.mli \
 	$(OBJDIR)/l2lExpandNodes.ml \
+	$(OBJDIR)/l2lExpandMetaOp.ml \
+	$(OBJDIR)/l2lExpandMetaOp.mli \
 	$(OBJDIR)/l2lRmPoly.mli \
 	$(OBJDIR)/l2lRmPoly.ml \
 	$(OBJDIR)/l2lAliasType.mli \
diff --git a/src/compile.ml b/src/compile.ml
index 09747369..98bc64af 100644
--- a/src/compile.ml
+++ b/src/compile.ml
@@ -1,4 +1,4 @@
-(* Time-stamp: <modified the 18/12/2012 (at 14:39) by Erwan Jahier> *)
+(* Time-stamp: <modified the 19/12/2012 (at 17:23) by Erwan Jahier> *)
 
 
 open Lxm
@@ -44,6 +44,10 @@ let (doit : AstV6.pack_or_model list -> Ident.idref option -> LicPrg.t) =
     let zelic = L2lRmPoly.doit zelic in
    (* alias des types array *)
     let zelic = L2lAliasType.doit zelic in
+    let zelic = if not !Global.inline_iterator then zelic else
+        (* Array and struct expansion: to do after polymorphism elimination *)
+        L2lExpandMetaOp.doit zelic 
+    in    
     let zelic = if not !Global.one_op_per_equation then zelic else 
         (* Split des equations (1 eq = 1 op) *)
         L2lSplit.doit zelic 
diff --git a/src/l2lExpandArrays.ml b/src/l2lExpandArrays.ml
index 0be003de..00b1a984 100644
--- a/src/l2lExpandArrays.ml
+++ b/src/l2lExpandArrays.ml
@@ -1,4 +1,4 @@
-(** Time-stamp: <modified the 18/12/2012 (at 14:46) by Erwan Jahier> *)
+(** Time-stamp: <modified the 18/12/2012 (at 15:54) by Erwan Jahier> *)
 
 (* Replace structures and arrays by as many variables as necessary.
    Since structures can be recursive, it migth be a lot of new variables...
@@ -292,7 +292,11 @@ and (var_trees_of_val_exp :
           )
           | CONST_REF idl -> (
             try
-              let const = LicPrg.find_const lctx.prg idl in 
+              let const = 
+                match LicPrg.find_const lctx.prg idl with 
+                  | Some c -> c 
+                  | None -> assert false 
+              in 
               let s, ve_const = 
                 UnifyClock.const_to_val_eff lxm true UnifyClock.empty_subst const
               in
diff --git a/src/l2lExpandMetaOp.ml b/src/l2lExpandMetaOp.ml
new file mode 100644
index 00000000..0f9c1534
--- /dev/null
+++ b/src/l2lExpandMetaOp.ml
@@ -0,0 +1,391 @@
+(** Time-stamp: <modified the 20/12/2012 (at 09:49) by Erwan Jahier> *)
+
+open Lxm
+open Lic
+
+let dbg=Some (Verbose.get_flag "ei")
+
+(* pack useful info into a single struct *)
+type local_ctx = { 
+  idgen : LicPrg.id_generator;
+  node : Lic.node_exp;
+  prg : LicPrg.t;
+}
+
+(********************************************************************************)
+(* stuff to create fresh var names. *)
+let new_var str lctx type_eff clock_eff = 
+  let id = Ident.of_string (LicName.new_local_var str) in
+  let var =
+    { 
+      var_name_eff   = id;
+      var_nature_eff = AstCore.VarLocal;
+      var_number_eff = -1; (* this field is used only for i/o. 
+                              Should i rather put something sensible there ? *)
+      var_type_eff   = type_eff;
+      var_clock_eff  = id, clock_eff;
+    }
+  in
+    var
+
+(********************************************************************************)
+(* A small util function followed by a quick unit test. *)
+let rec fill i size = if i >= size then [] else i::(fill (i+1) size) 
+let _ = assert (fill 0 5 = [0;1;2;3;4])
+      
+let rec (list_map3: 
+           ('a -> 'b -> 'c -> 'd) -> 'a list -> 'b list -> 'c list -> 'd list) =
+  fun f l1 l2 l3 ->
+    match (l1, l2, l3) with
+      |	([], [], []) -> []
+      | (e1::t1, e2::t2, e3::t3) -> (f e1 e2 e3)::(list_map3 f t1 t2 t3)
+      | _ -> (* should not occur *) 
+          print_string "*** list_map3 called with lists of different size.\n";
+          flush stdout;
+          assert false
+(********************************************************************************)
+(* Some utililities to build Lic expressions *)
+
+(* We generate code that does not correspond to any use source one *)
+let lxm = Lxm.dummy "no_source"
+
+let (val_exp_of_var_info : Lic.var_info -> Lic.val_exp) =
+  fun vi -> 
+    { 
+      ve_core = CallByPosLic({src=lxm;it=Lic.VAR_REF vi.var_name_eff}, OperLic []); 
+      ve_typ  = [vi.var_type_eff];
+      ve_clk  = [snd vi.var_clock_eff];
+    }
+
+let (val_exp_of_int : int -> Lic.val_exp) =
+  fun i -> 
+    let id_of_int i = AstPredef.ICONST_n(Ident.of_string (string_of_int i)) in
+    { 
+      ve_clk = [BaseLic]; 
+      ve_typ = [Int_type_eff]; 
+      ve_core = CallByPosLic({it=PREDEF_CALL(id_of_int i,[]);src=lxm},OperLic[])
+    }
+
+let rec (elt_type_of_array : Lic.type_ -> Lic.type_) =
+  function
+    | Array_type_eff(t, _) -> t
+    | Abstract_type_eff(_,t) -> elt_type_of_array t
+    | _  -> assert false 
+
+let (array_var_to_val_exp : int -> var_info -> val_exp) =
+  fun i vi -> 
+    (* vi holds x of type array and returns  x.[i] *)
+    let t_elt = elt_type_of_array vi.var_type_eff in
+    let op_flg = {src = lxm ; it = ARRAY_ACCES(i)} in
+    { 
+      ve_core = CallByPosLic(op_flg, OperLic [val_exp_of_var_info vi]); 
+      ve_typ  = [t_elt];
+      ve_clk  = [snd vi.var_clock_eff];
+    }
+
+let (op_to_val_exp : AstPredef.op -> val_exp -> val_exp -> val_exp) =
+  fun op ve1 ve2 -> 
+    let op = { it = PREDEF_CALL(op,[]) ; src = lxm } in
+    {
+      ve_clk = ve1.ve_clk; 
+      ve_typ = ve1.ve_typ;
+      ve_core = CallByPosLic(op, OperLic [ve1; ve2]) 
+    } 
+let (ite_to_val_exp : val_exp -> val_exp -> val_exp -> val_exp) =
+  fun ve1 ve2 ve3 ->
+    let ite_op  = { it = PREDEF_CALL(AstPredef.IF_n,[]); src = lxm } in
+    {
+      ve_clk = ve2.ve_clk; 
+      ve_typ = ve2.ve_typ;
+      ve_core = CallByPosLic(ite_op, OperLic [ve1; ve2; ve3]) 
+    } 
+
+let (array_var_to_left : int -> var_info -> Lic.left) =
+  fun i vi -> 
+    let lp = LeftVarLic(vi,lxm) in
+    let t_elt = elt_type_of_array vi.var_type_eff in
+    LeftArrayLic(lp,i,t_elt)
+
+
+let (create_fillred_body: local_ctx -> Lic.static_arg list -> Lic.node_body * var_info list) =
+  fun lctx sargs ->
+    (* Given 
+       - a node n of type : tau * tau_1 * ... * tau_n -> tau * teta_1 * ... * teta_l
+       - a integer c
+       
+       the fillred expression has the profile: 
+       tau * tau_1^c * ... * tau_n^c  -> tau * teta_1^c * ... * teta_l^c
+    *)
+    let iter_node,c = match sargs with
+      | [ConstStaticArgLic(_,Int_const_eff(c)) ; NodeStaticArgLic(_,_node_key)]
+      | [NodeStaticArgLic(_,_node_key) ; ConstStaticArgLic(_,Int_const_eff(c))] -> 
+        _node_key,c
+      | _ -> assert false
+    in
+    let iter_node = Lxm.flagit iter_node lxm in
+        (*
+          Hence:
+          node(acc_in:tau; X1:tau_1^c ; ... ; Xn:tau_n^c) 
+          returns (acc_out:tau; Y1:teta_1^c; ... ; Yl:teta_l^c) = fillred<<n,c>>;
+        *)
+    let (acc_in : var_info)      = List.hd lctx.node.Lic.inlist_eff  in
+    let (y1_yl  : var_info list) = List.tl lctx.node.Lic.inlist_eff  in
+    let (acc_out: var_info)      = List.hd lctx.node.Lic.outlist_eff in
+    let (x1_xn  : var_info list) = List.tl lctx.node.Lic.outlist_eff in
+        (*
+          can be defined like this:
+          node(acc_in:tau; X1:tau_1^c ; ... ; Xn:tau_n^c) 
+          returns (acc_out:tau; Y1 : teta1^c; ... ; Yl: teta_l^c) =
+          var
+          acc_1, ..., acc_c-2 : tau;
+          let 
+          
+          acc_1, Y1[0], ... ,Yl[0] = n(acc_in,X1[0], ... ,Xk[0]);
+          acc_2, Y1[1], ... ,Yl[1] = n(acc_1, X1[1], ... ,Xk[1]);
+          ... 
+          acc_i+1, Y1[i], ... ,Yl[i] = n(acc_i,X1[i], ... ,Xk[i]);
+          ...
+          acc_out, Y1[c-1], ... ,Yl[c-1] = n(acc_c-1,X1[c-1], ... ,Xk[c-1]);
+          
+	       « for all i = 0, ..., c-1 » 
+          acc_i+1, Y1[i], ... ,Yl[i] = n(acc_i,X1[i], ... ,Xk[i])
+          tel
+        *)
+    let index_list = fill 0 c in        
+        (* Building this list "acc_left_list" as [acc_1, ..., acc_c-2, acc_out] *)
+    let type_exp,clock_exp = acc_in.var_type_eff, snd acc_in.var_clock_eff in
+    let (acc_vars : var_info list) =
+      let rec f i acc = if i = 0 then acc else
+          f (i-1) ((new_var "acc" lctx type_exp clock_exp)::acc)
+      in
+      List.rev(f (c-1) [])
+    in
+    let (acc_left_list : left list) =
+      (List.map (fun vi -> LeftVarLic(vi,lxm)) (acc_vars@[acc_out]))
+    in
+        (* Ditto for rigth part :  [acc_in, acc_1, ..., acc_c-1]*)
+    let (acc_rigth_list : val_exp list) =
+      List.map val_exp_of_var_info (acc_in::acc_vars)
+    in
+    let neqs =
+          (*
+            So now we build those equations ;
+            acc_1, Y1[0], ... ,Yl[0] = n(acc_in,X1[0], ... ,Xk[0]);
+            acc_2, Y1[1], ... ,Yl[1] = n(acc_1, X1[1], ... ,Xk[1]);
+            ... 
+            acc_i+1, Y1[i], ... ,Yl[i] = n(acc_i,X1[i], ... ,Xk[i]);
+            ...
+            acc_out, Y1[c-1], ... ,Yl[c-1] = n(acc_c-1,X1[c-1], ... ,Xk[c-1]);
+          *)
+      list_map3
+        (fun i acc_left acc_rigth ->
+          let (xi_j:val_exp list) = (* X1[i], ... ,Xn[i] *)
+            List.map (array_var_to_val_exp i) y1_yl
+          in
+          let args = acc_rigth::xi_j in
+          let (yi_k : left list) =  (* Y1[i], ... ,Yl[i] *)
+            List.map (array_var_to_left i) x1_xn
+          in
+          let lhs = acc_left::yi_k in
+		    let cl = 
+            List.map (fun l -> snd (Lic.var_info_of_left l).var_clock_eff) lhs
+          in
+          let rhs = {
+            ve_typ = List.map Lic.type_of_left lhs;
+            ve_clk = cl;
+            ve_core = CallByPosLic({src=lxm;it=(CALL iter_node)}, OperLic args) }
+          in
+		    let eq = { src = lxm ; it = (lhs, rhs) } in
+          eq 
+        )
+        index_list
+        acc_left_list
+        acc_rigth_list
+    in
+    { asserts_eff = []; eqs_eff = List.rev neqs }, acc_vars
+
+let (create_map_body: local_ctx -> Lic.static_arg list -> Lic.node_body * var_info list) =
+  fun lctx sargs ->
+	 (* Given
+	    - a node n of type: tau_1 * ... * tau_n -> teta_1 * ... * teta_l
+	    - and an integer c
+       
+	    The profile of map<<node,c>> is:
+  	    tau_1^c * ... * tau_n^c -> teta_1^c * ... * teta_l^c
+       and
+       
+	    Y1, ... ,Yl = map<<node; c>>(X1,...,Xk)
+       <=>
+	    for all i = 0, ..., c-1; (Y1[i], ... ,Yl[i]) = N(X_1[i], ... ,X_k[i])
+    *)
+    let iter_node,c = match sargs with
+      | [ConstStaticArgLic(_,Int_const_eff(c)) ; NodeStaticArgLic(_,_node_key)]
+      | [NodeStaticArgLic(_,_node_key) ; ConstStaticArgLic(_,Int_const_eff(c))] -> 
+        _node_key,c
+      | _ -> assert false
+    in
+    let iter_node = Lxm.flagit iter_node lxm in
+    let (y1_yl  : var_info list) = lctx.node.Lic.inlist_eff  in
+    let (x1_xn  : var_info list) = lctx.node.Lic.outlist_eff in
+    let index_list = fill 0 c in        
+    let neqs =
+      List.map
+        (fun  i ->
+          let (xi_j:val_exp list) = (* X1[i], ... ,Xn[i] *)
+            List.map (array_var_to_val_exp i) y1_yl
+          in
+          let (lhs : left list) =  (* Y1[i], ... ,Yl[i] *)
+            List.map (array_var_to_left i) x1_xn
+          in
+		    let cl = 
+            List.map (fun l -> snd (Lic.var_info_of_left l).var_clock_eff) lhs
+          in
+          let rhs = {
+            ve_typ = List.map Lic.type_of_left lhs;
+            ve_clk = cl;
+            ve_core = CallByPosLic({src=lxm;it=(CALL iter_node)}, OperLic xi_j) }
+          in
+		    let eq = { src = lxm ; it = (lhs, rhs) } in
+          eq 
+        )
+        index_list
+    in
+    { asserts_eff = []; eqs_eff = List.rev neqs }, []
+
+let (create_boolred_body: local_ctx -> int -> int -> int -> Lic.node_body * var_info list) =
+  fun lctx i j k ->
+    (* Given - 3 integers i, j, k boolred<<i,j,k>> has the profile: bool^n -> bool
+       and is defined by
+       node toto = boolred<<i,j,k>>(tab); 
+       <=>
+       node toto(tab:bool^n) returns (res:bool);
+       var 
+       cpt:int;
+       let 
+       cpt = (if tab[0] then 1 else 0) + ... + (if tab[k-1] then 1 else 0);
+       res = i <= cpt && cpt <= j;
+       tel
+    *)
+    assert(0 <= i && i <= j && j <= k && k>0);
+    let (tab_vi : var_info) = match lctx.node.Lic.inlist_eff with
+      | [vi] -> vi 
+      | _ -> assert false
+    in
+    let (res_vi : var_info) = match lctx.node.Lic.outlist_eff with
+      | [vi] -> vi 
+      | _ -> assert false
+    in
+    let (cpt_vi : var_info) = new_var "cpt" lctx Int_type_eff BaseLic in
+    let cpt_left = LeftVarLic (cpt_vi,lxm) in
+    let zero = val_exp_of_int 0
+    and one = val_exp_of_int  1 in
+    let index_list = fill 0 k in (* [0;1; ...;k-1]*)
+    let (ite_list:Lic.val_exp list) = List.map
+      (fun i -> (* returns [if A[i] then 1 else 0]_i=0,k-1 *)
+        let tab_ve_i = array_var_to_val_exp i tab_vi in
+        ite_to_val_exp tab_ve_i one zero
+      )
+      index_list
+    in
+    let cpt_rigth = List.fold_left (op_to_val_exp AstPredef.IPLUS_n)
+      (List.hd ite_list) (List.tl ite_list) in
+    let res_left = LeftVarLic (res_vi,lxm) in
+    let res_rigth = (* i <= cpt && cpt <= j; *)
+      let i_eff   = val_exp_of_int i in
+      let j_eff   = val_exp_of_int j in
+      let cpt_eff = val_exp_of_var_info cpt_vi in
+      let i_inf_cpt = op_to_val_exp AstPredef.LTE_n i_eff cpt_eff in
+      let cpt_inf_j = op_to_val_exp AstPredef.LTE_n cpt_eff j_eff in
+      op_to_val_exp AstPredef.AND_n i_inf_cpt cpt_inf_j
+    in 
+    let cpt_eq = { src = lxm ; it = ([cpt_left], cpt_rigth) } in
+    let res_eq = { src = lxm ; it = ([res_left], res_rigth) } in
+    { 
+      asserts_eff = []; 
+      eqs_eff = [cpt_eq; res_eq] 
+    }, [cpt_vi]
+
+let (create_condact_body: local_ctx -> Lic.static_arg list -> Lic.node_body * var_info list) =
+  fun lctx sargs ->
+    assert false (* XXX finish me! *)
+
+let (create_merge_body: local_ctx -> Lic.static_arg list -> Lic.node_body * var_info list) =
+  fun lctx sargs ->
+    assert false (* XXX finish me! *)
+
+let rec (create_meta_op_body:  local_ctx -> Lic.node_key -> Lic.node_body * var_info list) =
+  fun lctx (nk,sargs) ->
+    match nk with
+      | "Lustre", "fill" 
+      | "Lustre", "red" 
+      | "Lustre", "fillred" -> create_fillred_body lctx sargs
+      | "Lustre", "map"     -> create_map_body lctx sargs
+      | "Lustre", "boolred" -> (
+        let (i,j,k) =
+          match sargs with 
+            | [ConstStaticArgLic(_, Int_const_eff i);
+               ConstStaticArgLic(_, Int_const_eff j);
+               ConstStaticArgLic(_, Int_const_eff k)
+              ] -> 
+              (i,j,k)
+            | _ -> assert false
+        in
+        create_boolred_body lctx i j k  
+      )
+      | "Lustre", "diese" -> (
+        (* a diese is a particular kind of boolred:
+           #(A,...,an) = boolred(1,1,n)([a1,...,an])
+        *)
+        let n = List.length lctx.node.Lic.inlist_eff in
+        create_boolred_body lctx 1 1 n 
+      )
+      | "Lustre", "nor" -> (
+        (* a nor is a particular kind of boolred too:
+           nor(A,...,an) = boolred(0,0,n)([a1,...,an])
+        *)
+        let n = List.length lctx.node.Lic.inlist_eff in
+        create_boolred_body lctx 0 0 n 
+      )
+      | "Lustre", "condact" -> create_condact_body lctx sargs
+      | "Lustre", "merge"   -> create_merge_body lctx sargs
+      | _,_  -> assert false
+
+
+let rec (node : local_ctx -> Lic.node_exp -> Lic.node_exp) =
+  fun lctx n ->
+    let sonk = Lic.string_of_node_key in
+    Verbose.printf ~flag:dbg "#DBG: L2lInlineMetaOp %s\n" (sonk n.node_key_eff);
+    match n.def_eff with
+      | MetaOpLic nk ->
+        let nbody, nlocs = create_meta_op_body lctx nk in
+        { n with 
+          def_eff = BodyLic nbody;
+          loclist_eff = Some nlocs;
+        }
+      | ExternLic 
+      | AbstractLic None -> n
+      | AbstractLic (Some pn) ->
+        { n with def_eff = AbstractLic (Some (node lctx pn)) }
+      | BodyLic b -> n
+
+(* exported *)
+and (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 (do_node : Lic.node_key -> Lic.node_exp -> LicPrg.t -> LicPrg.t) = 
+      fun nk ne outprg -> 
+        let lctx = {
+          idgen = LicPrg.fresh_var_id_generator inprg ne;
+          node = ne;
+          prg = outprg;
+        }
+        in
+        let ne = node lctx ne in
+        LicPrg.add_node nk ne outprg
+    in
+    let outprg = LicPrg.fold_nodes do_node inprg outprg in
+    outprg
diff --git a/src/l2lExpandMetaOp.mli b/src/l2lExpandMetaOp.mli
new file mode 100644
index 00000000..87fe7758
--- /dev/null
+++ b/src/l2lExpandMetaOp.mli
@@ -0,0 +1,6 @@
+(** Time-stamp: <modified the 19/12/2012 (at 17:26) by Erwan Jahier> *)
+
+
+(** Expand Meta operators (red, map, etc.)  *)
+
+val doit : LicPrg.t -> LicPrg.t
diff --git a/src/l2lRmPoly.ml b/src/l2lRmPoly.ml
index 502aaba2..72ed3785 100644
--- a/src/l2lRmPoly.ml
+++ b/src/l2lRmPoly.ml
@@ -1,4 +1,4 @@
-(* Time-stamp: <modified the 18/12/2012 (at 10:20) by Erwan Jahier> *)
+(* Time-stamp: <modified the 18/12/2012 (at 15:57) by Erwan Jahier> *)
 
 (*
 Source 2 source transformation :
@@ -28,151 +28,159 @@ let static_args_of_matches matches =
    ) matches
 
 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
+  (* 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 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 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 polymorphes/surchagés, on fait rien du tout *)
-         Verbose.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 (
-            fst eq.it,
-            do_exp m (snd eq.it)
-         ) eq.src
+  (** TRAITE LES NOEUDS : *)
+  let rec do_node k (ne:Lic.node_exp) = (
+    if node_is_poly ne then
+      (* pour les noeuds polymorphes/surchagés, on fait rien du tout *)
+      Verbose.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
-      {
-         asserts_eff = List.map do_assert nb.asserts_eff;
-         eqs_eff = List.map do_eq nb.eqs_eff;
-      }
-   (* TRAITEMENT DES EXP : on passe en parametre un Lic.type_matches *)
-   and do_exp
+      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 (
+        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;
+    }
+  (* 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
+  (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, OperLic ops) -> (
-         let ops' = OperLic (List.map (do_exp m) ops) in
-         match posop.it with
-         | PREDEF_CALL (pop,sas) ->
+        let ops' = OperLic (List.map (do_exp m) ops) in
+        match posop.it with
+          | PREDEF_CALL (pop,sas) ->
             (* 12/07 ICI version provisoise : 
                les macros predef n'existe plus ! (ce sont des calls classiques)
             *)
             assert (sas = []);
             CallByPosLic (posop, ops')
-         | CALL nk ->
-            let ne = LicPrg.find_node inprg nk.it in
+          | CALL nk ->
+            let ne = 
+              match LicPrg.find_node inprg nk.it with 
+                | Some n -> n
+                | None -> assert false 
+            in
             let nk' = if node_is_poly ne then (
-               Verbose.exe ~flag:dbg (fun () ->
-                  Printf.fprintf stderr "#DBG: CALL poly node %s\n"
+              Verbose.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}
+              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 ->
+          | 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')
-      in
-      { e with ve_core = core'; ve_typ = typ' }
-   (* TRAITEMENT DES PARAMS STATIQUES *)
-   and do_static_arg  
+        let idops' = List.map (fun (id, ve) -> (id, (do_exp m) ve)) idops in
+        CallByNameLic (namop, idops')
+    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
+  (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",_),[]) -> a
-         | _ ->
-            let ne = LicPrg.find_node inprg nk in
+        match nk with
+          | (("Lustre",_),[]) -> a
+          | _ ->
+            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 :
+  (** 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 
+  *)
+  and solve_poly 
       (tmatches: Lic.type_matches)
-      (nk: Lic.node_key)
-      (ne: Lic.node_exp)
-   : Lic.node_key = 
-      Verbose.printf ~flag:dbg
-         "#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
-      (* nouvelle clé unique = ancienne + tmatches *)
-      let (nid, sargs) = nk in
-      let sargs' = sargs@(static_args_of_matches tmatches) in
-      let nk' = (nid, sargs') in
-      let def' = match ne.def_eff with
-         | ExternLic
-         | AbstractLic _ -> assert false 
-         | MetaOpLic (bid, sas) -> MetaOpLic (bid, List.map (do_static_arg tmatches) sas)
-         | 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;
-      } in
-      res := LicPrg.add_node nk' ne' !res;
-      nk'
-   in
-   (*LET's GO *)
-   LicPrg.iter_nodes do_node inprg;
-   !res
+  (nk: Lic.node_key)
+  (ne: Lic.node_exp)
+  : Lic.node_key = 
+    Verbose.printf ~flag:dbg
+      "#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
+    (* nouvelle clé unique = ancienne + tmatches *)
+    let (nid, sargs) = nk in
+    let sargs' = sargs@(static_args_of_matches tmatches) in
+    let nk' = (nid, sargs') in
+    let def' = match ne.def_eff with
+      | ExternLic
+      | AbstractLic _ -> assert false 
+      | MetaOpLic (bid, sas) -> MetaOpLic (bid, List.map (do_static_arg tmatches) sas)
+      | 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;
+    } in
+    res := LicPrg.add_node nk' ne' !res;
+    nk'
+  in
+  (*LET's GO *)
+  LicPrg.iter_nodes do_node inprg;
+  !res
diff --git a/src/lic.ml b/src/lic.ml
index 98f05832..c22fac77 100644
--- a/src/lic.ml
+++ b/src/lic.ml
@@ -1,4 +1,4 @@
-(* Time-stamp: <modified the 13/12/2012 (at 16:16) by Erwan Jahier> *)
+(* Time-stamp: <modified the 19/12/2012 (at 10:18) by Erwan Jahier> *)
 
 
 (** Define the Data Structure representing Compiled programs. *)
@@ -174,11 +174,12 @@ and val_exp =
            a cleaner solution would be to define two versions of val_exp: one with
            type info, and one without. But it is a big mutually recursive thing,
            and doing that would be a little bit heavy...
+           XXX why not an option type?
         *)
       ve_clk : clock list
         (* ditto *)
     }
-(** CallByPosLicest (sans doute ?)
+(** CallByPosLic est (sans doute ?)
    le BON endroit pour stocker l'information de 'matches',
    i.e. est-ce qu'un 'type_matches' a été nécessaire
    pour typer l'appel de l'opérateur ?
@@ -320,8 +321,7 @@ and type_matches = (type_var * type_) list
 
 and node_def =
   | ExternLic
-  | MetaOpLic of node_key
-   (* ICI A QUOI CA SERT ???? *)
+  | MetaOpLic of node_key (* ICI A QUOI CA SERT ???? *)
   | AbstractLic of node_exp option (* None if extern in the provide part *)
   | BodyLic of node_body
 
@@ -637,7 +637,7 @@ let rec string_of_type = function
   | Abstract_type_eff (name, t) -> (string_of_ident name)
   | Enum_type_eff (name, _) -> (string_of_ident name)
   | Array_type_eff (ty, sz) ->
-      Printf.sprintf "%s^%d" (string_of_type ty) sz
+    Printf.sprintf "%s^%d" (string_of_type ty) sz
   | Struct_type_eff (name, _) -> (string_of_ident name)
   | TypeVar Any -> "any"
   | (TypeVar AnyNum) -> "anynum"
@@ -656,51 +656,51 @@ and string_of_clock = function
   | On (id, ck) -> " on "^(Ident.string_of_clk id)^(string_of_clock ck)
 
 and string_of_const = function
-   | Bool_const_eff true -> "true"
-   | Bool_const_eff false -> "false"
-   | Int_const_eff i -> (sprintf "%d" i)
-   | Real_const_eff r -> r
-   | Extern_const_eff (s,_) -> (string_of_ident s)
-   | Abstract_const_eff (s,t,v,_) -> (string_of_ident s)
-   | Enum_const_eff   (s,_) -> (string_of_ident s)
-   | Struct_const_eff (fl, t) -> 
-      let string_of_field (id, veff) =
-        (Ident.to_string id)^" = "^ (string_of_const veff)
-      in
-      Printf.sprintf "%s{%s}"
-         (string_of_type t)
-         (String.concat "; " (List.map string_of_field fl))
-   | Array_const_eff (ctab, t) ->
-      Printf.sprintf "[%s]"
-         (String.concat ", " (List.map string_of_const ctab))
-   | Tuple_const_eff   cl ->
-      Printf.sprintf "(%s)"
-         (String.concat ", " (List.map string_of_const cl))
+  | Bool_const_eff true -> "true"
+  | Bool_const_eff false -> "false"
+  | Int_const_eff i -> (sprintf "%d" i)
+  | Real_const_eff r -> r
+  | Extern_const_eff (s,_) -> (string_of_ident s)
+  | Abstract_const_eff (s,t,v,_) -> (string_of_ident s)
+  | Enum_const_eff   (s,_) -> (string_of_ident s)
+  | Struct_const_eff (fl, t) -> 
+    let string_of_field (id, veff) =
+      (Ident.to_string id)^" = "^ (string_of_const veff)
+    in
+    Printf.sprintf "%s{%s}"
+      (string_of_type t)
+      (String.concat "; " (List.map string_of_field fl))
+  | Array_const_eff (ctab, t) ->
+    Printf.sprintf "[%s]"
+      (String.concat ", " (List.map string_of_const ctab))
+  | Tuple_const_eff   cl ->
+    Printf.sprintf "(%s)"
+      (String.concat ", " (List.map string_of_const cl))
 
 and string_of_var_info x =
-   (Ident.to_string x.var_name_eff) ^ ":"^(string_of_type x.var_type_eff)^(string_of_clock (snd x.var_clock_eff))
+  (Ident.to_string x.var_name_eff) ^ ":"^(string_of_type x.var_type_eff)^(string_of_clock (snd x.var_clock_eff))
 and string_of_var_list vl = String.concat " ; " (List.map string_of_var_info vl)
 
 and string_of_node_key = function
-| (ik, []) ->
-   (string_of_ident ik)
-| (ik, sargs)  -> Printf.sprintf "%s<<%s>>"
-   (string_of_ident ik)
-   (String.concat ", " (List.map string_of_static_arg sargs))
+  | (ik, []) ->
+    (string_of_ident ik)
+  | (ik, sargs)  -> Printf.sprintf "%s<<%s>>"
+    (string_of_ident ik)
+    (String.concat ", " (List.map string_of_static_arg sargs))
 
 and string_of_static_arg = function
-| ConstStaticArgLic(id, ceff) -> Printf.sprintf "const %s = %s" id (string_of_const ceff)
-| TypeStaticArgLic (id, teff) -> Printf.sprintf "type %s = %s" id (string_of_type teff)
+  | ConstStaticArgLic(id, ceff) -> Printf.sprintf "const %s = %s" id (string_of_const ceff)
+  | TypeStaticArgLic (id, teff) -> Printf.sprintf "type %s = %s" id (string_of_type teff)
 (* | NodeStaticArgLic (id, ((long,sargs), _, _), _) -> *)
-| NodeStaticArgLic (id, nk) ->
-   Printf.sprintf "node %s = %s" id (string_of_node_key nk)
+  | NodeStaticArgLic (id, nk) ->
+    Printf.sprintf "node %s = %s" id (string_of_node_key nk)
 
 and string_of_type_var tv = string_of_type (TypeVar tv)
 and string_of_type_matches pm =
-   let sotm (tv,t) = Printf.sprintf "%s <- %s"
-      (string_of_type_var tv) (string_of_type t)
-   in
-   String.concat ", " (List.map sotm pm)
+  let sotm (tv,t) = Printf.sprintf "%s <- %s"
+    (string_of_type_var tv) (string_of_type t)
+  in
+  String.concat ", " (List.map sotm pm)
 
 let string_of_node_exp ne =
   (Printf.sprintf "   node_key_eff = %s\n" (string_of_node_key ne.node_key_eff))
diff --git a/src/licPrg.ml b/src/licPrg.ml
index a7e26248..ee70de4c 100644
--- a/src/licPrg.ml
+++ b/src/licPrg.ml
@@ -58,9 +58,9 @@ let fresh_type_id this pname pfx =
    fresh 0
 
 (** RECHERCHE *)
-let find_type  this k = ItemKeyMap.find k this.types
-let find_const this k = ItemKeyMap.find k this.consts
-let find_node  this k = NodeKeyMap.find k this.nodes
+let find_type  this k = try Some(ItemKeyMap.find k this.types ) with Not_found -> None
+let find_const this k = try Some(ItemKeyMap.find k this.consts) with Not_found -> None
+let find_node  this k = try Some(NodeKeyMap.find k this.nodes ) with Not_found -> None
    
 let (find_var : Ident.t -> Lic.node_exp -> Lic.var_info option) = 
   fun id ne -> 
diff --git a/src/licPrg.mli b/src/licPrg.mli
index 2fe9641d..297e6c60 100644
--- a/src/licPrg.mli
+++ b/src/licPrg.mli
@@ -1,4 +1,4 @@
-(* Time-stamp: <modified the 18/12/2012 (at 14:25) by Erwan Jahier> *)
+(* Time-stamp: <modified the 18/12/2012 (at 15:51) by Erwan Jahier> *)
 
 (** The data structure resulting from the compilation process *)
 
@@ -43,12 +43,9 @@ val iter_nodes  : (Lic.node_key -> Lic.node_exp -> unit) -> t -> unit
 
 val to_file : out_channel -> t -> unit
 
-(* Raises Not_found. *)
-val find_type  : t -> Lic.item_key -> Lic.type_
-val find_const : t -> Lic.item_key -> Lic.const
-val find_node  : t -> Lic.node_key -> Lic.node_exp
-
-
+val find_type  : t -> Lic.item_key -> Lic.type_ option
+val find_const : t -> Lic.item_key -> Lic.const option
+val find_node  : t -> Lic.node_key -> Lic.node_exp option
 val find_var : Ident.t -> Lic.node_exp -> Lic.var_info option
 
 val fresh_type_id : t -> Ident.pack_name -> string -> Ident.long
diff --git a/src/uglyStuff.ml b/src/uglyStuff.ml
index 3a9c6fac..1ed25936 100644
--- a/src/uglyStuff.ml
+++ b/src/uglyStuff.ml
@@ -1,7 +1,7 @@
 
 (** XXX REMOVE ME : Crutch for make it works
 
-   Des béquilles et autres trucs moches qui ne devraient etre refaits ... 
+   Des béquilles et autres trucs moches qui devraient etre refaits ... 
 *)
 
 
@@ -12,25 +12,19 @@ ACCES AUX INFOS DEJA COMPILEES,
 infos déjà compilées, alors que c'est pas fait pour...
 - Y'a un probleme de gestion d'environnement a revoir ... 
 *)
-let node_exp_of_node_key 
-    (id_solver: Lic.id_solver)
-    (node_key: Lic.node_key)
-    (lxm : Lxm.t)
+let node_exp_of_node_key
+    (id_solver: Lic.id_solver) (node_key: Lic.node_key) (lxm : Lxm.t)
     : Lic.node_exp =
   let (id, sargs) = node_key in
   id_solver.Lic.id2node (Ident.idref_of_long id) sargs lxm
 
 let var_info_of_ident 
-    (id_solver: Lic.id_solver)
-    (id: Ident.t)
-    (lxm : Lxm.t)
+    (id_solver: Lic.id_solver) (id: Ident.t) (lxm : Lxm.t)
     : Lic.var_info =
   id_solver.Lic.id2var (Ident.idref_of_id id) lxm
 
 let const_eff_of_item_key
-    (id_solver: Lic.id_solver)
-    (id: Lic.item_key)
-    (lxm : Lxm.t) 
+    (id_solver: Lic.id_solver) (id: Lic.item_key) (lxm : Lxm.t) 
     : Lic.const =
   id_solver.Lic.id2const (Ident.idref_of_long id) lxm
 
-- 
GitLab