From de5b5fb623eef8b909ce1894db79ceb318f2be06 Mon Sep 17 00:00:00 2001
From: "Emmanouil (Manos) Koukoutos" <emmanouil.koukoutos@epfl.ch>
Date: Thu, 22 Jan 2015 20:02:25 +0100
Subject: [PATCH] Add/Fix benchmarks

---
 testcases/repair/Desugar/Desugar2.scala       |   2 +-
 testcases/repair/HeapSort/HeapSort5.scala     |   4 +-
 testcases/repair/HeapSort/HeapSort8.scala     |   4 +-
 testcases/repair/List/FirstIndexOf.scala      |  31 --
 testcases/repair/List/FirstIndexOf1.scala     |  31 --
 testcases/repair/List/FirstIndexOf2.scala     |  31 --
 testcases/repair/List/FirstIndexOf3.scala     |  31 --
 testcases/repair/List/FirstIndexOf4.scala     |  31 --
 testcases/repair/List/List.scala              | 420 +++++++++++++++++
 testcases/repair/List/List1.scala             | 420 +++++++++++++++++
 testcases/repair/List/List2.scala             | 426 +++++++++++++++++
 testcases/repair/List/List3.scala             | 428 ++++++++++++++++++
 testcases/repair/List/List4.scala             | 420 +++++++++++++++++
 testcases/repair/List/List5.scala             | 417 +++++++++++++++++
 testcases/repair/List/List6.scala             | 423 +++++++++++++++++
 testcases/repair/List/Size.scala              |  19 -
 testcases/repair/List/Size1.scala             |  17 -
 testcases/repair/List/Sum.scala               |  19 -
 testcases/repair/List/Sum1.scala              |  19 -
 .../RedBlackTree-old/RedBlackTree.scala       | 101 +++++
 .../RedBlackTree-old/RedBlackTree1.scala      | 143 ++++++
 .../RedBlackTree-old/RedBlackTree2.scala      | 143 ++++++
 .../RedBlackTree-old/RedBlackTree3.scala      | 143 ++++++
 .../RedBlackTree4.scala                       |   0
 .../RedBlackTree5.scala                       |   0
 .../RedBlackTree-old/RedBlackTree6.scala      | 142 ++++++
 .../RedBlackTree7.scala                       |   0
 .../repair/RedBlackTree/RedBlackTree.scala    | 154 +++++--
 .../repair/RedBlackTree/RedBlackTree1.scala   | 202 +++++----
 .../repair/RedBlackTree/RedBlackTree2.scala   | 188 ++++----
 .../repair/RedBlackTree/RedBlackTree3.scala   | 202 +++++----
 .../repair/RedBlackTree/RedBlackTree6.scala   | 191 ++++----
 32 files changed, 4151 insertions(+), 651 deletions(-)
 delete mode 100644 testcases/repair/List/FirstIndexOf.scala
 delete mode 100644 testcases/repair/List/FirstIndexOf1.scala
 delete mode 100644 testcases/repair/List/FirstIndexOf2.scala
 delete mode 100644 testcases/repair/List/FirstIndexOf3.scala
 delete mode 100644 testcases/repair/List/FirstIndexOf4.scala
 create mode 100644 testcases/repair/List/List.scala
 create mode 100644 testcases/repair/List/List1.scala
 create mode 100644 testcases/repair/List/List2.scala
 create mode 100644 testcases/repair/List/List3.scala
 create mode 100644 testcases/repair/List/List4.scala
 create mode 100644 testcases/repair/List/List5.scala
 create mode 100644 testcases/repair/List/List6.scala
 delete mode 100644 testcases/repair/List/Size.scala
 delete mode 100644 testcases/repair/List/Size1.scala
 delete mode 100644 testcases/repair/List/Sum.scala
 delete mode 100644 testcases/repair/List/Sum1.scala
 create mode 100644 testcases/repair/RedBlackTree-old/RedBlackTree.scala
 create mode 100644 testcases/repair/RedBlackTree-old/RedBlackTree1.scala
 create mode 100644 testcases/repair/RedBlackTree-old/RedBlackTree2.scala
 create mode 100644 testcases/repair/RedBlackTree-old/RedBlackTree3.scala
 rename testcases/repair/{RedBlackTree => RedBlackTree-old}/RedBlackTree4.scala (100%)
 rename testcases/repair/{RedBlackTree => RedBlackTree-old}/RedBlackTree5.scala (100%)
 create mode 100644 testcases/repair/RedBlackTree-old/RedBlackTree6.scala
 rename testcases/repair/{RedBlackTree => RedBlackTree-old}/RedBlackTree7.scala (100%)

