diff --git a/src/lib/constraints/simple.template.mlw b/src/lib/constraints/simple.template.mlw
index 27761e3737789034e89738d9940e6e42ed5eed31..260800f0d3ac304b40f828ead27217219ab5b8c2 100644
--- a/src/lib/constraints/simple.template.mlw
+++ b/src/lib/constraints/simple.template.mlw
@@ -3,12 +3,12 @@ module Simple
    use cp.Type
    use cp.Var as Var
    use mach.int.Int
-   use Bool
+   use utils.extstd.Bool
    use set.Fset as S
    use cp.DomI
    use cp.DomB
    use seq.Seq as Seq
-   use cp.Int63 as Int63
+   use utils.extstd.Int63 as Int63
 
    use export cp.ConstraintHelpers
 {% for cstr in constraints %}   use {{ cstr.file }}.{{ cstr.module }} as {{ cstr.module }}
diff --git a/src/lib/cp.mlw b/src/lib/cp.mlw
index 18223145b0945f0a94ac062dcc1205b959abb5e5..811eb1bff75f9f2b086fc82e3aef5484420ea1cf 100644
--- a/src/lib/cp.mlw
+++ b/src/lib/cp.mlw
@@ -9,664 +9,9 @@
 (*                                                                  *)
 (********************************************************************)
 
