From 35f3ffeca39e020729f84ab9d99f471c96d36854 Mon Sep 17 00:00:00 2001
From: Bouillaguet Quentin <quentin.bouillaguet@cea.fr>
Date: Thu, 12 Sep 2019 14:16:07 +0200
Subject: [PATCH] [Eva] Reorder + simplify some parts of trace domain

---
 src/plugins/value/domains/traces_domain.ml  | 420 +++++++++-----------
 src/plugins/value/domains/traces_domain.mli |   4 +
 2 files changed, 191 insertions(+), 233 deletions(-)

diff --git a/src/plugins/value/domains/traces_domain.ml b/src/plugins/value/domains/traces_domain.ml
index c300d052d27..b1ba21dd40c 100644
--- a/src/plugins/value/domains/traces_domain.ml
+++ b/src/plugins/value/domains/traces_domain.ml
@@ -36,15 +36,17 @@ open Cil_datatype
 module Node : sig
   include Datatype.S_with_collections
   val id: t -> int
-  val of_int: int -> t
+  val start: t
   val dumb: t
   val next: unit -> t
 end = struct
   include Datatype.Int
   let id x = x
-  let of_int x = x
-  let dumb = 0
-  module Counter = State_builder.Counter(struct let name = "Traces_domain.Edge.Counter" end)
+  let start = 0
+  let dumb = (- 1)
+  module Counter =
+    State_builder.Counter
+      (struct let name = "Value.Traces_domain.Node.Counter" end)
   let next () = Counter.next ()
 end
 
@@ -73,6 +75,8 @@ module rec Edge : sig
   val succ : t -> node
   val change_next : node -> t -> t
 
+  val has_transition : transition -> edge -> bool
+
   val pretty_list : t list Pretty_utils.formatter
 end = struct
   module T = struct
@@ -83,7 +87,7 @@ end = struct
 
     let reprs = [ {
         edge_trans = Msg "msg";
-        edge_dst = Node.dumb;
+        edge_dst = Node.start;
       }]
 
     let structural_descr = Structural_descr.t_abstract
@@ -105,6 +109,8 @@ end = struct
 
   include Datatype.Make_with_collections(T)
 
+  let has_transition t e = Transition.equal t e.edge_trans
+
   let pretty_list fmt l = Pretty_utils.pp_list ~sep:";@ " pretty fmt l
 
   let succ e = e.edge_dst
@@ -215,7 +221,8 @@ end = struct
 end
 
 module EdgeList = struct
-  include Datatype.List_with_collections(Edge)(struct let module_name = "Traces_domain.EdgeList" end)
+  include Datatype.List_with_collections(Edge)
+      (struct let module_name = "Value.Traces_domain.EdgeList" end)
   let pretty = Edge.pretty_list
   let pretty_debug = pretty
 end
@@ -275,46 +282,72 @@ module Graph = struct
     merge ~cache ~symmetric:false ~idempotent:false
       ~decide_both ~decide_left ~decide_right
 
-  let succs g (n : Node.t) = try find n g with Not_found -> []
+  let succs (n : Node.t) g = try find n g with Not_found -> []
+
+  let rec epsilon_path current stop g =
+    Node.equal current stop ||
+    begin
+      Node.compare current stop <= 0 &&
+      match find current g with
+      | exception Not_found -> false
+      | l ->
+        let exists = function
+          | { edge_dst; edge_trans = Msg _ } -> epsilon_path edge_dst stop g
+          | _ -> false
+        in
+        List.exists exists l
+    end
 end
 