diff --git a/testcases/repair/Desugar/Desugar2.scala b/testcases/repair/Desugar/Desugar2.scala
index d070fc4a2..a068dadcb 100644
--- a/testcases/repair/Desugar/Desugar2.scala
+++ b/testcases/repair/Desugar/Desugar2.scala
@@ -146,7 +146,7 @@ object Desugar {
   @induct
   def desugar(e : Trees.Expr) : SimpleE = { e match {
     case Trees.Plus (lhs, rhs) => Plus(desugar(lhs), desugar(rhs))
-    case Trees.Minus(lhs, rhs) => Plus(desugar(lhs), desugar(rhs)) // FIXME forgot Neg
+    case Trees.Minus(lhs, rhs) => Literal(0)//Plus(desugar(lhs), desugar(rhs)) // FIXME forgot Neg
     case Trees.LessThan(lhs, rhs) => LessThan(desugar(lhs), desugar(rhs))
     case Trees.And  (lhs, rhs) => Ite(desugar(lhs), desugar(rhs), Literal(0)) 
     case Trees.Or   (lhs, rhs) => Ite(desugar(lhs), Literal(1), desugar(rhs))
diff --git a/testcases/repair/HeapSort/HeapSort5.scala b/testcases/repair/HeapSort/HeapSort5.scala
index 83a75b7ae..33a3ff5aa 100644
--- a/testcases/repair/HeapSort/HeapSort5.scala
+++ b/testcases/repair/HeapSort/HeapSort5.scala
@@ -60,7 +60,7 @@ object HeapSort {
       case (Leaf(), _) => h2
       case (_, Leaf()) => h1
       case (Node(v1, l1, r1), Node(v2, l2, r2)) =>
-        if(v1 >= v2)
+        if(v1 <= v2) // FIXME should be >=
           makeN(v1, l1, merge(r1, h2))
         else
           makeN(v2, l2, merge(h1, r2))
@@ -85,7 +85,7 @@ object HeapSort {
   def insert(element: Int, heap: Heap) : Heap = {
     require(hasLeftistProperty(heap) && hasHeapProperty(heap))
 
-    merge(Node(element + 1, Leaf(), Leaf()), heap) // FIXME lol.
+    merge(Node(element, Leaf(), Leaf()), heap)
 
   } ensuring { res =>
     hasLeftistProperty(res) && hasHeapProperty(res) &&
diff --git a/testcases/repair/HeapSort/HeapSort8.scala b/testcases/repair/HeapSort/HeapSort8.scala
index 33a3ff5aa..83a75b7ae 100644
--- a/testcases/repair/HeapSort/HeapSort8.scala
+++ b/testcases/repair/HeapSort/HeapSort8.scala
@@ -60,7 +60,7 @@ object HeapSort {
       case (Leaf(), _) => h2
       case (_, Leaf()) => h1
       case (Node(v1, l1, r1), Node(v2, l2, r2)) =>
-        if(v1 <= v2) // FIXME should be >=
+        if(v1 >= v2)
           makeN(v1, l1, merge(r1, h2))
         else
           makeN(v2, l2, merge(h1, r2))
@@ -85,7 +85,7 @@ object HeapSort {
   def insert(element: Int, heap: Heap) : Heap = {
     require(hasLeftistProperty(heap) && hasHeapProperty(heap))
 
-    merge(Node(element, Leaf(), Leaf()), heap)
+    merge(Node(element + 1, Leaf(), Leaf()), heap) // FIXME lol.
 
   } ensuring { res =>
     hasLeftistProperty(res) && hasHeapProperty(res) &&
diff --git a/testcases/repair/List/FirstIndexOf.scala b/testcases/repair/List/FirstIndexOf.scala
deleted file mode 100644
index d59131506..000000000
--- a/testcases/repair/List/FirstIndexOf.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-import leon.lang._
-import leon.collection._
-import leon.lang.synthesis._
-
-
-object FirstIndexOf {
-  def firstIndexOf(l: List[Int], v: Int): Int = {
-    l match {
-      case Cons(h, t) if v == h => 0
-      case Cons(h, t) =>
-        if (firstIndexOf(t, v) >= 0) {
-          firstIndexOf(t, v)+1
-        } else {
-          -1
-        }
-      case Nil() =>
-        -1
-    }
-  } ensuring {
-    (res: Int) => (if (l.content contains v) {
-      l.size > res && l.apply(res) == v
-    } else {
-      res == -1
-    }) && (((l,v), res) passes {
-      case (Cons(0, Cons(1, Cons(2, Cons(3, Nil())))), 3) => 3
-      case (Cons(0, Cons(2, Cons(3, Cons(1, Nil())))), 1) => 3
-      case (Cons(0, Cons(1, Cons(3, Cons(1, Nil())))), 1) => 1
-      case (Cons(0, Cons(1, Cons(3, Cons(1, Nil())))), 2) => -1
-    })
-  }
-}
diff --git a/testcases/repair/List/FirstIndexOf1.scala b/testcases/repair/List/FirstIndexOf1.scala
deleted file mode 100644
index 382e09a2f..000000000
--- a/testcases/repair/List/FirstIndexOf1.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-import leon.lang._
-import leon.collection._
-import leon.lang.synthesis._
-
-
-object FirstIndexOf {
-  def firstIndexOf(l: List[Int], v: Int): Int = {
-    l match {
-      case Cons(h, t) if v == h => 0
-      case Cons(h, t) =>
-        if (firstIndexOf(t, v) >= 0) {
-          firstIndexOf(t, v) // Should be +1 (Solves with CEGIS)
-        } else {
-          -1
-        }
-      case Nil() =>
-        -1
-    }
-  } ensuring {
-    (res: Int) => (if (l.content contains v) {
-      l.size > res && l.apply(res) == v
-    } else {
-      res == -1
-    }) && (((l,v), res) passes {
-      case (Cons(0, Cons(1, Cons(2, Cons(3, Nil())))), 3) => 3
-      case (Cons(0, Cons(2, Cons(3, Cons(1, Nil())))), 1) => 3
-      case (Cons(0, Cons(1, Cons(3, Cons(1, Nil())))), 1) => 1
-      case (Cons(0, Cons(1, Cons(3, Cons(1, Nil())))), 2) => -1
-    })
-  }
-}
diff --git a/testcases/repair/List/FirstIndexOf2.scala b/testcases/repair/List/FirstIndexOf2.scala
deleted file mode 100644
index bf78b606f..000000000
--- a/testcases/repair/List/FirstIndexOf2.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-import leon.lang._
-import leon.collection._
-import leon.lang.synthesis._
-
-
-object FirstIndexOf {
-  def firstIndexOf(l: List[Int], v: Int): Int = {
-    l match {
-      case Cons(h, t) if v == h => 0
-      case Cons(h, t) =>
-        if (firstIndexOf(t, v) >= 0) {
-          firstIndexOf(t, v)+2 // Should be +1
-        } else {
-          -1
-        }
-      case Nil() =>
-        -1
-    }
-  } ensuring {
-    (res: Int) => (if (l.content contains v) {
-      l.size > res && l.apply(res) == v
-    } else {
-      res == -1
-    }) && (((l,v), res) passes {
-      case (Cons(0, Cons(1, Cons(2, Cons(3, Nil())))), 3) => 3
-      case (Cons(0, Cons(2, Cons(3, Cons(1, Nil())))), 1) => 3
-      case (Cons(0, Cons(1, Cons(3, Cons(1, Nil())))), 1) => 1
-      case (Cons(0, Cons(1, Cons(3, Cons(1, Nil())))), 2) => -1
-    })
-  }
-}
diff --git a/testcases/repair/List/FirstIndexOf3.scala b/testcases/repair/List/FirstIndexOf3.scala
deleted file mode 100644
index 9904ef804..000000000
--- a/testcases/repair/List/FirstIndexOf3.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-import leon.lang._
-import leon.collection._
-import leon.lang.synthesis._
-
-
-object FirstIndexOf {
-  def firstIndexOf(l: List[Int], v: Int): Int = {
-    l match {
-      case Cons(h, t) if v == h => 0
-      case Cons(h, t) =>
-        if (firstIndexOf(t, v) > 0) { // FIXME: Should be >=
-          firstIndexOf(t, v)+1
-        } else {
-          -1
-        }
-      case Nil() =>
-        -1
-    }
-  } ensuring { (res: Int) => 
-    (if (l.content contains v) {
-      l.size > res && l.apply(res) == v
-    } else {
-      res == -1
-    }) && (((l,v), res) passes {
-      case (Cons(0, Cons(1, Cons(2, Cons(3, Nil())))), 3) => 3
-      case (Cons(0, Cons(2, Cons(3, Cons(1, Nil())))), 1) => 3
-      case (Cons(0, Cons(1, Cons(3, Cons(1, Nil())))), 1) => 1
-      case (Cons(0, Cons(1, Cons(3, Cons(1, Nil())))), 2) => -1
-    })
-  }
-}
diff --git a/testcases/repair/List/FirstIndexOf4.scala b/testcases/repair/List/FirstIndexOf4.scala
deleted file mode 100644
index df3c90f78..000000000
--- a/testcases/repair/List/FirstIndexOf4.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-import leon.lang._
-import leon.collection._
-import leon.lang.synthesis._
-
-
-object FirstIndexOf {
-  def firstIndexOf(l: List[Int], v: Int): Int = {
-    l match {
-      case Cons(h, t) if v == h => 0
-      case Cons(h, t) =>
-        if (firstIndexOf(t,v) <= 0) { // FIXME: should be >= 0
-          firstIndexOf(t, v)+1
-        } else {
-          -1
-        }
-      case Nil() =>
-        -1
-    }
-  } ensuring { (res: Int) => 
-    (if (l.content contains v) {
-      l.size > res && l.apply(res) == v
-    } else {
-      res == -1
-    }) && (((l,v), res) passes {
-      case (Cons(0, Cons(1, Cons(2, Cons(3, Nil())))), 3) => 3
-      case (Cons(0, Cons(2, Cons(3, Cons(1, Nil())))), 1) => 3
-      case (Cons(0, Cons(1, Cons(3, Cons(1, Nil())))), 1) => 1
-      case (Cons(0, Cons(1, Cons(3, Cons(1, Nil())))), 2) => -1
-    })
-  }
-}
diff --git a/testcases/repair/List/List.scala b/testcases/repair/List/List.scala
new file mode 100644
index 000000000..19cf5ed3f
--- /dev/null
+++ b/testcases/repair/List/List.scala
@@ -0,0 +1,420 @@
+/* Copyright 2009-2014 EPFL, Lausanne */
+
+package leon.custom
+
+import leon._
+import leon.lang._
+import leon.annotation._
+
+sealed abstract class List0[T] {
+  def size: Int = (this match {
+    case Nil0() => 0
+    case Cons0(h, t) => 1 + t.size
+  }) ensuring (_ >= 0)
+
+  def content: Set[T] = this match {
+    case Nil0() => Set()
+    case Cons0(h, t) => Set(h) ++ t.content
+  }
+
+  def contains(v: T): Boolean = (this match {
+    case Cons0(h, t) if h == v => true
+    case Cons0(_, t) => t.contains(v)
+    case Nil0() => false
+  }) ensuring { res => res == (content contains v) }
+
+  def ++(that: List0[T]): List0[T] = (this match {
+    case Nil0() => that
+    case Cons0(x, xs) => Cons0(x, xs ++ that)
+  }) ensuring { res => (res.content == this.content ++ that.content) && (res.size == this.size + that.size)}
+
+  def head: T = {
+    require(this != Nil0[T]())
+    this match {
+      case Cons0(h, t) => h
+    }
+  }
+
+  def tail: List0[T] = {
+    require(this != Nil0[T]())
+    this match {
+      case Cons0(h, t) => t
+    }
+  }
+
+  def apply(index: Int): T = {
+    require(0 <= index && index < size)
+    if (index == 0) {
+      head
+    } else {
+       tail(index-1)
+    }
+  }
+
+  def ::(t:T): List0[T] = Cons0(t, this)
+
+  def :+(t:T): List0[T] = {
+    this match {
+      case Nil0() => Cons0(t, this)
+      case Cons0(x, xs) => Cons0(x, xs :+ (t))
+    }
+  } ensuring(res => (res.size == size + 1) && (res.content == content ++ Set(t)))
+
+  def reverse: List0[T] = {
+    this match {
+      case Nil0() => this
+      case Cons0(x,xs) => xs.reverse :+ x
+    }
+  } ensuring (res => (res.size == size) && (res.content == content))
+
+  def take(i: Int): List0[T] = (this, i) match {
+    case (Nil0(), _) => Nil0()
+    case (Cons0(h, t), i) =>
+      if (i == 0) {
+        Nil0()
+      } else {
+        Cons0(h, t.take(i-1))
+      }
+  }
+
+  def drop(i: Int): List0[T] = (this, i) match {
+    case (Nil0(), _) => Nil0()
+    case (Cons0(h, t), i) =>
+      if (i == 0) {
+        Cons0(h, t)
+      } else {
+        t.drop(i-1)
+      }
+  }
+
+  def slice(from: Int, to: Int): List0[T] = {
+    require(from < to && to < size && from >= 0)
+    drop(from).take(to-from)
+  }
+
+  def replace(from: T, to: T): List0[T] = this match {
+    case Nil0() => Nil0()
+    case Cons0(h, t) =>
+      val r = t.replace(from, to)
+      if (h == from) {
+        Cons0(to, r)
+      } else {
+        Cons0(h, r)
+      }
+  }
+
+  private def chunk0(s: Int, l: List0[T], acc: List0[T], res: List0[List0[T]], s0: Int): List0[List0[T]] = l match {
+    case Nil0() =>
+      if (acc.size > 0) {
+        res :+ acc
+      } else {
+        res
+      }
+    case Cons0(h, t) =>
+      if (s0 == 0) {
+        chunk0(s, l, Nil0(), res :+ acc, s)
+      } else {
+        chunk0(s, t, acc :+ h, res, s0-1)
+      }
+  }
+
+  def chunks(s: Int): List0[List0[T]] = {
+    require(s > 0)
+
+    chunk0(s, this, Nil0(), Nil0(), s)
+  }
+
+  def zip[B](that: List0[B]): List0[(T, B)] = (this, that) match {
+    case (Cons0(h1, t1), Cons0(h2, t2)) =>
+      Cons0((h1, h2), t1.zip(t2))
+    case (_) =>
+      Nil0()
+  }
+
+  def -(e: T): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (e == h) {
+        t - e
+      } else {
+        Cons0(h, t - e)
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def --(that: List0[T]): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (that.contains(h)) {
+        t -- that
+      } else {
+        Cons0(h, t -- that)
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def &(that: List0[T]): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (that.contains(h)) {
+        Cons0(h, t & that)
+      } else {
+        t & that
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def pad(s: Int, e: T): List0[T] = { (this, s) match {
+    case (_, s) if s <= 0 =>
+      this
+    case (Nil0(), s) =>
+      Cons0(e, Nil0().pad(s-1, e))
+    case (Cons0(h, t), s) =>
+      Cons0(h, t.pad(s, e))
+  }} ensuring { res =>
+    ((this,s,e), res) passes {
+      case (Cons0(a,Nil0()), 2, x) => Cons0(a, Cons0(x, Cons0(x, Nil0())))
+    }
+  }
+
+  def find(e: T): Option[Int] = this match {
+    case Nil0() => None()
+    case Cons0(h, t) =>
+      if (h == e) {
+        Some(0)
+      } else {
+        t.find(e) match {
+          case None()  => None()
+          case Some(i) => Some(i+1)
+        }
+      }
+  }
+
+  def init: List0[T] = (this match {
+    case Cons0(h, Nil0()) =>
+      Nil0[T]()
+    case Cons0(h, t) =>
+      Cons0[T](h, t.init)
+    case Nil0() =>
+      Nil0[T]()
+  }) ensuring ( (r: List0[T]) => ((r.size < this.size) || (this.size == 0)) )
+
+  def lastOption: Option[T] = this match {
+    case Cons0(h, t) =>
+      t.lastOption.orElse(Some(h))
+    case Nil0() =>
+      None()
+  }
+
+  def firstOption: Option[T] = this match {
+    case Cons0(h, t) =>
+      Some(h)
+    case Nil0() =>
+      None()
+  }
+
+  def unique: List0[T] = this match {
+    case Nil0() => Nil0()
+    case Cons0(h, t) =>
+      Cons0(h, t.unique - h)
+  }
+
+  def splitAt(e: T): List0[List0[T]] =  split(Cons0(e, Nil0()))
+
+  def split(seps: List0[T]): List0[List0[T]] = this match {
+    case Cons0(h, t) =>
+      if (seps.contains(h)) {
+        Cons0(Nil0(), t.split(seps))
+      } else {
+        val r = t.split(seps)
+        Cons0(Cons0(h, r.head), r.tail)
+      }
+    case Nil0() =>
+      Cons0(Nil0(), Nil0())
+  }
+
+  def count(e: T): Int = this match {
+    case Cons0(h, t) =>
+      if (h == e) {
+        1 + t.count(e)
+      } else {
+        t.count(e)
+      }
+    case Nil0() =>
+      0
+  }
+
+  def evenSplit: (List0[T], List0[T]) = {
+    val c = size/2
+    (take(c), drop(c))
+  }
+
+  def insertAt(pos: Int, l: List0[T]): List0[T] = {
+    if(pos < 0) {
+      insertAt(size + pos, l)
+    } else if(pos == 0) {
+      l ++ this
+    } else {
+      this match {
+        case Cons0(h, t) =>
+          Cons0(h, t.insertAt(pos-1, l))
+        case Nil0() =>
+          l
+      }
+    }
+  }
+
+  def replaceAt(pos: Int, l: List0[T]): List0[T] = {
+    if(pos < 0) {
+      replaceAt(size + pos, l)
+    } else if(pos == 0) {
+      l ++ this.drop(l.size)
+    } else {
+      this match {
+        case Cons0(h, t) =>
+          Cons0(h, t.replaceAt(pos-1, l))
+        case Nil0() =>
+          l
+      }
+    }
+  }
+
+  def rotate(s: Int): List0[T] = {
+    if (s < 0) {
+      rotate(size+s)
+    } else {
+      val s2 = s % size
+      drop(s2) ++ take(s2)
+    }
+  }
+
+  def isEmpty = this match { 
+    case Nil0() => true
+    case _ => false 
+  }
+
+}
+
+@ignore
+object List0 {
+  def apply[T](elems: T*): List0[T] = ???
+}
+
+@library
+object List0Ops {
+  def flatten[T](ls: List0[List0[T]]): List0[T] = ls match {
+    case Cons0(h, t) => h ++ flatten(t)
+    case Nil0() => Nil0()
+  }
+
+  def isSorted(ls: List0[Int]): Boolean = ls match {
+    case Nil0() => true
+    case Cons0(_, Nil0()) => true
+    case Cons0(h1, Cons0(h2, _)) if(h1 > h2) => false
+    case Cons0(_, t) => isSorted(t)
+  }
+
+  def sorted(ls: List0[Int]): List0[Int] = ls match {
+    case Cons0(h, t) => insSort(sorted(t), h)
+    case Nil0() => Nil0()
+  }
+
+  def insSort(ls: List0[Int], v: Int): List0[Int] = ls match {
+    case Nil0() => Cons0(v, Nil0())
+    case Cons0(h, t) =>
+      if (v <= h) {
+        Cons0(v, t)
+      } else {
+        Cons0(h, insSort(t, v))
+      }
+  }
+}
+
+
+case class Cons0[T](h: T, t: List0[T]) extends List0[T]
+case class Nil0[T]() extends List0[T]
+
+@library
+object List0Specs {
+  def snocIndex[T](l : List0[T], t : T, i : Int) : Boolean = {
+    require(0 <= i && i < l.size + 1)
+    // proof:
+    (l match {
+      case Nil0() => true
+      case Cons0(x, xs) => if (i > 0) snocIndex[T](xs, t, i-1) else true
+    }) &&
+    // claim:
+    ((l :+ t).apply(i) == (if (i < l.size) l(i) else t))
+  }.holds
+
+  def reverseIndex[T](l : List0[T], i : Int) : Boolean = {
+    require(0 <= i && i < l.size)
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => snocIndex(l, x, i) && reverseIndex[T](l,i)
+    }) &&
+    (l.reverse.apply(i) == l.apply(l.size - 1 - i))
+  }.holds
+
+  def appendIndex[T](l1 : List0[T], l2 : List0[T], i : Int) : Boolean = {
+    require(0 <= i && i < l1.size + l2.size)
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) => if (i==0) true else appendIndex[T](xs,l2,i-1)
+    }) &&
+    ((l1 ++ l2).apply(i) == (if (i < l1.size) l1(i) else l2(i - l1.size)))
+  }.holds
+
+  def appendAssoc[T](l1 : List0[T], l2 : List0[T], l3 : List0[T]) : Boolean = {
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) => appendAssoc(xs,l2,l3)
+    }) &&
+    (((l1 ++ l2) ++ l3) == (l1 ++ (l2 ++ l3)))
+  }.holds
+
+  def snocIsAppend[T](l : List0[T], t : T) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) =>  snocIsAppend(xs,t)
+    }) &&
+    ((l :+ t) == l ++ Cons0[T](t, Nil0()))
+  }.holds
+
+  def snocAfterAppend[T](l1 : List0[T], l2 : List0[T], t : T) : Boolean = {
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) =>  snocAfterAppend(xs,l2,t)
+    }) &&
+    ((l1 ++ l2) :+ t == (l1 ++ (l2 :+ t)))
+  }.holds
+
+  def snocReverse[T](l : List0[T], t : T) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => snocReverse(xs,t)
+    }) &&
+    ((l :+ t).reverse == Cons0(t, l.reverse))
+  }.holds
+
+  def reverseReverse[T](l : List0[T]) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => reverseReverse[T](xs) && snocReverse[T](xs.reverse, x)
+    }) &&
+    (l.reverse.reverse == l)
+  }.holds
+
+  //// my hand calculation shows this should work, but it does not seem to be found
+  //def reverseAppend[T](l1 : List0[T], l2 : List0[T]) : Boolean = {
+  //  (l1 match {
+  //    case Nil0() => true
+  //    case Cons0(x,xs) => {
+  //      reverseAppend(xs,l2) &&
+  //      snocAfterAppend[T](l2.reverse, xs.reverse, x) &&
+  //      l1.reverse == (xs.reverse :+ x)
+  //    }
+  //  }) &&
+  //  ((l1 ++ l2).reverse == (l2.reverse ++ l1.reverse))
+  //}.holds
+}
diff --git a/testcases/repair/List/List1.scala b/testcases/repair/List/List1.scala
new file mode 100644
index 000000000..1e18ca898
--- /dev/null
+++ b/testcases/repair/List/List1.scala
@@ -0,0 +1,420 @@
+/* Copyright 2009-2014 EPFL, Lausanne */
+
+package leon.custom
+
+import leon._
+import leon.lang._
+import leon.annotation._
+
+sealed abstract class List0[T] {
+  def size: Int = (this match {
+    case Nil0() => 0
+    case Cons0(h, t) => 1 + t.size
+  }) ensuring (_ >= 0)
+
+  def content: Set[T] = this match {
+    case Nil0() => Set()
+    case Cons0(h, t) => Set(h) ++ t.content
+  }
+
+  def contains(v: T): Boolean = (this match {
+    case Cons0(h, t) if h == v => true
+    case Cons0(_, t) => t.contains(v)
+    case Nil0() => false
+  }) ensuring { res => res == (content contains v) }
+
+  def ++(that: List0[T]): List0[T] = (this match {
+    case Nil0() => that
+    case Cons0(x, xs) => Cons0(x, xs ++ that)
+  }) ensuring { res => (res.content == this.content ++ that.content) && (res.size == this.size + that.size)}
+
+  def head: T = {
+    require(this != Nil0[T]())
+    this match {
+      case Cons0(h, t) => h
+    }
+  }
+
+  def tail: List0[T] = {
+    require(this != Nil0[T]())
+    this match {
+      case Cons0(h, t) => t
+    }
+  }
+
+  def apply(index: Int): T = {
+    require(0 <= index && index < size)
+    if (index == 0) {
+      head
+    } else {
+       tail(index-1)
+    }
+  }
+
+  def ::(t:T): List0[T] = Cons0(t, this)
+
+  def :+(t:T): List0[T] = {
+    this match {
+      case Nil0() => Cons0(t, this)
+      case Cons0(x, xs) => Cons0(x, xs :+ (t))
+    }
+  } ensuring(res => (res.size == size + 1) && (res.content == content ++ Set(t)))
+
+  def reverse: List0[T] = {
+    this match {
+      case Nil0() => this
+      case Cons0(x,xs) => xs.reverse :+ x
+    }
+  } ensuring (res => (res.size == size) && (res.content == content))
+
+  def take(i: Int): List0[T] = (this, i) match {
+    case (Nil0(), _) => Nil0()
+    case (Cons0(h, t), i) =>
+      if (i == 0) {
+        Nil0()
+      } else {
+        Cons0(h, t.take(i-1))
+      }
+  }
+
+  def drop(i: Int): List0[T] = (this, i) match {
+    case (Nil0(), _) => Nil0()
+    case (Cons0(h, t), i) =>
+      if (i == 0) {
+        Cons0(h, t)
+      } else {
+        t.drop(i-1)
+      }
+  }
+
+  def slice(from: Int, to: Int): List0[T] = {
+    require(from < to && to < size && from >= 0)
+    drop(from).take(to-from)
+  }
+
+  def replace(from: T, to: T): List0[T] = this match {
+    case Nil0() => Nil0()
+    case Cons0(h, t) =>
+      val r = t.replace(from, to)
+      if (h == from) {
+        Cons0(to, r)
+      } else {
+        Cons0(h, r)
+      }
+  }
+
+  private def chunk0(s: Int, l: List0[T], acc: List0[T], res: List0[List0[T]], s0: Int): List0[List0[T]] = l match {
+    case Nil0() =>
+      if (acc.size > 0) {
+        res :+ acc
+      } else {
+        res
+      }
+    case Cons0(h, t) =>
+      if (s0 == 0) {
+        chunk0(s, l, Nil0(), res :+ acc, s)
+      } else {
+        chunk0(s, t, acc :+ h, res, s0-1)
+      }
+  }
+
+  def chunks(s: Int): List0[List0[T]] = {
+    require(s > 0)
+
+    chunk0(s, this, Nil0(), Nil0(), s)
+  }
+
+  def zip[B](that: List0[B]): List0[(T, B)] = (this, that) match {
+    case (Cons0(h1, t1), Cons0(h2, t2)) =>
+      Cons0((h1, h2), t1.zip(t2))
+    case (_) =>
+      Nil0()
+  }
+
+  def -(e: T): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (e == h) {
+        t - e
+      } else {
+        Cons0(h, t - e)
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def --(that: List0[T]): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (that.contains(h)) {
+        t -- that
+      } else {
+        Cons0(h, t -- that)
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def &(that: List0[T]): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (that.contains(h)) {
+        Cons0(h, t & that)
+      } else {
+        t & that
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def pad(s: Int, e: T): List0[T] = { (this, s) match {
+    case (_, s) if s <= 0 =>
+      this
+    case (Nil0(), s) =>
+      Cons0(e, Nil0().pad(s-1, e))
+    case (Cons0(h, t), s) =>
+      Cons0(h, t.pad(s-1, e)) // FIXME should be s
+  }} ensuring { res =>
+    ((this,s,e), res) passes {
+      case (Cons0(a,Nil0()), 2, x) => Cons0(a, Cons0(x, Cons0(x, Nil0())))
+    }
+  }
+
+  def find(e: T): Option[Int] = this match {
+    case Nil0() => None()
+    case Cons0(h, t) =>
+      if (h == e) {
+        Some(0)
+      } else {
+        t.find(e) match {
+          case None()  => None()
+          case Some(i) => Some(i+1)
+        }
+      }
+  }
+
+  def init: List0[T] = (this match {
+    case Cons0(h, Nil0()) =>
+      Nil0[T]()
+    case Cons0(h, t) =>
+      Cons0[T](h, t.init)
+    case Nil0() =>
+      Nil0[T]()
+  }) ensuring ( (r: List0[T]) => ((r.size < this.size) || (this.size == 0)) )
+
+  def lastOption: Option[T] = this match {
+    case Cons0(h, t) =>
+      t.lastOption.orElse(Some(h))
+    case Nil0() =>
+      None()
+  }
+
+  def firstOption: Option[T] = this match {
+    case Cons0(h, t) =>
+      Some(h)
+    case Nil0() =>
+      None()
+  }
+
+  def unique: List0[T] = this match {
+    case Nil0() => Nil0()
+    case Cons0(h, t) =>
+      Cons0(h, t.unique - h)
+  }
+
+  def splitAt(e: T): List0[List0[T]] =  split(Cons0(e, Nil0()))
+
+  def split(seps: List0[T]): List0[List0[T]] = this match {
+    case Cons0(h, t) =>
+      if (seps.contains(h)) {
+        Cons0(Nil0(), t.split(seps))
+      } else {
+        val r = t.split(seps)
+        Cons0(Cons0(h, r.head), r.tail)
+      }
+    case Nil0() =>
+      Cons0(Nil0(), Nil0())
+  }
+
+  def count(e: T): Int = this match {
+    case Cons0(h, t) =>
+      if (h == e) {
+        1 + t.count(e)
+      } else {
+        t.count(e)
+      }
+    case Nil0() =>
+      0
+  }
+
+  def evenSplit: (List0[T], List0[T]) = {
+    val c = size/2
+    (take(c), drop(c))
+  }
+
+  def insertAt(pos: Int, l: List0[T]): List0[T] = {
+    if(pos < 0) {
+      insertAt(size + pos, l)
+    } else if(pos == 0) {
+      l ++ this
+    } else {
+      this match {
+        case Cons0(h, t) =>
+          Cons0(h, t.insertAt(pos-1, l))
+        case Nil0() =>
+          l
+      }
+    }
+  }
+
+  def replaceAt(pos: Int, l: List0[T]): List0[T] = {
+    if(pos < 0) {
+      replaceAt(size + pos, l)
+    } else if(pos == 0) {
+      l ++ this.drop(l.size)
+    } else {
+      this match {
+        case Cons0(h, t) =>
+          Cons0(h, t.replaceAt(pos-1, l))
+        case Nil0() =>
+          l
+      }
+    }
+  }
+
+  def rotate(s: Int): List0[T] = {
+    if (s < 0) {
+      rotate(size+s)
+    } else {
+      val s2 = s % size
+      drop(s2) ++ take(s2)
+    }
+  }
+
+  def isEmpty = this match { 
+    case Nil0() => true
+    case _ => false 
+  }
+
+}
+
+@ignore
+object List0 {
+  def apply[T](elems: T*): List0[T] = ???
+}
+
+@library
+object List0Ops {
+  def flatten[T](ls: List0[List0[T]]): List0[T] = ls match {
+    case Cons0(h, t) => h ++ flatten(t)
+    case Nil0() => Nil0()
+  }
+
+  def isSorted(ls: List0[Int]): Boolean = ls match {
+    case Nil0() => true
+    case Cons0(_, Nil0()) => true
+    case Cons0(h1, Cons0(h2, _)) if(h1 > h2) => false
+    case Cons0(_, t) => isSorted(t)
+  }
+
+  def sorted(ls: List0[Int]): List0[Int] = ls match {
+    case Cons0(h, t) => insSort(sorted(t), h)
+    case Nil0() => Nil0()
+  }
+
+  def insSort(ls: List0[Int], v: Int): List0[Int] = ls match {
+    case Nil0() => Cons0(v, Nil0())
+    case Cons0(h, t) =>
+      if (v <= h) {
+        Cons0(v, t)
+      } else {
+        Cons0(h, insSort(t, v))
+      }
+  }
+}
+
+
+case class Cons0[T](h: T, t: List0[T]) extends List0[T]
+case class Nil0[T]() extends List0[T]
+
+@library
+object List0Specs {
+  def snocIndex[T](l : List0[T], t : T, i : Int) : Boolean = {
+    require(0 <= i && i < l.size + 1)
+    // proof:
+    (l match {
+      case Nil0() => true
+      case Cons0(x, xs) => if (i > 0) snocIndex[T](xs, t, i-1) else true
+    }) &&
+    // claim:
+    ((l :+ t).apply(i) == (if (i < l.size) l(i) else t))
+  }.holds
+
+  def reverseIndex[T](l : List0[T], i : Int) : Boolean = {
+    require(0 <= i && i < l.size)
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => snocIndex(l, x, i) && reverseIndex[T](l,i)
+    }) &&
+    (l.reverse.apply(i) == l.apply(l.size - 1 - i))
+  }.holds
+
+  def appendIndex[T](l1 : List0[T], l2 : List0[T], i : Int) : Boolean = {
+    require(0 <= i && i < l1.size + l2.size)
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) => if (i==0) true else appendIndex[T](xs,l2,i-1)
+    }) &&
+    ((l1 ++ l2).apply(i) == (if (i < l1.size) l1(i) else l2(i - l1.size)))
+  }.holds
+
+  def appendAssoc[T](l1 : List0[T], l2 : List0[T], l3 : List0[T]) : Boolean = {
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) => appendAssoc(xs,l2,l3)
+    }) &&
+    (((l1 ++ l2) ++ l3) == (l1 ++ (l2 ++ l3)))
+  }.holds
+
+  def snocIsAppend[T](l : List0[T], t : T) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) =>  snocIsAppend(xs,t)
+    }) &&
+    ((l :+ t) == l ++ Cons0[T](t, Nil0()))
+  }.holds
+
+  def snocAfterAppend[T](l1 : List0[T], l2 : List0[T], t : T) : Boolean = {
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) =>  snocAfterAppend(xs,l2,t)
+    }) &&
+    ((l1 ++ l2) :+ t == (l1 ++ (l2 :+ t)))
+  }.holds
+
+  def snocReverse[T](l : List0[T], t : T) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => snocReverse(xs,t)
+    }) &&
+    ((l :+ t).reverse == Cons0(t, l.reverse))
+  }.holds
+
+  def reverseReverse[T](l : List0[T]) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => reverseReverse[T](xs) && snocReverse[T](xs.reverse, x)
+    }) &&
+    (l.reverse.reverse == l)
+  }.holds
+
+  //// my hand calculation shows this should work, but it does not seem to be found
+  //def reverseAppend[T](l1 : List0[T], l2 : List0[T]) : Boolean = {
+  //  (l1 match {
+  //    case Nil0() => true
+  //    case Cons0(x,xs) => {
+  //      reverseAppend(xs,l2) &&
+  //      snocAfterAppend[T](l2.reverse, xs.reverse, x) &&
+  //      l1.reverse == (xs.reverse :+ x)
+  //    }
+  //  }) &&
+  //  ((l1 ++ l2).reverse == (l2.reverse ++ l1.reverse))
+  //}.holds
+}
diff --git a/testcases/repair/List/List2.scala b/testcases/repair/List/List2.scala
new file mode 100644
index 000000000..e3246d5e8
--- /dev/null
+++ b/testcases/repair/List/List2.scala
@@ -0,0 +1,426 @@
+/* Copyright 2009-2014 EPFL, Lausanne */
+
+package leon.custom
+
+import leon._
+import leon.lang._
+import leon.annotation._
+
+sealed abstract class List0[T] {
+  def size: Int = (this match {
+    case Nil0() => 0
+    case Cons0(h, t) => 1 + t.size
+  }) ensuring (_ >= 0)
+
+  def content: Set[T] = this match {
+    case Nil0() => Set()
+    case Cons0(h, t) => Set(h) ++ t.content
+  }
+
+  def contains(v: T): Boolean = (this match {
+    case Cons0(h, t) if h == v => true
+    case Cons0(_, t) => t.contains(v)
+    case Nil0() => false
+  }) ensuring { res => res == (content contains v) }
+
+  def ++(that: List0[T]): List0[T] = (this match {
+    case Nil0() => that
+    case Cons0(x, xs) => xs ++ that // FIXME did not Cons 
+  }) ensuring { res =>
+    res.content == this.content ++ that.content && 
+    res.size == this.size + that.size &&
+    (((this, that), res) passes {
+      case ( x@Cons0(x1, Cons0(x2, Nil0())), y) => x
+    })
+  }
+
+  def head: T = {
+    require(this != Nil0[T]())
+    this match {
+      case Cons0(h, t) => h
+    }
+  }
+
+  def tail: List0[T] = {
+    require(this != Nil0[T]())
+    this match {
+      case Cons0(h, t) => t
+    }
+  }
+
+  def apply(index: Int): T = {
+    require(0 <= index && index < size)
+    if (index == 0) {
+      head
+    } else {
+       tail(index-1)
+    }
+  }
+
+  def ::(t:T): List0[T] = Cons0(t, this)
+
+  def :+(t:T): List0[T] = {
+    this match {
+      case Nil0() => Cons0(t, this)
+      case Cons0(x, xs) => Cons0(x, xs :+ (t))
+    }
+  } ensuring(res => (res.size == size + 1) && (res.content == content ++ Set(t)))
+
+  def reverse: List0[T] = {
+    this match {
+      case Nil0() => this
+      case Cons0(x,xs) => xs.reverse :+ x
+    }
+  } ensuring (res => (res.size == size) && (res.content == content))
+
+  def take(i: Int): List0[T] = (this, i) match {
+    case (Nil0(), _) => Nil0()
+    case (Cons0(h, t), i) =>
+      if (i == 0) {
+        Nil0()
+      } else {
+        Cons0(h, t.take(i-1))
+      }
+  }
+
+  def drop(i: Int): List0[T] = (this, i) match {
+    case (Nil0(), _) => Nil0()
+    case (Cons0(h, t), i) =>
+      if (i == 0) {
+        Cons0(h, t)
+      } else {
+        t.drop(i-1)
+      }
+  }
+
+  def slice(from: Int, to: Int): List0[T] = {
+    require(from < to && to < size && from >= 0)
+    drop(from).take(to-from)
+  }
+
+  def replace(from: T, to: T): List0[T] = this match {
+    case Nil0() => Nil0()
+    case Cons0(h, t) =>
+      val r = t.replace(from, to)
+      if (h == from) {
+        Cons0(to, r)
+      } else {
+        Cons0(h, r)
+      }
+  }
+
+  private def chunk0(s: Int, l: List0[T], acc: List0[T], res: List0[List0[T]], s0: Int): List0[List0[T]] = l match {
+    case Nil0() =>
+      if (acc.size > 0) {
+        res :+ acc
+      } else {
+        res
+      }
+    case Cons0(h, t) =>
+      if (s0 == 0) {
+        chunk0(s, l, Nil0(), res :+ acc, s)
+      } else {
+        chunk0(s, t, acc :+ h, res, s0-1)
+      }
+  }
+
+  def chunks(s: Int): List0[List0[T]] = {
+    require(s > 0)
+
+    chunk0(s, this, Nil0(), Nil0(), s)
+  }
+
+  def zip[B](that: List0[B]): List0[(T, B)] = (this, that) match {
+    case (Cons0(h1, t1), Cons0(h2, t2)) =>
+      Cons0((h1, h2), t1.zip(t2))
+    case (_) =>
+      Nil0()
+  }
+
+  def -(e: T): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (e == h) {
+        t - e
+      } else {
+        Cons0(h, t - e)
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def --(that: List0[T]): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (that.contains(h)) {
+        t -- that
+      } else {
+        Cons0(h, t -- that)
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def &(that: List0[T]): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (that.contains(h)) {
+        Cons0(h, t & that)
+      } else {
+        t & that
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def pad(s: Int, e: T): List0[T] = { (this, s) match {
+    case (_, s) if s <= 0 =>
+      this
+    case (Nil0(), s) =>
+      Cons0(e, Nil0().pad(s-1, e))
+    case (Cons0(h, t), s) =>
+      Cons0(h, t.pad(s, e))
+  }} ensuring { res =>
+    ((this,s,e), res) passes {
+      case (Cons0(a,Nil0()), 2, x) => Cons0(a, Cons0(x, Cons0(x, Nil0())))
+    }
+  }
+
+  def find(e: T): Option[Int] = this match {
+    case Nil0() => None()
+    case Cons0(h, t) =>
+      if (h == e) {
+        Some(0)
+      } else {
+        t.find(e) match {
+          case None()  => None()
+          case Some(i) => Some(i+1)
+        }
+      }
+  }
+
+  def init: List0[T] = (this match {
+    case Cons0(h, Nil0()) =>
+      Nil0[T]()
+    case Cons0(h, t) =>
+      Cons0[T](h, t.init)
+    case Nil0() =>
+      Nil0[T]()
+  }) ensuring ( (r: List0[T]) => ((r.size < this.size) || (this.size == 0)) )
+
+  def lastOption: Option[T] = this match {
+    case Cons0(h, t) =>
+      t.lastOption.orElse(Some(h))
+    case Nil0() =>
+      None()
+  }
+
+  def firstOption: Option[T] = this match {
+    case Cons0(h, t) =>
+      Some(h)
+    case Nil0() =>
+      None()
+  }
+
+  def unique: List0[T] = this match {
+    case Nil0() => Nil0()
+    case Cons0(h, t) =>
+      Cons0(h, t.unique - h)
+  }
+
+  def splitAt(e: T): List0[List0[T]] =  split(Cons0(e, Nil0()))
+
+  def split(seps: List0[T]): List0[List0[T]] = this match {
+    case Cons0(h, t) =>
+      if (seps.contains(h)) {
+        Cons0(Nil0(), t.split(seps))
+      } else {
+        val r = t.split(seps)
+        Cons0(Cons0(h, r.head), r.tail)
+      }
+    case Nil0() =>
+      Cons0(Nil0(), Nil0())
+  }
+
+  def count(e: T): Int = this match {
+    case Cons0(h, t) =>
+      if (h == e) {
+        1 + t.count(e)
+      } else {
+        t.count(e)
+      }
+    case Nil0() =>
+      0
+  }
+
+  def evenSplit: (List0[T], List0[T]) = {
+    val c = size/2
+    (take(c), drop(c))
+  }
+
+  def insertAt(pos: Int, l: List0[T]): List0[T] = {
+    if(pos < 0) {
+      insertAt(size + pos, l)
+    } else if(pos == 0) {
+      l ++ this
+    } else {
+      this match {
+        case Cons0(h, t) =>
+          Cons0(h, t.insertAt(pos-1, l))
+        case Nil0() =>
+          l
+      }
+    }
+  }
+
+  def replaceAt(pos: Int, l: List0[T]): List0[T] = {
+    if(pos < 0) {
+      replaceAt(size + pos, l)
+    } else if(pos == 0) {
+      l ++ this.drop(l.size)
+    } else {
+      this match {
+        case Cons0(h, t) =>
+          Cons0(h, t.replaceAt(pos-1, l))
+        case Nil0() =>
+          l
+      }
+    }
+  }
+
+  def rotate(s: Int): List0[T] = {
+    if (s < 0) {
+      rotate(size+s)
+    } else {
+      val s2 = s % size
+      drop(s2) ++ take(s2)
+    }
+  }
+
+  def isEmpty = this match { 
+    case Nil0() => true
+    case _ => false 
+  }
+
+}
+
+@ignore
+object List0 {
+  def apply[T](elems: T*): List0[T] = ???
+}
+
+@library
+object List0Ops {
+  def flatten[T](ls: List0[List0[T]]): List0[T] = ls match {
+    case Cons0(h, t) => h ++ flatten(t)
+    case Nil0() => Nil0()
+  }
+
+  def isSorted(ls: List0[Int]): Boolean = ls match {
+    case Nil0() => true
+    case Cons0(_, Nil0()) => true
+    case Cons0(h1, Cons0(h2, _)) if(h1 > h2) => false
+    case Cons0(_, t) => isSorted(t)
+  }
+
+  def sorted(ls: List0[Int]): List0[Int] = ls match {
+    case Cons0(h, t) => insSort(sorted(t), h)
+    case Nil0() => Nil0()
+  }
+
+  def insSort(ls: List0[Int], v: Int): List0[Int] = ls match {
+    case Nil0() => Cons0(v, Nil0())
+    case Cons0(h, t) =>
+      if (v <= h) {
+        Cons0(v, t)
+      } else {
+        Cons0(h, insSort(t, v))
+      }
+  }
+}
+
+
+case class Cons0[T](h: T, t: List0[T]) extends List0[T]
+case class Nil0[T]() extends List0[T]
+
+@library
+object List0Specs {
+  def snocIndex[T](l : List0[T], t : T, i : Int) : Boolean = {
+    require(0 <= i && i < l.size + 1)
+    // proof:
+    (l match {
+      case Nil0() => true
+      case Cons0(x, xs) => if (i > 0) snocIndex[T](xs, t, i-1) else true
+    }) &&
+    // claim:
+    ((l :+ t).apply(i) == (if (i < l.size) l(i) else t))
+  }.holds
+
+  def reverseIndex[T](l : List0[T], i : Int) : Boolean = {
+    require(0 <= i && i < l.size)
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => snocIndex(l, x, i) && reverseIndex[T](l,i)
+    }) &&
+    (l.reverse.apply(i) == l.apply(l.size - 1 - i))
+  }.holds
+
+  def appendIndex[T](l1 : List0[T], l2 : List0[T], i : Int) : Boolean = {
+    require(0 <= i && i < l1.size + l2.size)
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) => if (i==0) true else appendIndex[T](xs,l2,i-1)
+    }) &&
+    ((l1 ++ l2).apply(i) == (if (i < l1.size) l1(i) else l2(i - l1.size)))
+  }.holds
+
+  def appendAssoc[T](l1 : List0[T], l2 : List0[T], l3 : List0[T]) : Boolean = {
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) => appendAssoc(xs,l2,l3)
+    }) &&
+    (((l1 ++ l2) ++ l3) == (l1 ++ (l2 ++ l3)))
+  }.holds
+
+  def snocIsAppend[T](l : List0[T], t : T) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) =>  snocIsAppend(xs,t)
+    }) &&
+    ((l :+ t) == l ++ Cons0[T](t, Nil0()))
+  }.holds
+
+  def snocAfterAppend[T](l1 : List0[T], l2 : List0[T], t : T) : Boolean = {
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) =>  snocAfterAppend(xs,l2,t)
+    }) &&
+    ((l1 ++ l2) :+ t == (l1 ++ (l2 :+ t)))
+  }.holds
+
+  def snocReverse[T](l : List0[T], t : T) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => snocReverse(xs,t)
+    }) &&
+    ((l :+ t).reverse == Cons0(t, l.reverse))
+  }.holds
+
+  def reverseReverse[T](l : List0[T]) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => reverseReverse[T](xs) && snocReverse[T](xs.reverse, x)
+    }) &&
+    (l.reverse.reverse == l)
+  }.holds
+
+  //// my hand calculation shows this should work, but it does not seem to be found
+  //def reverseAppend[T](l1 : List0[T], l2 : List0[T]) : Boolean = {
+  //  (l1 match {
+  //    case Nil0() => true
+  //    case Cons0(x,xs) => {
+  //      reverseAppend(xs,l2) &&
+  //      snocAfterAppend[T](l2.reverse, xs.reverse, x) &&
+  //      l1.reverse == (xs.reverse :+ x)
+  //    }
+  //  }) &&
+  //  ((l1 ++ l2).reverse == (l2.reverse ++ l1.reverse))
+  //}.holds
+}
diff --git a/testcases/repair/List/List3.scala b/testcases/repair/List/List3.scala
new file mode 100644
index 000000000..87a1214c7
--- /dev/null
+++ b/testcases/repair/List/List3.scala
@@ -0,0 +1,428 @@
+/* Copyright 2009-2014 EPFL, Lausanne */
+
+package leon.custom
+
+import leon._
+import leon.lang._
+import leon.annotation._
+
+sealed abstract class List0[T] {
+  def size: Int = (this match {
+    case Nil0() => 0
+    case Cons0(h, t) => 1 + t.size
+  }) ensuring (_ >= 0)
+
+  def content: Set[T] = this match {
+    case Nil0() => Set()
+    case Cons0(h, t) => Set(h) ++ t.content
+  }
+
+  def contains(v: T): Boolean = (this match {
+    case Cons0(h, t) if h == v => true
+    case Cons0(_, t) => t.contains(v)
+    case Nil0() => false
+  }) ensuring { res => res == (content contains v) }
+
+  def ++(that: List0[T]): List0[T] = (this match {
+    case Nil0() => that
+    case Cons0(x, xs) => Cons0(x, xs ++ that)
+  }) ensuring { res => (res.content == this.content ++ that.content) && (res.size == this.size + that.size)}
+
+  def head: T = {
+    require(this != Nil0[T]())
+    this match {
+      case Cons0(h, t) => h
+    }
+  }
+
+  def tail: List0[T] = {
+    require(this != Nil0[T]())
+    this match {
+      case Cons0(h, t) => t
+    }
+  }
+
+  def apply(index: Int): T = {
+    require(0 <= index && index < size)
+    if (index == 0) {
+      head
+    } else {
+       tail(index-1)
+    }
+  }
+
+  def ::(t:T): List0[T] = Cons0(t, this)
+
+  def ap(t:T): List0[T] = {
+    this match {
+      case Nil0() => Nil0() // FIXME did not add element
+      case Cons0(x, xs) => Cons0(x, xs ap (t))
+    }
+  } ensuring(res => (res.size == size + 1) && (res.content == content ++ Set(t)))
+
+
+  def :+(t:T) = this ap t
+
+  def reverse: List0[T] = {
+    this match {
+      case Nil0() => this
+      case Cons0(x,xs) => xs.reverse :+ x
+    }
+  } ensuring (res => (res.size == size) && (res.content == content))
+
+  def take(i: Int): List0[T] = (this, i) match {
+    case (Nil0(), _) => Nil0()
+    case (Cons0(h, t), i) =>
+      if (i == 0) {
+        Nil0()
+      } else {
+        Cons0(h, t.take(i-1))
+      }
+  }
+
+  def drop(i: Int): List0[T] = (this, i) match {
+    case (Nil0(), _) => Nil0()
+    case (Cons0(h, t), i) =>
+      if (i == 0) {
+        Cons0(h, t)
+      } else {
+        t.drop(i-1)
+      }
+  }
+
+  def slice(from: Int, to: Int): List0[T] = {
+    require(from < to && to < size && from >= 0)
+    drop(from).take(to-from)
+  }
+
+  def replace(from: T, to: T): List0[T] = this match {
+    case Nil0() => Nil0()
+    case Cons0(h, t) =>
+      val r = t.replace(from, to)
+      if (h == from) {
+        Cons0(to, r)
+      } else {
+        Cons0(h, r)
+      }
+  }
+
+  private def chunk0(s: Int, l: List0[T], acc: List0[T], res: List0[List0[T]], s0: Int): List0[List0[T]] = l match {
+    case Nil0() =>
+      if (acc.size > 0) {
+        res :+ acc
+      } else {
+        res
+      }
+    case Cons0(h, t) =>
+      if (s0 == 0) {
+        chunk0(s, l, Nil0(), res :+ acc, s)
+      } else {
+        chunk0(s, t, acc :+ h, res, s0-1)
+      }
+  }
+
+  def chunks(s: Int): List0[List0[T]] = {
+    require(s > 0)
+
+    chunk0(s, this, Nil0(), Nil0(), s)
+  }
+
+  def zip[B](that: List0[B]): List0[(T, B)] = (this, that) match {
+    case (Cons0(h1, t1), Cons0(h2, t2)) =>
+      Cons0((h1, h2), t1.zip(t2))
+    case (_) =>
+      Nil0()
+  }
+
+  def -(e: T): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (e == h) {
+        t - e
+      } else {
+        Cons0(h, t - e)
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def --(that: List0[T]): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (that.contains(h)) {
+        t -- that
+      } else {
+        Cons0(h, t -- that)
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def &(that: List0[T]): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (that.contains(h)) {
+        Cons0(h, t & that)
+      } else {
+        t & that
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def pad(s: Int, e: T): List0[T] = { (this, s) match {
+    case (_, s) if s <= 0 =>
+      this
+    case (Nil0(), s) =>
+      Cons0(e, Nil0().pad(s-1, e))
+    case (Cons0(h, t), s) =>
+      Cons0(h, t.pad(s, e))
+  }} ensuring { res =>
+    ((this,s,e), res) passes {
+      case (Cons0(a,Nil0()), 2, x) => Cons0(a, Cons0(x, Cons0(x, Nil0())))
+    }
+  }
+
+  def find(e: T): Option[Int] = this match {
+    case Nil0() => None()
+    case Cons0(h, t) =>
+      if (h == e) {
+        Some(0)
+      } else {
+        t.find(e) match {
+          case None()  => None()
+          case Some(i) => Some(i+1)
+        }
+      }
+  }
+
+  def init: List0[T] = (this match {
+    case Cons0(h, Nil0()) =>
+      Nil0[T]()
+    //case Cons0(h, t) =>
+    //  Cons0[T](h, t.init)
+    case Nil0() =>
+      Nil0[T]()
+  }) ensuring ( (r: List0[T]) => 
+    ((r.size < this.size) || (this.size == 0)) &&
+    ((this, r) passes {
+      case Cons0(a, Cons0(b, Cons0(c, Nil0()))) => Cons0(a, Cons0(b, Nil0()))
+    })
+  )
+
+  def lastOption: Option[T] = this match {
+    case Cons0(h, t) =>
+      t.lastOption.orElse(Some(h))
+    case Nil0() =>
+      None()
+  }
+
+  def firstOption: Option[T] = this match {
+    case Cons0(h, t) =>
+      Some(h)
+    case Nil0() =>
+      None()
+  }
+
+  def unique: List0[T] = this match {
+    case Nil0() => Nil0()
+    case Cons0(h, t) =>
+      Cons0(h, t.unique - h)
+  }
+
+  def splitAt(e: T): List0[List0[T]] =  split(Cons0(e, Nil0()))
+
+  def split(seps: List0[T]): List0[List0[T]] = this match {
+    case Cons0(h, t) =>
+      if (seps.contains(h)) {
+        Cons0(Nil0(), t.split(seps))
+      } else {
+        val r = t.split(seps)
+        Cons0(Cons0(h, r.head), r.tail)
+      }
+    case Nil0() =>
+      Cons0(Nil0(), Nil0())
+  }
+
+  def count(e: T): Int = this match {
+    case Cons0(h, t) =>
+      if (h == e) {
+        1 + t.count(e)
+      } else {
+        t.count(e)
+      }
+    case Nil0() =>
+      0
+  }
+
+  def evenSplit: (List0[T], List0[T]) = {
+    val c = size/2
+    (take(c), drop(c))
+  }
+
+  def insertAt(pos: Int, l: List0[T]): List0[T] = {
+    if(pos < 0) {
+      insertAt(size + pos, l)
+    } else if(pos == 0) {
+      l ++ this
+    } else {
+      this match {
+        case Cons0(h, t) =>
+          Cons0(h, t.insertAt(pos-1, l))
+        case Nil0() =>
+          l
+      }
+    }
+  }
+
+  def replaceAt(pos: Int, l: List0[T]): List0[T] = {
+    if(pos < 0) {
+      replaceAt(size + pos, l)
+    } else if(pos == 0) {
+      l ++ this.drop(l.size)
+    } else {
+      this match {
+        case Cons0(h, t) =>
+          Cons0(h, t.replaceAt(pos-1, l))
+        case Nil0() =>
+          l
+      }
+    }
+  }
+
+  def rotate(s: Int): List0[T] = {
+    if (s < 0) {
+      rotate(size+s)
+    } else {
+      val s2 = s % size
+      drop(s2) ++ take(s2)
+    }
+  }
+
+  def isEmpty = this match { 
+    case Nil0() => true
+    case _ => false 
+  }
+
+}
+
+@ignore
+object List0 {
+  def apply[T](elems: T*): List0[T] = ???
+}
+
+@library
+object List0Ops {
+  def flatten[T](ls: List0[List0[T]]): List0[T] = ls match {
+    case Cons0(h, t) => h ++ flatten(t)
+    case Nil0() => Nil0()
+  }
+
+  def isSorted(ls: List0[Int]): Boolean = ls match {
+    case Nil0() => true
+    case Cons0(_, Nil0()) => true
+    case Cons0(h1, Cons0(h2, _)) if(h1 > h2) => false
+    case Cons0(_, t) => isSorted(t)
+  }
+
+  def sorted(ls: List0[Int]): List0[Int] = ls match {
+    case Cons0(h, t) => insSort(sorted(t), h)
+    case Nil0() => Nil0()
+  }
+
+  def insSort(ls: List0[Int], v: Int): List0[Int] = ls match {
+    case Nil0() => Cons0(v, Nil0())
+    case Cons0(h, t) =>
+      if (v <= h) {
+        Cons0(v, t)
+      } else {
+        Cons0(h, insSort(t, v))
+      }
+  }
+}
+
+
+case class Cons0[T](h: T, t: List0[T]) extends List0[T]
+case class Nil0[T]() extends List0[T]
+
+@library
+object List0Specs {
+  def snocIndex[T](l : List0[T], t : T, i : Int) : Boolean = {
+    require(0 <= i && i < l.size + 1)
+    // proof:
+    (l match {
+      case Nil0() => true
+      case Cons0(x, xs) => if (i > 0) snocIndex[T](xs, t, i-1) else true
+    }) &&
+    // claim:
+    ((l :+ t).apply(i) == (if (i < l.size) l(i) else t))
+  }.holds
+
+  def reverseIndex[T](l : List0[T], i : Int) : Boolean = {
+    require(0 <= i && i < l.size)
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => snocIndex(l, x, i) && reverseIndex[T](l,i)
+    }) &&
+    (l.reverse.apply(i) == l.apply(l.size - 1 - i))
+  }.holds
+
+  def appendIndex[T](l1 : List0[T], l2 : List0[T], i : Int) : Boolean = {
+    require(0 <= i && i < l1.size + l2.size)
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) => if (i==0) true else appendIndex[T](xs,l2,i-1)
+    }) &&
+    ((l1 ++ l2).apply(i) == (if (i < l1.size) l1(i) else l2(i - l1.size)))
+  }.holds
+
+  def appendAssoc[T](l1 : List0[T], l2 : List0[T], l3 : List0[T]) : Boolean = {
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) => appendAssoc(xs,l2,l3)
+    }) &&
+    (((l1 ++ l2) ++ l3) == (l1 ++ (l2 ++ l3)))
+  }.holds
+
+  def snocIsAppend[T](l : List0[T], t : T) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) =>  snocIsAppend(xs,t)
+    }) &&
+    ((l :+ t) == l ++ Cons0[T](t, Nil0()))
+  }.holds
+
+  def snocAfterAppend[T](l1 : List0[T], l2 : List0[T], t : T) : Boolean = {
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) =>  snocAfterAppend(xs,l2,t)
+    }) &&
+    ((l1 ++ l2) :+ t == (l1 ++ (l2 :+ t)))
+  }.holds
+
+  def snocReverse[T](l : List0[T], t : T) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => snocReverse(xs,t)
+    }) &&
+    ((l :+ t).reverse == Cons0(t, l.reverse))
+  }.holds
+
+  def reverseReverse[T](l : List0[T]) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => reverseReverse[T](xs) && snocReverse[T](xs.reverse, x)
+    }) &&
+    (l.reverse.reverse == l)
+  }.holds
+
+  //// my hand calculation shows this should work, but it does not seem to be found
+  //def reverseAppend[T](l1 : List0[T], l2 : List0[T]) : Boolean = {
+  //  (l1 match {
+  //    case Nil0() => true
+  //    case Cons0(x,xs) => {
+  //      reverseAppend(xs,l2) &&
+  //      snocAfterAppend[T](l2.reverse, xs.reverse, x) &&
+  //      l1.reverse == (xs.reverse :+ x)
+  //    }
+  //  }) &&
+  //  ((l1 ++ l2).reverse == (l2.reverse ++ l1.reverse))
+  //}.holds
+}
diff --git a/testcases/repair/List/List4.scala b/testcases/repair/List/List4.scala
new file mode 100644
index 000000000..210a5544b
--- /dev/null
+++ b/testcases/repair/List/List4.scala
@@ -0,0 +1,420 @@
+/* Copyright 2009-2014 EPFL, Lausanne */
+
+package leon.custom
+
+import leon._
+import leon.lang._
+import leon.annotation._
+
+sealed abstract class List0[T] {
+  def size: Int = (this match {
+    case Nil0() => 0
+    case Cons0(h, t) => 1 + t.size
+  }) ensuring (_ >= 0)
+
+  def content: Set[T] = this match {
+    case Nil0() => Set()
+    case Cons0(h, t) => Set(h) ++ t.content
+  }
+
+  def contains(v: T): Boolean = (this match {
+    case Cons0(h, t) if h == v => true
+    case Cons0(_, t) => t.contains(v)
+    case Nil0() => false
+  }) ensuring { res => res == (content contains v) }
+
+  def ++(that: List0[T]): List0[T] = (this match {
+    case Nil0() => that
+    case Cons0(x, xs) => Cons0(x, xs ++ that)
+  }) ensuring { res => (res.content == this.content ++ that.content) && (res.size == this.size + that.size)}
+
+  def head: T = {
+    require(this != Nil0[T]())
+    this match {
+      case Cons0(h, t) => h
+    }
+  }
+
+  def tail: List0[T] = {
+    require(this != Nil0[T]())
+    this match {
+      case Cons0(h, t) => t
+    }
+  }
+
+  def apply(index: Int): T = {
+    require(0 <= index && index < size)
+    if (index == 0) {
+      head
+    } else {
+       tail(index-1)
+    }
+  }
+
+  def ::(t:T): List0[T] = Cons0(t, this)
+
+  def :+(t:T): List0[T] = {
+    this match {
+      case Nil0() => Cons0(t, this)
+      case Cons0(x, xs) => Cons0(x, xs :+ (t))
+    }
+  } ensuring(res => (res.size == size + 1) && (res.content == content ++ Set(t)))
+
+  def reverse: List0[T] = {
+    this match {
+      case Nil0() => this
+      case Cons0(x,xs) => xs.reverse :+ x
+    }
+  } ensuring (res => (res.size == size) && (res.content == content))
+
+  def take(i: Int): List0[T] = (this, i) match {
+    case (Nil0(), _) => Nil0()
+    case (Cons0(h, t), i) =>
+      if (i == 0) {
+        Nil0()
+      } else {
+        Cons0(h, t.take(i-1))
+      }
+  }
+
+  def drop(i: Int): List0[T] = { (this, i) match {
+    case (Nil0(), _) => Nil0()
+    case (Cons0(h, t), i) =>
+      t.drop(i-1) //FIXME missing if-split
+  }} ensuring { res => ((this, i), res) passes { 
+    case (l@Cons0(_, Nil0()), 42) => l
+    case (Cons0(a, t), 0) => t
+    case (Cons0(a, Cons0(b, Nil0())), 1) => Cons0(a, Nil0())
+  }}
+
+  def slice(from: Int, to: Int): List0[T] = {
+    require(from < to && to < size && from >= 0)
+    drop(from).take(to-from)
+  }
+
+  def replace(from: T, to: T): List0[T] = this match {
+    case Nil0() => Nil0()
+    case Cons0(h, t) =>
+      val r = t.replace(from, to)
+      if (h == from) {
+        Cons0(to, r)
+      } else {
+        Cons0(h, r)
+      }
+  }
+
+  private def chunk0(s: Int, l: List0[T], acc: List0[T], res: List0[List0[T]], s0: Int): List0[List0[T]] = l match {
+    case Nil0() =>
+      if (acc.size > 0) {
+        res :+ acc
+      } else {
+        res
+      }
+    case Cons0(h, t) =>
+      if (s0 == 0) {
+        chunk0(s, l, Nil0(), res :+ acc, s)
+      } else {
+        chunk0(s, t, acc :+ h, res, s0-1)
+      }
+  }
+
+  def chunks(s: Int): List0[List0[T]] = {
+    require(s > 0)
+
+    chunk0(s, this, Nil0(), Nil0(), s)
+  }
+
+  def zip[B](that: List0[B]): List0[(T, B)] = (this, that) match {
+    case (Cons0(h1, t1), Cons0(h2, t2)) =>
+      Cons0((h1, h2), t1.zip(t2))
+    case (_) =>
+      Nil0()
+  }
+
+  def -(e: T): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (e == h) {
+        t - e
+      } else {
+        Cons0(h, t - e)
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def --(that: List0[T]): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (that.contains(h)) {
+        t -- that
+      } else {
+        Cons0(h, t -- that)
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def &(that: List0[T]): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (that.contains(h)) {
+        Cons0(h, t & that)
+      } else {
+        t & that
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def pad(s: Int, e: T): List0[T] = { (this, s) match {
+    case (_, s) if s <= 0 =>
+      this
+    case (Nil0(), s) =>
+      Cons0(e, Nil0().pad(s-1, e))
+    case (Cons0(h, t), s) =>
+      Cons0(h, t.pad(s, e))
+  }} ensuring { res =>
+    ((this,s,e), res) passes {
+      case (Cons0(a,Nil0()), 2, x) => Cons0(a, Cons0(x, Cons0(x, Nil0())))
+    }
+  }
+
+  def find(e: T): Option[Int] = this match {
+    case Nil0() => None()
+    case Cons0(h, t) =>
+      if (h == e) {
+        Some(0)
+      } else {
+        t.find(e) match {
+          case None()  => None()
+          case Some(i) => Some(i+1)
+        }
+      }
+  }
+
+  def init: List0[T] = (this match {
+    case Cons0(h, Nil0()) =>
+      Nil0[T]()
+    case Cons0(h, t) =>
+      Cons0[T](h, t.init)
+    case Nil0() =>
+      Nil0[T]()
+  }) ensuring ( (r: List0[T]) => ((r.size < this.size) || (this.size == 0)) )
+
+  def lastOption: Option[T] = this match {
+    case Cons0(h, t) =>
+      t.lastOption.orElse(Some(h))
+    case Nil0() =>
+      None()
+  }
+
+  def firstOption: Option[T] = this match {
+    case Cons0(h, t) =>
+      Some(h)
+    case Nil0() =>
+      None()
+  }
+
+  def unique: List0[T] = this match {
+    case Nil0() => Nil0()
+    case Cons0(h, t) =>
+      Cons0(h, t.unique - h)
+  }
+
+  def splitAt(e: T): List0[List0[T]] =  split(Cons0(e, Nil0()))
+
+  def split(seps: List0[T]): List0[List0[T]] = this match {
+    case Cons0(h, t) =>
+      if (seps.contains(h)) {
+        Cons0(Nil0(), t.split(seps))
+      } else {
+        val r = t.split(seps)
+        Cons0(Cons0(h, r.head), r.tail)
+      }
+    case Nil0() =>
+      Cons0(Nil0(), Nil0())
+  }
+
+  def count(e: T): Int = this match {
+    case Cons0(h, t) =>
+      if (h == e) {
+        1 + t.count(e)
+      } else {
+        t.count(e)
+      }
+    case Nil0() =>
+      0
+  }
+
+  def evenSplit: (List0[T], List0[T]) = {
+    val c = size/2
+    (take(c), drop(c))
+  }
+
+  def insertAt(pos: Int, l: List0[T]): List0[T] = {
+    if(pos < 0) {
+      insertAt(size + pos, l)
+    } else if(pos == 0) {
+      l ++ this
+    } else {
+      this match {
+        case Cons0(h, t) =>
+          Cons0(h, t.insertAt(pos-1, l))
+        case Nil0() =>
+          l
+      }
+    }
+  }
+
+  def replaceAt(pos: Int, l: List0[T]): List0[T] = {
+    if(pos < 0) {
+      replaceAt(size + pos, l)
+    } else if(pos == 0) {
+      l ++ this.drop(l.size)
+    } else {
+      this match {
+        case Cons0(h, t) =>
+          Cons0(h, t.replaceAt(pos-1, l))
+        case Nil0() =>
+          l
+      }
+    }
+  }
+
+  def rotate(s: Int): List0[T] = {
+    if (s < 0) {
+      rotate(size+s)
+    } else {
+      val s2 = s % size
+      drop(s2) ++ take(s2)
+    }
+  }
+
+  def isEmpty = this match { 
+    case Nil0() => true
+    case _ => false 
+  }
+
+}
+
+@ignore
+object List0 {
+  def apply[T](elems: T*): List0[T] = ???
+}
+
+@library
+object List0Ops {
+  def flatten[T](ls: List0[List0[T]]): List0[T] = ls match {
+    case Cons0(h, t) => h ++ flatten(t)
+    case Nil0() => Nil0()
+  }
+
+  def isSorted(ls: List0[Int]): Boolean = ls match {
+    case Nil0() => true
+    case Cons0(_, Nil0()) => true
+    case Cons0(h1, Cons0(h2, _)) if(h1 > h2) => false
+    case Cons0(_, t) => isSorted(t)
+  }
+
+  def sorted(ls: List0[Int]): List0[Int] = ls match {
+    case Cons0(h, t) => insSort(sorted(t), h)
+    case Nil0() => Nil0()
+  }
+
+  def insSort(ls: List0[Int], v: Int): List0[Int] = ls match {
+    case Nil0() => Cons0(v, Nil0())
+    case Cons0(h, t) =>
+      if (v <= h) {
+        Cons0(v, t)
+      } else {
+        Cons0(h, insSort(t, v))
+      }
+  }
+}
+
+
+case class Cons0[T](h: T, t: List0[T]) extends List0[T]
+case class Nil0[T]() extends List0[T]
+
+@library
+object List0Specs {
+  def snocIndex[T](l : List0[T], t : T, i : Int) : Boolean = {
+    require(0 <= i && i < l.size + 1)
+    // proof:
+    (l match {
+      case Nil0() => true
+      case Cons0(x, xs) => if (i > 0) snocIndex[T](xs, t, i-1) else true
+    }) &&
+    // claim:
+    ((l :+ t).apply(i) == (if (i < l.size) l(i) else t))
+  }.holds
+
+  def reverseIndex[T](l : List0[T], i : Int) : Boolean = {
+    require(0 <= i && i < l.size)
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => snocIndex(l, x, i) && reverseIndex[T](l,i)
+    }) &&
+    (l.reverse.apply(i) == l.apply(l.size - 1 - i))
+  }.holds
+
+  def appendIndex[T](l1 : List0[T], l2 : List0[T], i : Int) : Boolean = {
+    require(0 <= i && i < l1.size + l2.size)
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) => if (i==0) true else appendIndex[T](xs,l2,i-1)
+    }) &&
+    ((l1 ++ l2).apply(i) == (if (i < l1.size) l1(i) else l2(i - l1.size)))
+  }.holds
+
+  def appendAssoc[T](l1 : List0[T], l2 : List0[T], l3 : List0[T]) : Boolean = {
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) => appendAssoc(xs,l2,l3)
+    }) &&
+    (((l1 ++ l2) ++ l3) == (l1 ++ (l2 ++ l3)))
+  }.holds
+
+  def snocIsAppend[T](l : List0[T], t : T) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) =>  snocIsAppend(xs,t)
+    }) &&
+    ((l :+ t) == l ++ Cons0[T](t, Nil0()))
+  }.holds
+
+  def snocAfterAppend[T](l1 : List0[T], l2 : List0[T], t : T) : Boolean = {
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) =>  snocAfterAppend(xs,l2,t)
+    }) &&
+    ((l1 ++ l2) :+ t == (l1 ++ (l2 :+ t)))
+  }.holds
+
+  def snocReverse[T](l : List0[T], t : T) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => snocReverse(xs,t)
+    }) &&
+    ((l :+ t).reverse == Cons0(t, l.reverse))
+  }.holds
+
+  def reverseReverse[T](l : List0[T]) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => reverseReverse[T](xs) && snocReverse[T](xs.reverse, x)
+    }) &&
+    (l.reverse.reverse == l)
+  }.holds
+
+  //// my hand calculation shows this should work, but it does not seem to be found
+  //def reverseAppend[T](l1 : List0[T], l2 : List0[T]) : Boolean = {
+  //  (l1 match {
+  //    case Nil0() => true
+  //    case Cons0(x,xs) => {
+  //      reverseAppend(xs,l2) &&
+  //      snocAfterAppend[T](l2.reverse, xs.reverse, x) &&
+  //      l1.reverse == (xs.reverse :+ x)
+  //    }
+  //  }) &&
+  //  ((l1 ++ l2).reverse == (l2.reverse ++ l1.reverse))
+  //}.holds
+}
diff --git a/testcases/repair/List/List5.scala b/testcases/repair/List/List5.scala
new file mode 100644
index 000000000..266f4037f
--- /dev/null
+++ b/testcases/repair/List/List5.scala
@@ -0,0 +1,417 @@
+/* Copyright 2009-2014 EPFL, Lausanne */
+
+package leon.custom
+
+import leon._
+import leon.lang._
+import leon.annotation._
+
+sealed abstract class List0[T] {
+  def size: Int = (this match {
+    case Nil0() => 0
+    case Cons0(h, t) => 1 + t.size
+  }) ensuring (_ >= 0)
+
+  def content: Set[T] = this match {
+    case Nil0() => Set()
+    case Cons0(h, t) => Set(h) ++ t.content
+  }
+
+  def contains(v: T): Boolean = (this match {
+    case Cons0(h, t) if h == v => true
+    case Cons0(_, t) => t.contains(v)
+    case Nil0() => false
+  }) ensuring { res => res == (content contains v) }
+
+  def ++(that: List0[T]): List0[T] = (this match {
+    case Nil0() => that
+    case Cons0(x, xs) => Cons0(x, xs ++ that)
+  }) ensuring { res => (res.content == this.content ++ that.content) && (res.size == this.size + that.size)}
+
+  def head: T = {
+    require(this != Nil0[T]())
+    this match {
+      case Cons0(h, t) => h
+    }
+  }
+
+  def tail: List0[T] = {
+    require(this != Nil0[T]())
+    this match {
+      case Cons0(h, t) => t
+    }
+  }
+
+  def apply(index: Int): T = {
+    require(0 <= index && index < size)
+    if (index == 0) {
+      head
+    } else {
+       tail(index-1)
+    }
+  }
+
+  def ::(t:T): List0[T] = Cons0(t, this)
+
+  def :+(t:T): List0[T] = {
+    this match {
+      case Nil0() => Cons0(t, this)
+      case Cons0(x, xs) => Cons0(x, xs :+ (t))
+    }
+  } ensuring(res => (res.size == size + 1) && (res.content == content ++ Set(t)))
+
+  def reverse: List0[T] = {
+    this match {
+      case Nil0() => this
+      case Cons0(x,xs) => xs.reverse :+ x
+    }
+  } ensuring (res => (res.size == size) && (res.content == content))
+
+  def take(i: Int): List0[T] = (this, i) match {
+    case (Nil0(), _) => Nil0()
+    case (Cons0(h, t), i) =>
+      if (i == 0) {
+        Nil0()
+      } else {
+        Cons0(h, t.take(i-1))
+      }
+  }
+
+  def drop(i: Int): List0[T] = (this, i) match {
+    case (Nil0(), _) => Nil0()
+    case (Cons0(h, t), i) =>
+      if (i == 0) {
+        Cons0(h, t)
+      } else {
+        t.drop(i-1)
+      }
+  }
+
+  def slice(from: Int, to: Int): List0[T] = {
+    require(from < to && to < size && from >= 0)
+    drop(from).take(to-from)
+  }
+
+  def replace(from: T, to: T): List0[T] = { this match {
+    case Nil0() => Nil0()
+    case Cons0(h, t) =>
+      val r = t.replace(from, to)
+      Cons0(to, r) // FIXME
+  }} ensuring { res => (res.content == this.content -- Set(from) ++ Set(to)) && res.size == this.size 
+  }
+
+  private def chunk0(s: Int, l: List0[T], acc: List0[T], res: List0[List0[T]], s0: Int): List0[List0[T]] = l match {
+    case Nil0() =>
+      if (acc.size > 0) {
+        res :+ acc
+      } else {
+        res
+      }
+    case Cons0(h, t) =>
+      if (s0 == 0) {
+        chunk0(s, l, Nil0(), res :+ acc, s)
+      } else {
+        chunk0(s, t, acc :+ h, res, s0-1)
+      }
+  }
+
+  def chunks(s: Int): List0[List0[T]] = {
+    require(s > 0)
+
+    chunk0(s, this, Nil0(), Nil0(), s)
+  }
+
+  def zip[B](that: List0[B]): List0[(T, B)] = (this, that) match {
+    case (Cons0(h1, t1), Cons0(h2, t2)) =>
+      Cons0((h1, h2), t1.zip(t2))
+    case (_) =>
+      Nil0()
+  }
+
+  def -(e: T): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (e == h) {
+        t - e
+      } else {
+        Cons0(h, t - e)
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def --(that: List0[T]): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (that.contains(h)) {
+        t -- that
+      } else {
+        Cons0(h, t -- that)
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def &(that: List0[T]): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (that.contains(h)) {
+        Cons0(h, t & that)
+      } else {
+        t & that
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def pad(s: Int, e: T): List0[T] = { (this, s) match {
+    case (_, s) if s <= 0 =>
+      this
+    case (Nil0(), s) =>
+      Cons0(e, Nil0().pad(s-1, e))
+    case (Cons0(h, t), s) =>
+      Cons0(h, t.pad(s, e))
+  }} ensuring { res =>
+    ((this,s,e), res) passes {
+      case (Cons0(a,Nil0()), 2, x) => Cons0(a, Cons0(x, Cons0(x, Nil0())))
+    }
+  }
+
+  def find(e: T): Option[Int] = this match {
+    case Nil0() => None()
+    case Cons0(h, t) =>
+      if (h == e) {
+        Some(0)
+      } else {
+        t.find(e) match {
+          case None()  => None()
+          case Some(i) => Some(i+1)
+        }
+      }
+  }
+
+  def init: List0[T] = (this match {
+    case Cons0(h, Nil0()) =>
+      Nil0[T]()
+    case Cons0(h, t) =>
+      Cons0[T](h, t.init)
+    case Nil0() =>
+      Nil0[T]()
+  }) ensuring ( (r: List0[T]) => ((r.size < this.size) || (this.size == 0)) )
+
+  def lastOption: Option[T] = this match {
+    case Cons0(h, t) =>
+      t.lastOption.orElse(Some(h))
+    case Nil0() =>
+      None()
+  }
+
+  def firstOption: Option[T] = this match {
+    case Cons0(h, t) =>
+      Some(h)
+    case Nil0() =>
+      None()
+  }
+
+  def unique: List0[T] = this match {
+    case Nil0() => Nil0()
+    case Cons0(h, t) =>
+      Cons0(h, t.unique - h)
+  }
+
+  def splitAt(e: T): List0[List0[T]] =  split(Cons0(e, Nil0()))
+
+  def split(seps: List0[T]): List0[List0[T]] = this match {
+    case Cons0(h, t) =>
+      if (seps.contains(h)) {
+        Cons0(Nil0(), t.split(seps))
+      } else {
+        val r = t.split(seps)
+        Cons0(Cons0(h, r.head), r.tail)
+      }
+    case Nil0() =>
+      Cons0(Nil0(), Nil0())
+  }
+
+  def count(e: T): Int = this match {
+    case Cons0(h, t) =>
+      if (h == e) {
+        1 + t.count(e)
+      } else {
+        t.count(e)
+      }
+    case Nil0() =>
+      0
+  }
+
+  def evenSplit: (List0[T], List0[T]) = {
+    val c = size/2
+    (take(c), drop(c))
+  }
+
+  def insertAt(pos: Int, l: List0[T]): List0[T] = {
+    if(pos < 0) {
+      insertAt(size + pos, l)
+    } else if(pos == 0) {
+      l ++ this
+    } else {
+      this match {
+        case Cons0(h, t) =>
+          Cons0(h, t.insertAt(pos-1, l))
+        case Nil0() =>
+          l
+      }
+    }
+  }
+
+  def replaceAt(pos: Int, l: List0[T]): List0[T] = {
+    if(pos < 0) {
+      replaceAt(size + pos, l)
+    } else if(pos == 0) {
+      l ++ this.drop(l.size)
+    } else {
+      this match {
+        case Cons0(h, t) =>
+          Cons0(h, t.replaceAt(pos-1, l))
+        case Nil0() =>
+          l
+      }
+    }
+  }
+
+  def rotate(s: Int): List0[T] = {
+    if (s < 0) {
+      rotate(size+s)
+    } else {
+      val s2 = s % size
+      drop(s2) ++ take(s2)
+    }
+  }
+
+  def isEmpty = this match { 
+    case Nil0() => true
+    case _ => false 
+  }
+
+}
+
+@ignore
+object List0 {
+  def apply[T](elems: T*): List0[T] = ???
+}
+
+@library
+object List0Ops {
+  def flatten[T](ls: List0[List0[T]]): List0[T] = ls match {
+    case Cons0(h, t) => h ++ flatten(t)
+    case Nil0() => Nil0()
+  }
+
+  def isSorted(ls: List0[Int]): Boolean = ls match {
+    case Nil0() => true
+    case Cons0(_, Nil0()) => true
+    case Cons0(h1, Cons0(h2, _)) if(h1 > h2) => false
+    case Cons0(_, t) => isSorted(t)
+  }
+
+  def sorted(ls: List0[Int]): List0[Int] = ls match {
+    case Cons0(h, t) => insSort(sorted(t), h)
+    case Nil0() => Nil0()
+  }
+
+  def insSort(ls: List0[Int], v: Int): List0[Int] = ls match {
+    case Nil0() => Cons0(v, Nil0())
+    case Cons0(h, t) =>
+      if (v <= h) {
+        Cons0(v, t)
+      } else {
+        Cons0(h, insSort(t, v))
+      }
+  }
+}
+
+
+case class Cons0[T](h: T, t: List0[T]) extends List0[T]
+case class Nil0[T]() extends List0[T]
+
+@library
+object List0Specs {
+  def snocIndex[T](l : List0[T], t : T, i : Int) : Boolean = {
+    require(0 <= i && i < l.size + 1)
+    // proof:
+    (l match {
+      case Nil0() => true
+      case Cons0(x, xs) => if (i > 0) snocIndex[T](xs, t, i-1) else true
+    }) &&
+    // claim:
+    ((l :+ t).apply(i) == (if (i < l.size) l(i) else t))
+  }.holds
+
+  def reverseIndex[T](l : List0[T], i : Int) : Boolean = {
+    require(0 <= i && i < l.size)
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => snocIndex(l, x, i) && reverseIndex[T](l,i)
+    }) &&
+    (l.reverse.apply(i) == l.apply(l.size - 1 - i))
+  }.holds
+
+  def appendIndex[T](l1 : List0[T], l2 : List0[T], i : Int) : Boolean = {
+    require(0 <= i && i < l1.size + l2.size)
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) => if (i==0) true else appendIndex[T](xs,l2,i-1)
+    }) &&
+    ((l1 ++ l2).apply(i) == (if (i < l1.size) l1(i) else l2(i - l1.size)))
+  }.holds
+
+  def appendAssoc[T](l1 : List0[T], l2 : List0[T], l3 : List0[T]) : Boolean = {
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) => appendAssoc(xs,l2,l3)
+    }) &&
+    (((l1 ++ l2) ++ l3) == (l1 ++ (l2 ++ l3)))
+  }.holds
+
+  def snocIsAppend[T](l : List0[T], t : T) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) =>  snocIsAppend(xs,t)
+    }) &&
+    ((l :+ t) == l ++ Cons0[T](t, Nil0()))
+  }.holds
+
+  def snocAfterAppend[T](l1 : List0[T], l2 : List0[T], t : T) : Boolean = {
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) =>  snocAfterAppend(xs,l2,t)
+    }) &&
+    ((l1 ++ l2) :+ t == (l1 ++ (l2 :+ t)))
+  }.holds
+
+  def snocReverse[T](l : List0[T], t : T) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => snocReverse(xs,t)
+    }) &&
+    ((l :+ t).reverse == Cons0(t, l.reverse))
+  }.holds
+
+  def reverseReverse[T](l : List0[T]) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => reverseReverse[T](xs) && snocReverse[T](xs.reverse, x)
+    }) &&
+    (l.reverse.reverse == l)
+  }.holds
+
+  //// my hand calculation shows this should work, but it does not seem to be found
+  //def reverseAppend[T](l1 : List0[T], l2 : List0[T]) : Boolean = {
+  //  (l1 match {
+  //    case Nil0() => true
+  //    case Cons0(x,xs) => {
+  //      reverseAppend(xs,l2) &&
+  //      snocAfterAppend[T](l2.reverse, xs.reverse, x) &&
+  //      l1.reverse == (xs.reverse :+ x)
+  //    }
+  //  }) &&
+  //  ((l1 ++ l2).reverse == (l2.reverse ++ l1.reverse))
+  //}.holds
+}
diff --git a/testcases/repair/List/List6.scala b/testcases/repair/List/List6.scala
new file mode 100644
index 000000000..028f94109
--- /dev/null
+++ b/testcases/repair/List/List6.scala
@@ -0,0 +1,423 @@
+/* Copyright 2009-2014 EPFL, Lausanne */
+
+package leon.custom
+
+import leon._
+import leon.lang._
+import leon.annotation._
+
+sealed abstract class List0[T] {
+  def size: Int = (this match {
+    case Nil0() => 0
+    case Cons0(h, t) => 1 + t.size
+  }) ensuring (_ >= 0)
+
+  def content: Set[T] = this match {
+    case Nil0() => Set()
+    case Cons0(h, t) => Set(h) ++ t.content
+  }
+
+  def contains(v: T): Boolean = (this match {
+    case Cons0(h, t) if h == v => true
+    case Cons0(_, t) => t.contains(v)
+    case Nil0() => false
+  }) ensuring { res => res == (content contains v) }
+
+  def ++(that: List0[T]): List0[T] = (this match {
+    case Nil0() => that
+    case Cons0(x, xs) => Cons0(x, xs ++ that)
+  }) ensuring { res => (res.content == this.content ++ that.content) && (res.size == this.size + that.size)}
+
+  def head: T = {
+    require(this != Nil0[T]())
+    this match {
+      case Cons0(h, t) => h
+    }
+  }
+
+  def tail: List0[T] = {
+    require(this != Nil0[T]())
+    this match {
+      case Cons0(h, t) => t
+    }
+  }
+
+  def apply(index: Int): T = {
+    require(0 <= index && index < size)
+    if (index == 0) {
+      head
+    } else {
+       tail(index-1)
+    }
+  }
+
+  def ::(t:T): List0[T] = Cons0(t, this)
+
+  def :+(t:T): List0[T] = {
+    this match {
+      case Nil0() => Cons0(t, this)
+      case Cons0(x, xs) => Cons0(x, xs :+ (t))
+    }
+  } ensuring(res => (res.size == size + 1) && (res.content == content ++ Set(t)))
+
+  def reverse: List0[T] = {
+    this match {
+      case Nil0() => this
+      case Cons0(x,xs) => xs.reverse :+ x
+    }
+  } ensuring (res => (res.size == size) && (res.content == content))
+
+  def take(i: Int): List0[T] = (this, i) match {
+    case (Nil0(), _) => Nil0()
+    case (Cons0(h, t), i) =>
+      if (i == 0) {
+        Nil0()
+      } else {
+        Cons0(h, t.take(i-1))
+      }
+  }
+
+  def drop(i: Int): List0[T] = (this, i) match {
+    case (Nil0(), _) => Nil0()
+    case (Cons0(h, t), i) =>
+      if (i == 0) {
+        Cons0(h, t)
+      } else {
+        t.drop(i-1)
+      }
+  }
+
+  def slice(from: Int, to: Int): List0[T] = {
+    require(from < to && to < size && from >= 0)
+    drop(from).take(to-from)
+  }
+
+  def replace(from: T, to: T): List0[T] = this match {
+    case Nil0() => Nil0()
+    case Cons0(h, t) =>
+      val r = t.replace(from, to)
+      if (h == from) {
+        Cons0(to, r)
+      } else {
+        Cons0(h, r)
+      }
+  }
+
+  private def chunk0(s: Int, l: List0[T], acc: List0[T], res: List0[List0[T]], s0: Int): List0[List0[T]] = l match {
+    case Nil0() =>
+      if (acc.size > 0) {
+        res :+ acc
+      } else {
+        res
+      }
+    case Cons0(h, t) =>
+      if (s0 == 0) {
+        chunk0(s, l, Nil0(), res :+ acc, s)
+      } else {
+        chunk0(s, t, acc :+ h, res, s0-1)
+      }
+  }
+
+  def chunks(s: Int): List0[List0[T]] = {
+    require(s > 0)
+
+    chunk0(s, this, Nil0(), Nil0(), s)
+  }
+
+  def zip[B](that: List0[B]): List0[(T, B)] = (this, that) match {
+    case (Cons0(h1, t1), Cons0(h2, t2)) =>
+      Cons0((h1, h2), t1.zip(t2))
+    case (_) =>
+      Nil0()
+  }
+
+  def -(e: T): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (e == h) {
+        t - e
+      } else {
+        Cons0(h, t - e)
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def --(that: List0[T]): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (that.contains(h)) {
+        t -- that
+      } else {
+        Cons0(h, t -- that)
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def &(that: List0[T]): List0[T] = this match {
+    case Cons0(h, t) =>
+      if (that.contains(h)) {
+        Cons0(h, t & that)
+      } else {
+        t & that
+      }
+    case Nil0() =>
+      Nil0()
+  }
+
+  def pad(s: Int, e: T): List0[T] = { (this, s) match {
+    case (_, s) if s <= 0 =>
+      this
+    case (Nil0(), s) =>
+      Cons0(e, Nil0().pad(s-1, e))
+    case (Cons0(h, t), s) =>
+      Cons0(h, t.pad(s, e))
+  }} ensuring { res =>
+    ((this,s,e), res) passes {
+      case (Cons0(a,Nil0()), 2, x) => Cons0(a, Cons0(x, Cons0(x, Nil0())))
+    }
+  }
+
+  def find(e: T): Option[Int] = this match {
+    case Nil0() => None()
+    case Cons0(h, t) =>
+      if (h == e) {
+        Some(0)
+      } else {
+        t.find(e) match {
+          case None()  => None()
+          case Some(i) => Some(i+1)
+        }
+      }
+  }
+
+  def init: List0[T] = (this match {
+    case Cons0(h, Nil0()) =>
+      Nil0[T]()
+    case Cons0(h, t) =>
+      Cons0[T](h, t.init)
+    case Nil0() =>
+      Nil0[T]()
+  }) ensuring ( (r: List0[T]) => ((r.size < this.size) || (this.size == 0)) )
+
+  def lastOption: Option[T] = this match {
+    case Cons0(h, t) =>
+      t.lastOption.orElse(Some(h))
+    case Nil0() =>
+      None()
+  }
+
+  def firstOption: Option[T] = this match {
+    case Cons0(h, t) =>
+      Some(h)
+    case Nil0() =>
+      None()
+  }
+
+  def unique: List0[T] = this match {
+    case Nil0() => Nil0()
+    case Cons0(h, t) =>
+      Cons0(h, t.unique - h)
+  }
+
+  def splitAt(e: T): List0[List0[T]] =  split(Cons0(e, Nil0()))
+
+  def split(seps: List0[T]): List0[List0[T]] = this match {
+    case Cons0(h, t) =>
+      if (seps.contains(h)) {
+        Cons0(Nil0(), t.split(seps))
+      } else {
+        val r = t.split(seps)
+        Cons0(Cons0(h, r.head), r.tail)
+      }
+    case Nil0() =>
+      Cons0(Nil0(), Nil0())
+  }
+
+  def count(e: T): Int = { this match {
+    case Cons0(h, t) =>
+      if (h == e) {
+        t.count(e) // FIXME +1
+      } else {
+        t.count(e)
+      }
+    case Nil0() =>
+      0
+  }} ensuring {((this, e), _) passes {
+    case (Cons0(a, Cons0(b, Cons0(a1, Cons0(b2, Nil0())))), a2) if a == a1 && a == a2 && b != a2 && b2 != a2 => 2
+    case (Cons0(a, Cons0(b, Nil0())), c) if a != c && b != c => 0
+  }}
+
+  def evenSplit: (List0[T], List0[T]) = {
+    val c = size/2
+    (take(c), drop(c))
+  }
+
+  def insertAt(pos: Int, l: List0[T]): List0[T] = {
+    if(pos < 0) {
+      insertAt(size + pos, l)
+    } else if(pos == 0) {
+      l ++ this
+    } else {
+      this match {
+        case Cons0(h, t) =>
+          Cons0(h, t.insertAt(pos-1, l))
+        case Nil0() =>
+          l
+      }
+    }
+  }
+
+  def replaceAt(pos: Int, l: List0[T]): List0[T] = {
+    if(pos < 0) {
+      replaceAt(size + pos, l)
+    } else if(pos == 0) {
+      l ++ this.drop(l.size)
+    } else {
+      this match {
+        case Cons0(h, t) =>
+          Cons0(h, t.replaceAt(pos-1, l))
+        case Nil0() =>
+          l
+      }
+    }
+  }
+
+  def rotate(s: Int): List0[T] = {
+    if (s < 0) {
+      rotate(size+s)
+    } else {
+      val s2 = s % size
+      drop(s2) ++ take(s2)
+    }
+  }
+
+  def isEmpty = this match { 
+    case Nil0() => true
+    case _ => false 
+  }
+
+}
+
+@ignore
+object List0 {
+  def apply[T](elems: T*): List0[T] = ???
+}
+
+@library
+object List0Ops {
+  def flatten[T](ls: List0[List0[T]]): List0[T] = ls match {
+    case Cons0(h, t) => h ++ flatten(t)
+    case Nil0() => Nil0()
+  }
+
+  def isSorted(ls: List0[Int]): Boolean = ls match {
+    case Nil0() => true
+    case Cons0(_, Nil0()) => true
+    case Cons0(h1, Cons0(h2, _)) if(h1 > h2) => false
+    case Cons0(_, t) => isSorted(t)
+  }
+
+  def sorted(ls: List0[Int]): List0[Int] = ls match {
+    case Cons0(h, t) => insSort(sorted(t), h)
+    case Nil0() => Nil0()
+  }
+
+  def insSort(ls: List0[Int], v: Int): List0[Int] = ls match {
+    case Nil0() => Cons0(v, Nil0())
+    case Cons0(h, t) =>
+      if (v <= h) {
+        Cons0(v, t)
+      } else {
+        Cons0(h, insSort(t, v))
+      }
+  }
+}
+
+
+case class Cons0[T](h: T, t: List0[T]) extends List0[T]
+case class Nil0[T]() extends List0[T]
+
+@library
+object List0Specs {
+  def snocIndex[T](l : List0[T], t : T, i : Int) : Boolean = {
+    require(0 <= i && i < l.size + 1)
+    // proof:
+    (l match {
+      case Nil0() => true
+      case Cons0(x, xs) => if (i > 0) snocIndex[T](xs, t, i-1) else true
+    }) &&
+    // claim:
+    ((l :+ t).apply(i) == (if (i < l.size) l(i) else t))
+  }.holds
+
+  def reverseIndex[T](l : List0[T], i : Int) : Boolean = {
+    require(0 <= i && i < l.size)
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => snocIndex(l, x, i) && reverseIndex[T](l,i)
+    }) &&
+    (l.reverse.apply(i) == l.apply(l.size - 1 - i))
+  }.holds
+
+  def appendIndex[T](l1 : List0[T], l2 : List0[T], i : Int) : Boolean = {
+    require(0 <= i && i < l1.size + l2.size)
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) => if (i==0) true else appendIndex[T](xs,l2,i-1)
+    }) &&
+    ((l1 ++ l2).apply(i) == (if (i < l1.size) l1(i) else l2(i - l1.size)))
+  }.holds
+
+  def appendAssoc[T](l1 : List0[T], l2 : List0[T], l3 : List0[T]) : Boolean = {
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) => appendAssoc(xs,l2,l3)
+    }) &&
+    (((l1 ++ l2) ++ l3) == (l1 ++ (l2 ++ l3)))
+  }.holds
+
+  def snocIsAppend[T](l : List0[T], t : T) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) =>  snocIsAppend(xs,t)
+    }) &&
+    ((l :+ t) == l ++ Cons0[T](t, Nil0()))
+  }.holds
+
+  def snocAfterAppend[T](l1 : List0[T], l2 : List0[T], t : T) : Boolean = {
+    (l1 match {
+      case Nil0() => true
+      case Cons0(x,xs) =>  snocAfterAppend(xs,l2,t)
+    }) &&
+    ((l1 ++ l2) :+ t == (l1 ++ (l2 :+ t)))
+  }.holds
+
+  def snocReverse[T](l : List0[T], t : T) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => snocReverse(xs,t)
+    }) &&
+    ((l :+ t).reverse == Cons0(t, l.reverse))
+  }.holds
+
+  def reverseReverse[T](l : List0[T]) : Boolean = {
+    (l match {
+      case Nil0() => true
+      case Cons0(x,xs) => reverseReverse[T](xs) && snocReverse[T](xs.reverse, x)
+    }) &&
+    (l.reverse.reverse == l)
+  }.holds
+
+  //// my hand calculation shows this should work, but it does not seem to be found
+  //def reverseAppend[T](l1 : List0[T], l2 : List0[T]) : Boolean = {
+  //  (l1 match {
+  //    case Nil0() => true
+  //    case Cons0(x,xs) => {
+  //      reverseAppend(xs,l2) &&
+  //      snocAfterAppend[T](l2.reverse, xs.reverse, x) &&
+  //      l1.reverse == (xs.reverse :+ x)
+  //    }
+  //  }) &&
+  //  ((l1 ++ l2).reverse == (l2.reverse ++ l1.reverse))
+  //}.holds
+}
diff --git a/testcases/repair/List/Size.scala b/testcases/repair/List/Size.scala
deleted file mode 100644
index 8e36fc6ab..000000000
--- a/testcases/repair/List/Size.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-import leon._
-import leon.lang._
-import leon.collection._
-import leon.lang.synthesis._
-
-object List {
-  def size(l: List[Int]): Int = (l match {
-    case Nil() => 1
-    case Cons(h, t) => 1 + size(t)
-  }) ensuring {
-    (res: Int) =>
-      ((l, res) passes {
-        case Cons(a, Nil()) => 1
-        case Cons(a, Cons(b, Nil())) => 2
-        case Cons(a, Cons(b, Cons(c, Nil()))) => 3
-        case Nil() => 0
-      })
-  }
-}
diff --git a/testcases/repair/List/Size1.scala b/testcases/repair/List/Size1.scala
deleted file mode 100644
index e6aa4e37d..000000000
--- a/testcases/repair/List/Size1.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-import leon._
-import leon.lang._
-import leon.collection._
-import leon.lang.synthesis._
-
-object List {
-  def size(l: List[Int]): Int = (l match {
-    case Cons(h, t) => 3 + size(t) // FIXME: 1 + ...
-  }) ensuring {
-    (res: Int) =>
-      ((l, res) passes {
-        case Cons(a, Nil()) => 1
-        case Nil() => 0
-      })
-  }
-
-}
diff --git a/testcases/repair/List/Sum.scala b/testcases/repair/List/Sum.scala
deleted file mode 100644
index df8ea2e25..000000000
--- a/testcases/repair/List/Sum.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-import leon._
-import leon.lang._
-import leon.collection._
-import leon.lang.synthesis._
-
-object List {
-  def sum(l: List[Int]): Int = (l match {
-    case Nil() => 0
-    case Cons(h, t) => h + sum(t)
-  }) ensuring {
-    (res: Int) =>
-      ((l, res) passes {
-        case Cons(a, Nil()) => a
-        case Cons(a, Cons(b, Nil())) => a+b
-        case Cons(a, Cons(b, Cons(c, Nil()))) => a+b+c
-        case Nil() => 0
-      })
-  }
-}
diff --git a/testcases/repair/List/Sum1.scala b/testcases/repair/List/Sum1.scala
deleted file mode 100644
index b809f5c71..000000000
--- a/testcases/repair/List/Sum1.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-import leon._
-import leon.lang._
-import leon.collection._
-import leon.lang.synthesis._
-
-object List {
-  def sum(l: List[Int]): Int = (l match {
-    case Nil() => 0
-    case Cons(h, t) => 1 + sum(t) // FIXME: 1 instead of h
-  }) ensuring {
-    (res: Int) =>
-      ((l, res) passes {
-        case Cons(a, Nil()) => a
-        case Cons(a, Cons(b, Nil())) => a+b
-        case Cons(a, Cons(b, Cons(c, Nil()))) => a+b+c
-        case Nil() => 0
-      })
-  }
-}
diff --git a/testcases/repair/RedBlackTree-old/RedBlackTree.scala b/testcases/repair/RedBlackTree-old/RedBlackTree.scala
new file mode 100644
index 000000000..8f88abf28
--- /dev/null
+++ b/testcases/repair/RedBlackTree-old/RedBlackTree.scala
@@ -0,0 +1,101 @@
+import leon._ 
+import lang._
+import annotation._
+
+object RedBlackTree { 
+  sealed abstract class Color
+  case object Red extends Color
+  case object Black extends Color
+ 
+  sealed abstract class Tree
+  case object Empty extends Tree
+  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+
+  def content(t: Tree) : Set[Int] = t match {
+    case Empty => Set.empty
+    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
+  }
+
+  def size(t: Tree) : Int = t match {
+    case Empty => 0
+    case Node(_, l, v, r) => size(l) + 1 + size(r)
+  }
+
+  /* We consider leaves to be black by definition */
+  def isBlack(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black,_,_,_) => true
+    case _ => false
+  }
+
+  def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_,l,_,r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def blackBalanced(t : Tree) : Boolean = t match {
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Empty => true
+  }
+
+  def blackHeight(t : Tree) : Int = t match {
+    case Empty => 1
+    case Node(Black, l, _, _) => blackHeight(l) + 1
+    case Node(Red, l, _, _) => blackHeight(l)
+  }
+ 
+    
+  // <<insert element x into the tree t>>
+  def ins(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+    t match {
+      case Empty => Node(Red,Empty,x,Empty)
+      case Node(c,a,y,b) =>
+        if      (x < y)  balance(c, ins(x, a), y, b)
+        else if (x == y) Node(c,a,y,b)
+        else             balance(c,a,y,ins(x, b))
+    }
+  } ensuring (res => 
+    content(res) == content(t) ++ Set(x) && 
+    size(t) <= size(res) && 
+    size(res) <= size(t) + 1 && 
+    redDescHaveBlackChildren(res) && 
+    blackBalanced(res) 
+  )
+
+  def makeBlack(n: Tree): Tree = {
+    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    n match {
+      case Node(Red,l,v,r) => Node(Black,l,v,r)
+      case _ => n
+    }
+  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+
+  def add(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    makeBlack(ins(x, t))
+  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  
+  
+  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+
+    (c,a,x,b) match {
+      case (Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case (Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case (Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case (Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case (c,a,xV,b) => Node(c,a,xV,b)
+    }
+  } ensuring (res => content(res) == content(Node(c,a,x,b)))// && redDescHaveBlackChildren(res))
+
+}
diff --git a/testcases/repair/RedBlackTree-old/RedBlackTree1.scala b/testcases/repair/RedBlackTree-old/RedBlackTree1.scala
new file mode 100644
index 000000000..93d5b61e9
--- /dev/null
+++ b/testcases/repair/RedBlackTree-old/RedBlackTree1.scala
@@ -0,0 +1,143 @@
+import leon._ 
+import lang._
+import annotation._
+
+object RedBlackTree { 
+  sealed abstract class Color
+  case object Red extends Color
+  case object Black extends Color
+ 
+  sealed abstract class Tree
+  case object Empty extends Tree
+  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+
+  def content(t: Tree) : Set[Int] = t match {
+    case Empty => Set.empty
+    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
+  }
+
+  def size(t: Tree) : Int = t match {
+    case Empty => 0
+    case Node(_, l, v, r) => size(l) + 1 + size(r)
+  }
+
+  /* We consider leaves to be black by definition */
+  def isBlack(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black,_,_,_) => true
+    case _ => false
+  }
+
+  def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_,l,_,r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def blackBalanced(t : Tree) : Boolean = t match {
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Empty => true
+  }
+
+  def blackHeight(t : Tree) : Int = t match {
+    case Empty => 1
+    case Node(Black, l, _, _) => blackHeight(l) + 1
+    case Node(Red, l, _, _) => blackHeight(l)
+  }
+ 
+    
+  // <<insert element x into the tree t>>
+  def ins(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+    t match {
+      case Empty => Node(Red,Empty,x,Empty)
+      case Node(c,a,y,b) =>
+        if      (x < y)  balance(c, ins(x, a), y, b)
+        else if (x == y) Node(c,a,y,b)
+        else             balance(c,a,y,ins(x, b))
+    }
+  } ensuring (res => 
+    content(res) == content(t) ++ Set(x) && 
+    size(t) <= size(res) && 
+    size(res) <= size(t) + 1 && 
+    redDescHaveBlackChildren(res) && 
+    blackBalanced(res) 
+  )
+
+  def makeBlack(n: Tree): Tree = {
+    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    n match {
+      case Node(Red,l,v,r) => Node(Black,l,v,r)
+      case _ => n
+    }
+  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+
+  def add(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    makeBlack(ins(x, t))
+  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  
+//  def buggyAdd(x: Int, t: Tree): Tree = {
+//    require(redNodesHaveBlackChildren(t))
+//    // makeBlack(ins(x, t))
+//    ins(x, t)
+//  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res))
+  
+  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+    // require(
+    //   Node(c,a,x,b) match {
+    //     case Node(Black,Node(Red,Node(Red,a,_,b),_,c),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,Node(Red,a,_,Node(Red,b,_,c)),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,Node(Red,b,_,c),_,d)) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,b,_,Node(Red,c,_,d))) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case t => redDescHaveBlackChildren(t)
+    //   }
+    // )
+    Node(c,a,x,b) match {
+      case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,xV,d))  // FIXME: xV instead of zV in right node
+      case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,xV,d))  // FIXME: xV instead of zV in right node
+      case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case Node(c,a,xV,b) => Node(c,a,xV,b)
+    }
+  } ensuring (res => content(res) == content(Node(c,a,x,b))) //&& redDescHaveBlackChildren(res))
+
+  // def buggyBalance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+  //   Node(c,a,x,b) match {
+  //     case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
+  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+  //     case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
+  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+  //     case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
+  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+  //     case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
+  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+  //   }
+  // } ensuring (res => content(res) == content(Node(c,a,x,b)) ) // && redDescHaveBlackChildren(res))
+
+}
diff --git a/testcases/repair/RedBlackTree-old/RedBlackTree2.scala b/testcases/repair/RedBlackTree-old/RedBlackTree2.scala
new file mode 100644
index 000000000..d4675cadb
--- /dev/null
+++ b/testcases/repair/RedBlackTree-old/RedBlackTree2.scala
@@ -0,0 +1,143 @@
+import leon._ 
+import lang._
+import annotation._
+
+object RedBlackTree { 
+  sealed abstract class Color
+  case object Red extends Color
+  case object Black extends Color
+ 
+  sealed abstract class Tree
+  case object Empty extends Tree
+  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+
+  def content(t: Tree) : Set[Int] = t match {
+    case Empty => Set.empty
+    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
+  }
+
+  def size(t: Tree) : Int = t match {
+    case Empty => 0
+    case Node(_, l, v, r) => size(l) + 1 + size(r)
+  }
+
+  /* We consider leaves to be black by definition */
+  def isBlack(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black,_,_,_) => true
+    case _ => false
+  }
+
+  def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_,l,_,r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def blackBalanced(t : Tree) : Boolean = t match {
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Empty => true
+  }
+
+  def blackHeight(t : Tree) : Int = t match {
+    case Empty => 1
+    case Node(Black, l, _, _) => blackHeight(l) + 1
+    case Node(Red, l, _, _) => blackHeight(l)
+  }
+ 
+    
+  // <<insert element x into the tree t>>
+  def ins(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+    t match {
+      case Empty => Node(Red,Empty,x,Empty)
+      case Node(c,a,y,b) =>
+        if      (x < y)  Node(c, ins(x, a), y, b) // FIXME : forgot to balance
+        else if (x == y) Node(c,a,y,b)
+        else             balance(c,a,y,ins(x, b))
+    }
+  } ensuring (res => 
+    content(res) == content(t) ++ Set(x) && 
+    size(t) <= size(res) && 
+    size(res) <= size(t) + 1 && 
+    redDescHaveBlackChildren(res) && 
+    blackBalanced(res) 
+  )
+
+  def makeBlack(n: Tree): Tree = {
+    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    n match {
+      case Node(Red,l,v,r) => Node(Black,l,v,r)
+      case _ => n
+    }
+  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+
+  def add(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    makeBlack(ins(x, t))
+  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  
+//  def buggyAdd(x: Int, t: Tree): Tree = {
+//    require(redNodesHaveBlackChildren(t))
+//    // makeBlack(ins(x, t))
+//    ins(x, t)
+//  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res))
+  
+  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+    // require(
+    //   Node(c,a,x,b) match {
+    //     case Node(Black,Node(Red,Node(Red,a,_,b),_,c),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,Node(Red,a,_,Node(Red,b,_,c)),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,Node(Red,b,_,c),_,d)) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,b,_,Node(Red,c,_,d))) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case t => redDescHaveBlackChildren(t)
+    //   }
+    // )
+    Node(c,a,x,b) match {
+      case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case Node(c,a,xV,b) => Node(c,a,xV,b)
+    }
+  } ensuring (res => content(res) == content(Node(c,a,x,b)) )// && redDescHaveBlackChildren(res))
+
+  // def buggyBalance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+  //   Node(c,a,x,b) match {
+  //     case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
+  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+  //     case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
+  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+  //     case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
+  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+  //     case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
+  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+  //   }
+  // } ensuring (res => content(res) == content(Node(c,a,x,b)) ) // && redDescHaveBlackChildren(res))
+
+}
diff --git a/testcases/repair/RedBlackTree-old/RedBlackTree3.scala b/testcases/repair/RedBlackTree-old/RedBlackTree3.scala
new file mode 100644
index 000000000..4d8e1f39d
--- /dev/null
+++ b/testcases/repair/RedBlackTree-old/RedBlackTree3.scala
@@ -0,0 +1,143 @@
+import leon._ 
+import lang._
+import annotation._
+
+object RedBlackTree { 
+  sealed abstract class Color
+  case object Red extends Color
+  case object Black extends Color
+ 
+  sealed abstract class Tree
+  case object Empty extends Tree
+  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+
+  def content(t: Tree) : Set[Int] = t match {
+    case Empty => Set.empty
+    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
+  }
+
+  def size(t: Tree) : Int = t match {
+    case Empty => 0
+    case Node(_, l, v, r) => size(l) + 1 + size(r)
+  }
+
+  /* We consider leaves to be black by definition */
+  def isBlack(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black,_,_,_) => true
+    case _ => false
+  }
+
+  def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_,l,_,r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def blackBalanced(t : Tree) : Boolean = t match {
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Empty => true
+  }
+
+  def blackHeight(t : Tree) : Int = t match {
+    case Empty => 1
+    case Node(Black, l, _, _) => blackHeight(l) + 1
+    case Node(Red, l, _, _) => blackHeight(l)
+  }
+ 
+    
+  // <<insert element x into the tree t>>
+  def ins(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+    t match {
+      case Empty => Node(Red,Empty,x,Empty)
+      case Node(c,a,y,b) =>
+        if      (x < y)  balance(c, ins(x, a), y, b)
+        else if (x == y) Node(c,a,y,b)
+        else             balance(c,a,y,ins(x, b))
+    }
+  } ensuring (res => 
+    content(res) == content(t) ++ Set(x) && 
+    size(t) <= size(res) && 
+    size(res) <= size(t) + 1 && 
+    redDescHaveBlackChildren(res) && 
+    blackBalanced(res) 
+  )
+
+  def makeBlack(n: Tree): Tree = {
+    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    n match {
+      case Node(Red,l,v,r) => Node(Black,l,v,r)
+      case _ => n
+    }
+  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+
+  def add(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    makeBlack(ins(x, t))
+  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  
+//  def buggyAdd(x: Int, t: Tree): Tree = {
+//    require(redNodesHaveBlackChildren(t))
+//    // makeBlack(ins(x, t))
+//    ins(x, t)
+//  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res))
+  
+  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+    // require(
+    //   Node(c,a,x,b) match {
+    //     case Node(Black,Node(Red,Node(Red,a,_,b),_,c),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,Node(Red,a,_,Node(Red,b,_,c)),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,Node(Red,b,_,c),_,d)) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,b,_,Node(Red,c,_,d))) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case t => redDescHaveBlackChildren(t)
+    //   }
+    // )
+    Node(c,a,x,b) match {
+      case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,xV,d))  // FIXME: xV instead of zV in right node
+      case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case Node(c,a,xV,b) => Node(c,a,xV,b)
+    }
+  } ensuring (res => content(res) == content(Node(c,a,x,b))) //&& redDescHaveBlackChildren(res))
+
+  // def buggyBalance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+  //   Node(c,a,x,b) match {
+  //     case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
+  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+  //     case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
+  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+  //     case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
+  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+  //     case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
+  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+  //   }
+  // } ensuring (res => content(res) == content(Node(c,a,x,b)) ) // && redDescHaveBlackChildren(res))
+
+}
diff --git a/testcases/repair/RedBlackTree/RedBlackTree4.scala b/testcases/repair/RedBlackTree-old/RedBlackTree4.scala
similarity index 100%
rename from testcases/repair/RedBlackTree/RedBlackTree4.scala
rename to testcases/repair/RedBlackTree-old/RedBlackTree4.scala
diff --git a/testcases/repair/RedBlackTree/RedBlackTree5.scala b/testcases/repair/RedBlackTree-old/RedBlackTree5.scala
similarity index 100%
rename from testcases/repair/RedBlackTree/RedBlackTree5.scala
rename to testcases/repair/RedBlackTree-old/RedBlackTree5.scala
diff --git a/testcases/repair/RedBlackTree-old/RedBlackTree6.scala b/testcases/repair/RedBlackTree-old/RedBlackTree6.scala
new file mode 100644
index 000000000..36cfb692b
--- /dev/null
+++ b/testcases/repair/RedBlackTree-old/RedBlackTree6.scala
@@ -0,0 +1,142 @@
+import leon._ 
+import lang._
+import annotation._
+
+object RedBlackTree { 
+  sealed abstract class Color
+  case object Red extends Color
+  case object Black extends Color
+ 
+  sealed abstract class Tree
+  case object Empty extends Tree
+  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+
+  def content(t: Tree) : Set[Int] = t match {
+    case Empty => Set.empty
+    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
+  }
+
+  def size(t: Tree) : Int = t match {
+    case Empty => 0
+    case Node(_, l, v, r) => size(l) + 1 + size(r)
+  }
+
+  /* We consider leaves to be black by definition */
+  def isBlack(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black,_,_,_) => true
+    case _ => false
+  }
+
+  def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_,l,_,r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def blackBalanced(t : Tree) : Boolean = t match {
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Empty => true
+  }
+
+  def blackHeight(t : Tree) : Int = t match {
+    case Empty => 1
+    case Node(Black, l, _, _) => blackHeight(l) + 1
+    case Node(Red, l, _, _) => blackHeight(l)
+  }
+ 
+    
+  // <<insert element x into the tree t>>
+  def ins(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+    t match {
+      case Empty => Node(Red,Empty,x,Empty)
+      case Node(c,a,y,b) =>
+        if      (x < y)  balance(c, ins(x, a), y, b)
+        else if (x == y) Node(c,a,y,b)
+        else             balance(c,a,y,ins(x, b))
+    }
+  } ensuring (res => 
+    content(res) == content(t) ++ Set(x) && 
+    size(t) <= size(res) && 
+    size(res) <= size(t) + 1 && 
+    redDescHaveBlackChildren(res) && 
+    blackBalanced(res) 
+  )
+
+  def makeBlack(n: Tree): Tree = {
+    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    n match {
+      case Node(Red,l,v,r) => Node(Black,l,v,r)
+      case _ => n
+    }
+  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+
+  //def add(x: Int, t: Tree): Tree = {
+  //  require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+  //  makeBlack(ins(x, t))
+  //} ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
+ 
+  def add(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    ins(x, t) // FIXME: makeBlack(ins(x, t))
+  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  
+  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+    // require(
+    //   Node(c,a,x,b) match {
+    //     case Node(Black,Node(Red,Node(Red,a,_,b),_,c),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,Node(Red,a,_,Node(Red,b,_,c)),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,Node(Red,b,_,c),_,d)) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,b,_,Node(Red,c,_,d))) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case t => redDescHaveBlackChildren(t)
+    //   }
+    // )
+    Node(c,a,x,b) match {
+      case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case Node(c,a,xV,b) => Node(c,a,xV,b)
+    }
+  } ensuring (res => content(res) == content(Node(c,a,x,b)) )// && redDescHaveBlackChildren(res))
+
+  // def buggyBalance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+  //   Node(c,a,x,b) match {
+  //     case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
+  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+  //     case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
+  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+  //     case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
+  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+  //     case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
+  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+  //   }
+  // } ensuring (res => content(res) == content(Node(c,a,x,b)) ) // && redDescHaveBlackChildren(res))
+
+}
diff --git a/testcases/repair/RedBlackTree/RedBlackTree7.scala b/testcases/repair/RedBlackTree-old/RedBlackTree7.scala
similarity index 100%
rename from testcases/repair/RedBlackTree/RedBlackTree7.scala
rename to testcases/repair/RedBlackTree-old/RedBlackTree7.scala
diff --git a/testcases/repair/RedBlackTree/RedBlackTree.scala b/testcases/repair/RedBlackTree/RedBlackTree.scala
index 8f88abf28..d80fafc08 100644
--- a/testcases/repair/RedBlackTree/RedBlackTree.scala
+++ b/testcases/repair/RedBlackTree/RedBlackTree.scala
@@ -1,4 +1,4 @@
-import leon._ 
+import leon._
 import lang._
 import annotation._
 
