diff --git a/examples/stdlib/tagset/why3session.xml b/examples/stdlib/tagset/why3session.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d2acd2f1201537185d60368a8f80c7c287e46bff
--- /dev/null
+++ b/examples/stdlib/tagset/why3session.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE why3session PUBLIC "-//Why3//proof session v5//EN"
+"http://why3.lri.fr/why3session.dtd">
+<why3session shape_version="5">
+<prover id="0" name="Alt-Ergo" version="2.2.0" timelimit="1" steplimit="0" memlimit="1000"/>
+<prover id="1" name="CVC4" version="1.6" timelimit="1" steplimit="0" memlimit="1000"/>
+<prover id="2" name="Z3" version="4.4.1" timelimit="1" steplimit="0" memlimit="1000"/>
+<file proved="true">
+<path name=".."/>
+<path name=".."/>
+<path name=".."/>
+<path name="stdlib"/>
+<path name="mach"/>
+<path name="tagset.mlw"/>
+<theory name="TagSetIntf" proved="true">
+ <goal name="VC t" expl="VC for t" proved="true">
+ <proof prover="1"><result status="valid" time="0.08"/></proof>
+ </goal>
+ <goal name="VC iterator" expl="VC for iterator" proved="true">
+ <proof prover="0" obsolete="true"><result status="unknown" time="0.01"/></proof>
+ <proof prover="1"><result status="valid" time="0.05"/></proof>
+ <proof prover="2" obsolete="true"><result status="timeout" time="1.00"/></proof>
+ </goal>
+</theory>
+<theory name="TagSet" proved="true">
+ <goal name="VC iteration_state" expl="VC for iteration_state" proved="true">
+ <proof prover="1"><result status="valid" time="0.08"/></proof>
+ </goal>
+ <goal name="VC t" expl="VC for t" proved="true">
+ <proof prover="1"><result status="valid" time="0.03"/></proof>
+ </goal>
+ <goal name="VC create" expl="VC for create" proved="true">
+ <proof prover="1"><result status="valid" time="0.12"/></proof>
+ </goal>
+ <goal name="VC mem" expl="VC for mem" proved="true">
+ <proof prover="1"><result status="valid" time="0.09"/></proof>
+ </goal>
+ <goal name="VC max_tags" expl="VC for max_tags" proved="true">
+ <proof prover="1"><result status="valid" time="0.06"/></proof>
+ </goal>
+ <goal name="VC add" expl="VC for add" proved="true">
+ <proof prover="1"><result status="valid" time="0.28"/></proof>
+ </goal>
+ <goal name="VC iterator" expl="VC for iterator" proved="true">
+ <proof prover="1"><result status="valid" time="0.10"/></proof>
+ </goal>
+ <goal name="Iterator.VC create" expl="VC for create" proved="true">
+ <proof prover="1"><result status="valid" time="0.36"/></proof>
+ </goal>
+ <goal name="Iterator.VC is_empty" expl="VC for is_empty" proved="true">
+ <proof prover="1"><result status="valid" time="0.16"/></proof>
+ </goal>
+ <goal name="Iterator.VC next" expl="VC for next" proved="true">
+ <transf name="split_vc" proved="true" >
+  <goal name="VC next.0" expl="assertion" proved="true">
+  <proof prover="0"><result status="valid" time="0.02" steps="122"/></proof>
+  </goal>
+  <goal name="VC next.1" expl="index in array bounds" proved="true">
+  <proof prover="1"><result status="valid" time="0.06"/></proof>
+  </goal>
+  <goal name="VC next.2" expl="integer overflow" proved="true">
+  <proof prover="1"><result status="valid" time="0.06"/></proof>
+  </goal>
+  <goal name="VC next.3" expl="loop invariant init" proved="true">
+  <proof prover="1"><result status="valid" time="0.05"/></proof>
+  </goal>
+  <goal name="VC next.4" expl="loop invariant init" proved="true">
+  <proof prover="1"><result status="valid" time="0.06"/></proof>
+  </goal>
+  <goal name="VC next.5" expl="index in array bounds" proved="true">
+  <proof prover="1"><result status="valid" time="0.07"/></proof>
+  </goal>
+  <goal name="VC next.6" expl="integer overflow" proved="true">
+  <proof prover="1"><result status="valid" time="0.05"/></proof>
+  </goal>
+  <goal name="VC next.7" expl="loop variant decrease" proved="true">
+  <proof prover="1"><result status="valid" time="0.05"/></proof>
+  </goal>
+  <goal name="VC next.8" expl="loop invariant preservation" proved="true">
+  <proof prover="1"><result status="valid" time="0.04"/></proof>
+  </goal>
+  <goal name="VC next.9" expl="loop invariant preservation" proved="true">
+  <proof prover="1"><result status="valid" time="0.07"/></proof>
+  </goal>
+  <goal name="VC next.10" expl="assertion" proved="true">
+  <proof prover="1"><result status="valid" time="0.07"/></proof>
+  </goal>
+  <goal name="VC next.11" expl="type invariant" proved="true">
+  <proof prover="1"><result status="valid" time="0.10"/></proof>
+  </goal>
+  <goal name="VC next.12" expl="type invariant" proved="true">
+  <proof prover="1"><result status="valid" time="0.06"/></proof>
+  </goal>
+  <goal name="VC next.13" expl="type invariant" proved="true">
+  <proof prover="1"><result status="valid" time="0.08"/></proof>
+  </goal>
+  <goal name="VC next.14" expl="type invariant" proved="true">
+  <proof prover="1"><result status="valid" time="0.07"/></proof>
+  </goal>
+  <goal name="VC next.15" expl="type invariant" proved="true">
+  <proof prover="1"><result status="valid" time="0.24"/></proof>
+  </goal>
+  <goal name="VC next.16" expl="type invariant" proved="true">
+  <proof prover="1"><result status="valid" time="0.12"/></proof>
+  </goal>
+  <goal name="VC next.17" expl="postcondition" proved="true">
+  <proof prover="1"><result status="valid" time="0.12"/></proof>
+  </goal>
+  <goal name="VC next.18" expl="postcondition" proved="true">
+  <proof prover="1"><result status="valid" time="0.04"/></proof>
+  </goal>
+  <goal name="VC next.19" expl="postcondition" proved="true">
+  <proof prover="1"><result status="valid" time="0.04"/></proof>
+  </goal>
+ </transf>
+ </goal>
+</theory>
+</file>
+</why3session>
diff --git a/stdlib/mach/tagset.mlw b/stdlib/mach/tagset.mlw
new file mode 100644
index 0000000000000000000000000000000000000000..eae1e170466851de81b5f0ae4d9e5faace1a0edd
--- /dev/null
+++ b/stdlib/mach/tagset.mlw
@@ -0,0 +1,316 @@
+module S
+
+  use int.Int
+  use mach.int.Int63 as Int63
+
+  type key
+
+  val function tag (k:key): Int63.int63
+      ensures { 0 <= result }
+
+  axiom tag_correct: forall x y. tag x = tag y -> x = y
+
+end
+
+module TagSetIntf
+
+  use int.Int
+  use import mach.int.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
+  use ref.Ref
+
+  clone import S as S with axiom tag_correct
+
+  type iteration_state = mutable { }
+
+  type t = abstract {
+         mutable elts: S.set key;
+         max_tags_: int;
+         mutable iterated: iteration_state;
+       }
+   invariant { forall v. S.mem v elts -> tag v <= max_tags_ }
+   by {
+      elts = S.empty;
+      max_tags_ = 0;
+      iterated = any iteration_state;
+    }
+
+  val create (s:Int63.int63) (def:key) : t
+   requires { -1 <= s < Int63.max_int63 }
+   ensures { result.elts = S.empty }
+   ensures { result.max_tags_ = s }
+
+  val function mem (k: key) (h: t) : bool
+   ensures { result = S.mem k h.elts }
+
+  val function max_tags (h: t) : Int63.int63
+    ensures { result = h.max_tags_ }
+
+  val add (h: t) (k: key): unit
+    requires { tag k <= h.max_tags }
+    ensures { h.elts = S.add k (old h.elts) }
+    writes { h.elts, h.iterated }
+
+  type iterator = abstract {
+       iterating: iteration_state;
+       mutable seen: S.set key;
+       mutable todo: S.set key;
+       all: S.set key;
+  }
+  invariant { S.(union seen todo == all) }
+  invariant { S.(inter seen todo == S.empty) }
+  by {
+    iterating = any iteration_state;
+    seen = S.empty;
+    todo = S.empty;
+    all = S.empty
+    }
+
+  scope Iterator
+
+     val create (h:t) : iterator
+          ensures { result.seen = S.empty }
+          ensures { result.todo = h.elts }
+          ensures { result.all = h.elts }
+          alias { result.iterating with h.iterated }
+
+      predicate is_empty (i:iterator) = S.is_empty i.todo
+
+      val is_empty (i:iterator) : bool
+          ensures { result = (S.is_empty i.todo) }
+
+      val next (i:iterator) : key
+          requires { not (S.is_empty i.todo) }
+          writes { i.seen, i.todo }
+          ensures { S.mem result (old i.todo) }
+          ensures { i.todo = S.remove result (old i.todo) }
+          ensures { i.seen = S.add result (old i.seen) }
+  end
+
+end
+
+module TagSet
+
+  use int.Int
+  use import mach.int.Int63 as Int63
+  use set.Fset as S
+  use import mach.array.Array63 as Array
+  use seq.Seq
+  use bool.Bool
+  use mach.peano.Peano as Peano
+  use mach.peano.Int63 as PeanoInt63
+  use ref.Ref
+
+  clone import S as S with axiom tag_correct
+
+  type iteration_state = mutable {
+       ghost max_tags_': int;
+       ghost mutable elts': S.set key;
+       present: array bool;
+       value: array key;
+  }
+  invariant { forall v. S.mem v elts' -> tag v <= max_tags_'  }
+  invariant { forall v. S.mem v elts' -> present[tag v] }
+  invariant { forall i. 0 <= i <= max_tags_' -> present[i] -> tag (value[i]) = i }
+  invariant { forall i. 0 <= i <= max_tags_' -> present[i] -> forall v. tag v = i -> S.mem v elts' }
+  invariant { present.length = max_tags_' + 1 }
+  invariant { value.length = max_tags_' + 1 }
+  by {
+     max_tags_' = -1;
+     elts' = S.empty;
+     present = Array.make 0 false;
+     value = Array.make 0 (any key);
+   }
+
+  type t = {
+         ghost mutable elts: S.set key;
+         ghost max_tags_: int;
+         mutable iterated: iteration_state;
+       }
+   invariant { max_tags_ = iterated.max_tags_' }
+   invariant { elts = iterated.elts' }
+
+  let create (s:Int63.int63) (def:key) : t
+   requires { -1 <= s < Int63.max_int63 }
+   ensures { result.elts = S.empty }
+   ensures { result.max_tags_ = s } =
+   let iterated =  {
+         elts' = S.empty;
+         max_tags_' = Int63.to_int s;
+         present = Array.make (s+1) false;
+         value = Array.make (s+1) def;
+      }
+   in
+   {
+      elts = S.empty;
+      max_tags_ = Int63.to_int s;
+      iterated = iterated;
+   }
+
+  let function mem (k: key) (h: t) : bool
+   ensures { result = S.mem k h.elts } =
+     tag k < Array.length h.iterated.present && Array.(h.iterated.present[tag k])
+
+  let function max_tags (h: t) : Int63.int63
+    ensures { result = h.max_tags_ } =
+    Array.(length h.iterated.present) - 1
+
+  let add (h: t) (k: key): unit
+    requires { tag k <= h.max_tags }
+    ensures { h.elts = S.add k (old h.elts) }
+    writes { h.elts , h.iterated, h.iterated.present, h.iterated.value(*, h.iterated.elts'*) } =
+    h.elts <- S.add k h.elts;
+    h.iterated.elts' <- S.add k h.iterated.elts';
+    h.iterated.present[tag k] <- true;
+    h.iterated.value[tag k] <- k ;
+    if false then
+       h.iterated <- {
+           max_tags_' = h.iterated.max_tags_';
+           elts' = h.iterated.elts';
+           present = h.iterated.present;
+           value = h.iterated.value;
+         }
+
+  type iterator = {
+       iterating: iteration_state;
+       ghost mutable seen: S.set key;
+       ghost mutable todo: S.set key;
+       ghost all: S.set key;
+       mutable offset: int63;
+  }
+  invariant { S.(==) all (S.union seen todo) }
+  invariant { all = iterating.elts' }
+  invariant { 0 <= offset <= Seq.length iterating.present }
+  invariant { offset < Seq.length iterating.present -> iterating.present[offset] }
+  invariant { forall v. S.mem v all -> (0 <= tag v < offset) <-> S.mem v seen }
+  invariant { forall v. S.mem v all -> (offset <= tag v < Seq.length iterating.present) <-> S.mem v todo }
+  by {
+    seen = S.empty;
+    todo = S.empty;
+    all = S.empty;
+    offset = 0;
+    iterating =  {
+     max_tags_' = -1;
+     elts' = S.empty;
+     present = Array.make 0 false;
+     value = Array.make 0 (any key);
+   }
+ }
+
+  scope Iterator
+
+      let create (h:t) : iterator
+          ensures { result.seen = S.empty }
+          ensures { result.todo = h.elts }
+          ensures { result.all = h.elts }
+          alias { result.iterating with h.iterated }
+      =
+       let i = ref 0 in
+       while !i < Array.length h.iterated.present && notb Array.(h.iterated.present[!i]) do
+          variant { Array.length h.iterated.present - !i }
+          invariant { 0 <= !i <= Array.length h.iterated.present }
+          invariant { forall j. 0 <= j < !i -> notb h.iterated.present[j] }
+          i := !i + 1
+       done;
+       {
+          iterating = h.iterated;
+          seen = S.empty;
+          todo = h.elts;
+          all = h.elts;
+          offset = !i;
+        }
+
+
+      predicate is_empty (i:iterator) = S.is_empty i.todo
+
+      let is_empty (i:iterator) : bool
+          ensures { result = (S.is_empty i.todo) } =
+          if i.offset = Array.length i.iterating.present
+          then begin
+            assert { forall v. S.mem v i.todo -> S.mem v i.all };
+            True
+          end
+          else begin
+            assert { i.offset < Array.length i.iterating.present };
+            assert { i.iterating.present[i.offset] };
+            assert { i.iterating.present[i.offset] };
+            assert { S.mem i.iterating.value[i.offset] i.all };
+            assert { S.mem i.iterating.value[i.offset] i.todo };
+            False
+          end
+
+      let next (i:iterator) : key
+          requires { not (S.is_empty i.todo) }
+          writes { i.seen, i.todo, i.offset }
+          ensures { S.mem result (old i.todo) }
+          ensures { i.todo = S.remove result (old i.todo) }
+          ensures { i.seen = S.add result (old i.seen) } =
+           assert { i.offset < Array.length i.iterating.present };
+           let k = Array.(i.iterating.value[i.offset]) in
+           i.seen <- S.add k i.seen;
+           i.todo <- S.remove k i.todo;
+           i.offset <- i.offset + 1;
+           while i.offset < Array.length i.iterating.present && notb Array.(i.iterating.present[i.offset]) do
+             invariant { old i.offset < i.offset <= Array.length i.iterating.present }
+             invariant { forall j. old i.offset < j < i.offset -> notb i.iterating.present[j] }
+             variant { Array.length i.iterating.present - i.offset }
+             i.offset <- i.offset + 1
+           done;
+           assert { forall j. old i.offset < j < i.offset -> notb i.iterating.present[j] };
+           k
+  end
+
+(*
+  clone TagSetIntf with
+        type S.key = key,
+        val S.tag = tag,
+        lemma S.tag_correct,
+        type iteration_state = iteration_state,
+        type t = t,
+        val create = create,
+        val mem = mem,
+        val max_tags = max_tags,
+        val add = add,
+        type iterator = iterator,
+        val Iterator.create = Iterator.create,
+        val Iterator.is_empty = Iterator.is_empty,
+        val Iterator.next = Iterator.next
+*)
+
+end
+
+(* module T *)
+
+(*        use mach.int.Int63 *)
+
+(*        type t = *)
+(*        | A *)
+(*        | B *)
+
+(*        let function tag (x:t) : int63 = match x with A -> 0 | B -> 1 end *)
+(*        clone TagSet with type S.key = t, val S.tag = tag *)
+
+(*        let test () = *)
+(*            let s = create 10 A in *)
+(*            add s A; *)
+(*            let iter1 = Iterator.create s in *)
+(*            assert { not (Iterator.is_empty iter1) }; *)
+(*            let b = Iterator.is_empty iter1 in *)
+(*            assert { not b }; *)
+(*            let x = Iterator.next iter1 in *)
+(*            assert { x = A }; *)
+(*            add s B; *)
+(*            let x = Iterator.next iter1 in *)
+(*            assert { x = A } *)
+
+
+(* end *)