-let is_included_graph = Graph.is_included
-
-let join_graph = Graph.join
-
-let diff_graph = Graph.diff
-
-let rec epsilon_path current stop g =
-  Node.equal current stop ||
-  begin
-    Node.compare current stop <= 0 &&
-    match Graph.find current g with
-    | exception Not_found -> false
-    | l ->
-      let exists = function
-        | { edge_dst; edge_trans = Msg _ } -> epsilon_path edge_dst stop g
-        | _ -> false
-      in
-      List.exists exists l
-  end
-
-
+let create_edge all_edges_ever_created current e =
+  let m = Graph.singleton current [e] in
+  let old = !all_edges_ever_created in
+  let new_ = Graph.join old m in
+  (* if not (Graph.equal old new_) then *)
+  (*   Format.printf "@[<hv>@[create_edge: %a ->@]@ %a@]@." *)
+  (*     Node.pretty current Edge.pretty e; *)
+  all_edges_ever_created := new_;
+  m
+
+let join_path ~all_edges_ever_created g c1 c2 =
+  if Graph.epsilon_path c1 c2 g then (c2, g)
+  else if Graph.epsilon_path c2 c1 g then (c1, g)
+  else
+    let t_join = Msg "join" in
+    let is_join e = Transition.equal e.edge_trans t_join in
+    let e =
+      let succs1 = Graph.succs c1 !all_edges_ever_created in
+      let succs2 = Graph.succs c2 !all_edges_ever_created in
+      let succs1 = List.filter is_join succs1 in
+      let find s1 = List.exists (Edge.equal s1) succs2 in
+      begin match List.find find succs1 with
+        | exception Not_found ->
+          { edge_dst = Node.next () ; edge_trans = t_join }
+        | m ->
+          { edge_dst = Edge.succ m ; edge_trans = t_join }
+      end
+    in
+    let m1 = create_edge all_edges_ever_created c1 e in
+    let m2 = create_edge all_edges_ever_created c2 e in
+    let g = Graph.join (Graph.join m1 g) m2 in
+    (e.edge_dst, g)
 
-(* A loop
-   .*)
+(* A loop .*)
 type loops =
   | Base of Node.t * Graph.t (* current last *)
   | OpenLoop of Cil_types.stmt * Node.t (* start node *) * Graph.t (* last iteration *) * Node.t (** current *) * Graph.t * loops
   | UnrollLoop of Cil_types.stmt * loops
 
 module Loops = struct
+  type t = loops
+
   let rec is_included l1 l2 = match l1, l2 with
     | Base _, (OpenLoop _ | UnrollLoop _)
     | (OpenLoop _ | UnrollLoop _), Base _ ->
       (* not in the same number of loops *)
       false
     | Base (c1,_), Base (c2,g2) ->
-      epsilon_path c1 c2 g2
+      Graph.epsilon_path c1 c2 g2
     | (OpenLoop(stmt1,_,_,_,_,_) | UnrollLoop(stmt1,_)),
       (OpenLoop(stmt2,_,_,_,_,_) | UnrollLoop(stmt2,_)) when not (Stmt.equal stmt1 stmt2) ->
       (* not same loop *)
@@ -327,7 +360,7 @@ module Loops = struct
       is_included l1 l2 &&
       Graph.is_included last1 last2 &&
       Graph.is_included g1 g2' &&
-      epsilon_path c1 c2 g2'
+      Graph.epsilon_path c1 c2 g2'
     | UnrollLoop(_,l1), UnrollLoop(_,l2) ->
       is_included l1 l2
     | OpenLoop(_,_,_,_,_,_), UnrollLoop(_,_) ->
@@ -414,11 +447,59 @@ module Loops = struct
       Format.fprintf fmt "@[<hv>@[unroll(%a)@]@ %a"
         Stmt.pretty_sid stmt
         pretty l
+
+  let rec hash = function
+    | Base (c,g) ->
+      Hashtbl.seeded_hash (Hashtbl.seeded_hash 1 (Graph.hash g)) (Node.hash c)
+    | OpenLoop(stmt,s,last,c,g,l) ->
+      Hashtbl.seeded_hash 2
+        (Stmt.hash stmt, Node.hash s, Graph.hash last, Node.hash c,
+         Graph.hash g, hash l)
+    | UnrollLoop(stmt,l) ->
+      Hashtbl.seeded_hash 2
+        (Stmt.hash stmt, hash l)
 end
 