@@ -7,31 +7,67 @@ object RedBlackTree {
   case object Red extends Color
   case object Black extends Color
  
-  sealed abstract class Tree
-  case object Empty extends Tree
-  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+  sealed abstract class Tree {
+    /* We consider leaves to be black by definition */
+    def color = this match {
+      case Empty => Black
+      case Node(c,_,_,_) => c
+    }
 
-  def content(t: Tree) : Set[Int] = t match {
-    case Empty => Set.empty
-    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
-  }
+    def content : Set[Int] = this match {
+      case Empty => Set.empty
+      case Node(_, l, v, r) => l.content ++ Set(v) ++ r.content
+    }
 
-  def size(t: Tree) : Int = t match {
-    case Empty => 0
-    case Node(_, l, v, r) => size(l) + 1 + size(r)
-  }
+    def size : Int = this match {
+      case Empty => 0
+      case Node(_, l, v, r) => l.size + 1 + r.size
+    }
 
-  /* We consider leaves to be black by definition */
-  def isBlack(t: Tree) : Boolean = t match {
-    case Empty => true
-    case Node(Black,_,_,_) => true
-    case _ => false
+    def isBlack = color == Black
+
+    def blackHeight : Int = this match {
+      case Empty => 1
+      case Node(Black, l, _, _) => l.blackHeight + 1
+      case Node(Red, l, _, _) => l.blackHeight
+    }
+
+    def max : Option[Int] = this match {
+      case Empty => None()
+      case Node(_, l, v, r) => 
+        maxOption(Some(v), maxOption(l.max, r.max))
+    }
+
+    def min : Option[Int] = this match {
+      case Empty => None()
+      case Node(_, l, v, r) => 
+        minOption(Some(v), minOption(l.max, r.max)) 
+    }
+
+  }
+  
+  def minOption(i1 : Option[Int], i2 : Option[Int]) : Option[Int] = (i1, i2) match {
+    case (Some(i1), Some(i2)) => Some(if (i1 < i2) i1 else i2)
+    case _ => i1 orElse i2
+  }
+   
+  def maxOption(i1 : Option[Int], i2 : Option[Int]) : Option[Int] = (i1, i2) match {
+    case (Some(i1), Some(i2)) => Some(if (i1 > i2) i1 else i2)
+    case _ => i1 orElse i2
   }
 
+  case object Empty extends Tree
+  case class Node(color_ : Color, left: Tree, value: Int, right: Tree) extends Tree
+  
   def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
     case Empty => true
-    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
-    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Black, l, _, r) =>
+      redNodesHaveBlackChildren(l) &&
+      redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) =>
+      l.isBlack && r.isBlack &&
+      redNodesHaveBlackChildren(l) &&
+      redNodesHaveBlackChildren(r)
   }
 
   def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
