From 499a3f474c0f9672a9b0c2898d05332538e0c0e4 Mon Sep 17 00:00:00 2001
From: Erwan Jahier <jahier@imag.fr>
Date: Wed, 22 May 2013 14:46:03 +0200
Subject: [PATCH] Fix a bug when expanding nodes (-en). A Node that calls a
 node that itself calls another node on a non-trivial clock (i.e., using a
 when) was not producing correct code.

I've fixed this by performing the fix-point on nodes rather than on
equations. Indeed its more natural and efficient, and it avoid the
problem above. However, I did not really fix the problem, but just
turn around it. All tests seems to work fine though.

nb : #FAILS=81->80 (and -2 unresolved, but because I fixed the prog)
---
 src/l2lExpandNodes.ml                         | 162 +++++++++---------
 src/licPrg.mli                                |   4 +-
 src/rif_base.ml                               |   3 +-
 test/Makefile                                 |   1 +
 test/lus2lic.sum                              |  16 +-
 test/lus2lic.time                             |   4 +-
 test/should_work/ck5.lus                      |   5 +-
 .../long_et_stupide_nom_de_noeud.lus          |   2 +-
 test/site.exp                                 |   4 +
 todo.org                                      |  19 ++
 todo.org_archive                              |  11 ++
 11 files changed, 140 insertions(+), 91 deletions(-)

diff --git a/src/l2lExpandNodes.ml b/src/l2lExpandNodes.ml
index dccfcb71..e6597dc5 100644
--- a/src/l2lExpandNodes.ml
+++ b/src/l2lExpandNodes.ml
@@ -1,4 +1,4 @@
-(* Time-stamp: <modified the 24/04/2013 (at 17:42) by Erwan Jahier> *)
+(* Time-stamp: <modified the 22/05/2013 (at 11:17) by Erwan Jahier> *)
 
 
 open Lxm
@@ -9,10 +9,9 @@ let dbg = (Verbose.get_flag "en")
 
 (* pack useful info into a single struct *)
 type local_ctx = { 
-  idgen : LicPrg.id_generator;
-  node : Lic.node_exp;
-  prg : LicPrg.t;
-  nodes : string list; (* nodes to repserve from expansion *)
+  init_prg : LicPrg.t; (* nodes before expansion *)
+  curr_prg : LicPrg.t; (* nodes that have already been expanded *)
+  nodes : string list; (* nodes to preserve from expansion *)
 }
 
 (********************************************************************************)
@@ -119,6 +118,8 @@ let mk_loc_subst l1 l2 = List.combine (List.map (fun v -> v.var_name_eff) l1) l2
    (1) the assertions
    (2) the new equations 
    (3) the fresh variables
+
+The fix-point is performed on nodes.
 *)
 
 type acc = 