-let is_included_loops = Loops.is_included
+let rec join_loops ~all_edges_ever_created l1 l2 =
+  match l1, l2 with
+  | Base _, (OpenLoop _ | UnrollLoop _) | (OpenLoop _ | UnrollLoop _), Base _ ->
+    (* not in the same number of loops *)
+    `Top
+  | Base (c1,g1), Base (c2,g2) ->
+    let g = Graph.join g1 g2 in
+    let (n,g) = join_path ~all_edges_ever_created g c1 c2 in
+    `Value( Base (n, g))
+  | (OpenLoop(stmt1,_,_,_,_,_) | UnrollLoop(stmt1,_)),
+    (OpenLoop(stmt2,_,_,_,_,_) | UnrollLoop(stmt2,_)) when not (Stmt.equal stmt1 stmt2) ->
+    (* not same loop *)
+    `Top
+  | OpenLoop(stmt1,s1,last1,c1,g1,l1), OpenLoop(_,s2,_,_,_,l2) when not (Node.equal s1 s2) ->
+    (* not entered in the loop at the same time, take arbitrarily one of them *)
+    begin match join_loops ~all_edges_ever_created l1 l2 with
+      | `Top -> `Top
+      | `Value(l) -> `Value(OpenLoop(stmt1,s1,last1,c1,g1,l))
+    end
+  | OpenLoop(stmt,s,last1,c1,g1,l1), OpenLoop(_,_,last2,c2,g2,l2) ->
+    begin match join_loops ~all_edges_ever_created l1 l2 with
+      | `Top -> `Top
+      | `Value(l) ->
+        let last = Graph.join last1 last2 in
+        let g = Graph.join g1 g2 in
+        let (n,g) = join_path ~all_edges_ever_created g c1 c2 in
+        `Value(OpenLoop(stmt,s,last,n,g,l))
+    end
+  | UnrollLoop(stmt,l1), UnrollLoop(_,l2) ->
+    begin match join_loops ~all_edges_ever_created l1 l2 with
+      | `Top -> `Top
+      | `Value l -> `Value (UnrollLoop(stmt,l))
+    end
+  | (OpenLoop(stmt,s,last,c,g,l1), UnrollLoop(_,l2))
+  | (UnrollLoop(_,l2), OpenLoop(stmt,s,last,c,g,l1)) ->
+    begin match join_loops ~all_edges_ever_created l1 l2 with
+      | `Top -> `Top
+      | `Value l -> `Value (OpenLoop(stmt,s,last,c,g,l))
+    end
 
-let diff_loops = Loops.diff
 
 type state = { start : Node.t; current : loops;
                call_declared_function: bool;
@@ -438,18 +519,14 @@ let entry_formals s = s.main_formals
 module Traces = struct
 
   (** impossible for normal values start must be bigger than current *)
-  let new_empty () = { start = Node.of_int 0; current = Base (Node.of_int 0, Graph.empty);
+  let new_empty () = { start = Node.start; current = Base (Node.start, Graph.empty);
                        call_declared_function = false;
                        globals = []; main_formals = [];
                        all_edges_ever_created = ref Graph.empty;
                        all_loop_start = Stmt.Hashtbl.create 10;
                      }
   let empty = new_empty ()
-  let top = { (new_empty ()) with current = Base (Node.of_int (-1), Graph.empty); }
-
-  let compare_loops = Loops.compare
-
-  let pretty_loops = Loops.pretty
+  let top = { (new_empty ()) with current = Base (Node.dumb, Graph.empty); }
 
   (* Frama-C "datatype" for type [inout] *)
   include Datatype.Make_with_collections(struct
@@ -472,7 +549,7 @@ module Traces = struct
       let compare m1 m2 =
         let c = Node.compare m1.start m2.start in
         if c <> 0 then c else
-          let c = compare_loops m1.current m2.current in
+          let c = Loops.compare m1.current m2.current in
           if c <> 0 then c else
             let c = Datatype.Bool.compare m1.call_declared_function m2.call_declared_function in
             if c <> 0 then c else
@@ -487,19 +564,10 @@ module Traces = struct
             Node.pretty m.start
             (Pretty_utils.pp_list ~sep:",@ " Varinfo.pretty) m.globals
             (Pretty_utils.pp_list ~sep:",@ " Varinfo.pretty) m.main_formals
-            pretty_loops m.current
-
-      let rec hash_loops = function
-        | Base (c,g) -> Hashtbl.seeded_hash (Hashtbl.seeded_hash 1 (Graph.hash g)) (Node.hash c)
-        | OpenLoop(stmt,s,last,c,g,l) ->
-          Hashtbl.seeded_hash 2
-            (Stmt.hash stmt, Node.hash s, Graph.hash last, Node.hash c, Graph.hash g, hash_loops l)
-        | UnrollLoop(stmt,l) ->
-          Hashtbl.seeded_hash 2
-            (Stmt.hash stmt, hash_loops l)
+            Loops.pretty m.current
 
       let hash m =
-        Hashtbl.seeded_hash (Node.hash m.start) (hash_loops m.current)
+        Hashtbl.seeded_hash (Node.hash m.start) (Loops.hash m.current)
 
       let copy c = c
 
@@ -509,25 +577,17 @@ module Traces = struct
     if m == top then `Top
     else `Other m
 
-  let move_to c g state =
+  let map_base f state =
     let rec aux = function
-      | Base (_,_) -> Base (c,g)
-      | OpenLoop(stmt,s,last,_,_,l) ->
-        OpenLoop(stmt,s,last,c,g,l)
-      | UnrollLoop(stmt,l) ->
-        UnrollLoop(stmt,aux l)
-    in
-    let current = aux state.current in
-    {state with current}
+      | Base (c, g) ->
+        let c, g = f (c, g) in Base (c, g)
+      | OpenLoop (stmt, s, last, c, g, l) ->
+        let c, g = f (c, g) in OpenLoop(stmt, s, last, c, g, l)
+      | UnrollLoop (stmt, l) -> UnrollLoop (stmt, aux l)
+    in { state with current = aux state.current }
 
-  let replace_to c state =
-    let rec aux = function
-      | Base (_,g) -> Base (c,g)
-      | OpenLoop(stmt,s,last,_,g,l) ->
-        OpenLoop(stmt,s,last,c,g,l)
-      | UnrollLoop(stmt,l) -> UnrollLoop(stmt,aux l) in
-    let current = aux state.current in
-    {state with current}
+  let move_to c g = map_base (fun _ -> c, g)
+  let replace_to c = map_base (fun (_, g) -> c, g)
 
   let get_current state =
     let rec aux = function
@@ -537,81 +597,48 @@ module Traces = struct
         aux l in
     aux state.current
 
-  let find_succs current g =
-    match Graph.find current g with
-    | exception Not_found -> []
-    | l -> l
-
-  let change_next = Edge.change_next
-
-  let same_edge edge edge' =
-    Transition.equal edge.edge_trans edge'.edge_trans
-
-  let create_edge all_edges_ever_created current e =
-    let m = Graph.singleton current [e] in
-    let old = !all_edges_ever_created in
-    let new_ = join_graph old m in
-    (* if not (Graph.equal old new_) then *)
-    (*   Format.printf "@[<hv>@[create_edge: %a ->@]@ %a@]@." *)
-    (*     Node.pretty current Edge.pretty e; *)
-    all_edges_ever_created := new_;
-    m
-
-  let get_node = Edge.succ
-
-  let add_edge_aux c edge =
-    let (current,graph) = get_current c in
-    let reusable =
-      let succs = find_succs current !(c.all_edges_ever_created) in
-      List.find_opt (same_edge edge) succs
-    in
-    let (n,e) = match reusable with
-      | Some e ->
-        (** reuse an edge from last *)
-        let n = get_node e in
-        (n,e)
-      | None ->
-        (** create a new edge *)
-        let n = Node.next () in
-        let e = change_next n edge in
-        (n,e)
+  let add_trans_aux state t =
+    let add_edge (current, graph) =
+      let e =
+        (** try to reuse an edge from the pool *)
+        let succs = Graph.succs current !(state.all_edges_ever_created) in
+        try List.find (Edge.has_transition t) succs
+        with Not_found ->
+          (** create a new edge *)
+          { edge_trans = t; edge_dst = Node.next () }
+      in
+      let n = e.edge_dst in
+      let m = create_edge state.all_edges_ever_created current e in
+      let graph = Graph.join m graph in
+      (n, graph)
     in
-    let m = create_edge c.all_edges_ever_created current e in
-    let graph = join_graph m graph in
-    move_to n graph c
+    map_base add_edge state
 
-  let add_edge c e =
+  let add_trans c t =
     if c == top then c
     else if c.call_declared_function then c (** forget intermediary state *)
     else
       let c = if c == empty then new_empty () else c in
-      add_edge_aux c e
-
-  let add_edge_tmp c dest trans =
-    if c == top then c
-    else if c.call_declared_function then c (** forget intermediary state *)
-    else
-      let c = if c == empty then new_empty () else c in
-      add_edge_aux c { edge_dst = dest; edge_trans = trans }
+      add_trans_aux c t
 
   let copy_edges s old_current_node g state =
     let cache = Node.Hashtbl.create 10 in
     let rec aux old_current_node state =
       let current_node = (fst (get_current state)) in
-      let succs = find_succs old_current_node g in
+      let succs = Graph.succs old_current_node g in
       let fold state e =
-        let next_old = get_node e in
+        let next_old = Edge.succ e in
         let state = match Node.Hashtbl.find cache next_old with
           | exception Not_found ->
-            let state = add_edge state e in
+            let state = add_trans state e.edge_trans in
             Node.Hashtbl.add cache next_old (fst (get_current state));
             let state = aux next_old state in
             replace_to current_node state
           | next ->
             let (_,g) = get_current state in
-            let e = change_next next e in
+            let e = Edge.change_next next e in
             let m = create_edge state.all_edges_ever_created current_node e in
-            let g = join_graph m g in
+            let g = Graph.join m g in
             move_to next g state
         in
         replace_to current_node state
@@ -626,7 +653,7 @@ module Traces = struct
     (* start is the same *)
     let r =
       c1.start = c2.start &&
-      is_included_loops c1.current c2.current in
+      Loops.is_included c1.current c2.current in
     if not r && compare c1 c2 = 0 then
       Printf.printf "bad is_included@.";
     r
@@ -637,75 +664,6 @@ module Traces = struct
     c1.main_formals != c2.main_formals ||
     c1.all_edges_ever_created != c2.all_edges_ever_created
 
-  let join_path ~all_edges_ever_created graph c1 c2 =
-    if epsilon_path c1 c2 graph
-    then (c2, graph)
-    else if epsilon_path c2 c1 graph
-    then (c1, graph)
-    else
-      let m = { edge_dst = Node.dumb; edge_trans = Msg("join") } in (* TODO *)
-      let reusable =
-        let succs1 = find_succs c1 !all_edges_ever_created in
-        let succs1 = List.filter (same_edge m) succs1 in
-        let succs2 = find_succs c2 !all_edges_ever_created in
-        let find s1 = List.exists (Edge.equal s1) succs2 in
-        List.find_opt find succs1
-      in
-      let (n,m) = match reusable with
-        | None ->
-          let n = Node.next () in
-          let m = change_next n m in
-          (n,m)
-        | Some m ->
-          (** reuse an edge from last *)
-          let n = get_node m in
-          (n,m)
-      in
-      let m1 = create_edge all_edges_ever_created c1 m in
-      let m2 = create_edge all_edges_ever_created c2 m in
-      let g = join_graph (join_graph m1 graph) m2 in
-      ( n, g)
-
-  let rec join_loops ~all_edges_ever_created l1 l2 =
-    match l1, l2 with
-    | Base _, (OpenLoop _ | UnrollLoop _) | (OpenLoop _ | UnrollLoop _), Base _ ->
-      (* not in the same number of loops *)
-      `Top
-    | Base (c1,g1), Base (c2,g2) ->
-      let g = join_graph g1 g2 in
-      let (n,g) = join_path ~all_edges_ever_created g c1 c2 in
-      `Value( Base (n, g))
-    | (OpenLoop(stmt1,_,_,_,_,_) | UnrollLoop(stmt1,_)),
-      (OpenLoop(stmt2,_,_,_,_,_) | UnrollLoop(stmt2,_)) when not (Stmt.equal stmt1 stmt2) ->
-      (* not same loop *)
-      `Top
-    | OpenLoop(stmt1,s1,last1,c1,g1,l1), OpenLoop(_,s2,_,_,_,l2) when not (Node.equal s1 s2) ->
-      (* not entered in the loop at the same time, take arbitrarily one of them *)
-      begin match join_loops ~all_edges_ever_created l1 l2 with
-        | `Top -> `Top
-        | `Value(l) -> `Value(OpenLoop(stmt1,s1,last1,c1,g1,l))
-      end
-    | OpenLoop(stmt,s,last1,c1,g1,l1), OpenLoop(_,_,last2,c2,g2,l2) ->
-      begin match join_loops ~all_edges_ever_created l1 l2 with
-        | `Top -> `Top
-        | `Value(l) ->
-          let last = join_graph last1 last2 in
-          let g = join_graph g1 g2 in
-          let (n,g) = join_path ~all_edges_ever_created g c1 c2 in
-          `Value(OpenLoop(stmt,s,last,n,g,l))
-      end
-    | UnrollLoop(stmt,l1), UnrollLoop(_,l2) ->
-      begin match join_loops ~all_edges_ever_created l1 l2 with
-        | `Top -> `Top
-        | `Value l -> `Value (UnrollLoop(stmt,l))
-      end
-    | (OpenLoop(stmt,s,last,c,g,l1), UnrollLoop(_,l2))
-    | (UnrollLoop(_,l2), OpenLoop(stmt,s,last,c,g,l1)) ->
-      begin match join_loops ~all_edges_ever_created l1 l2 with
-        | `Top -> `Top
-        | `Value l -> `Value (OpenLoop(stmt,s,last,c,g,l))
-      end
-
   let join c1 c2 =
     if c1.call_declared_function <> c2.call_declared_function
     then