@@ -40,62 +76,84 @@ object RedBlackTree {
   }
 
   def blackBalanced(t : Tree) : Boolean = t match {
-    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && l.blackHeight == r.blackHeight
     case Empty => true
   }
-
-  def blackHeight(t : Tree) : Int = t match {
-    case Empty => 1
-    case Node(Black, l, _, _) => blackHeight(l) + 1
-    case Node(Red, l, _, _) => blackHeight(l)
+  
+  def keysSorted(t : Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_, l, v, r) =>
+      keysSorted(l) && keysSorted(r) && 
+      (l.max.getOrElse (v-1) < v) && 
+      (r.min.getOrElse (v+1) > v)
   }
- 
-    
+
+
   // <<insert element x into the tree t>>
   def ins(x: Int, t: Tree): Tree = {
-    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) && keysSorted(t))
     t match {
       case Empty => Node(Red,Empty,x,Empty)
-      case Node(c,a,y,b) =>
-        if      (x < y)  balance(c, ins(x, a), y, b)
-        else if (x == y) Node(c,a,y,b)
-        else             balance(c,a,y,ins(x, b))
+      case n@Node(c,a,y,b) =>
+        if      (x < y)  balance(Node(c, ins(x, a), y, b))
+        else if (x == y) n
+        else             balance(Node(c, a, y, ins(x, b)))
     }
   } ensuring (res => 
-    content(res) == content(t) ++ Set(x) && 
-    size(t) <= size(res) && 
-    size(res) <= size(t) + 1 && 
+    res.content == t.content ++ Set(x) &&
+    t.size <= res.size &&
+    res.size <= t.size + 1 &&
+    keysSorted(res) &&
     redDescHaveBlackChildren(res) && 
     blackBalanced(res) 
   )
 
   def makeBlack(n: Tree): Tree = {
-    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    require(
+      redDescHaveBlackChildren(n) &&
+      blackBalanced(n) &&
+      keysSorted(n)
+    )
     n match {
       case Node(Red,l,v,r) => Node(Black,l,v,r)
       case _ => n
     }
-  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  } ensuring { res =>
+    res.isBlack &&
+    redNodesHaveBlackChildren(res) && 
+    blackBalanced(res) && 
+    keysSorted(res)
+  }
 
   def add(x: Int, t: Tree): Tree = {
-    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) && keysSorted(t))
     makeBlack(ins(x, t))
