diff --git a/src/solver.ml b/src/solver.ml
index 2c552813428a3c5d1efe5acd426380d3cf10713d..c01b8722593207464c2fb7e49c2dc7f9525c2fb4 100644
--- a/src/solver.ml
+++ b/src/solver.ml
@@ -264,6 +264,24 @@ module type Dem' = sig
 
 end
 
+module type DemFast' = sig
+  type delayed
+  type d
+
+  module Data: sig
+    type t = d
+    val print: Format.formatter -> t -> unit
+  end
+
+  val key: (unit, Data.t) dem
+
+  (** not immediate and never killed *)
+  val throttle: int (** todo int ref? *)
+    (** number of time run in a row *)
+  val wakeup: delayed -> Data.t Events.Fired.event -> unit
+
+end
+
 module DecTag = DInt
 
 module type DomTable' = sig
@@ -311,12 +329,15 @@ module type DemTable' = sig
 
 end
 
+
+type ('k,'d,'delayed) demtable' =
+| DemT': (module DemTable' with type delayed = 'delayed
+                           and type dk = 'k
+                           and type dd = 'd) -> ('k,'d,'delayed) demtable'
+| DemFastT': 'd Events.Fired.event list  -> (unit,'d,'delayed) demtable'
+
 module VDemTable = Dem.MkVector