@@ -727,7 +685,7 @@ module Traces = struct
 
   let add_loop stmt state =
     let (n,g) = get_current state in
-    let succs = find_succs n g in
+    let succs = Graph.succs n g in
     let rec find_same_loop = function
       | [] ->
         Stmt.Hashtbl.memo state.all_loop_start stmt (fun _ -> Node.next (),Graph.empty)
@@ -741,32 +699,31 @@ module Traces = struct
     let current = OpenLoop(stmt,s,last,s,Graph.empty,state.current) in
     { state with current }
 
-
   let widen _ stmt' c1 c2 =
     if false then
       begin
-        if compare_loops c1.current c2.current = 0
+        if Loops.compare c1.current c2.current = 0
         then
           Format.printf "@[<hv 2>@[widen %a: same loops, states are%s equal @]@]@."
             Stmt.pretty_sid stmt' (if compare c1 c2 = 0 then "" else " not")
         else
-          let c1' = diff_loops c1.current c2.current in
-          let c2' = diff_loops c2.current c1.current in
-          if (Bottom.compare compare_loops) c1' c2' = 0 then
+          let c1' = Loops.diff c1.current c2.current in
+          let c2' = Loops.diff c2.current c1.current in
+          if (Bottom.compare Loops.compare) c1' c2' = 0 then
             Format.printf "@[<hv 2>@[widen %a diff equal:@]@ @[<hv 1>@[c1:@]@ %a@]@ @[<hv 1>@[c2:@]@ %a@]@]@."
               Stmt.pretty_sid stmt'