-  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  } ensuring { res => 
+    res.content == t.content ++ Set(x) && 
+    redNodesHaveBlackChildren(res) && 
+    blackBalanced(res) &&
+    keysSorted(res)
+  }
   
   
-  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
-
-    (c,a,x,b) match {
-      case (Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
+  def balance(t : Tree) : Tree = {
+    require(keysSorted(t))
+    t match {
+      case Empty => Empty
+      case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
         Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-      case (Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
+      case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
         Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-      case (Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
+      case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
         Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-      case (Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
+      case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
         Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-      case (c,a,xV,b) => Node(c,a,xV,b)
+      case other => other 
     }
-  } ensuring (res => content(res) == content(Node(c,a,x,b)))// && redDescHaveBlackChildren(res))
+  } ensuring { res => 
+    res.content == t.content &&
+    keysSorted(res)
+  }
+    
 
 }
diff --git a/testcases/repair/RedBlackTree/RedBlackTree1.scala b/testcases/repair/RedBlackTree/RedBlackTree1.scala
index 93d5b61e9..d219c0094 100644
--- a/testcases/repair/RedBlackTree/RedBlackTree1.scala
+++ b/testcases/repair/RedBlackTree/RedBlackTree1.scala
@@ -1,4 +1,4 @@
-import leon._ 
+import leon._
 import lang._
 import annotation._
 
@@ -7,31 +7,67 @@ object RedBlackTree {
   case object Red extends Color
   case object Black extends Color
  
-  sealed abstract class Tree
-  case object Empty extends Tree
-  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+  sealed abstract class Tree {
+    /* We consider leaves to be black by definition */
+    def color = this match {
+      case Empty => Black
+      case Node(c,_,_,_) => c
+    }
 
-  def content(t: Tree) : Set[Int] = t match {
-    case Empty => Set.empty
-    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
-  }
+    def content : Set[Int] = this match {
+      case Empty => Set.empty
+      case Node(_, l, v, r) => l.content ++ Set(v) ++ r.content
+    }
 
-  def size(t: Tree) : Int = t match {
-    case Empty => 0
-    case Node(_, l, v, r) => size(l) + 1 + size(r)
-  }
+    def size : Int = this match {
+      case Empty => 0
+      case Node(_, l, v, r) => l.size + 1 + r.size
+    }
 
-  /* We consider leaves to be black by definition */
-  def isBlack(t: Tree) : Boolean = t match {
-    case Empty => true
-    case Node(Black,_,_,_) => true
-    case _ => false
+    def isBlack = color == Black
+
+    def blackHeight : Int = this match {
+      case Empty => 1
+      case Node(Black, l, _, _) => l.blackHeight + 1
+      case Node(Red, l, _, _) => l.blackHeight
+    }
+
+    def max : Option[Int] = this match {
+      case Empty => None()
+      case Node(_, l, v, r) => 
+        maxOption(Some(v), maxOption(l.max, r.max))
+    }
+
+    def min : Option[Int] = this match {
+      case Empty => None()
+      case Node(_, l, v, r) => 
+        minOption(Some(v), minOption(l.max, r.max)) 
+    }
+
+  }
+  
+  def minOption(i1 : Option[Int], i2 : Option[Int]) : Option[Int] = (i1, i2) match {
+    case (Some(i1), Some(i2)) => Some(if (i1 < i2) i1 else i2)
+    case _ => i1 orElse i2
+  }
+   
+  def maxOption(i1 : Option[Int], i2 : Option[Int]) : Option[Int] = (i1, i2) match {
+    case (Some(i1), Some(i2)) => Some(if (i1 > i2) i1 else i2)
+    case _ => i1 orElse i2
   }
 
+  case object Empty extends Tree
+  case class Node(color_ : Color, left: Tree, value: Int, right: Tree) extends Tree
+  
   def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
     case Empty => true
-    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
-    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Black, l, _, r) =>
+      redNodesHaveBlackChildren(l) &&
+      redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) =>
+      l.isBlack && r.isBlack &&
+      redNodesHaveBlackChildren(l) &&
+      redNodesHaveBlackChildren(r)
   }
 
   def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
@@ -40,104 +76,74 @@ object RedBlackTree {
   }
 
   def blackBalanced(t : Tree) : Boolean = t match {
-    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && l.blackHeight == r.blackHeight
     case Empty => true
   }
-
-  def blackHeight(t : Tree) : Int = t match {
-    case Empty => 1
-    case Node(Black, l, _, _) => blackHeight(l) + 1
-    case Node(Red, l, _, _) => blackHeight(l)
+  
+  def keysSorted(t : Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_, l, v, r) =>
+      keysSorted(l) && keysSorted(r) && 
+      (l.max.getOrElse (v-1) < v) && 
+      (r.min.getOrElse (v+1) > v)
   }
- 
-    
+
+
   // <<insert element x into the tree t>>
   def ins(x: Int, t: Tree): Tree = {
-    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
-    t match {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) && keysSorted(t))
+    val newT = t match {
       case Empty => Node(Red,Empty,x,Empty)
-      case Node(c,a,y,b) =>
-        if      (x < y)  balance(c, ins(x, a), y, b)
-        else if (x == y) Node(c,a,y,b)
-        else             balance(c,a,y,ins(x, b))
+      case n@Node(c,a,y,b) =>
+        if      (x < y)  Node(c, ins(x, a), y, b)
+        else if (x == y) n
+        else             Node(c, a, y, ins(x, b))
+    }
+    newT match {
+      case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) =>
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,xV,d)) // FIXME: second xV -> zV
+      case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,xV,d)) // FIXME: same
+      case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case other => other 
     }
   } ensuring (res => 
-    content(res) == content(t) ++ Set(x) && 
-    size(t) <= size(res) && 
-    size(res) <= size(t) + 1 && 
+    res.content == t.content ++ Set(x) &&
+    t.size <= res.size &&
+    res.size <= t.size + 1 &&
+    keysSorted(res) &&
     redDescHaveBlackChildren(res) && 
     blackBalanced(res) 
   )
 
   def makeBlack(n: Tree): Tree = {
-    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    require(
+      redDescHaveBlackChildren(n) &&
+      blackBalanced(n) &&
+      keysSorted(n)
+    )
     n match {
       case Node(Red,l,v,r) => Node(Black,l,v,r)
       case _ => n
     }
-  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  } ensuring { res =>
+    res.isBlack &&
+    redNodesHaveBlackChildren(res) && 
+    blackBalanced(res) && 
+    keysSorted(res)
+  }
 
   def add(x: Int, t: Tree): Tree = {
-    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) && keysSorted(t))
     makeBlack(ins(x, t))