@@ -204,32 +205,39 @@ let (mk_output_subst : local_ctx -> Lxm.t -> var_info list -> Lic.left list -> c
       vl 
       leftl
 
-let rec (expand_eq : local_ctx -> acc -> Lic.eq_info Lxm.srcflagged -> acc) =
-  fun lctx (asserts, eqs, locs) { src = lxm_eq ; it = eq } ->
+let rec (expand_eq : local_ctx * acc -> Lic.eq_info Lxm.srcflagged -> local_ctx * acc) =
+  fun (lctx, (asserts, eqs, locs)) { src = lxm_eq ; it = eq } ->
     match expand_eq_aux lctx eq with
-      | None -> asserts, { src = lxm_eq ; it = eq }::eqs, locs
-      | Some(nasserts, neqs, nlocs) -> 
-        List.rev_append nasserts asserts, 
-        List.rev_append neqs eqs, 
-        List.rev_append nlocs locs
+      | lctx, None -> lctx, (asserts, { src = lxm_eq ; it = eq }::eqs, locs)
+      | lctx, Some(nasserts, neqs, nlocs) -> 
+        (lctx,
+         (List.rev_append nasserts asserts, 
+          List.rev_append neqs eqs, 
+          List.rev_append nlocs locs))
 
-and (expand_eq_aux: local_ctx -> Lic.eq_info -> acc option)=
+and (expand_eq_aux: local_ctx -> Lic.eq_info -> local_ctx * acc option)=
   fun lctx (lhs,ve) -> 
     match ve.ve_core with
       | CallByPosLic( { it = Lic.CALL node_key ; src = lxm }, vel) ->
-        let node = 
-          match LicPrg.find_node lctx.prg node_key.it with 
-            | Some n -> n
-            | None ->
-              prerr_string (
-                "*** "^ (LicDump.string_of_node_key_rec false node_key.it) ^" not defined.\n" ^
-                  "*** Defined nodes are:"^ 
-                  (String.concat ",\n"  
-                     (List.map (fun (nk,_) -> "\""^LicDump.string_of_node_key_rec false nk^"\"")
-                        (LicPrg.list_nodes lctx.prg)))
-              );
-              flush stderr;
-              assert false 
+        let lctx, node = 
+          match LicPrg.find_node lctx.curr_prg node_key.it with 
+            | Some node -> lctx, node
+            | None -> (* node has not been expanded yet: fix point! *)
+              let raw_node =
+                match LicPrg.find_node lctx.init_prg node_key.it with 
+                  | Some n -> n
+                  | None ->
+                    prerr_string (
+                      "*** "^ (LicDump.string_of_node_key_rec false node_key.it) ^" not defined.\n" ^
+                        "*** Defined nodes are:"^ 
+                        (String.concat ",\n"  
+                           (List.map (fun (nk,_) -> "\""^LicDump.string_of_node_key_rec false nk^"\"")
+                              (LicPrg.list_nodes lctx.init_prg)))
+                    );
+                    flush stderr;
+                    assert false 
+              in
+              expand_node lctx raw_node 
         in
         let node = flagit node lxm in
         let node = match node.it.def_eff with
@@ -240,10 +248,10 @@ and (expand_eq_aux: local_ctx -> Lic.eq_info -> acc option)=
           let nname = Ident.string_of_long2 (fst node.it.node_key_eff) in
           (List.mem nname lctx.nodes)
         then
-          None
+          lctx, None
         else
           (match get_node_body lctx node.it with
-            | None -> None
+            | None -> lctx, None
             | Some node_body ->
               let node_eqs = node_body.eqs_eff
               and asserts = node_body.asserts_eff in
@@ -272,20 +280,18 @@ and (expand_eq_aux: local_ctx -> Lic.eq_info -> acc option)=
                   { v with var_clock_eff = id, subst_in_clock s clk }) 
                   fresh_locs
               in
-              let acc = match acc with (a,b,c) ->  (a,b,c@fresh_locs) in
               let node_eqs = List.map (substitute s) node_eqs in
               let subst_assert x = Lxm.flagit (subst_in_val_exp s x.it) x.src in
-              let asserts = List.map subst_assert asserts in
-              let acc = List.fold_left (expand_eq lctx) acc node_eqs in
-              let acc = List.fold_left (expand_assert lctx) acc asserts in
-              Some acc
+              let asserts = List.map subst_assert asserts in              
+              let acc = match acc with (a,b,c) ->  (a@asserts,b@node_eqs,c@fresh_locs) in
+              lctx, Some acc
           )
       | CallByPosLic (_, _)
       | Merge (_, _) 
-      | CallByNameLic (_, _) -> None
+      | CallByNameLic (_, _) -> lctx, None
 
-and (expand_assert : local_ctx -> acc -> val_exp srcflagged -> acc) =
-  fun lctx (a_acc,e_acc,v_acc) ve -> 
+and (expand_assert : local_ctx * acc -> val_exp srcflagged -> local_ctx * acc) =
+  fun (lctx, (a_acc,e_acc,v_acc)) ve -> 
     let lxm = ve.src in
     let ve = ve.it in
     let clk = Ident.of_string "dummy_expand_assert", BaseLic in