-              pretty_loops c1.current
-              pretty_loops c2.current
+              Loops.pretty c1.current
+              Loops.pretty c2.current
 
           else
             Format.printf "@[<hv 2>@[widen %a diff different:@]@ @[<hv 1>@[c1':@]@ %a@]@ @[<hv 1>@[c2':@]@ %a@]@]@."
               Stmt.pretty_sid stmt'
-              (Bottom.pretty pretty_loops) c1'
-              (Bottom.pretty pretty_loops) c2'
+              (Bottom.pretty Loops.pretty) c1'
+              (Bottom.pretty Loops.pretty) c2'
       end;
     if false then
       begin
-        if compare_loops c1.current c2.current = 0
+        if Loops.compare c1.current c2.current = 0
         then
           Format.printf "@[<hv 2>@[widen %a: same loops, states are%s equal @]@]@."
             Stmt.pretty_sid stmt' (if compare c1 c2 = 0 then "" else " not")
@@ -786,7 +743,6 @@ module Traces = struct
         add_loop stmt' {c2 with current = l}
     end
 
-
   let narrow _c1 c2 = `Value c2
 end
 
@@ -804,7 +760,7 @@ module GraphDot = OCamlGraph.Graphviz.Dot(struct
         | Head (src,loops,_,_) -> {node=src;loops}
         | Back (_,loops,src) -> {node=src;loops}
       let dst = function
-        | Usual (_,edge,loops) -> {node=Traces.get_node edge;loops}
+        | Usual (_,edge,loops) -> {node=Edge.succ edge;loops}
         | Head (_,_,s,loops) -> {node=s;loops}
         | Back (dst,loops,_) -> {node=dst;loops}
     end
@@ -870,7 +826,7 @@ let rec complete_graph (graph:Graph.t) =
   Graph.fold (fun k l graph ->
       let graph, l =
         Extlib.fold_map (fun graph e ->
-            let m = Graph.singleton (Traces.get_node e) [] in
+            let m = Graph.singleton (Edge.succ e) [] in
             let e = match e.edge_trans with
               | Assign (_,_,_)
               | Assume (_,_)
@@ -883,10 +839,10 @@ let rec complete_graph (graph:Graph.t) =
                 let g = Graph.shape (complete_graph (Graph.from_shape_id g)) in
                 { edge_dst = n; edge_trans = Loop(stmt,s,g) }
             in
-            join_graph graph m, e)
+            Graph.join graph m, e)
           graph l
       in
-      join_graph graph (Graph.singleton k l)
+      Graph.join graph (Graph.singleton k l)
     ) graph Graph.empty
 
 
@@ -924,22 +880,22 @@ module Internal = struct
 
     let assign _ki lv e _v _valuation state =
       let trans = Assign (lv.Eval.lval, lv.Eval.ltyp, e) in
-      `Value (Traces.add_edge_tmp state Node.dumb trans)
+      `Value (Traces.add_trans state trans)
 
     let assume _stmt e pos _valuation state =
       let trans = Assume (e, pos) in
-      `Value (Traces.add_edge_tmp state Node.dumb trans)
+      `Value (Traces.add_trans state trans)
 
     let start_call _stmt call _valuation state =
       if Kernel_function.is_definition call.Eval.kf
       then
         let msg = Format.asprintf "start_call: %s (%b)" (Kernel_function.get_name call.Eval.kf)
             (Kernel_function.is_definition call.Eval.kf) in
-        let state = Traces.add_edge_tmp state Node.dumb (Msg msg) in
+        let state = Traces.add_trans state (Msg msg) in
         let formals = List.map (fun arg -> arg.Eval.formal) call.Eval.arguments in
-        let state = Traces.add_edge_tmp state Node.dumb (EnterScope formals) in
+        let state = Traces.add_trans state (EnterScope formals) in
         let state = List.fold_left (fun state arg ->
-            Traces.add_edge_tmp state Node.dumb
+            Traces.add_trans state
               (Assign (Cil.var arg.Eval.formal,
                        arg.Eval.formal.Cil_types.vtype,
                        arg.Eval.concrete))) state call.Eval.arguments in
@@ -948,10 +904,10 @@ module Internal = struct
         (** enter the scope of the dumb result variable *)
         let var = call.Eval.return in
         let state = match var with
-          | Some var -> Traces.add_edge_tmp state Node.dumb (EnterScope [var])
+          | Some var -> Traces.add_trans state (EnterScope [var])
           | None -> state in
         let exps = List.map (fun arg -> arg.Eval.concrete) call.Eval.arguments in
-        let state = Traces.add_edge_tmp state Node.dumb
+        let state = Traces.add_trans state
             (CallDeclared (call.Eval.kf, exps, Extlib.opt_map Cil.var var))
         in `Value {state with call_declared_function = true}
 