-  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
-  
-//  def buggyAdd(x: Int, t: Tree): Tree = {
-//    require(redNodesHaveBlackChildren(t))
-//    // makeBlack(ins(x, t))
-//    ins(x, t)
-//  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res))
+  } ensuring { res => 
+    res.content == t.content ++ Set(x) && 
+    redNodesHaveBlackChildren(res) && 
+    blackBalanced(res) &&
+    keysSorted(res)
+  }
   
-  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
-    // require(
-    //   Node(c,a,x,b) match {
-    //     case Node(Black,Node(Red,Node(Red,a,_,b),_,c),_,d) =>
-    //       redNodesHaveBlackChildren(a) &&
-    //       redNodesHaveBlackChildren(b) &&
-    //       redNodesHaveBlackChildren(c) &&
-    //       redNodesHaveBlackChildren(d)
-    //     case Node(Black,Node(Red,a,_,Node(Red,b,_,c)),_,d) =>
-    //       redNodesHaveBlackChildren(a) &&
-    //       redNodesHaveBlackChildren(b) &&
-    //       redNodesHaveBlackChildren(c) &&
-    //       redNodesHaveBlackChildren(d)
-    //     case Node(Black,a,_,Node(Red,Node(Red,b,_,c),_,d)) => 
-    //       redNodesHaveBlackChildren(a) &&
-    //       redNodesHaveBlackChildren(b) &&
-    //       redNodesHaveBlackChildren(c) &&
-    //       redNodesHaveBlackChildren(d)
-    //     case Node(Black,a,_,Node(Red,b,_,Node(Red,c,_,d))) => 
-    //       redNodesHaveBlackChildren(a) &&
-    //       redNodesHaveBlackChildren(b) &&
-    //       redNodesHaveBlackChildren(c) &&
-    //       redNodesHaveBlackChildren(d)
-    //     case t => redDescHaveBlackChildren(t)
-    //   }
-    // )
-    Node(c,a,x,b) match {
-      case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
-        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-      case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
-        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,xV,d))  // FIXME: xV instead of zV in right node
-      case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
-        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,xV,d))  // FIXME: xV instead of zV in right node
-      case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
-        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-      case Node(c,a,xV,b) => Node(c,a,xV,b)
-    }
-  } ensuring (res => content(res) == content(Node(c,a,x,b))) //&& redDescHaveBlackChildren(res))
-
-  // def buggyBalance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
-  //   Node(c,a,x,b) match {
-  //     case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
-  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-  //     case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
-  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-  //     case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
-  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-  //     case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
-  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-  //   }
-  // } ensuring (res => content(res) == content(Node(c,a,x,b)) ) // && redDescHaveBlackChildren(res))
-
 }