@@ -298,33 +304,40 @@ and (expand_assert : local_ctx -> acc -> val_exp srcflagged -> acc) =
       ve_clk = [BaseLic]
     }
     in
-    expand_eq lctx ((Lxm.flagit nve lxm)::a_acc, e_acc, assert_var::v_acc) assert_eq
-
+    expand_eq (lctx, ((Lxm.flagit nve lxm)::a_acc, e_acc, assert_var::v_acc)) assert_eq
 
-
-let (node : local_ctx -> Lic.node_exp -> Lic.node_exp) =
+and (expand_node : local_ctx -> Lic.node_exp -> local_ctx * Lic.node_exp) =
   fun lctx n ->
-    match n.def_eff with
-      | ExternLic 
-      | AbstractLic _ -> n
-      | BodyLic b -> 
-          let locs = get_locals n in
-          let acc = List.fold_left (expand_eq lctx) ([],[],locs) b.eqs_eff in
-          let acc = List.fold_left (expand_assert lctx) acc b.asserts_eff in
-          let (asserts,neqs, nv) = acc in
-          let nb = { 
-            eqs_eff = neqs ; 
-            asserts_eff = asserts
-          } 
-          in
-          let res =
-            { n with 
-                loclist_eff = Some nv;
-                def_eff = BodyLic nb
-            }
-          in
-            res
-      | MetaOpLic -> n
+    match LicPrg.find_node lctx.curr_prg n.node_key_eff with 
+      | Some n -> lctx, n
+      | None ->
+        let lctx, exp_node =
+          match n.def_eff with
+            | ExternLic 
+            | AbstractLic _ -> lctx, n
+            | BodyLic b -> 
+              let locs = get_locals n in
+              let lctx,acc = List.fold_left expand_eq (lctx, ([],[],locs)) b.eqs_eff in
+              let lctx,acc = List.fold_left expand_assert (lctx, acc) b.asserts_eff in
+              let (asserts,neqs, nv) = acc in
+              let nb = { 
+                eqs_eff = neqs ; 
+                asserts_eff = asserts
+              } 
+              in
+              let res =
+                { n with 
+                  loclist_eff = Some nv;
+                  def_eff = BodyLic nb
+                }
+              in
+              Verbose.exe ~flag:dbg (fun () ->
+                Printf.printf "#DBG: expand nodes of '%s'\n" (Lic.string_of_node_key n.node_key_eff));
+              lctx, res
+            | MetaOpLic -> lctx, n
+        in
+        { lctx with curr_prg = LicPrg.add_node n.node_key_eff exp_node lctx.curr_prg },
+        exp_node
 
 (* exported *)
 let (doit : string list -> LicPrg.t -> LicPrg.t) =