@@ -960,7 +916,7 @@ module Internal = struct
       then `Value {post with call_declared_function = false}
       else
         let msg = Format.asprintf "finalize_call: %s" (Kernel_function.get_name call.Eval.kf) in
-        let state = Traces.add_edge_tmp post Node.dumb (Msg msg) in
+        let state = Traces.add_trans post (Msg msg) in
         `Value state
 
     let update _valuation state = `Value state
@@ -983,7 +939,7 @@ module Internal = struct
   let introduce_globals vars state =
     {state with globals = vars @ state.globals}
   let initialize_variable lv _ ~initialized:_ _ state =
-    Traces.add_edge_tmp state Node.dumb (Msg(Format.asprintf "initialize variable: %a" Printer.pp_lval lv ))
+    Traces.add_trans state (Msg(Format.asprintf "initialize variable: %a" Printer.pp_lval lv ))
   let initialize_variable_using_type init_kind varinfo state =
     let state =
       match init_kind with
@@ -999,11 +955,11 @@ module Internal = struct
         init_kind
         Varinfo.pretty varinfo
     in
-    Traces.add_edge_tmp state Node.dumb (Msg msg)
+    Traces.add_trans state (Msg msg)
 
   (* TODO *)
   let logic_assign _assign _location ~pre:_ state =
-    Traces.add_edge_tmp state Node.dumb (Msg "logic assign")
+    Traces.add_trans state (Msg "logic assign")
 
   (* Logic *)
   let evaluate_predicate _ _ _ = Alarmset.Unknown
@@ -1020,7 +976,7 @@ module Internal = struct
     `Value (loc, value)
 
   let enter_loop stmt state =