diff --git a/testcases/repair/RedBlackTree/RedBlackTree2.scala b/testcases/repair/RedBlackTree/RedBlackTree2.scala
index d4675cadb..7f0c029c8 100644
--- a/testcases/repair/RedBlackTree/RedBlackTree2.scala
+++ b/testcases/repair/RedBlackTree/RedBlackTree2.scala
@@ -1,4 +1,4 @@
-import leon._ 
+import leon._
 import lang._
 import annotation._
 
@@ -7,31 +7,67 @@ object RedBlackTree {
   case object Red extends Color
   case object Black extends Color
  
-  sealed abstract class Tree
-  case object Empty extends Tree
-  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+  sealed abstract class Tree {
+    /* We consider leaves to be black by definition */
+    def color = this match {
+      case Empty => Black
+      case Node(c,_,_,_) => c
+    }
 
-  def content(t: Tree) : Set[Int] = t match {
-    case Empty => Set.empty
-    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
-  }
+    def content : Set[Int] = this match {
+      case Empty => Set.empty
+      case Node(_, l, v, r) => l.content ++ Set(v) ++ r.content
+    }
 
-  def size(t: Tree) : Int = t match {
-    case Empty => 0
-    case Node(_, l, v, r) => size(l) + 1 + size(r)
-  }
+    def size : Int = this match {
+      case Empty => 0
+      case Node(_, l, v, r) => l.size + 1 + r.size
+    }
 
-  /* We consider leaves to be black by definition */
-  def isBlack(t: Tree) : Boolean = t match {
-    case Empty => true
-    case Node(Black,_,_,_) => true
-    case _ => false
+    def isBlack = color == Black
+
+    def blackHeight : Int = this match {
+      case Empty => 1
+      case Node(Black, l, _, _) => l.blackHeight + 1
+      case Node(Red, l, _, _) => l.blackHeight
+    }
+
+    def max : Option[Int] = this match {
+      case Empty => None()
+      case Node(_, l, v, r) => 
+        maxOption(Some(v), maxOption(l.max, r.max))
+    }
+
+    def min : Option[Int] = this match {
+      case Empty => None()
+      case Node(_, l, v, r) => 
+        minOption(Some(v), minOption(l.max, r.max)) 
+    }
+
+  }
+  
+  def minOption(i1 : Option[Int], i2 : Option[Int]) : Option[Int] = (i1, i2) match {
+    case (Some(i1), Some(i2)) => Some(if (i1 < i2) i1 else i2)
+    case _ => i1 orElse i2
+  }
+   
+  def maxOption(i1 : Option[Int], i2 : Option[Int]) : Option[Int] = (i1, i2) match {
+    case (Some(i1), Some(i2)) => Some(if (i1 > i2) i1 else i2)
+    case _ => i1 orElse i2
   }
 
+  case object Empty extends Tree
+  case class Node(color_ : Color, left: Tree, value: Int, right: Tree) extends Tree
+  
   def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
     case Empty => true
-    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
-    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Black, l, _, r) =>
+      redNodesHaveBlackChildren(l) &&
+      redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) =>
+      l.isBlack && r.isBlack &&
+      redNodesHaveBlackChildren(l) &&
+      redNodesHaveBlackChildren(r)
   }
 
   def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
@@ -40,81 +76,70 @@ object RedBlackTree {
   }
 
   def blackBalanced(t : Tree) : Boolean = t match {
-    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && l.blackHeight == r.blackHeight
     case Empty => true
   }
-
-  def blackHeight(t : Tree) : Int = t match {
-    case Empty => 1
-    case Node(Black, l, _, _) => blackHeight(l) + 1
-    case Node(Red, l, _, _) => blackHeight(l)
+  
+  def keysSorted(t : Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_, l, v, r) =>
+      keysSorted(l) && keysSorted(r) && 
+      (l.max.getOrElse (v-1) < v) && 
+      (r.min.getOrElse (v+1) > v)
   }