-module Bool
-       use export bool.Bool
-
-       let function andb' (x y : bool) : bool
-        ensures { result = (x /\ y) } =
-       match x with
-       | True -> y
-       | False -> False
-       end
-
-       let function eqb (x y:bool) =
-         match x,y with
-         | True, True | False, False -> true
-         | _ -> false
-         end
-end
-
-module Int63
-
-       use export mach.int.Int63
-
-       let function min x y = if x <= y then x else y
-       let function max x y = if x <= y then y else x
-
-end
-
-module S
-
-  use int.Int
-  use Int63 as Int63
-
-  type key
-
-  val function tag (_:key): Int63.int63
-      ensures { 0 <= result }
-
-  axiom tag_correct: forall x y. tag x = tag y -> x = y
-
-end
-
-module TagtblIntf
-
-  use int.Int
-  use import Int63 as Int63
-  use map.Map
-  use map.Const
-  use set.Fset as S
-  use list.List
-  use list.Mem as LMem
-  use import mach.array.Array63 as Array
-  use seq.Seq as Seq
-  use bool.Bool
-  use mach.peano.Peano as Peano
-  use mach.peano.Int63 as PeanoInt63
-
-  clone import S as S with axiom tag_correct
-
-  type t 'a = private {
-         ghost mutable contents: map key 'a;
-         ghost defined: S.fset key;
-       }
-
-  function ([]) (h: t 'a) (k: key) : 'a = Map.([]) h.contents k
-
-  val create (s:Int63.int63) (def:'a) (ghost defined: S.fset key): t 'a
-   requires { forall k. S.mem k defined -> tag k <= s }
-   requires { -1 <= s < Int63.max_int63 }
-   ensures { result.contents = const def }
-   ensures { result.defined = defined }
-
-  predicate mem (k: key) (h: t 'a) = S.mem k h.defined
-
-  val function max_tags (h: t 'a) : Int63.int63
-    ensures { forall k. mem k h -> tag k <= result }
-    ensures { -1 <= result < Int63.max_int63 }
-
-  predicate set_ (h1: t 'a) (h2: t 'a) (k: key) (v: 'a) =
-    h1.defined = h2.defined /\ h1.contents = h2.contents[k<-v]
-
-  val set (h: t 'a) (k: key) (v: 'a) : unit
-    requires { mem k h }
-    ensures { set_ h (old h) k v }
-    writes { h.contents }
-
-  function get (h: t 'a) (k: key) : 'a = Map.get h.contents k
-
-  val function find (h: t 'a) (k: key) : 'a
-    requires { mem k h }
-    ensures  { result = h[k] }
-
-  scope Lock
-    type t 'a = abstract {
-         contents: map key 'a;
-         defined: S.fset key;
-       }
-
-    function ([]) (h: t 'a) (k: key) : 'a = Map.([]) h.contents k
-
-    predicate mem (k: key) (h: t 'a) = S.mem k h.defined
-
-    function get (h: t 'a) (k: key) : 'a = Map.get h.contents k
-
-    val function find (h: t 'a) (k: key) : 'a
-      requires { mem k h }
-      ensures  { result = h[k] }
-
-   end
-
-   val copy_lock (h: t 'a): Lock.t 'a
-       ensures { result.Lock.defined = h.defined }
-       ensures { result.Lock.contents = h.contents }
-
-   val copy_unlock (h: Lock.t 'a): t 'a
-       ensures { h.Lock.defined = result.defined }
-       ensures { h.Lock.contents = result.contents }
-
-
-end
-
-
-module Tagtbl
-
-  use int.Int
-  use import Int63 as Int63
-  use map.Map
-  use map.Const
-  use set.Fset as S
-  use list.List
-  use list.Mem as LMem
-  use import mach.array.Array63 as Array
-  use seq.Seq as Seq
-  use bool.Bool
-  use mach.peano.Peano as Peano
-  use mach.peano.Int63 as PeanoInt63
-
-scope Make
-  clone  S as S with axiom tag_correct
-
-  type key = S.key
-
-  type t 'a = {
-         arr : Array.array 'a;
-         ghost mutable contents: map key 'a;
-         ghost defined: S.fset key;
-       }
-  invariant { forall k. S.mem k defined -> S.tag k < Seq.length arr }
-  invariant { forall k. S.mem k defined -> Map.([]) contents k = Seq.get arr (S.tag k) }
-  by {
-    arr = (Array.make 0 (any 'a): Array.array 'a);
-    defined = S.empty;
-    contents = (const (any 'a): map key 'a);
-  }
-
-  function ([]) (h: t 'a) (k: key) : 'a = Map.([]) h.contents k
-
-  let create (s:Int63.int63) (def:'a) (ghost defined: S.fset key): t 'a
-   requires { forall k. S.mem k defined -> S.tag k <= s }
-   requires { -1 <= s < Int63.max_int63 }
-   ensures { result.contents = const def }
-   ensures { result.defined = defined } =
-   {
-     arr = Array.make (Int63.(+) s 1) def;
-     contents = const def;
-     defined = defined;
-   }
-
-  predicate mem (k: key) (h: t 'a) = S.mem k h.defined
-
-  let function max_tags (h: t 'a) : Int63.int63
-    ensures { forall k. mem k h -> S.tag k <= result }
-    ensures { -1 <= result < Int63.max_int63 }
-  =
-    Int63.(-) (Array.length h.arr) 1
-
-  predicate set_ (h1: t 'a) (h2: t 'a) (k: key) (v: 'a) =
-    h1.defined = h2.defined /\ h1.contents = h2.contents[k<-v]
-
-  let set (h: t 'a) (k: key) (v: 'a) : unit
-    requires { mem k h }
-    ensures { set_ h (old h) k v }
-      =
-      let t = S.tag k in
-      h.arr[t] <- v;
-      h.contents <- Map.set h.contents k v
-
-  function get (h: t 'a) (k: key) : 'a = Map.get h.contents k
-
-
-  let function find (h: t 'a) (k: key) : 'a
-    requires { mem k h }
-    ensures  { result = h[k] } =
-      let t = S.tag k in
-      h.arr[t]
-
-  scope Lock
-    type t 'a = {
-         arr : Array.array 'a;
-         ghost contents: map key 'a;
-         ghost defined: S.fset key;
-       }
-  invariant { forall k. S.mem k defined -> S.tag k < Seq.length arr }
-  invariant { forall k. S.mem k defined -> Map.([]) contents k = Seq.get arr (S.tag k) }
-  by {
-    arr = (Array.make 0 (any 'a): Array.array 'a);
-    defined = S.empty;
-    contents = (const (any 'a): map key 'a);
-  }
-
-    function ([]) (h: t 'a) (k: key) : 'a = Map.([]) h.contents k
-
-    predicate mem (k: key) (h: t 'a) = S.mem k h.defined
-
-    function get (h: t 'a) (k: key) : 'a = Map.get h.contents k
-
-
-    let function find (h: t 'a) (k: key) : 'a
-      requires { mem k h }
-      ensures  { result = h[k] } =
-        let t = S.tag k in
-        h.arr[t]
-
-   end
-
-   let copy_lock (h: t 'a): Lock.t 'a
-       ensures { result.Lock.defined = h.defined }
-       ensures { result.Lock.contents = h.contents } =
-       { Lock.arr = Array.copy h.arr;
-         Lock.contents = h.contents;
-         Lock.defined = h.defined;
-       }
-
-   let copy_unlock (h: Lock.t 'a): t 'a
-       ensures { h.Lock.defined = result.defined }
-       ensures { h.Lock.contents = result.contents } =
-       { arr = Array.copy h.Lock.arr;
-         contents = h.Lock.contents;
-         defined = h.Lock.defined;
-       }
-(*
-    clone TagtblIntf with
-          type S.key = S.key,
-          val S.tag = S.tag,
-          lemma S.tag_correct,
-          type t = t,
-          val create = create,
-          val max_tags = max_tags,
-          val find = find,
-          val set = set,
-          type Lock.t = Lock.t,
-          val Lock.find = Lock.find
-*)
-end
-end
-
-
-module TagtblBacktrackableIntf
-
-  use int.Int
-  use import Int63 as Int63
-  use map.Map
-  use map.Const
-  use set.Fset as S
-  use list.List
-  use list.Mem as LMem
-  use import mach.array.Array63 as Array
-  use seq.Seq as Seq
-  use bool.Bool
-  use mach.peano.Peano as Peano
-  use mach.peano.Int63 as PeanoInt63
-
-  clone import S as S with axiom tag_correct
-
-  type token 'a
-  function saved_contents (token 'a) : map key 'a
-  function saved_tokens (token 'a): list (token 'a)
-
-  type t 'a = private {
-         ghost mutable contents: map key 'a;
-         ghost defined: S.fset key;
-         ghost mutable tokens : list (token 'a);
-       }
-
-  function ([]) (h: t 'a) (k: key) : 'a = Map.([]) h.contents k
-
-  val create (s:Int63.int63) (def:'a) (ghost defined: S.fset key): t 'a
-   requires { forall k. S.mem k defined -> tag k <= s }
-   requires { -1 <= s < Int63.max_int63 }
-   ensures { result.contents = const def }
-   ensures { result.tokens = Nil }
-   ensures { result.defined = defined }
-
-  predicate mem (k: key) (h: t 'a) = S.mem k h.defined
-
-  val function max_tags (h: t 'a) : Int63.int63
-    ensures { forall k. mem k h -> tag k <= result }
-    ensures { -1 <= result < Int63.max_int63 }
-
-  predicate set_ (h1: t 'a) (h2: t 'a) (k: key) (v: 'a) =
-    h1.defined = h2.defined /\ h1.contents = h2.contents[k<-v]
-
-  val partial set (h: t 'a) (k: key) (v: 'a) : unit
-    requires { mem k h }
-    ensures { set_ h (old h) k v }
-    writes { h.contents }
-
-  function get (h: t 'a) (k: key) : 'a = Map.get h.contents k
-
-  val function find (h: t 'a) (k: key) : 'a
-    requires { mem k h }
-    ensures  { result = h[k] }
-
-  val create_backtrack_point (h: t 'a) : token 'a
-    writes { h.tokens }
-    ensures { result.saved_contents = old h.contents }
-    ensures { result.saved_tokens = (old h.tokens) }
-    ensures { h.tokens = Cons result (old h.tokens) }
-
-
-  val backtrack (h: t 'a) (token:token 'a): unit
-    requires { LMem.mem token h.tokens }
-    ensures { h.tokens = Cons token token.saved_tokens }
-    ensures { h.contents = token.saved_contents }
-    writes { h.tokens, h.contents }
-
-end
-
-
-module TagtblBacktrackable
-
-  use int.Int
-  use import Int63 as Int63
-  use map.Map
-  use map.Const
-  use set.Fset as S
-  use list.List
-  use list.Mem as LMem
-  use import mach.array.Array63 as Array
-  use seq.Seq as Seq
-  use bool.Bool
-  use mach.peano.Peano as Peano
-  use mach.peano.Int63 as PeanoInt63
-
-scope Make
-  clone  S as S with axiom tag_correct
-
-  type key = S.key
-
-  type token 'a = {
-       offset: Int63.int63;
-       ghost saved_contents: map key 'a;
-       ghost saved_tokens: list (token 'a);
-  }
-
-
-  type history_item 'a = {
-    hist_offset : Int63.int63;
-    hist_value  : 'a;
-  }
-
-  predicate good_contents (contents:map key 'a) (arr:Seq.seq 'a) =
-     forall e. S.tag e < (Seq.length arr) -> contents[e] = Seq.get arr (S.tag e)
-
-  function revert_arr (arr:Seq.seq 'a) (history:Seq.seq (history_item 'a)) (current_offset : int) : Seq.seq 'a =
-    let hi = Seq.get history current_offset in
-    let arr = Seq.set arr (Int63.to_int hi.hist_offset) hi.hist_value in
-    arr
-
-
-  let rec ghost function good_tokens
-      (arr:Seq.seq 'a) (history:Seq.seq (history_item 'a))
-      (current_offset : int)
-      (l: list (token 'a)) : bool
-        variant { current_offset+1, l }
-    =
-        match l with
-          | Nil -> true
-          | Cons t l' ->
-          if (current_offset = (Int63.to_int t.offset))
-          then begin
-            andb (pure {l' = t.saved_tokens})
-            (andb (good_contents t.saved_contents arr)
-            (good_tokens arr history current_offset l'))
-          end
-          else begin
-            (0 <= current_offset) &&
-            let arr = revert_arr arr history current_offset in
-            good_tokens arr history (current_offset - 1) l
-           end
-        end
-
-  let rec lemma good_tokens_frame_history
-      (arr:Seq.seq 'a) (history1:Seq.seq (history_item 'a))
-      (history2:Seq.seq (history_item 'a))
-      (current_offset : int)
-      (l: list (token 'a)) : unit
-      requires { current_offset < Seq.length history1 }
-      requires { current_offset < Seq.length history2 }
-      requires { forall i. 0 <= i <= current_offset -> Seq.get history1 i = Seq.get history2 i }
-      requires { forall i. 0 <= i <= current_offset -> 0 <= (Seq.get history1 i).hist_offset < Seq.length arr }
-      requires { good_tokens arr history1 current_offset l }
-      variant { current_offset, l }
-      ensures { good_tokens arr history2 current_offset l }
-       =
-        match l with
-          | Nil -> ()
-          | Cons t l' ->
-          if (current_offset = (Int63.to_int t.offset))
-          then begin
-             assert { l' = t.saved_tokens };
-             assert { good_contents t.saved_contents arr };
-             assert { good_tokens arr history1 current_offset l' };
-             good_tokens_frame_history arr history1 history2 current_offset l'
-          end
-          else begin
-           let arr = revert_arr arr history2 current_offset in
-           good_tokens_frame_history arr history1 history2 (current_offset - 1) l
-           end
-        end
-
-   let rec lemma good_tokens_smaller_offset
-      (arr:Seq.seq 'a) (history:Seq.seq (history_item 'a))
-      (current_offset : int)
-      (l: list (token 'a)) : unit
-        requires { current_offset < Seq.length history }
-        requires { good_tokens arr history current_offset l }
-        variant { current_offset, l }
-        ensures { forall t. LMem.mem t l -> (Int63.to_int t.offset) <= current_offset }
-    =
-        match l with
-          | Nil -> ()
-          | Cons t l' ->
-          if (current_offset = (Int63.to_int t.offset))
-          then begin 
-             good_tokens_smaller_offset arr history current_offset l'
-          end
-          else begin
-            let arr = revert_arr arr history current_offset in
-              good_tokens_smaller_offset arr history (current_offset - 1) l
-           end
-        end
-
-
-  type t 'a = {
-         arr : Array.array 'a;
-         ghost mutable contents: map key 'a;
-         ghost defined: S.fset key;
-         ghost mutable tokens : list (token 'a);
-         mutable current_offset: Int63.int63;
-         mutable co_peano: Peano.t;
-         mutable history: Array.array (history_item 'a);
-       }
-  invariant { good_contents contents arr }
-  invariant { good_tokens arr history current_offset tokens }
-  invariant { -1 <= current_offset < Array.length history }
-  invariant { 0 < history.length }
-  invariant { forall k. S.mem k defined -> S.tag k < Seq.length arr }
-  invariant { current_offset = co_peano - 2 }
-  invariant { current_offset < Seq.length history }
-  invariant { forall i. 0 <= i <= current_offset -> 0 <= (Seq.get history i).hist_offset < arr.length }
-  invariant { forall i. 0 <= i <= current_offset -> exists k. (Seq.get history i).hist_offset = S.tag k }
-  by {
-    arr = (Array.make 0 (any 'a): Array.array 'a);
-    history = (Array.make 1 {hist_offset = 0; hist_value = any 'a});
-    tokens = Nil;
-    current_offset = -1;
-    co_peano = Peano.one;
-    defined = S.empty;
-    contents = (const (any 'a): map key 'a);
-  }
-
-  function ([]) (h: t 'a) (k: key) : 'a = Map.([]) h.contents k
-
-  let create (s:Int63.int63) (def:'a) (ghost defined: S.fset key): t 'a
-   requires { forall k. S.mem k defined -> S.tag k <= s }
-   requires { -1 <= s < Int63.max_int63 }
-   ensures { result.contents = const def }
-   ensures { result.tokens = Nil }
-   ensures { result.defined = defined } =
-   {
-     arr = Array.make (Int63.(+) s 1) def;
-     contents = const def;
-     tokens = Nil;
-     current_offset = -1;
-     co_peano = Peano.one;
-     defined = defined;
-     history = Array.make 8 {hist_offset = 0; hist_value = def};
-   }
-
-  predicate mem (k: key) (h: t 'a) = S.mem k h.defined
-
-  let function max_tags (h: t 'a) : Int63.int63
-    ensures { forall k. mem k h -> S.tag k <= result }
-    ensures { -1 <= result < Int63.max_int63 }
-  =
-    Int63.(-) (Array.length h.arr) 1
-
-  let resize (h: t 'a) : unit
-    writes { h.history }
-    ensures { h.current_offset + 1 < Array.length h.history }
-    =
-    let s = Array.length h.history in
-    if h.current_offset + 1 = s then
-      let _co_peano = PeanoInt63.to_int63 h.co_peano in
-      assert { h.current_offset < _co_peano <= Int63.max_int };
-      assert { s < Int63.max_int };
-      let s' = if Int63.(/) Int63.max_int 2 < s then Int63.max_int else Int63.(*) s 2 in
-      let ndata = Array.make s' (Array.([]) h.history 0) in
-      Array.blit h.history 0 ndata 0 s;
-      good_tokens_frame_history h.arr.elts h.history.elts ndata.elts (Int63.to_int h.current_offset) h.tokens;
-      h.history <- ndata
-
-  predicate set_ (h1: t 'a) (h2: t 'a) (k: key) (v: 'a) =
-    h1.defined = h2.defined /\ h1.contents = h2.contents[k<-v]
-
-  let set (h: t 'a) (k: key) (v: 'a) : unit
-    requires { mem k h }
-    ensures { set_ h (old h) k v }
-      =
-      resize h;
-      assert { forall i. 0 <= i <= h.current_offset -> 0 <= (Seq.get h.history i).hist_offset < h.arr.length };
-      let t = S.tag k in
-      let ghost h_before = h.history.elts in
-      let ghost arr_before = h.arr.elts in
-      let ghost co_before = h.current_offset in
-      h.current_offset <- h.current_offset + 1;
-      let old_v = (Array.([]) h.arr t) in
-(*      assert { 0 <= t < h.arr.length };
-      assert { forall i. 0 <= i <= co_before -> 0 <= (Seq.get h.history i).hist_offset < h.arr.length }; *)
-      h.history[h.current_offset] <- {hist_offset=t; hist_value=old_v};
-(*      assert { forall i. 0 <= i <= co_before -> (Seq.get h.history i).hist_offset = (Seq.get h_before i).hist_offset }; *)
-(*      assert { forall i. 0 <= i <= co_before -> 0 <= (Seq.get h.history i).hist_offset < h.arr.length }; *)
-      assert { forall i. 0 <= i <= h.current_offset -> 0 <= (Seq.get h.history i).hist_offset < h.arr.length
-        by (forall i. 0 <= i <= co_before -> (Seq.get h.history i).hist_offset = (Seq.get h_before i).hist_offset)
-       };
-      assert { exists k. (Seq.get h.history h.current_offset).hist_offset = S.tag k };
-      good_tokens_frame_history h.arr.elts h_before h.history.elts (Int63.to_int h.current_offset - 1) h.tokens;
-      assert { exists k. (Seq.get h.history h.current_offset).hist_offset = S.tag k };
-      assert { forall i. 0 <= i <= h.current_offset - 1 -> exists k. (Seq.get h.history i).hist_offset = S.tag k };
-      h.arr[t] <- v;
-      h.contents <- Map.set h.contents k v;
-      h.co_peano <- Peano.succ h.co_peano;
-      assert { arr_before = Seq.set h.arr.elts (Int63.to_int t) old_v };
-      assert { match h.tokens with
-      | Nil -> true
-      | Cons t _ ->  t.offset <= (old h.current_offset)
-      end };
-      ()
-
-  function get (h: t 'a) (k: key) : 'a = Map.get h.contents k
-
-
-  let function find (h: t 'a) (k: key) : 'a
-    requires { mem k h }
-    ensures  { result = h[k] } =
-      let t = S.tag k in
-      h.arr[t]
-
-  let create_backtrack_point (h: t 'a) : token 'a
-    writes { h.tokens }
-    ensures { result.saved_contents = old h.contents }
-    ensures { result.saved_tokens = old h.tokens }
-    ensures { h.tokens = Cons result (old h.tokens) } =
-    let t = { offset = h.current_offset;
-      saved_tokens = h.tokens;
-      saved_contents = h.contents;
-     } in
-    h.tokens <- Cons t h.tokens;
-    t
-
-  predicate backtrack_aux (token : token 'a) (h: t 'a) =
-     if token.offset = h.current_offset
-     then begin
-                    good_contents token.saved_contents h.arr
-                   /\  good_tokens h.arr h.history h.current_offset h.tokens
-                   /\  Cons token token.saved_tokens = h.tokens
-                     end
-                     else begin
-                      LMem.mem token h.tokens
-                   /\ (0 <= h.current_offset) /\
-                     let arr = revert_arr h.arr h.history h.current_offset in
-                     good_tokens arr h.history (h.current_offset - 1) h.tokens
-                   end
-
-  let backtrack (h: t 'a) (token:token 'a): unit
-    requires { LMem.mem token h.tokens }
-    ensures { h.tokens = Cons token token.saved_tokens }
-    ensures { h.contents = token.saved_contents } =
-    let rec aux () : unit
-        requires { LMem.mem token h.tokens }
-        variant { h.current_offset }
-        ensures { h.tokens = Cons token token.saved_tokens }
-        ensures { h.contents = token.saved_contents }
-    =
-        let rec ghost aux' (l: list (token 'a)) : unit
-          requires { LMem.mem token l }
-          requires { good_tokens h.arr h.history h.current_offset l }
-          ensures { backtrack_aux token h }
-          variant { l }
-        =
-         match l with
-         | Nil -> absurd
-         | Cons t l' ->
-          if pure { h.current_offset = t.offset }
-          then begin if pure { t = token }
-          then h.tokens <- l
-          else aux' l'
-          end
-          else begin
-           assert { LMem.mem token l };
-           let arr = revert_arr h.arr.elts h.history.elts (Int63.to_int h.current_offset) in
-           assert { good_tokens arr h.history (h.current_offset - 1) l };
-           h.tokens <- l
-           end
-        end
-        in
-        aux' h.tokens;
-        if (Int63.(=) h.current_offset token.offset)
-        then begin
-          h.contents <- token.saved_contents
-        end
-        else begin
-          let hi = Array.([]) h.history h.current_offset in
-          Array.([]<-) h.arr hi.hist_offset hi.hist_value;
-          let ghost k = any key ensures { hi.hist_offset = S.tag result } in
-          h.contents <- Map.set h.contents k hi.hist_value;
-          h.current_offset <- h.current_offset - 1;
-          h.co_peano <- Peano.pred h.co_peano;
-          assert { Map.get h.contents k = Seq.get h.arr (S.tag k) };
-          assert { forall e. S.tag e < (Seq.length h.arr) -> Map.get h.contents e = Seq.get h.arr (S.tag e) };
-          assert { good_tokens h.arr h.history h.current_offset h.tokens };
-          aux ()
-         end
-    in
-    aux ()
-
-
-    clone TagtblBacktrackableIntf with
-          type S.key = S.key,
-          val S.tag = S.tag,
-          lemma S.tag_correct,
-          type token = token,
-          function saved_contents = saved_contents,
-          function saved_tokens = saved_tokens,
-          type t = t,
-          val create = create,
-          val max_tags = max_tags,
-          val find = find,
-          val set = set,
-          val create_backtrack_point = create_backtrack_point,
-          val backtrack = backtrack
-
-
-end
-end
-
 module Var0
 
-       use Int63 as Int63
+       use utils.extstd.Int63 as Int63
        use int.Int
 
        type ti = { vi: Int63.int63 } invariant { 0 <= vi < Int63.max_int63 } by { vi = 1 }
@@ -723,12 +68,12 @@ module Var
 
        use export Var0
 
-       clone TagtblBacktrackableIntf as Hbi with type S.key = ti, val S.tag = tag_ti
-       clone TagtblBacktrackableIntf as Hbb with type S.key = tb, val S.tag = tag_tb
+       clone utils.tagtbl.TagtblBacktrackableIntf as Hbi with type S.key = ti, val S.tag = tag_ti
+       clone utils.tagtbl.TagtblBacktrackableIntf as Hbb with type S.key = tb, val S.tag = tag_tb
        clone mach.tagset.TagSetIntf as Si with type S.key = ti, val S.tag = tag_ti, val S.dummy = dummy_ti
        clone mach.tagset.TagSetIntf as Sb with type S.key = tb, val S.tag = tag_tb, val S.dummy = dummy_tb
-       clone TagtblIntf as Hi with type S.key = ti, val S.tag = tag_ti
-       clone TagtblIntf as Hb with type S.key = tb, val S.tag = tag_tb
+       clone utils.tagtbl.TagtblIntf as Hi with type S.key = ti, val S.tag = tag_ti
+       clone utils.tagtbl.TagtblIntf as Hb with type S.key = tb, val S.tag = tag_tb
 
 end
 
@@ -736,12 +81,12 @@ end
 module Impl0
        use Var0
 
-       clone TagtblBacktrackable as Hbi with type Make.S.key = Var0.ti, val Make.S.tag = Var0.tag_ti
-       clone TagtblBacktrackable as Hbb with type Make.S.key = Var0.tb, val Make.S.tag = Var0.tag_tb
+       clone utils.tagtbl.TagtblBacktrackable as Hbi with type Make.S.key = Var0.ti, val Make.S.tag = Var0.tag_ti
+       clone utils.tagtbl.TagtblBacktrackable as Hbb with type Make.S.key = Var0.tb, val Make.S.tag = Var0.tag_tb
        clone mach.tagset.TagSet as Si with type S.key = ti, val S.tag = tag_ti, val S.dummy = dummy_ti
        clone mach.tagset.TagSet as Sb with type S.key = tb, val S.tag = tag_tb, val S.dummy = dummy_tb
-       clone Tagtbl as Hi with type Make.S.key = Var0.ti, val Make.S.tag = Var0.tag_ti
-       clone Tagtbl as Hb with type Make.S.key = Var0.tb, val Make.S.tag = Var0.tag_tb
+       clone utils.tagtbl.Tagtbl as Hi with type Make.S.key = Var0.ti, val Make.S.tag = Var0.tag_ti
+       clone utils.tagtbl.Tagtbl as Hb with type Make.S.key = Var0.tb, val Make.S.tag = Var0.tag_tb
 
 end
 
@@ -815,11 +160,11 @@ module Constraint
      use Type
      use Var as Var
      use mach.int.Int
-     use Bool
+     use utils.extstd.Bool
      use set.Fset as S
      use list.List
      use list.Mem as LMem
-     use Int63 as Int63
+     use utils.extstd.Int63 as Int63
      use seq.Seq
      use mach.array.Array63
 
@@ -897,12 +242,12 @@ module Engine
      clone Dom as DomB with axiom .
      clone Constraint as Constraint with type value1 = DomI.value, type value2 = DomB.value, axiom .
      use set.Fset as S
-     use Bool
+     use utils.extstd.Bool
      use list.List
      use mach.int.Int
      use import Type as Type
      use list.Mem as LMem
-     use Int63 as Int63
+     use utils.extstd.Int63 as Int63
      use ref.Ref
 
      type env = Type.env DomI.t DomB.t
@@ -1407,7 +752,7 @@ end
 
 module DomB
 
-     use Bool
+     use utils.extstd.Bool
      use mach.int.Int
      use Type
 
@@ -1490,7 +835,7 @@ end
 
 module DomI
 
-     use Bool
+     use utils.extstd.Bool
      use mach.int.Int
      use Type
 
@@ -1561,12 +906,12 @@ module ConstraintHelpers
      use Type
      use Var as Var
      use mach.int.Int
-     use Bool
+     use utils.extstd.Bool
      use set.Fset as S
      use DomI
      use DomB
      use seq.Seq as Seq
-     use Int63 as Int63
+     use utils.extstd.Int63 as Int63
 
      type env = Type.env DomI.t DomB.t
      type interp = Type.interp DomI.value DomB.value
@@ -1796,12 +1141,12 @@ module ConstraintCst
      use Type
      use Var as Var
      use mach.int.Int
-     use Bool
+     use utils.extstd.Bool
      use set.Fset as S
      use DomI
      use DomB
      use seq.Seq as Seq
-     use Int63 as Int63
+     use utils.extstd.Int63 as Int63
 
      use ConstraintHelpers
 
@@ -1871,12 +1216,12 @@ module ConstraintIsTrue
      use Type
      use Var as Var
      use mach.int.Int
-     use Bool
+     use utils.extstd.Bool
      use set.Fset as S
      use DomI
      use DomB
      use seq.Seq as Seq
-     use Int63 as Int63
+     use utils.extstd.Int63 as Int63
 
      use ConstraintHelpers
 
@@ -1934,12 +1279,12 @@ module ConstraintAdd
      use Type
      use Var as Var
      use mach.int.Int
-     use Bool
+     use utils.extstd.Bool
      use set.Fset as S
      use DomI
      use DomB
      use seq.Seq as Seq
-     use Int63 as Int63
+     use utils.extstd.Int63 as Int63
 
      use ConstraintHelpers
 
@@ -2077,12 +1422,12 @@ module ConstraintLe
      use Type
      use Var as Var
      use mach.int.Int
-     use Bool
+     use utils.extstd.Bool
      use set.Fset as S
      use DomI
      use DomB
      use seq.Seq as Seq
-     use Int63 as Int63
+     use utils.extstd.Int63 as Int63
 
      use ConstraintHelpers
 
@@ -2157,12 +1502,12 @@ module ConstraintOr
      use Type
      use Var as Var
      use mach.int.Int
-     use Bool
+     use utils.extstd.Bool
      use set.Fset as S
      use DomI
      use DomB
      use seq.Seq as Seq
-     use Int63 as Int63
+     use utils.extstd.Int63 as Int63
 
      use ConstraintHelpers
 
@@ -2226,12 +1571,12 @@ module ConstraintEquiv
      use Type
      use Var as Var
      use mach.int.Int
-     use Bool
+     use utils.extstd.Bool
      use set.Fset as S
      use DomI
      use DomB
      use seq.Seq as Seq
-     use Int63 as Int63
+     use utils.extstd.Int63 as Int63
 
      use ConstraintHelpers
 
@@ -2295,12 +1640,12 @@ module ConstraintNot
      use Type
      use Var as Var
      use mach.int.Int
-     use Bool
+     use utils.extstd.Bool
      use set.Fset as S
      use DomI
      use DomB
      use seq.Seq as Seq
-     use Int63 as Int63
+     use utils.extstd.Int63 as Int63
 
      use ConstraintHelpers
 
@@ -2365,12 +1710,12 @@ module ConstraintBoolPresent
      use Type
      use Var as Var
      use mach.int.Int
-     use Bool
+     use utils.extstd.Bool
      use set.Fset as S
      use DomI
      use DomB
      use seq.Seq as Seq
-     use Int63 as Int63
+     use utils.extstd.Int63 as Int63
 
      use ConstraintHelpers
 
diff --git a/src/lib/dune b/src/lib/dune
index 64ea512384e55422a9883396546f9db5eeabe211..b20899b84d000f5ca8cc9f31a1b15b91d1ef2c8e 100644
--- a/src/lib/dune
+++ b/src/lib/dune
@@ -1,16 +1,16 @@
 (library
         (public_name colibrics)
-        (modules cp__Int63 cp__Bool cp__Impl0 cp__Var0 cp__Type cp__Var cp__DomI cp__DomB constraints__simple__Simple cp__ConstraintIsTrue cp__ConstraintAdd cp__ConstraintLe cp__ConstraintOr cp__ConstraintEquiv cp__ConstraintNot cp__ConstraintBoolPresent cp__ConstraintCst all__All cp__ConstraintHelpers all__API all__APIDefensive colibrics)
+        (modules utils__extstd__Int63 utils__extstd__Bool cp__Impl0 cp__Var0 cp__Type cp__Var cp__DomI cp__DomB constraints__simple__Simple cp__ConstraintIsTrue cp__ConstraintAdd cp__ConstraintLe cp__ConstraintOr cp__ConstraintEquiv cp__ConstraintNot cp__ConstraintBoolPresent cp__ConstraintCst all__All cp__ConstraintHelpers all__API all__APIDefensive colibrics)
         (libraries zarith)
         (private_modules
-          cp__Int63 cp__Bool cp__Impl0 cp__Var0 cp__Type cp__Var cp__DomI cp__DomB constraints__simple__Simple cp__ConstraintIsTrue cp__ConstraintAdd cp__ConstraintLe cp__ConstraintOr cp__ConstraintEquiv cp__ConstraintNot cp__ConstraintBoolPresent cp__ConstraintCst all__All cp__ConstraintHelpers all__API all__APIDefensive)
+          utils__extstd__Int63 utils__extstd__Bool cp__Impl0 cp__Var0 cp__Type cp__Var cp__DomI cp__DomB constraints__simple__Simple cp__ConstraintIsTrue cp__ConstraintAdd cp__ConstraintLe cp__ConstraintOr cp__ConstraintEquiv cp__ConstraintNot cp__ConstraintBoolPresent cp__ConstraintCst all__All cp__ConstraintHelpers all__API all__APIDefensive)
        (flags (-w -3))
 )
 
 (rule
    (deps cp.mlw all.mlw cp.drv constraints/simple.mlw)
-   (targets cp__Int63.ml cp__Bool.ml cp__Impl0.ml cp__Var.ml cp__Var0.ml cp__Type.ml cp__DomB.ml cp__DomI.ml constraints__simple__Simple.ml cp__ConstraintIsTrue.ml cp__ConstraintAdd.ml cp__ConstraintLe.ml cp__ConstraintOr.ml cp__ConstraintEquiv.ml cp__ConstraintNot.ml cp__ConstraintBoolPresent.ml cp__ConstraintCst.ml cp__ConstraintHelpers.ml all__All.ml all__API.ml all__APIDefensive.ml)
+   (targets utils__extstd__Int63.ml utils__extstd__Bool.ml cp__Impl0.ml cp__Var.ml cp__Var0.ml cp__Type.ml cp__DomB.ml cp__DomI.ml constraints__simple__Simple.ml cp__ConstraintIsTrue.ml cp__ConstraintAdd.ml cp__ConstraintLe.ml cp__ConstraintOr.ml cp__ConstraintEquiv.ml cp__ConstraintNot.ml cp__ConstraintBoolPresent.ml cp__ConstraintCst.ml cp__ConstraintHelpers.ml all__All.ml all__API.ml all__APIDefensive.ml)
    (action (run why3 extract -L . -D ocaml64 -D cp.drv -o . --modular
-     cp.Int63 cp.Bool cp.Impl0 cp.Var cp.Var0 cp.Type cp.DomI cp.DomB cp.ConstraintCst cp.ConstraintCst
+     utils.extstd.Int63 utils.extstd.Bool cp.Impl0 cp.Var cp.Var0 cp.Type cp.DomI cp.DomB cp.ConstraintCst cp.ConstraintCst
      cp.ConstraintIsTrue cp.ConstraintAdd cp.ConstraintLe cp.ConstraintCst cp.ConstraintOr cp.ConstraintEquiv cp.ConstraintNot cp.ConstraintBoolPresent constraints.simple.Simple cp.ConstraintHelpers all.All all.API all.APIDefensive))
 )
diff --git a/src/lib/utils/bool.mlw b/src/lib/utils/bool.mlw
new file mode 100644
index 0000000000000000000000000000000000000000..54534cb9b9f5754cd2d0fcc248cfe17fbf6cfba0
--- /dev/null
+++ b/src/lib/utils/bool.mlw
@@ -0,0 +1,25 @@
+module Bool
+       use export bool.Bool
+
+       let function andb' (x y : bool) : bool
+        ensures { result = (x /\ y) } =
+       match x with
+       | True -> y
+       | False -> False
+       end
+
+       let function eqb (x y:bool) =
+         match x,y with
+         | True, True | False, False -> true
+         | _ -> false
+         end
+end
+
+module Int63
+
+       use export mach.int.Int63
+
+       let function min x y = if x <= y then x else y
+       let function max x y = if x <= y then y else x
+
+end
diff --git a/src/lib/utils/extstd.mlw b/src/lib/utils/extstd.mlw
new file mode 100644
index 0000000000000000000000000000000000000000..54534cb9b9f5754cd2d0fcc248cfe17fbf6cfba0
--- /dev/null
+++ b/src/lib/utils/extstd.mlw
@@ -0,0 +1,25 @@
+module Bool
+       use export bool.Bool
+
+       let function andb' (x y : bool) : bool
+        ensures { result = (x /\ y) } =
+       match x with
+       | True -> y
+       | False -> False
+       end
+
+       let function eqb (x y:bool) =
+         match x,y with
+         | True, True | False, False -> true
+         | _ -> false
+         end
+end
+
+module Int63
+
+       use export mach.int.Int63
+
+       let function min x y = if x <= y then x else y
+       let function max x y = if x <= y then y else x
+
+end
diff --git a/src/lib/utils/tagtbl.mlw b/src/lib/utils/tagtbl.mlw
new file mode 100644
index 0000000000000000000000000000000000000000..94ba8414c7a3e69f155eaf9fee66e32961533a0c
--- /dev/null
+++ b/src/lib/utils/tagtbl.mlw
@@ -0,0 +1,628 @@
+module S
+
+  use int.Int
+  use utils.extstd.Int63 as Int63
+
+  type key
+
+  val function tag (_:key): Int63.int63
+      ensures { 0 <= result }
+
+  axiom tag_correct: forall x y. tag x = tag y -> x = y
+
+end
+
+module TagtblIntf
+
+  use int.Int
+  use import utils.extstd.Int63 as Int63
+  use map.Map
+  use map.Const
+  use set.Fset as S
+  use list.List
+  use list.Mem as LMem
+  use import mach.array.Array63 as Array
+  use seq.Seq as Seq
+  use bool.Bool
+  use mach.peano.Peano as Peano
+  use mach.peano.Int63 as PeanoInt63
+
+  clone import S as S with axiom tag_correct
+
+  type t 'a = private {
+         ghost mutable contents: map key 'a;
+         ghost defined: S.fset key;
+       }
+
+  function ([]) (h: t 'a) (k: key) : 'a = Map.([]) h.contents k
+
+  val create (s:Int63.int63) (def:'a) (ghost defined: S.fset key): t 'a
+   requires { forall k. S.mem k defined -> tag k <= s }
+   requires { -1 <= s < Int63.max_int63 }
+   ensures { result.contents = const def }
+   ensures { result.defined = defined }
+
+  predicate mem (k: key) (h: t 'a) = S.mem k h.defined
+
+  val function max_tags (h: t 'a) : Int63.int63
+    ensures { forall k. mem k h -> tag k <= result }
+    ensures { -1 <= result < Int63.max_int63 }
+
+  predicate set_ (h1: t 'a) (h2: t 'a) (k: key) (v: 'a) =
+    h1.defined = h2.defined /\ h1.contents = h2.contents[k<-v]
+
+  val set (h: t 'a) (k: key) (v: 'a) : unit
+    requires { mem k h }
+    ensures { set_ h (old h) k v }
+    writes { h.contents }
+
+  function get (h: t 'a) (k: key) : 'a = Map.get h.contents k
+
+  val function find (h: t 'a) (k: key) : 'a
+    requires { mem k h }
+    ensures  { result = h[k] }
+
+  scope Lock
+    type t 'a = abstract {
+         contents: map key 'a;
+         defined: S.fset key;
+       }
+
+    function ([]) (h: t 'a) (k: key) : 'a = Map.([]) h.contents k
+
+    predicate mem (k: key) (h: t 'a) = S.mem k h.defined
+
+    function get (h: t 'a) (k: key) : 'a = Map.get h.contents k
+
+    val function find (h: t 'a) (k: key) : 'a
+      requires { mem k h }
+      ensures  { result = h[k] }
+
+   end
+
+   val copy_lock (h: t 'a): Lock.t 'a
+       ensures { result.Lock.defined = h.defined }
+       ensures { result.Lock.contents = h.contents }
+
+   val copy_unlock (h: Lock.t 'a): t 'a
+       ensures { h.Lock.defined = result.defined }
+       ensures { h.Lock.contents = result.contents }
+
+
+end
+
+
+module Tagtbl
+
+  use int.Int
+  use import utils.extstd.Int63 as Int63
+  use map.Map
+  use map.Const
+  use set.Fset as S
+  use list.List
+  use list.Mem as LMem
+  use import mach.array.Array63 as Array
+  use seq.Seq as Seq
+  use bool.Bool
+  use mach.peano.Peano as Peano
+  use mach.peano.Int63 as PeanoInt63
+
+scope Make
+  clone  S as S with axiom tag_correct
+
+  type key = S.key
+
+  type t 'a = {
+         arr : Array.array 'a;
+         ghost mutable contents: map key 'a;
+         ghost defined: S.fset key;
+       }
+  invariant { forall k. S.mem k defined -> S.tag k < Seq.length arr }
+  invariant { forall k. S.mem k defined -> Map.([]) contents k = Seq.get arr (S.tag k) }
+  by {
+    arr = (Array.make 0 (any 'a): Array.array 'a);
+    defined = S.empty;
+    contents = (const (any 'a): map key 'a);
+  }
+
+  function ([]) (h: t 'a) (k: key) : 'a = Map.([]) h.contents k
+
+  let create (s:Int63.int63) (def:'a) (ghost defined: S.fset key): t 'a
+   requires { forall k. S.mem k defined -> S.tag k <= s }
+   requires { -1 <= s < Int63.max_int63 }
+   ensures { result.contents = const def }
+   ensures { result.defined = defined } =
+   {
+     arr = Array.make (Int63.(+) s 1) def;
+     contents = const def;
+     defined = defined;
+   }
+
+  predicate mem (k: key) (h: t 'a) = S.mem k h.defined
+
+  let function max_tags (h: t 'a) : Int63.int63
+    ensures { forall k. mem k h -> S.tag k <= result }
+    ensures { -1 <= result < Int63.max_int63 }
+  =
+    Int63.(-) (Array.length h.arr) 1
+
+  predicate set_ (h1: t 'a) (h2: t 'a) (k: key) (v: 'a) =
+    h1.defined = h2.defined /\ h1.contents = h2.contents[k<-v]
+
+  let set (h: t 'a) (k: key) (v: 'a) : unit
+    requires { mem k h }
+    ensures { set_ h (old h) k v }
+      =
+      let t = S.tag k in
+      h.arr[t] <- v;
+      h.contents <- Map.set h.contents k v
+
+  function get (h: t 'a) (k: key) : 'a = Map.get h.contents k
+
+
+  let function find (h: t 'a) (k: key) : 'a
+    requires { mem k h }
+    ensures  { result = h[k] } =
+      let t = S.tag k in
+      h.arr[t]
+
+  scope Lock
+    type t 'a = {
+         arr : Array.array 'a;
+         ghost contents: map key 'a;
+         ghost defined: S.fset key;
+       }
+  invariant { forall k. S.mem k defined -> S.tag k < Seq.length arr }
+  invariant { forall k. S.mem k defined -> Map.([]) contents k = Seq.get arr (S.tag k) }
+  by {
+    arr = (Array.make 0 (any 'a): Array.array 'a);
+    defined = S.empty;
+    contents = (const (any 'a): map key 'a);
+  }
+
+    function ([]) (h: t 'a) (k: key) : 'a = Map.([]) h.contents k
+
+    predicate mem (k: key) (h: t 'a) = S.mem k h.defined
+
+    function get (h: t 'a) (k: key) : 'a = Map.get h.contents k
+
+
+    let function find (h: t 'a) (k: key) : 'a
+      requires { mem k h }
+      ensures  { result = h[k] } =
+        let t = S.tag k in
+        h.arr[t]
+
+   end
+
+   let copy_lock (h: t 'a): Lock.t 'a
+       ensures { result.Lock.defined = h.defined }
+       ensures { result.Lock.contents = h.contents } =
+       { Lock.arr = Array.copy h.arr;
+         Lock.contents = h.contents;
+         Lock.defined = h.defined;
+       }
+
+   let copy_unlock (h: Lock.t 'a): t 'a
+       ensures { h.Lock.defined = result.defined }
+       ensures { h.Lock.contents = result.contents } =
+       { arr = Array.copy h.Lock.arr;
+         contents = h.Lock.contents;
+         defined = h.Lock.defined;
+       }
+(*
+    clone TagtblIntf with
+          type S.key = S.key,
+          val S.tag = S.tag,
+          lemma S.tag_correct,
+          type t = t,
+          val create = create,
+          val max_tags = max_tags,
+          val find = find,
+          val set = set,
+          type Lock.t = Lock.t,
+          val Lock.find = Lock.find
+*)
+end
+end
+
+
+module TagtblBacktrackableIntf
+
+  use int.Int
+  use import utils.extstd.Int63 as Int63
+  use map.Map
+  use map.Const
+  use set.Fset as S
+  use list.List
+  use list.Mem as LMem
+  use import mach.array.Array63 as Array
+  use seq.Seq as Seq
+  use bool.Bool
+  use mach.peano.Peano as Peano
+  use mach.peano.Int63 as PeanoInt63
+
+  clone import S as S with axiom tag_correct
+
+  type token 'a
+  function saved_contents (token 'a) : map key 'a
+  function saved_tokens (token 'a): list (token 'a)
+
+  type t 'a = private {
+         ghost mutable contents: map key 'a;
+         ghost defined: S.fset key;
+         ghost mutable tokens : list (token 'a);
+       }
+
+  function ([]) (h: t 'a) (k: key) : 'a = Map.([]) h.contents k
+
+  val create (s:Int63.int63) (def:'a) (ghost defined: S.fset key): t 'a
+   requires { forall k. S.mem k defined -> tag k <= s }
+   requires { -1 <= s < Int63.max_int63 }
+   ensures { result.contents = const def }
+   ensures { result.tokens = Nil }
+   ensures { result.defined = defined }
+
+  predicate mem (k: key) (h: t 'a) = S.mem k h.defined
+
+  val function max_tags (h: t 'a) : Int63.int63
+    ensures { forall k. mem k h -> tag k <= result }
+    ensures { -1 <= result < Int63.max_int63 }
+
+  predicate set_ (h1: t 'a) (h2: t 'a) (k: key) (v: 'a) =
+    h1.defined = h2.defined /\ h1.contents = h2.contents[k<-v]
+
+  val partial set (h: t 'a) (k: key) (v: 'a) : unit
+    requires { mem k h }
+    ensures { set_ h (old h) k v }
+    writes { h.contents }
+
+  function get (h: t 'a) (k: key) : 'a = Map.get h.contents k
+
+  val function find (h: t 'a) (k: key) : 'a
+    requires { mem k h }
+    ensures  { result = h[k] }
+
+  val create_backtrack_point (h: t 'a) : token 'a
+    writes { h.tokens }
+    ensures { result.saved_contents = old h.contents }
+    ensures { result.saved_tokens = (old h.tokens) }
+    ensures { h.tokens = Cons result (old h.tokens) }
+
+
+  val backtrack (h: t 'a) (token:token 'a): unit
+    requires { LMem.mem token h.tokens }
+    ensures { h.tokens = Cons token token.saved_tokens }
+    ensures { h.contents = token.saved_contents }
+    writes { h.tokens, h.contents }
+
+end
+
+
+module TagtblBacktrackable
+
+  use int.Int
+  use import utils.extstd.Int63 as Int63
+  use map.Map
+  use map.Const
+  use set.Fset as S
+  use list.List
+  use list.Mem as LMem
+  use import mach.array.Array63 as Array
+  use seq.Seq as Seq
+  use bool.Bool
+  use mach.peano.Peano as Peano
+  use mach.peano.Int63 as PeanoInt63
+
+scope Make
+  clone  S as S with axiom tag_correct
+
+  type key = S.key
+
+  type token 'a = {
+       offset: Int63.int63;
+       ghost saved_contents: map key 'a;
+       ghost saved_tokens: list (token 'a);
+  }
+
+
+  type history_item 'a = {
+    hist_offset : Int63.int63;
+    hist_value  : 'a;
+  }
+
+  predicate good_contents (contents:map key 'a) (arr:Seq.seq 'a) =
+     forall e. S.tag e < (Seq.length arr) -> contents[e] = Seq.get arr (S.tag e)
+
+  function revert_arr (arr:Seq.seq 'a) (history:Seq.seq (history_item 'a)) (current_offset : int) : Seq.seq 'a =
+    let hi = Seq.get history current_offset in
+    let arr = Seq.set arr (Int63.to_int hi.hist_offset) hi.hist_value in
+    arr
+
+
+  let rec ghost function good_tokens
+      (arr:Seq.seq 'a) (history:Seq.seq (history_item 'a))
+      (current_offset : int)
+      (l: list (token 'a)) : bool
+        variant { current_offset+1, l }
+    =
+        match l with
+          | Nil -> true
+          | Cons t l' ->
+          if (current_offset = (Int63.to_int t.offset))
+          then begin
+            andb (pure {l' = t.saved_tokens})
+            (andb (good_contents t.saved_contents arr)
+            (good_tokens arr history current_offset l'))
+          end
+          else begin
+            (0 <= current_offset) &&
+            let arr = revert_arr arr history current_offset in
+            good_tokens arr history (current_offset - 1) l
+           end
+        end
+
+  let rec lemma good_tokens_frame_history
+      (arr:Seq.seq 'a) (history1:Seq.seq (history_item 'a))
+      (history2:Seq.seq (history_item 'a))
+      (current_offset : int)
+      (l: list (token 'a)) : unit
+      requires { current_offset < Seq.length history1 }
+      requires { current_offset < Seq.length history2 }
+      requires { forall i. 0 <= i <= current_offset -> Seq.get history1 i = Seq.get history2 i }
+      requires { forall i. 0 <= i <= current_offset -> 0 <= (Seq.get history1 i).hist_offset < Seq.length arr }
+      requires { good_tokens arr history1 current_offset l }
+      variant { current_offset, l }
+      ensures { good_tokens arr history2 current_offset l }
+       =
+        match l with
+          | Nil -> ()
+          | Cons t l' ->
+          if (current_offset = (Int63.to_int t.offset))
+          then begin
+             assert { l' = t.saved_tokens };
+             assert { good_contents t.saved_contents arr };
+             assert { good_tokens arr history1 current_offset l' };
+             good_tokens_frame_history arr history1 history2 current_offset l'
+          end
+          else begin
+           let arr = revert_arr arr history2 current_offset in
+           good_tokens_frame_history arr history1 history2 (current_offset - 1) l
+           end
+        end
+
+   let rec lemma good_tokens_smaller_offset
+      (arr:Seq.seq 'a) (history:Seq.seq (history_item 'a))
+      (current_offset : int)
+      (l: list (token 'a)) : unit
+        requires { current_offset < Seq.length history }
+        requires { good_tokens arr history current_offset l }
+        variant { current_offset, l }
+        ensures { forall t. LMem.mem t l -> (Int63.to_int t.offset) <= current_offset }
+    =
+        match l with
+          | Nil -> ()
+          | Cons t l' ->
+          if (current_offset = (Int63.to_int t.offset))
+          then begin 
+             good_tokens_smaller_offset arr history current_offset l'
+          end
+          else begin
+            let arr = revert_arr arr history current_offset in
+              good_tokens_smaller_offset arr history (current_offset - 1) l
+           end
+        end
+
+
+  type t 'a = {
+         arr : Array.array 'a;
+         ghost mutable contents: map key 'a;
+         ghost defined: S.fset key;
+         ghost mutable tokens : list (token 'a);
+         mutable current_offset: Int63.int63;
+         mutable co_peano: Peano.t;
+         mutable history: Array.array (history_item 'a);
+       }
+  invariant { good_contents contents arr }
+  invariant { good_tokens arr history current_offset tokens }
+  invariant { -1 <= current_offset < Array.length history }
+  invariant { 0 < history.length }
+  invariant { forall k. S.mem k defined -> S.tag k < Seq.length arr }
+  invariant { current_offset = co_peano - 2 }
+  invariant { current_offset < Seq.length history }
+  invariant { forall i. 0 <= i <= current_offset -> 0 <= (Seq.get history i).hist_offset < arr.length }
+  invariant { forall i. 0 <= i <= current_offset -> exists k. (Seq.get history i).hist_offset = S.tag k }
+  by {
+    arr = (Array.make 0 (any 'a): Array.array 'a);
+    history = (Array.make 1 {hist_offset = 0; hist_value = any 'a});
+    tokens = Nil;
+    current_offset = -1;
+    co_peano = Peano.one;
+    defined = S.empty;
+    contents = (const (any 'a): map key 'a);
+  }
+
+  function ([]) (h: t 'a) (k: key) : 'a = Map.([]) h.contents k
+
+  let create (s:Int63.int63) (def:'a) (ghost defined: S.fset key): t 'a
+   requires { forall k. S.mem k defined -> S.tag k <= s }
+   requires { -1 <= s < Int63.max_int63 }
+   ensures { result.contents = const def }
+   ensures { result.tokens = Nil }
+   ensures { result.defined = defined } =
+   {
+     arr = Array.make (Int63.(+) s 1) def;
+     contents = const def;
+     tokens = Nil;
+     current_offset = -1;
+     co_peano = Peano.one;
+     defined = defined;
+     history = Array.make 8 {hist_offset = 0; hist_value = def};
+   }
+
+  predicate mem (k: key) (h: t 'a) = S.mem k h.defined
+
+  let function max_tags (h: t 'a) : Int63.int63
+    ensures { forall k. mem k h -> S.tag k <= result }
+    ensures { -1 <= result < Int63.max_int63 }
+  =
+    Int63.(-) (Array.length h.arr) 1
+
+  let resize (h: t 'a) : unit
+    writes { h.history }
+    ensures { h.current_offset + 1 < Array.length h.history }
+    =
+    let s = Array.length h.history in
+    if h.current_offset + 1 = s then
+      let _co_peano = PeanoInt63.to_int63 h.co_peano in
+      assert { h.current_offset < _co_peano <= Int63.max_int };
+      assert { s < Int63.max_int };
+      let s' = if Int63.(/) Int63.max_int 2 < s then Int63.max_int else Int63.(*) s 2 in
+      let ndata = Array.make s' (Array.([]) h.history 0) in
+      Array.blit h.history 0 ndata 0 s;
+      good_tokens_frame_history h.arr.elts h.history.elts ndata.elts (Int63.to_int h.current_offset) h.tokens;
+      h.history <- ndata
+
+  predicate set_ (h1: t 'a) (h2: t 'a) (k: key) (v: 'a) =
+    h1.defined = h2.defined /\ h1.contents = h2.contents[k<-v]
+
+  let set (h: t 'a) (k: key) (v: 'a) : unit
+    requires { mem k h }
+    ensures { set_ h (old h) k v }
+      =
+      resize h;
+      assert { forall i. 0 <= i <= h.current_offset -> 0 <= (Seq.get h.history i).hist_offset < h.arr.length };
+      let t = S.tag k in
+      let ghost h_before = h.history.elts in
+      let ghost arr_before = h.arr.elts in
+      let ghost co_before = h.current_offset in
+      h.current_offset <- h.current_offset + 1;
+      let old_v = (Array.([]) h.arr t) in
+(*      assert { 0 <= t < h.arr.length };
+      assert { forall i. 0 <= i <= co_before -> 0 <= (Seq.get h.history i).hist_offset < h.arr.length }; *)
+      h.history[h.current_offset] <- {hist_offset=t; hist_value=old_v};
+(*      assert { forall i. 0 <= i <= co_before -> (Seq.get h.history i).hist_offset = (Seq.get h_before i).hist_offset }; *)
+(*      assert { forall i. 0 <= i <= co_before -> 0 <= (Seq.get h.history i).hist_offset < h.arr.length }; *)
+      assert { forall i. 0 <= i <= h.current_offset -> 0 <= (Seq.get h.history i).hist_offset < h.arr.length
+        by (forall i. 0 <= i <= co_before -> (Seq.get h.history i).hist_offset = (Seq.get h_before i).hist_offset)
+       };
+      assert { exists k. (Seq.get h.history h.current_offset).hist_offset = S.tag k };
+      good_tokens_frame_history h.arr.elts h_before h.history.elts (Int63.to_int h.current_offset - 1) h.tokens;
+      assert { exists k. (Seq.get h.history h.current_offset).hist_offset = S.tag k };
+      assert { forall i. 0 <= i <= h.current_offset - 1 -> exists k. (Seq.get h.history i).hist_offset = S.tag k };
+      h.arr[t] <- v;
+      h.contents <- Map.set h.contents k v;
+      h.co_peano <- Peano.succ h.co_peano;
+      assert { arr_before = Seq.set h.arr.elts (Int63.to_int t) old_v };
+      assert { match h.tokens with
+      | Nil -> true
+      | Cons t _ ->  t.offset <= (old h.current_offset)
+      end };
+      ()
+
+  function get (h: t 'a) (k: key) : 'a = Map.get h.contents k
+
+
+  let function find (h: t 'a) (k: key) : 'a
+    requires { mem k h }
+    ensures  { result = h[k] } =
+      let t = S.tag k in
+      h.arr[t]
+
+  let create_backtrack_point (h: t 'a) : token 'a
+    writes { h.tokens }
+    ensures { result.saved_contents = old h.contents }
+    ensures { result.saved_tokens = old h.tokens }
+    ensures { h.tokens = Cons result (old h.tokens) } =
+    let t = { offset = h.current_offset;
+      saved_tokens = h.tokens;
+      saved_contents = h.contents;
+     } in
+    h.tokens <- Cons t h.tokens;
+    t
+
+  predicate backtrack_aux (token : token 'a) (h: t 'a) =
+     if token.offset = h.current_offset
+     then begin
+                    good_contents token.saved_contents h.arr
+                   /\  good_tokens h.arr h.history h.current_offset h.tokens
+                   /\  Cons token token.saved_tokens = h.tokens
+                     end
+                     else begin
+                      LMem.mem token h.tokens
+                   /\ (0 <= h.current_offset) /\
+                     let arr = revert_arr h.arr h.history h.current_offset in
+                     good_tokens arr h.history (h.current_offset - 1) h.tokens
+                   end
+
+  let backtrack (h: t 'a) (token:token 'a): unit
+    requires { LMem.mem token h.tokens }
+    ensures { h.tokens = Cons token token.saved_tokens }
+    ensures { h.contents = token.saved_contents } =
+    let rec aux () : unit
+        requires { LMem.mem token h.tokens }
+        variant { h.current_offset }
+        ensures { h.tokens = Cons token token.saved_tokens }
+        ensures { h.contents = token.saved_contents }
+    =
+        let rec ghost aux' (l: list (token 'a)) : unit
+          requires { LMem.mem token l }
+          requires { good_tokens h.arr h.history h.current_offset l }
+          ensures { backtrack_aux token h }
+          variant { l }
+        =
+         match l with
+         | Nil -> absurd
+         | Cons t l' ->
+          if pure { h.current_offset = t.offset }
+          then begin if pure { t = token }
+          then h.tokens <- l
+          else aux' l'
+          end
+          else begin
+           assert { LMem.mem token l };
+           let arr = revert_arr h.arr.elts h.history.elts (Int63.to_int h.current_offset) in
+           assert { good_tokens arr h.history (h.current_offset - 1) l };
+           h.tokens <- l
+           end
+        end
+        in
+        aux' h.tokens;
+        if (Int63.(=) h.current_offset token.offset)
+        then begin
+          h.contents <- token.saved_contents
+        end
+        else begin
+          let hi = Array.([]) h.history h.current_offset in
+          Array.([]<-) h.arr hi.hist_offset hi.hist_value;
+          let ghost k = any key ensures { hi.hist_offset = S.tag result } in
+          h.contents <- Map.set h.contents k hi.hist_value;
+          h.current_offset <- h.current_offset - 1;
+          h.co_peano <- Peano.pred h.co_peano;
+          assert { Map.get h.contents k = Seq.get h.arr (S.tag k) };
+          assert { forall e. S.tag e < (Seq.length h.arr) -> Map.get h.contents e = Seq.get h.arr (S.tag e) };
+          assert { good_tokens h.arr h.history h.current_offset h.tokens };
+          aux ()
+         end
+    in
+    aux ()
+
+
+    clone TagtblBacktrackableIntf with
+          type S.key = S.key,
+          val S.tag = S.tag,
+          lemma S.tag_correct,
+          type token = token,
+          function saved_contents = saved_contents,
+          function saved_tokens = saved_tokens,
+          type t = t,
+          val create = create,
+          val max_tags = max_tags,
+          val find = find,
+          val set = set,
+          val create_backtrack_point = create_backtrack_point,
+          val backtrack = backtrack
+
+
+end
+end