-    let state = Traces.add_edge_tmp state Node.dumb (Msg "enter_loop") in
+    let state = Traces.add_trans state (Msg "enter_loop") in
     let state = if not (Value_parameters.TracesUnrollLoop.get ())
       then Traces.add_loop stmt state
       else { state with current = UnrollLoop(stmt,state.current) } in
@@ -1031,10 +987,10 @@ module Internal = struct
     | Base _ -> assert false
     | UnrollLoop(_,_) -> state
     | OpenLoop(stmt,s,last,_,g,l) ->
-      let last = join_graph last g in
+      let last = Graph.join last g in
       let last = if Value_parameters.TracesUnifyLoop.get () then
           let s',old_last = Stmt.Hashtbl.find state.all_loop_start stmt in
-          let last = join_graph last old_last in
+          let last = Graph.join last old_last in
           assert (Node.equal s s');
           Stmt.Hashtbl.add state.all_loop_start stmt (s,last);
           last
@@ -1042,7 +998,7 @@ module Internal = struct
       in
       let current = OpenLoop(stmt,s,last,s,Graph.empty,l) in
       let state = { state with current } in
-      (* Traces.add_edge state (Msg(Node.dumb,"incr_loop_counter")) *)
+      (* Traces.add_trans state (Msg("incr_loop_counter")) *)
       state
 
   let leave_loop stmt' state =
@@ -1054,22 +1010,20 @@ module Internal = struct
       let state = { state with current } in
       let last = if Value_parameters.TracesUnifyLoop.get () then
           let s',old_last = Stmt.Hashtbl.find state.all_loop_start stmt in
-          let last = join_graph last old_last in
+          let last = Graph.join last old_last in
           assert (Node.equal s s');
           Stmt.Hashtbl.add state.all_loop_start stmt (s,last);
           last
         else last
       in
       let state = if Graph.is_empty last then state
-        else Traces.add_edge_tmp state Node.dumb (Loop(stmt,s,Graph.shape last)) in
+        else Traces.add_trans state (Loop(stmt,s,Graph.shape last)) in
       let state = Traces.copy_edges s old_current_node g state in
-      Traces.add_edge_tmp state Node.dumb (Msg "leave_loop")
+      Traces.add_trans state (Msg "leave_loop")
 
 
-  let enter_scope _kf vars state =
-    Traces.add_edge_tmp state Node.dumb (EnterScope vars)
-  let leave_scope _kf vars state =
-    Traces.add_edge_tmp state Node.dumb (LeaveScope vars)
+  let enter_scope _kf vars state = Traces.add_trans state (EnterScope vars)
+  let leave_scope _kf vars state = Traces.add_trans state (LeaveScope vars)
 
   let reduce_further _state _expr _value = [] (*Nothing intelligent to suggest*)
 
@@ -1174,7 +1128,7 @@ let rec stmts_of_cfg cfg current var_map locals return_exp acc =
       | Loop (_,s,g) ->
         let g = Graph.from_shape (fun _ v -> v) g in
         let is_while =
-          match Traces.find_succs s g, Traces.find_succs n cfg with
+          match Graph.succs s g, Graph.succs n cfg with
           | [{ edge_dst = n1'; edge_trans = Assume(exp1,b1) }],
             [{ edge_dst = n2'; edge_trans = Assume(exp2,b2) }]
             when ExpStructEq.equal exp1 exp2 && b1 != b2 ->
diff --git a/src/plugins/value/domains/traces_domain.mli b/src/plugins/value/domains/traces_domain.mli
index cebaa9298b6..73196817e42 100644
--- a/src/plugins/value/domains/traces_domain.mli
+++ b/src/plugins/value/domains/traces_domain.mli
@@ -60,6 +60,10 @@ type loops =
   | OpenLoop of Cil_types.stmt * Node.t (* start node *) * Graph.t (* last iteration *) * Node.t (** current *) * Graph.t * loops
   | UnrollLoop of Cil_types.stmt * loops
 
+module Loops : sig
+  type t = loops
+end
+
 type state
 
 val start: state -> Node.t
-- 
GitLab