-  (struct type ('k,'d,'delayed) t =
-            (module DemTable' with type delayed = 'delayed
-                               and type dk = 'k
-                               and type dd = 'd)
-   end)
+  (struct type ('k,'d,'delayed) t = ('k,'d,'delayed) demtable' end)
 
 type decdone  =
 | NoDec
@@ -355,8 +376,15 @@ and delayed_t = {
   todo_ext_action : action_ext Queue.t;
   sched_daemon : daemon_key -> unit;
   sched_decision : decision -> unit;
+  (** dem fast *)
+  mutable dem_fast_todo : dem_fast_todo;
 }
 
+and dem_fast_todo =
+| DemFastTodo:
+    (unit,'d) dem * int ref * 'd Events.Fired.event Queue.t -> dem_fast_todo
+| DemFastNone
+
 and action_dom =
 | SetDom   : pexp * 'a dom * Cl.t * 'a -> action_dom
 | UnsetDom : pexp * 'a dom * Cl.t -> action_dom
@@ -397,7 +425,8 @@ let mk_dumb_delayed () = { env = Obj.magic 0;
                            sched_daemon   = (fun _ -> (assert false : unit));
                            (* should never be called *)
                            sched_decision = (fun _ -> (assert false : unit));
-                         (* should never be called *)
+                           (* should never be called *)
+                           dem_fast_todo = DemFastNone;
                          }
 
 let dumb_delayed = mk_dumb_delayed ()
@@ -436,6 +465,7 @@ let new_handler t =
 module type Dom = Dom' with type delayed := delayed_t
 module type Sem = Sem' with type delayed := delayed_t
 module type Dem = Dem' with type delayed := delayed_t
+module type DemFast = DemFast' with type delayed := delayed_t
 
 module VDom = Dom.MkVector
   (struct type ('a,'unedeed) t =
@@ -445,11 +475,13 @@ module VSem = Sem.MkVector
   (struct type ('a,'unedeed) t =
             (module Sem with type t = 'a)
    end)
+
+type ('k,'d) demmod =
+| Dem: (module Dem with type k = 'k and type d = 'd) -> ('k,'d) demmod
+| DemFast: (module DemFast with type d = 'd)       -> (unit,'d) demmod
+
 module VDem = Dem.MkVector
-  (struct type ('k,'d,'unedeed) t =
-            (module Dem with type k = 'k
-                         and type d = 'd)
-   end)
+  (struct type ('k,'d,'unedeed) t = ('k,'d) demmod end)
 
 let defined_dom : unit VDom.t = VDom.create 8
 let defined_sem : unit VSem.t = VSem.create 8
@@ -484,7 +516,19 @@ module RegisterDem (D:Dem) = struct
     assert (if not (VDem.is_uninitialized defined_dem D.key)
       then raise AlreadyRegisteredKey else true);
     let dem = (module D: Dem with type k = D.k and type d = D.d) in
-    VDem.set defined_dem D.key dem
+    VDem.set defined_dem D.key (Dem dem)
+
+end
+
+module RegisterDemFast (D:DemFast) = struct
+
+  let () =
+    assert (D.throttle > 0);
+    VDem.inc_size D.key defined_dem;
+    assert (if not (VDem.is_uninitialized defined_dem D.key)
+      then raise AlreadyRegisteredKey else true);
+    let dem = (module D: DemFast with type d = D.d) in
+    VDem.set defined_dem D.key (DemFast dem)
 
 end
 
@@ -498,13 +542,12 @@ let get_sem k =
     then raise UnregisteredKey else true);
   VSem.get defined_sem k
 
-let get_dem : ('k,'d) dem -> (module Dem with type k = 'k and type d = 'd)
+let get_dem : ('k,'d) dem -> ('k,'d) demmod
   = fun (k: ('k,'d) dem) ->
     assert (if VDem.is_uninitialized defined_dem k
       then raise UnregisteredKey else true);
     VDem.get defined_dem k
 
-
 let print_dom (type a) (k : a dom) fmt s =
   let dom = get_dom k in
   let module D = (val dom : Dom with type t = a) in
@@ -519,15 +562,24 @@ let () = Print.psem.Print.psem <- print_sem
 
 let print_dem_key (type k) (type d) (k : (k,d) dem) fmt s =
   let dem = get_dem k in
-  let module S = (val dem : Dem with type k = k and type d = d) in
-  S.Key.print fmt s
+  match dem with
+  | Dem dem ->
+    let module S = (val dem : Dem with type k = k and type d = d) in
+    S.Key.print fmt s
+  | DemFast _ ->
+    DUnit.print fmt ( () : k)
 
 let () = Print.pdem_key.Print.pdem_key <- print_dem_key
 
 let print_dem_data (type k) (type d) (k : (k,d) dem) fmt s =
   let dem = get_dem k in
-  let module S = (val dem : Dem with type k = k and type d = d) in
-  S.Data.print fmt s
+  match dem with
+  | Dem dem ->
+    let module S = (val dem : Dem with type k = k and type d = d) in
+    S.Data.print fmt s
+  | DemFast dem ->
+    let module S = (val dem : DemFast with type d = d) in
+    S.Data.print fmt s
 
 let () = Print.pdem_data.Print.pdem_data <- print_dem_data
 
@@ -535,7 +587,6 @@ let () = Print.pdem_data.Print.pdem_data <- print_dem_data
 
 module type DomTable = DomTable' with type delayed = delayed_t
 module type SemTable = SemTable' with type delayed = delayed_t
-module type DemTable = DemTable' with type delayed = delayed_t
 
 let get_table_dom : t -> 'a dom -> (module DomTable with type dt = 'a)
   = fun (type a) t k ->
@@ -578,27 +629,26 @@ let get_table_sem : t -> 'a sem -> (module SemTable with type dt = 'a)
         : SemTable' with type dt = a and type delayed = delayed_t)
         : SemTable with type dt = a)
 
-let get_table_dem : t -> ('k,'d) dem -> (module DemTable with type dk = 'k
-                                                          and type dd = 'd)
-  = fun (type k) (type d) t k ->
+let get_table_dem : type k d. t -> (k,d) dem -> (k,d,delayed_t) demtable'
+  = fun t k ->
   assert (if VDem.is_uninitialized defined_dem k
     then raise UnregisteredKey else true);
   VDemTable.inc_size k t.dem;
   if VDemTable.is_uninitialized t.dem k then
     let dem = get_dem k in
-    let module DemTable = struct
-      type delayed = delayed_t
-      type dk = k
-      type dd = d
-      module D = (val dem : Dem with type k = dk and type d = dd)
-      let state = D.Key.M.empty
-    end in
-    (module DemTable : DemTable with type dk = k and type dd = d)
+    match dem with
+    | Dem dem ->
+      let module DemTable = struct
+        type delayed = delayed_t
+        type dk = k
+        type dd = d
+        module D = (val dem : Dem with type k = dk and type d = dd)
+        let state = D.Key.M.empty
+      end in
+      DemT' (module DemTable)
+    | DemFast _ -> DemFastT' []
   else
-    (module (val VDemTable.get t.dem k
-        : DemTable' with type dk = k and type dd = d
-                     and type delayed = delayed_t)
-        : DemTable  with type dk = k and type dd = d)
+    VDemTable.get t.dem k
 
 
   exception NotNormalized
@@ -784,11 +834,14 @@ module Delayed = struct
       List.iter (fun wevent ->
         match wevent with
         | Events.Wait.Event (dem,k,d) ->
-          let f (type k) (type d) (dem:(k,d)dem) (k:k) (d:d) =
-            let event = translate.Events.Fired.translate info d in
-            let demtable = get_table_dem t.env dem in
-            let module DemTable =
-                  (val demtable : DemTable with type dk = k and type dd = d) in
+          let f (type k) (type d) (dem:(k,d)dem) (k:k) (d:d) event =
+            match get_table_dem t.env dem with
+            | DemFastT' events ->
+              if events = [] then
+                t.sched_daemon (DaemonKey (dem,k));
+              VDemTable.set t.env.dem dem (DemFastT'(event::events))
+            | DemT' demtable ->
+            let module DemTable = (val demtable) in
             try
               let rec update_state k =
                 let module LE = struct exception ToRedirect of k end in
@@ -820,9 +873,21 @@ module Delayed = struct
                 include DemTable
                 let state = update_state k
               end in
-              VDemTable.set t.env.dem dem (module DemTable')
+              VDemTable.set t.env.dem dem (DemT'(module DemTable'))
             with Exit -> () in
-          f dem k d
+          let event = translate.Events.Fired.translate info d in
+          match t.dem_fast_todo with
+          | DemFastNone -> f dem k d event
+          | DemFastTodo(_,nb,q) when !nb == 0 ->
+            assert (Queue.is_empty q); f dem k d event
+          | DemFastTodo(dem',nb,q) ->
+            match Dem.Eq.eq_type dem' dem with
+            | None -> f dem k d event
+            | Some (Eqtype.Eq, Eqtype.Eq) ->
+              Queue.add event q;
+              decr nb;
+              assert (!nb >= 0);
+
       ) events
 
 
@@ -830,10 +895,11 @@ module Delayed = struct
   let mark_dem :
   type k d. t -> (k,d) dem -> k -> unit =
     fun t dem k ->
+      match get_table_dem t.env dem with
+      | DemFastT' _ -> ()
+      | DemT' demtable ->
       try
-        let demtable = get_table_dem t.env dem in
-        let module DemTable =
-              (val demtable : DemTable with type dk = k and type dd = d) in
+        let module DemTable = (val demtable) in
         let module DemTable' = struct
           include DemTable
           let state = DemTable.D.Key.M.change (function
@@ -843,7 +909,7 @@ module Delayed = struct
             | Some (Alive _) -> raise Exit)
             k DemTable.state
         end in
-        VDemTable.set t.env.dem dem (module DemTable')
+        VDemTable.set t.env.dem dem (DemT' (module DemTable'))
       with Exit -> ()
 
   let attach_events :
@@ -1015,20 +1081,24 @@ module Delayed = struct
   | SRedirected of 'k
 
   let is_attached (type k) (type d) t (dem: (k,d) dem) (k:k) =
-    let demtable = get_table_dem t.env dem in
-    let module DemTable =
-          (val demtable : DemTable with type dk = k and type dd = d) in
+    match get_table_dem t.env dem with
+    | DemFastT' _ -> SAlive
+    | DemT' demtable ->
+    let module DemTable = (val demtable) in
     match DemTable.D.Key.M.find_opt k DemTable.state with
     | None -> SUnborn
     | Some (Alive _) -> SAlive
     | Some Dead -> SDead
     | Some (Redirected k') -> SRedirected k'
 
+  exception CantBeKilled
+
   let kill_dem (type k) (type d) t (dem: (k,d) dem) (k:k) =
+    match get_table_dem t.env dem with
+    | DemFastT' _ -> raise CantBeKilled
+    | DemT' demtable ->
     try
-      let demtable = get_table_dem t.env dem in
-      let module DemTable =
-            (val demtable : DemTable with type dk = k and type dd = d) in
+      let module DemTable = (val demtable) in
       Debug.dprintf4 debug "[Solver] @[Kill dem %a %a@]@."
         Dem.print dem DemTable.D.Key.print k;
       let module DemTable' = struct
@@ -1038,7 +1108,7 @@ module Delayed = struct
           | _ -> Some Dead)
           k DemTable.state
       end in
-      VDemTable.set t.env.dem dem (module DemTable')
+      VDemTable.set t.env.dem dem (DemT' (module DemTable'))
     with Exit -> ()
 
   let are_waiting_cl_change
@@ -1514,6 +1584,48 @@ module Delayed = struct
     add_pending_unset_dom d pexp dom cl
 
 
+(**
+   DemFast
+*)
+
+
+  let rec do_pending_daemon_fast :
+    type d. t -> (unit,d) dem -> d Events.Fired.t -> unit =
+    fun delayed dem events ->
+    assert (events != []);
+    match get_dem dem with
+    | Dem _ -> assert false
+    | DemFast demfast ->
+      let module S = (val demfast) in
+      let rec last_rev q n = function
+        | [] -> [],n
+        | a::l ->
+          let rem,n = last_rev q n l in
+          if n > 0 then begin
+            assert (rem == []);
+            Queue.add a q;
+            rem,(n-1)
+          end
+          else a::rem, n in
+      let q = Queue.create () in
+      let events,n = last_rev q S.throttle events in
+      VDemTable.set delayed.env.dem dem (DemFastT' events);
+      assert (delayed.dem_fast_todo == DemFastNone);
+      delayed.dem_fast_todo <- DemFastTodo(dem,ref n,q);
+      let rec run_one () =
+        match delayed.dem_fast_todo with
+        | DemFastNone -> assert false
+        | DemFastTodo(dem',r,q) when Queue.is_empty q ->
+          delayed.dem_fast_todo <- DemFastNone
+        | DemFastTodo(dem',r,q) ->
+          assert (!r >= 0);
+          match Dem.Eq.coerce_type dem' dem with
+          | Eqtype.Eq, Eqtype.Eq ->
+            S.wakeup delayed (Queue.pop q);
+            flush delayed;
+            run_one () in
+      run_one ()
+
   (** TODO: WakeUp what they modify (not efficient) but for now simple
       can perhaps first apply what the daemon does first, then
       readd it to watch list then apply the others pending
@@ -1522,10 +1634,13 @@ module Delayed = struct
       Deamons modify and add wait what todo is it currently a
       problem?
   *)
-  let do_pending_daemon (type k) (type d) delayed (dem : (k,d) dem) (k : k) =
-    let demtable = get_table_dem delayed.env dem in
-    let module DemTable =
-          (val demtable : DemTable with type dk = k and type dd = d) in
+  and do_pending_daemon' : type k d. t -> (k,d) dem -> k -> unit =
+    fun delayed dem k ->
+    match get_table_dem delayed.env dem with
+    | DemFastT' [] -> ()
+    | DemFastT' events -> do_pending_daemon_fast delayed dem events
+    | DemT' demtable ->
+    let module DemTable = (val demtable) in
     match DemTable.D.Key.M.find k (DemTable.state) with
     | Dead ->
       Debug.dprintf4 debug "[Solver] @[Daemon %a for %a is dead@]@."
@@ -1546,7 +1661,7 @@ module Delayed = struct
         let state = DemTable.D.Key.M.add k (Alive []) (DemTable.state)
       end
       in
-      VDemTable.set delayed.env.dem dem (module DemTable');
+      VDemTable.set delayed.env.dem dem (DemT' (module DemTable'));
       (** wakeup *)
       let alive = DemTable.D.wakeup delayed k events in
       (** delayed can be modified *)
@@ -1557,25 +1672,27 @@ module Delayed = struct
           | AliveRedirected k' -> mark_dem delayed dem k'; Redirected k'
           | AliveReattached -> assert false  in
         Debug.dprintf0 debug "[Solver] @[Stop daemon@]@.";
-        let demtable = get_table_dem delayed.env dem in
-        let module DemTable =
-              (val demtable : DemTable with type dk = k and type dd = d) in
-        (** Dead even if event have been added *)
-        let state' = DemTable.D.Key.M.add k demstate (DemTable.state) in
-        let module DemTable' = struct
-          include DemTable
-          let state = state'
+        begin match get_table_dem delayed.env dem with
+        | DemFastT' _ -> assert false
+        | DemT' demtable ->
+          let module DemTable = (val demtable) in
+          (** Dead even if event have been added *)
+          let state' = DemTable.D.Key.M.add k demstate (DemTable.state) in
+          let module DemTable' = struct
+            include DemTable
+            let state = state'
+          end
+          in
+          VDemTable.set delayed.env.dem dem (DemT' (module DemTable'))
         end
-        in
-        VDemTable.set delayed.env.dem dem (module DemTable')
       | AliveReattached ->
         Debug.dprintf0 debug "[Solver] @[Reattach daemon@]@.";
       end
 
-  let do_pending_daemon delayed (DaemonKey (dem,k)) =
-      do_pending_daemon delayed dem k
+  and do_pending_daemon delayed (DaemonKey (dem,k)) =
+      do_pending_daemon' delayed dem k
 
-  let nothing_todo t =
+  and nothing_todo t =
     Queue.is_empty t.todo_dom
     && Queue.is_empty t.todo_sem
     && Queue.is_empty t.todo_immediate_dem
@@ -1583,7 +1700,7 @@ module Delayed = struct
     && Queue.is_empty t.todo_merge
     && Queue.is_empty t.todo_ext_action
 
-  let rec do_pending t =
+  and do_pending t =
     draw_graph t.env;
     if not (Queue.is_empty t.todo_dom) then
       match Queue.pop t.todo_dom with
@@ -1650,9 +1767,15 @@ module Delayed = struct
     else
       Debug.dprintf0 debug "[Solver] Nothing to do@."
 
-  let flush d =
+  and flush d =
     assert (d.env.current_delayed == d);
-    do_pending d;
+    if not (Queue.is_empty d.todo_ext_action) then
+      let saved_ext_action = Queue.create () in
+      Queue.transfer d.todo_ext_action saved_ext_action;
+      do_pending d;
+      Queue.transfer saved_ext_action d.todo_ext_action;
+    else
+      do_pending d;
     assert (nothing_todo d)
 
 
@@ -1696,7 +1819,9 @@ let new_delayed ~sched_daemon ~sched_decision t =
              todo_merge_dom = Queue.create ();
              todo_merge = Queue.create ();
              todo_ext_action = Queue.create ();
-             sched_daemon; sched_decision } in
+             sched_daemon; sched_decision;
+             dem_fast_todo = DemFastNone
+           } in
   t.current_delayed <- d;
   d
 
diff --git a/src/solver.mli b/src/solver.mli
index e8e1884512b61d9c4625d8aaf63defeb71328fd8..5a5dccf124ad0684f37b12be5854bd8bd70ac47f 100644
--- a/src/solver.mli
+++ b/src/solver.mli
@@ -214,12 +214,31 @@ module type Dem = sig
 
   val immediate: bool
   val wakeup: Delayed.t -> Key.t -> Data.t Events.Fired.t -> Key.t alive
-  (** the Events.t in wakeup is a subset of the one given in watch *)
 
 end
 
 module RegisterDem(D:Dem) : sig end
 
+module type DemFast = sig
+  type d
+
+  module Data: sig
+    type t = d
+    val print: Format.formatter -> t -> unit
+  end
+
+  val key: (unit, Data.t) dem
+
+  (** not immediate and never killed *)
+  val throttle: int (** todo int ref? *)
+    (** number of time run in a row *)
+  val wakeup: Delayed.t -> Data.t Events.Fired.event -> unit
+
+end
+
+module RegisterDemFast(D:DemFast) : sig end
+
+
 (** {2 External use of the solver} *)
 type t
 
diff --git a/src/util/bag.ml b/src/util/bag.ml
new file mode 100644
index 0000000000000000000000000000000000000000..af76fb3c9472232ee596f645f41e1a746b5e5e20
--- /dev/null
+++ b/src/util/bag.ml
@@ -0,0 +1,166 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2013                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+(* ------------------------------------------------------------------------ *)
+(* ---  List with constant-time concat                                  --- *)
+(* ------------------------------------------------------------------------ *)
+
+type 'a t =
+  | Empty
+  | Elt of 'a
+  | Add of 'a * 'a t
+  | App of 'a t * 'a
+  | List of 'a list
+  | Concat of 'a t * 'a t
+
+let empty = Empty
+let elt x = Elt x
+
+let length t =
+  let rec scan n = function
+    | Empty -> n
+    | Elt _ -> succ n
+    | Add(_,t) | App(t,_) -> scan (succ n) t
+    | List xs -> n + List.length xs
+    | Concat(a,b) -> scan (scan n a) b
+  in scan 0 t
+
+let add x = function
+  | Empty -> Elt x
+  | t -> Add(x,t)
+
+let append t x = match t with
+  | Empty -> Elt x
+  | t -> App(t,x)
+
+let list = function
+  | [] -> Empty
+  | [x] -> Elt x
+  | xs -> List xs
+
+let concat a b =
+  match a,b with
+    | Empty,c | c,Empty -> c
+    | Elt x,t -> Add(x,t)
+    | t,Elt x -> App(t,x)
+    | Concat(a,b),c -> Concat(a,Concat(b,c)) (* 1-time optim *)
+    | _ -> Concat(a,b)
+
+let rec ulist = function
+  | [] -> Empty
+  | x::xs -> concat x (ulist xs)
+
+let rec map f = function
+  | Empty -> Empty
+  | Elt x -> Elt (f x)
+  | Add(x,t) -> Add(f x,map f t)
+  | App(t,x) -> App(map f t,f x)
+  | List xs -> List(List.map f xs)
+  | Concat(a,b) -> Concat(map f a,map f b)
+
+let rec umap f = function
+  | Empty -> Empty
+  | Elt x -> f x
+  | Add(x,t) -> concat (f x) (umap f t)
+  | App(t,x) -> concat (umap f t) (f x)
+  | List xs -> umap_list f xs
+  | Concat(a,b) -> concat (umap f a) (umap f b)
+
+and umap_list f = function
+  | [] -> Empty
+  | x::xs -> concat (f x) (umap_list f xs)
+
+let rec iter f = function
+  | Empty -> ()
+  | Elt x -> f x
+  | Add(x,t) -> f x ; iter f t
+  | App(t,x) -> iter f t ; f x
+  | List xs -> List.iter f xs
+  | Concat(a,b) -> iter f a ; iter f b
+
+let rec fold_left f w = function
+  | Empty -> w
+  | Elt x -> f w x
+  | Add(x,t) -> fold_left f (f w x) t
+  | App(t,x) -> f (fold_left f w t) x
+  | List xs -> List.fold_left f w xs
+  | Concat(a,b) -> fold_left f (fold_left f w a) b
+
+let rec fold_right f t w = match t with
+  | Empty -> w
+  | Elt x -> f x w
+  | Add(x,t) -> f x (fold_right f t w)
+  | App(t,x) -> fold_right f t (f x w)
+  | List xs -> List.fold_right f xs w
+  | Concat(a,b) -> fold_right f a (fold_right f b w)
+
+let rec filter f = function
+  | Empty -> Empty
+  | Elt x as e -> if f x then e else Empty
+  | Add(x,ts) -> if f x then add x (filter f ts) else filter f ts
+  | App(ts,x) -> let ts = filter f ts in if f x then append ts x else ts
+  | List xs -> list (List.filter f xs)
+  | Concat(a,b) -> concat (filter f a) (filter f b)
+
+let rec partition f = function
+  | Empty -> Empty , Empty
+  | Elt x as e -> if f x then e,Empty else Empty,e
+  | Add(x,ts) ->
+      let pos,neg = partition f ts in
+      if f x then add x pos , neg else pos , add x neg
+  | App(ts,x) ->
+      let ok = f x in
+      let pos,neg = partition f ts in
+      if ok then append pos x , neg else pos , append neg x
+  | List xs ->
+      let pos,neg = List.partition f xs in
+      list pos , list neg
+  | Concat(a,b) ->
+      let apos,aneg = partition f a in
+      let bpos,bneg = partition f b in
+      concat apos bpos , concat aneg bneg
+
+let rec is_empty = function
+  | Empty | List [] -> true
+  | Add _ | App _ | Elt _ | List _ -> false
+  | Concat(a,b) -> is_empty a && is_empty b
+
+let rec singleton = function
+  | Elt x | List [x] -> Some x
+  | Empty | List _ -> None
+  | Add(x,t) | App(t,x) -> if is_empty t then Some x else None
+  | Concat(a,b) ->
+      match singleton a with
+        | Some x -> if is_empty b then Some x else None
+        | None -> if is_empty a then singleton b else None
+
+let rec collect t xs =
+  match t with
+    | Elt x -> x :: xs
+    | Empty -> xs
+    | Add(x,t) -> x :: collect t xs
+    | App(t,x) -> collect t (x::xs)
+    | List ys -> ys @ xs
+    | Concat(a,b) -> collect a (collect b xs)
+
+let elements t = collect t []
+
diff --git a/src/util/bag.mli b/src/util/bag.mli
new file mode 100644
index 0000000000000000000000000000000000000000..7f807d416cd2c823603d47b89f7d3555b395c0ac
--- /dev/null
+++ b/src/util/bag.mli
@@ -0,0 +1,51 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2013                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** List with constant-time concat operation.
+    @since Carbon-20101201
+*)
+
+type 'a t
+
+val empty : 'a t
+val elt : 'a -> 'a t
+val add : 'a -> 'a t -> 'a t
+val append : 'a t -> 'a -> 'a t
+val list : 'a list -> 'a t
+val ulist : 'a t list -> 'a t
+val concat : 'a t -> 'a t -> 'a t
+
+val map : ('a -> 'b) -> 'a t -> 'b t
+val umap : ('a -> 'b t) -> 'a t -> 'b t
+
+val iter : ('a -> unit) -> 'a t -> unit
+val fold_left : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b
+val fold_right : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b
+
+val filter : ('a -> bool) -> 'a t -> 'a t
+val partition : ('a -> bool) -> 'a t -> 'a t * 'a t
+
+val length : 'a t -> int
+
+val is_empty : 'a t -> bool
+val singleton : 'a t -> 'a option
+val elements : 'a t -> 'a list
diff --git a/src/util/lists.ml b/src/util/lists.ml
index 7089c5c79d199593adf7821a718a61147e4c4963..f4c6dbb191afb342e131837708612f9eb4e1390b 100644
--- a/src/util/lists.ml
+++ b/src/util/lists.ml
@@ -129,3 +129,9 @@ let rec chop_last = function
   | [r] -> [], r
   | x :: s -> let s, r = chop_last s in x :: s, r
 
+let rec last_rev n = function
+  | [] -> [],[],n
+  | a::l ->
+    let rev,rem,n = last_rev n l in
+    if n > 0 then a::rev,(assert (rem == []); rem),(n-1)
+    else rev,a::rem, n
diff --git a/src/util/lists.mli b/src/util/lists.mli
index fa561adafd432c0d4c09061596bff36ea1ed22b4..76f9c0927465947c0547e30be6b4aff80eefe494 100644
--- a/src/util/lists.mli
+++ b/src/util/lists.mli
@@ -70,3 +70,11 @@ val chop : int -> 'a list -> 'a list
 
 val chop_last : 'a list -> 'a list * 'a
 (** removes (and returns) the last element of a list *)
+
+val last_rev : int -> 'a list -> 'a list * 'a list * int
+(** return :
+     - the reverse the last n elements of a list;
+     - return the remaining part of the list.
+     - if the list is not long enough return the number
+    of elements needed ( [0] otherwise )
+*)