@@ -333,21 +346,16 @@ let (doit : string list -> LicPrg.t -> LicPrg.t) =
     (** 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
+    let lctx_init = {
+      init_prg = inprg;
+      curr_prg = outprg;
+      nodes = nodes;
+    }
+    in
     (** transform nodes *)
-    let rec (do_node : Lic.node_key -> Lic.node_exp -> LicPrg.t -> LicPrg.t) = 
-      fun nk ne outprg -> 
-        Verbose.exe ~flag:dbg (fun () ->
-          Printf.printf "#DBG: expand nodes of '%s'\n"
-            (Lic.string_of_node_key nk));
-        let lctx = {
-          idgen = LicPrg.fresh_var_id_generator inprg ne;
-          node = ne;
-          prg = inprg;
-          nodes = nodes;
-        }
-        in
-        let ne = node lctx ne in
-        LicPrg.add_node nk ne outprg
+    let rec (do_node : Lic.node_key -> Lic.node_exp -> local_ctx -> local_ctx) = 
+      fun nk ne lctx -> 
+        fst (expand_node lctx ne)
     in
-    let outprg = LicPrg.fold_nodes do_node inprg outprg in
-    outprg
+    let lctx = LicPrg.fold_nodes do_node inprg lctx_init in
+    lctx.curr_prg
diff --git a/src/licPrg.mli b/src/licPrg.mli
index b3c313c3..42d2fff4 100644
--- a/src/licPrg.mli
+++ b/src/licPrg.mli
@@ -1,4 +1,4 @@
-(* Time-stamp: <modified the 12/04/2013 (at 08:50) by Erwan Jahier> *)
+(* Time-stamp: <modified the 21/05/2013 (at 16:29) by Erwan Jahier> *)
 
 (** The data structure resulting from the compilation process *)
 
@@ -25,7 +25,7 @@
 
 type t
 
-
+(** nb: previous bindings disappear *)
 val add_type : Lic.item_key -> Lic.type_ -> t -> t 
 val add_const : Lic.item_key -> Lic.const -> t -> t 
 val add_node : Lic.node_key -> Lic.node_exp -> t -> t
diff --git a/src/rif_base.ml b/src/rif_base.ml
index f5f822fa..e33b12d0 100644
--- a/src/rif_base.ml
+++ b/src/rif_base.ml
@@ -11,7 +11,7 @@
 
 open List
 
-let lexer = Genlex.make_lexer ["q"; "nil"; "#"; "x"; "load_luc"; "#@"; "@#"]
+let lexer = Genlex.make_lexer ["q"; "nil"; "ERROR"; "#"; "x"; "load_luc"; "#@"; "@#"]
 
 (* xxx Which pragmas should be defined ? *)
 
@@ -164,6 +164,7 @@ and (parse_rif_stream :  in_channel -> out_channel option -> vntl -> stream ->
           parse_rif_stream ic oc vntl (get_stream ic oc)
             tbl pragma 
 	     | (Genlex.Kwd (_,"nil"))::_ -> print_string "# nil value read. bye!\n"; raise Bye
+	     | (Genlex.Kwd (_,"ERROR"))::_ -> print_string "#ERROR value read. bye!\n"; raise Bye
 	     | (Genlex.Kwd (_,"q"))::_ -> print_string "# bye!\n"; raise Bye
 	     | (Genlex.Kwd (_,"#@"))::_ ->
               (* Beginning of multi-line comment. Note that here,
diff --git a/test/Makefile b/test/Makefile
index 1e619e75..d3a16d3f 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -25,6 +25,7 @@ lus2lic.diff:
 
 lus2lic.time:
 	grep "testcase \./lus2lic" lus2lic.log > lus2lic.time
+	cat lus2lic.time >> lus2lic.sum
 	cat lus2lic.time
 
 utest:
diff --git a/test/lus2lic.sum b/test/lus2lic.sum
index 728de6c7..0e225769 100644
--- a/test/lus2lic.sum
+++ b/test/lus2lic.sum
@@ -1,4 +1,4 @@
-Test Run By jahier on Tue May 21 09:29:18 2013
+Test Run By jahier on Wed May 22 14:36:57 2013
 Native configuration is i686-pc-linux-gnu
 
 		=== lus2lic tests ===
@@ -20,7 +20,7 @@ PASS: ../utils/test_lus2lic_no_node should_work/argos.lus
 PASS: ./lus2lic {-o /tmp/ck5.lic should_work/ck5.lus}
 PASS: ./lus2lic {-ec -o /tmp/ck5.ec should_work/ck5.lus}
 PASS: ./ec2c {-o /tmp/ck5.c /tmp/ck5.ec}
-UNRESOLVED: Time out: ../utils/test_lus2lic_no_node should_work/ck5.lus
+PASS: ../utils/test_lus2lic_no_node should_work/ck5.lus
 PASS: ./lus2lic {-o /tmp/assertion.lic should_work/assertion.lus}
 PASS: ./lus2lic {-ec -o /tmp/assertion.ec should_work/assertion.lus}
 PASS: ./ec2c {-o /tmp/assertion.c /tmp/assertion.ec}
@@ -531,7 +531,7 @@ PASS: ../utils/test_lus2lic_no_node should_work/predef01.lus
 PASS: ./lus2lic {-o /tmp/long_et_stupide_nom_de_noeud.lic should_work/long_et_stupide_nom_de_noeud.lus}
 PASS: ./lus2lic {-ec -o /tmp/long_et_stupide_nom_de_noeud.ec should_work/long_et_stupide_nom_de_noeud.lus}
 PASS: ./ec2c {-o /tmp/long_et_stupide_nom_de_noeud.c /tmp/long_et_stupide_nom_de_noeud.ec}
-UNRESOLVED: Time out: ../utils/test_lus2lic_no_node should_work/long_et_stupide_nom_de_noeud.lus
+PASS: ../utils/test_lus2lic_no_node should_work/long_et_stupide_nom_de_noeud.lus
 PASS: ./lus2lic {-o /tmp/CURRENT.lic should_work/CURRENT.lus}
 PASS: ./lus2lic {-ec -o /tmp/CURRENT.ec should_work/CURRENT.lus}
 PASS: ./ec2c {-o /tmp/CURRENT.c /tmp/CURRENT.ec}
@@ -581,7 +581,7 @@ FAIL: Try to compare lus2lic -exec and ecexe: ../utils/test_lus2lic_no_node shou
 PASS: ./lus2lic {-o /tmp/TIME_STABLE.lic should_work/TIME_STABLE.lus}
 PASS: ./lus2lic {-ec -o /tmp/TIME_STABLE.ec should_work/TIME_STABLE.lus}
 PASS: ./ec2c {-o /tmp/TIME_STABLE.c /tmp/TIME_STABLE.ec}
-FAIL: Try to compare lus2lic -exec and ecexe: ../utils/test_lus2lic_no_node should_work/TIME_STABLE.lus
+PASS: ../utils/test_lus2lic_no_node should_work/TIME_STABLE.lus
 PASS: ./lus2lic {-o /tmp/cpt.lic should_work/cpt.lus}
 PASS: ./lus2lic {-ec -o /tmp/cpt.ec should_work/cpt.lus}
 PASS: ./ec2c {-o /tmp/cpt.c /tmp/cpt.ec}
@@ -1039,8 +1039,10 @@ XPASS: Test bad programs (semantics): lus2lic {-o /tmp/bug.lic should_fail/seman
 
 		=== lus2lic Summary ===
 
-# of expected passes		875
-# of unexpected failures	81
+# of expected passes		878
+# of unexpected failures	80
 # of unexpected successes	12
 # of expected failures		37
-# of unresolved testcases	22
+# of unresolved testcases	20
+testcase ./lus2lic.tests/non-reg.exp completed in 417 seconds
+testcase ./lus2lic.tests/progression.exp completed in 0 seconds
diff --git a/test/lus2lic.time b/test/lus2lic.time
index f1ae924f..cbc6a242 100644
--- a/test/lus2lic.time
+++ b/test/lus2lic.time
@@ -1,2 +1,2 @@
-testcase ./lus2lic.tests/non-reg.exp completed in 313 seconds
-testcase ./lus2lic.tests/progression.exp completed in 2 seconds
+testcase ./lus2lic.tests/non-reg.exp completed in 417 seconds
+testcase ./lus2lic.tests/progression.exp completed in 0 seconds
diff --git a/test/should_work/ck5.lus b/test/should_work/ck5.lus
index 8f27f6c7..dd0273ae 100644
--- a/test/should_work/ck5.lus
+++ b/test/should_work/ck5.lus
@@ -1,6 +1,9 @@
 node ck5 (b,c: bool) returns (e: bool);
+var 
+ c_prime: bool;
 let
-	e = current edge(b when c);
+   c_prime = true fby c;
+	e = current (edge(b when c_prime));
 tel
 
 node edge(x:bool) returns (y: bool);
diff --git a/test/should_work/long_et_stupide_nom_de_noeud.lus b/test/should_work/long_et_stupide_nom_de_noeud.lus
index 62a6f852..01210ed5 100644
--- a/test/should_work/long_et_stupide_nom_de_noeud.lus
+++ b/test/should_work/long_et_stupide_nom_de_noeud.lus
@@ -11,5 +11,5 @@
 node long_et_stupide_nom_de_noeud(long_parametre:int)
 returns (long_et_stupide_nom_de_sortie:int);
 let
-	long_et_stupide_nom_de_sortie = long_parametre + pre(long_parametre);
+	long_et_stupide_nom_de_sortie = long_parametre + 0 fby long_parametre;
 tel
diff --git a/test/site.exp b/test/site.exp
index cfcb120b..a4d838a5 100644
--- a/test/site.exp
+++ b/test/site.exp
@@ -34,6 +34,10 @@ proc should_work { test_name command_line args } {
             set failed 1
             exp_continue
         }
+        "ERROR" {
+            set failed 1
+            exp_continue
+        }
         "oops: an internal" {
             set failed 1
             exp_continue
diff --git a/todo.org b/todo.org
index 8ddc98f1..28d567aa 100644
--- a/todo.org
+++ b/todo.org
@@ -194,8 +194,27 @@ l'appel depuis l'oracle au noeud à tester est mal typé...
 modifer
 file:~/lus2lic/utils/test_lus2lic_no_node
 
+* Performances
+Ceux là sont particulierement long (dont certains vraiment sans raison)
+en fait, quand ecexe se plante (oracle), il bloque tout le monde...
+
+# of unresolved testcases	20
+
+../utils/test_lus2lic_no_node should_work/left.lus 
+../utils/test_lus2lic_no_node should_work/assertion.lus
+../utils/test_lus2lic_no_node should_work/normal.lus
+../utils/test_lus2lic_no_node should_work/Gyroscope2.lus
+ ../utils/test_lus2lic_no_node should_work/ELMU.lus
+ ../utils/test_lus2lic_no_node should_work/aux.lus
+../utils/test_lus2lic_no_node should_work/X1.lus
+../utils/test_lus2lic_no_node should_work/alarme.lus
+../utils/test_lus2lic_no_node should_work/onlyroll2.lus
+../utils/test_lus2lic_no_node should_work/integrator.lus
+../utils/test_lus2lic_no_node should_work/over2.lus
+../utils/test_lus2lic_no_node should_work/left.lus
 
 * Divers
+
 ** TODO msg d'erreur un peu mavais sur ce programme
 
 #+begin_src lustre
diff --git a/todo.org_archive b/todo.org_archive
index 71f5b7cb..5b3236ba 100644
--- a/todo.org_archive
+++ b/todo.org_archive
@@ -752,6 +752,17 @@ Bon, finalement, j'oblige les gens a ecrire Lustre::gt et puis ca marre.
 	File "objlinux/lic2soc.ml", line 680, column 18
  when compiling lustre program should_work/morel3.lus
 -> It was due to a bad handling in slices apprearinf at the lhs od equations.
+* TODO pb avec -en sur programme avec des when
+   - State "TODO"       from ""           [2013-05-21 Tue 11:10]
+  :PROPERTIES:
+  :ARCHIVE_TIME: 2013-05-21 Tue 17:30
+  :ARCHIVE_FILE: ~/lus2lic/todo.org
+  :ARCHIVE_OLPATH: Divers
+  :ARCHIVE_CATEGORY: lv6
+  :ARCHIVE_TODO: TODO
+  :END:
+ ./lus2lic _ck5_oracle.lus -n ck5_oracle  -en
+
 
 
 
-- 
GitLab