- 
-    
+
+
   // <<insert element x into the tree t>>
   def ins(x: Int, t: Tree): Tree = {
-    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) && keysSorted(t))
     t match {
       case Empty => Node(Red,Empty,x,Empty)
-      case Node(c,a,y,b) =>
-        if      (x < y)  Node(c, ins(x, a), y, b) // FIXME : forgot to balance
-        else if (x == y) Node(c,a,y,b)
-        else             balance(c,a,y,ins(x, b))
+      case n@Node(c,a,y,b) =>
+        if      (x < y)  Node(c, ins(x, a), y, b) // FIXME forgot to balance
+        else if (x == y) n
+        else             balance(Node(c, a, y, ins(x, b)))
     }
   } ensuring (res => 
-    content(res) == content(t) ++ Set(x) && 
-    size(t) <= size(res) && 
-    size(res) <= size(t) + 1 && 
+    res.content == t.content ++ Set(x) &&
+    t.size <= res.size &&
+    res.size <= t.size + 1 &&
+    keysSorted(res) &&
     redDescHaveBlackChildren(res) && 
     blackBalanced(res) 
   )
 
   def makeBlack(n: Tree): Tree = {
-    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    require(
+      redDescHaveBlackChildren(n) &&
+      blackBalanced(n) &&
+      keysSorted(n)
+    )
     n match {
       case Node(Red,l,v,r) => Node(Black,l,v,r)
       case _ => n
     }
-  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  } ensuring { res =>
+    res.isBlack &&
+    redNodesHaveBlackChildren(res) && 
+    blackBalanced(res) && 
+    keysSorted(res)
+  }
 
   def add(x: Int, t: Tree): Tree = {
-    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) && keysSorted(t))
     makeBlack(ins(x, t))
-  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  } ensuring { res => 
+    res.content == t.content ++ Set(x) && 
+    redNodesHaveBlackChildren(res) && 
+    blackBalanced(res) &&
+    keysSorted(res)
+  }
   
-//  def buggyAdd(x: Int, t: Tree): Tree = {
-//    require(redNodesHaveBlackChildren(t))
-//    // makeBlack(ins(x, t))
-//    ins(x, t)
-//  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res))
   
-  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
-    // require(
-    //   Node(c,a,x,b) match {
-    //     case Node(Black,Node(Red,Node(Red,a,_,b),_,c),_,d) =>
-    //       redNodesHaveBlackChildren(a) &&
-    //       redNodesHaveBlackChildren(b) &&
-    //       redNodesHaveBlackChildren(c) &&
-    //       redNodesHaveBlackChildren(d)
-    //     case Node(Black,Node(Red,a,_,Node(Red,b,_,c)),_,d) =>
-    //       redNodesHaveBlackChildren(a) &&
-    //       redNodesHaveBlackChildren(b) &&
-    //       redNodesHaveBlackChildren(c) &&
-    //       redNodesHaveBlackChildren(d)
-    //     case Node(Black,a,_,Node(Red,Node(Red,b,_,c),_,d)) => 
-    //       redNodesHaveBlackChildren(a) &&
-    //       redNodesHaveBlackChildren(b) &&
-    //       redNodesHaveBlackChildren(c) &&
-    //       redNodesHaveBlackChildren(d)
-    //     case Node(Black,a,_,Node(Red,b,_,Node(Red,c,_,d))) => 
-    //       redNodesHaveBlackChildren(a) &&
-    //       redNodesHaveBlackChildren(b) &&
-    //       redNodesHaveBlackChildren(c) &&
-    //       redNodesHaveBlackChildren(d)
-    //     case t => redDescHaveBlackChildren(t)
-    //   }
-    // )
-    Node(c,a,x,b) match {
+  def balance(t : Tree) : Tree = {
+    require(keysSorted(t))
+    t match {
+      case Empty => Empty
       case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
         Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
       case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
@@ -123,21 +148,12 @@ object RedBlackTree {
         Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
       case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
         Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-      case Node(c,a,xV,b) => Node(c,a,xV,b)
+      case other => other 
     }
-  } ensuring (res => content(res) == content(Node(c,a,x,b)) )// && redDescHaveBlackChildren(res))
-
-  // def buggyBalance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
-  //   Node(c,a,x,b) match {
-  //     case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
-  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-  //     case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
-  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-  //     case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
-  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-  //     case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
-  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-  //   }
-  // } ensuring (res => content(res) == content(Node(c,a,x,b)) ) // && redDescHaveBlackChildren(res))
+  } ensuring { res => 
+    res.content == t.content &&
+    keysSorted(res)
+  }
+    
 
 }
diff --git a/testcases/repair/RedBlackTree/RedBlackTree3.scala b/testcases/repair/RedBlackTree/RedBlackTree3.scala
index 4d8e1f39d..a5d561985 100644
--- a/testcases/repair/RedBlackTree/RedBlackTree3.scala
+++ b/testcases/repair/RedBlackTree/RedBlackTree3.scala
@@ -1,4 +1,4 @@
-import leon._ 
+import leon._
 import lang._
 import annotation._
 
@@ -7,31 +7,67 @@ object RedBlackTree {
   case object Red extends Color
   case object Black extends Color
  
-  sealed abstract class Tree
-  case object Empty extends Tree
-  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+  sealed abstract class Tree {
+    /* We consider leaves to be black by definition */
+    def color = this match {
+      case Empty => Black
+      case Node(c,_,_,_) => c
+    }
 
-  def content(t: Tree) : Set[Int] = t match {
-    case Empty => Set.empty
-    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
-  }
+    def content : Set[Int] = this match {
+      case Empty => Set.empty
+      case Node(_, l, v, r) => l.content ++ Set(v) ++ r.content
+    }
 
-  def size(t: Tree) : Int = t match {
-    case Empty => 0
-    case Node(_, l, v, r) => size(l) + 1 + size(r)
-  }
+    def size : Int = this match {
+      case Empty => 0
+      case Node(_, l, v, r) => l.size + 1 + r.size
+    }
 
-  /* We consider leaves to be black by definition */
-  def isBlack(t: Tree) : Boolean = t match {
-    case Empty => true
-    case Node(Black,_,_,_) => true
-    case _ => false
+    def isBlack = color == Black
+
+    def blackHeight : Int = this match {
+      case Empty => 1
+      case Node(Black, l, _, _) => l.blackHeight + 1
+      case Node(Red, l, _, _) => l.blackHeight
+    }
+
+    def max : Option[Int] = this match {
+      case Empty => None()
+      case Node(_, l, v, r) => 
+        maxOption(Some(v), maxOption(l.max, r.max))
+    }
+
+    def min : Option[Int] = this match {
+      case Empty => None()
+      case Node(_, l, v, r) => 
+        minOption(Some(v), minOption(l.max, r.max)) 
+    }
+
+  }
+  
+  def minOption(i1 : Option[Int], i2 : Option[Int]) : Option[Int] = (i1, i2) match {
+    case (Some(i1), Some(i2)) => Some(if (i1 < i2) i1 else i2)
+    case _ => i1 orElse i2
+  }
+   
+  def maxOption(i1 : Option[Int], i2 : Option[Int]) : Option[Int] = (i1, i2) match {
+    case (Some(i1), Some(i2)) => Some(if (i1 > i2) i1 else i2)
+    case _ => i1 orElse i2
   }
 
+  case object Empty extends Tree
+  case class Node(color_ : Color, left: Tree, value: Int, right: Tree) extends Tree
+  
   def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
     case Empty => true
-    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
-    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Black, l, _, r) =>
+      redNodesHaveBlackChildren(l) &&
+      redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) =>
+      l.isBlack && r.isBlack &&
+      redNodesHaveBlackChildren(l) &&
+      redNodesHaveBlackChildren(r)
   }
 
   def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
@@ -40,104 +76,74 @@ object RedBlackTree {
   }
 
   def blackBalanced(t : Tree) : Boolean = t match {
-    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && l.blackHeight == r.blackHeight
     case Empty => true
   }
-
-  def blackHeight(t : Tree) : Int = t match {
-    case Empty => 1
-    case Node(Black, l, _, _) => blackHeight(l) + 1
-    case Node(Red, l, _, _) => blackHeight(l)
+  
+  def keysSorted(t : Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_, l, v, r) =>
+      keysSorted(l) && keysSorted(r) && 
+      (l.max.getOrElse (v-1) < v) && 
+      (r.min.getOrElse (v+1) > v)
   }
- 
-    
+
+
   // <<insert element x into the tree t>>
   def ins(x: Int, t: Tree): Tree = {
-    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
-    t match {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) && keysSorted(t))
+    val newT = t match {
       case Empty => Node(Red,Empty,x,Empty)
-      case Node(c,a,y,b) =>
-        if      (x < y)  balance(c, ins(x, a), y, b)
-        else if (x == y) Node(c,a,y,b)
-        else             balance(c,a,y,ins(x, b))
+      case n@Node(c,a,y,b) =>
+        if      (x < y)  Node(c, ins(x, a), y, b)
+        else if (x == y) n
+        else             Node(c, a, y, ins(x, b))
+    }  
+    newT match {
+      case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,xV,d)) // FIXME: second xV -> zV
+      case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
+      case other => other 
     }
   } ensuring (res => 
-    content(res) == content(t) ++ Set(x) && 
-    size(t) <= size(res) && 
-    size(res) <= size(t) + 1 && 
+    res.content == t.content ++ Set(x) &&
+    t.size <= res.size &&
+    res.size <= t.size + 1 &&
+    keysSorted(res) &&
     redDescHaveBlackChildren(res) && 
     blackBalanced(res) 
   )
 
   def makeBlack(n: Tree): Tree = {
-    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    require(
+      redDescHaveBlackChildren(n) &&
+      blackBalanced(n) &&
+      keysSorted(n)
+    )
     n match {
       case Node(Red,l,v,r) => Node(Black,l,v,r)
       case _ => n
     }
-  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  } ensuring { res =>
+    res.isBlack &&
+    redNodesHaveBlackChildren(res) && 
+    blackBalanced(res) && 
+    keysSorted(res)
+  }
 
   def add(x: Int, t: Tree): Tree = {
-    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) && keysSorted(t))
     makeBlack(ins(x, t))
-  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
-  
-//  def buggyAdd(x: Int, t: Tree): Tree = {
-//    require(redNodesHaveBlackChildren(t))
-//    // makeBlack(ins(x, t))
-//    ins(x, t)
-//  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res))
+  } ensuring { res => 
+    res.content == t.content ++ Set(x) && 
+    redNodesHaveBlackChildren(res) && 
+    blackBalanced(res) &&
+    keysSorted(res)
+  }
   
-  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
-    // require(
-    //   Node(c,a,x,b) match {
-    //     case Node(Black,Node(Red,Node(Red,a,_,b),_,c),_,d) =>
-    //       redNodesHaveBlackChildren(a) &&
-    //       redNodesHaveBlackChildren(b) &&
-    //       redNodesHaveBlackChildren(c) &&
-    //       redNodesHaveBlackChildren(d)
-    //     case Node(Black,Node(Red,a,_,Node(Red,b,_,c)),_,d) =>
-    //       redNodesHaveBlackChildren(a) &&
-    //       redNodesHaveBlackChildren(b) &&
-    //       redNodesHaveBlackChildren(c) &&
-    //       redNodesHaveBlackChildren(d)
-    //     case Node(Black,a,_,Node(Red,Node(Red,b,_,c),_,d)) => 
-    //       redNodesHaveBlackChildren(a) &&
-    //       redNodesHaveBlackChildren(b) &&
-    //       redNodesHaveBlackChildren(c) &&
-    //       redNodesHaveBlackChildren(d)
-    //     case Node(Black,a,_,Node(Red,b,_,Node(Red,c,_,d))) => 
-    //       redNodesHaveBlackChildren(a) &&
-    //       redNodesHaveBlackChildren(b) &&
-    //       redNodesHaveBlackChildren(c) &&
-    //       redNodesHaveBlackChildren(d)
-    //     case t => redDescHaveBlackChildren(t)
-    //   }
-    // )
-    Node(c,a,x,b) match {
-      case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
-        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-      case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
-        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,xV,d))  // FIXME: xV instead of zV in right node
-      case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
-        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-      case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
-        Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-      case Node(c,a,xV,b) => Node(c,a,xV,b)
-    }
-  } ensuring (res => content(res) == content(Node(c,a,x,b))) //&& redDescHaveBlackChildren(res))
-
-  // def buggyBalance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
-  //   Node(c,a,x,b) match {
-  //     case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
-  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-  //     case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
-  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-  //     case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
-  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-  //     case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
-  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-  //   }
-  // } ensuring (res => content(res) == content(Node(c,a,x,b)) ) // && redDescHaveBlackChildren(res))
-
 }
diff --git a/testcases/repair/RedBlackTree/RedBlackTree6.scala b/testcases/repair/RedBlackTree/RedBlackTree6.scala
index 36cfb692b..9eed1ac3a 100644
--- a/testcases/repair/RedBlackTree/RedBlackTree6.scala
+++ b/testcases/repair/RedBlackTree/RedBlackTree6.scala
@@ -1,4 +1,4 @@
-import leon._ 
+import leon._
 import lang._
 import annotation._
 
@@ -7,31 +7,67 @@ object RedBlackTree {
   case object Red extends Color
   case object Black extends Color
  
-  sealed abstract class Tree
-  case object Empty extends Tree
-  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+  sealed abstract class Tree {
+    /* We consider leaves to be black by definition */
+    def color = this match {
+      case Empty => Black
+      case Node(c,_,_,_) => c
+    }
 
-  def content(t: Tree) : Set[Int] = t match {
-    case Empty => Set.empty
-    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
-  }
+    def content : Set[Int] = this match {
+      case Empty => Set.empty
+      case Node(_, l, v, r) => l.content ++ Set(v) ++ r.content
+    }
 
-  def size(t: Tree) : Int = t match {
-    case Empty => 0
-    case Node(_, l, v, r) => size(l) + 1 + size(r)
-  }
+    def size : Int = this match {
+      case Empty => 0
+      case Node(_, l, v, r) => l.size + 1 + r.size
+    }
 
-  /* We consider leaves to be black by definition */
-  def isBlack(t: Tree) : Boolean = t match {
-    case Empty => true
-    case Node(Black,_,_,_) => true
-    case _ => false
+    def isBlack = color == Black
+
+    def blackHeight : Int = this match {
+      case Empty => 1
+      case Node(Black, l, _, _) => l.blackHeight + 1
+      case Node(Red, l, _, _) => l.blackHeight
+    }
+
+    def max : Option[Int] = this match {
+      case Empty => None()
+      case Node(_, l, v, r) => 
+        maxOption(Some(v), maxOption(l.max, r.max))
+    }
+
+    def min : Option[Int] = this match {
+      case Empty => None()
+      case Node(_, l, v, r) => 
+        minOption(Some(v), minOption(l.max, r.max)) 
+    }
+
+  }
+  
+  def minOption(i1 : Option[Int], i2 : Option[Int]) : Option[Int] = (i1, i2) match {
+    case (Some(i1), Some(i2)) => Some(if (i1 < i2) i1 else i2)
+    case _ => i1 orElse i2
+  }
+   
+  def maxOption(i1 : Option[Int], i2 : Option[Int]) : Option[Int] = (i1, i2) match {
+    case (Some(i1), Some(i2)) => Some(if (i1 > i2) i1 else i2)
+    case _ => i1 orElse i2
   }
 
+  case object Empty extends Tree
+  case class Node(color_ : Color, left: Tree, value: Int, right: Tree) extends Tree
+  
   def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
     case Empty => true
-    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
-    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Black, l, _, r) =>
+      redNodesHaveBlackChildren(l) &&
+      redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) =>
+      l.isBlack && r.isBlack &&
+      redNodesHaveBlackChildren(l) &&
+      redNodesHaveBlackChildren(r)
   }
 
   def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
@@ -40,80 +76,70 @@ object RedBlackTree {
   }
 
   def blackBalanced(t : Tree) : Boolean = t match {
-    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && l.blackHeight == r.blackHeight
     case Empty => true
   }
-
-  def blackHeight(t : Tree) : Int = t match {
-    case Empty => 1
-    case Node(Black, l, _, _) => blackHeight(l) + 1
-    case Node(Red, l, _, _) => blackHeight(l)
+  
+  def keysSorted(t : Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_, l, v, r) =>
+      keysSorted(l) && keysSorted(r) && 
+      (l.max.getOrElse (v-1) < v) && 
+      (r.min.getOrElse (v+1) > v)
   }
- 
-    
+
+
   // <<insert element x into the tree t>>
   def ins(x: Int, t: Tree): Tree = {
-    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) && keysSorted(t))
     t match {
       case Empty => Node(Red,Empty,x,Empty)
-      case Node(c,a,y,b) =>
-        if      (x < y)  balance(c, ins(x, a), y, b)
-        else if (x == y) Node(c,a,y,b)
-        else             balance(c,a,y,ins(x, b))
+      case n@Node(c,a,y,b) =>
+        if      (x < y)  balance(Node(c, ins(x, a), y, b))
+        else if (x == y) n
+        else             balance(Node(c, a, y, ins(x, b)))
     }
   } ensuring (res => 
-    content(res) == content(t) ++ Set(x) && 
-    size(t) <= size(res) && 
-    size(res) <= size(t) + 1 && 
+    res.content == t.content ++ Set(x) &&
+    t.size <= res.size &&
+    res.size <= t.size + 1 &&
+    keysSorted(res) &&
     redDescHaveBlackChildren(res) && 
     blackBalanced(res) 
   )
 
   def makeBlack(n: Tree): Tree = {
-    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    require(
+      redDescHaveBlackChildren(n) &&
+      blackBalanced(n) &&
+      keysSorted(n)
+    )
     n match {
       case Node(Red,l,v,r) => Node(Black,l,v,r)
       case _ => n
     }
-  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  } ensuring { res =>
+    res.isBlack &&
+    redNodesHaveBlackChildren(res) && 
+    blackBalanced(res) && 
+    keysSorted(res)
+  }
 
-  //def add(x: Int, t: Tree): Tree = {
-  //  require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
-  //  makeBlack(ins(x, t))
-  //} ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
- 
   def add(x: Int, t: Tree): Tree = {
-    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
-    ins(x, t) // FIXME: makeBlack(ins(x, t))
-  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) && keysSorted(t))
+    ins(x, t) // FIXME forgot makeBlack
+  } ensuring { res => 
+    res.content == t.content ++ Set(x) && 
+    redNodesHaveBlackChildren(res) && 
+    blackBalanced(res) &&
+    keysSorted(res)
+  }
   
-  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
-    // require(
-    //   Node(c,a,x,b) match {
-    //     case Node(Black,Node(Red,Node(Red,a,_,b),_,c),_,d) =>
-    //       redNodesHaveBlackChildren(a) &&
-    //       redNodesHaveBlackChildren(b) &&
-    //       redNodesHaveBlackChildren(c) &&
-    //       redNodesHaveBlackChildren(d)
-    //     case Node(Black,Node(Red,a,_,Node(Red,b,_,c)),_,d) =>
-    //       redNodesHaveBlackChildren(a) &&
-    //       redNodesHaveBlackChildren(b) &&
-    //       redNodesHaveBlackChildren(c) &&
-    //       redNodesHaveBlackChildren(d)
-    //     case Node(Black,a,_,Node(Red,Node(Red,b,_,c),_,d)) => 
-    //       redNodesHaveBlackChildren(a) &&
-    //       redNodesHaveBlackChildren(b) &&
-    //       redNodesHaveBlackChildren(c) &&
-    //       redNodesHaveBlackChildren(d)
-    //     case Node(Black,a,_,Node(Red,b,_,Node(Red,c,_,d))) => 
-    //       redNodesHaveBlackChildren(a) &&
-    //       redNodesHaveBlackChildren(b) &&
-    //       redNodesHaveBlackChildren(c) &&
-    //       redNodesHaveBlackChildren(d)
-    //     case t => redDescHaveBlackChildren(t)
-    //   }
-    // )
-    Node(c,a,x,b) match {
+  
+  def balance(t : Tree) : Tree = {
+    require(keysSorted(t))
+    t match {
+      case Empty => Empty
       case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
         Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
       case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
@@ -122,21 +148,12 @@ object RedBlackTree {
         Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
       case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
         Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-      case Node(c,a,xV,b) => Node(c,a,xV,b)
+      case other => other 
     }
-  } ensuring (res => content(res) == content(Node(c,a,x,b)) )// && redDescHaveBlackChildren(res))
-
-  // def buggyBalance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
-  //   Node(c,a,x,b) match {
-  //     case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
-  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-  //     case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
-  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-  //     case Node(Black,a,xV,Node(Red,Node(Red,b,yV,c),zV,d)) => 
-  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-  //     case Node(Black,a,xV,Node(Red,b,yV,Node(Red,c,zV,d))) => 
-  //       Node(Red,Node(Black,a,xV,b),yV,Node(Black,c,zV,d))
-  //   }
-  // } ensuring (res => content(res) == content(Node(c,a,x,b)) ) // && redDescHaveBlackChildren(res))
+  } ensuring { res => 
+    res.content == t.content &&
+    keysSorted(res)
+  }
+    
 
 }
-- 
GitLab