diff --git a/library/lang/package.scala b/library/lang/package.scala
index 44351d02ca9328bbbf86063745d233f2db17cd7c..bb7ec69122f4814bd61b1ce79f94c2eab9054c74 100644
--- a/library/lang/package.scala
+++ b/library/lang/package.scala
@@ -47,6 +47,9 @@ package object lang {
   @ignore
   def error[T](reason: java.lang.String): T = sys.error(reason)
 
+  @ignore
+  def old[T](value: T): T = value
+
   @ignore
   implicit class Passes[A,B](io : (A,B)) {
     val (in, out) = io
diff --git a/src/main/scala/leon/frontends/scalac/ASTExtractors.scala b/src/main/scala/leon/frontends/scalac/ASTExtractors.scala
index db477ec494742b0dc2b0e42e098676c4ab55282d..fb64b3311dfdd2af5b06df85ab2cb26088d3233e 100644
--- a/src/main/scala/leon/frontends/scalac/ASTExtractors.scala
+++ b/src/main/scala/leon/frontends/scalac/ASTExtractors.scala
@@ -574,6 +574,15 @@ trait ASTExtractors {
       }
     }
 
+    object ExOldExpression {
+      def unapply(tree: Apply) : Option[Symbol] = tree match {
+        case a @ Apply(TypeApply(ExSymbol("leon", "lang", "old"), List(tpe)), List(arg)) =>
+          Some(arg.symbol)
+        case _ =>
+          None
+      }
+    }
+
     object ExHoleExpression {
       def unapply(tree: Tree) : Option[(Tree, List[Tree])] = tree match {
         case a @ Apply(TypeApply(s @ ExSymbol("leon", "lang", "synthesis", "$qmark"), List(tpt)), args1)  =>
diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
index 24ecca501029604f25dc9c285e797be4562c5a01..4bca0e76794e64a40f32b56679d4a502d0b1590c 100644
--- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
+++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
@@ -1054,6 +1054,15 @@ trait CodeExtraction extends ASTExtractors {
           val tupleExprs = exprs.map(e => extractTree(e))
           Tuple(tupleExprs)
 
+        case ex@ExOldExpression(sym) if dctx.isVariable(sym) =>
+          dctx.vars.get(sym).orElse(dctx.mutableVars.get(sym)) match {
+            case Some(builder) =>
+              val Variable(id) = builder()
+              Old(id).setPos(ex.pos)
+            case None =>
+              outOfSubsetError(current, "old can only be used with variables")
+          }
+
         case ExErrorExpression(str, tpt) =>
           Error(extractType(tpt), str)
 
diff --git a/src/main/scala/leon/purescala/ExprOps.scala b/src/main/scala/leon/purescala/ExprOps.scala
index c106d1393bcf793a7fe5d6944ecd533d84a42e36..c80d777480f66d795f2bc15eef0a3010452394fb 100644
--- a/src/main/scala/leon/purescala/ExprOps.scala
+++ b/src/main/scala/leon/purescala/ExprOps.scala
@@ -345,6 +345,7 @@ object ExprOps {
         val subvs = subs.flatten.toSet
         e match {
           case Variable(i) => subvs + i
+          case Old(i) => subvs + i
           case LetDef(fd, _) => subvs -- fd.params.map(_.id)
           case Let(i, _, _) => subvs - i
           case LetVar(i, _, _) => subvs - i
diff --git a/src/main/scala/leon/purescala/Expressions.scala b/src/main/scala/leon/purescala/Expressions.scala
index 6e9adae5f6ee3548b1fa70af41b127e6a46a76b4..1569ebfb8ab3d8c0ab7f0e09bbb31f82870fc8f9 100644
--- a/src/main/scala/leon/purescala/Expressions.scala
+++ b/src/main/scala/leon/purescala/Expressions.scala
@@ -76,6 +76,10 @@ object Expressions {
     val getType = tpe
   }
 
+  case class Old(id: Identifier) extends Expr with Terminal {
+    val getType = id.getType
+  }
+
   /** Precondition of an [[Expressions.Expr]]. Corresponds to the Leon keyword *require*
     *
     * @param pred The precondition formula inside ``require(...)``
diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala
index 6b22810e542bdb9af65251da1c9a4d4ab1ab7142..3b96fff138dd7bc6a91c66acf3e3928fac0e44d0 100644
--- a/src/main/scala/leon/purescala/PrettyPrinter.scala
+++ b/src/main/scala/leon/purescala/PrettyPrinter.scala
@@ -77,6 +77,9 @@ class PrettyPrinter(opts: PrinterOptions,
         }
         p"$name"
 
+      case Old(id) =>
+        p"old($id)"
+
       case Variable(id) =>
         p"$id"
 
diff --git a/src/main/scala/leon/xlang/ImperativeCodeElimination.scala b/src/main/scala/leon/xlang/ImperativeCodeElimination.scala
index 7ab5925cebf63dd462db2627a45299e46e05978a..e9802d500208b96b5af448391d69c6660a05f843 100644
--- a/src/main/scala/leon/xlang/ImperativeCodeElimination.scala
+++ b/src/main/scala/leon/xlang/ImperativeCodeElimination.scala
@@ -129,6 +129,7 @@ object ImperativeCodeElimination extends UnitPhase[Program] {
         (resId.toVariable, scope, scrutFun ++ modifiedVars.zip(freshIds).toMap)
  
       case wh@While(cond, body) =>
+        //TODO: rewrite by re-using the nested function transformation code
         val (condRes, condScope, condFun) = toFunction(cond)
         val (_, bodyScope, bodyFun) = toFunction(body)
         val condBodyFun = condFun ++ bodyFun
@@ -323,7 +324,9 @@ object ImperativeCodeElimination extends UnitPhase[Program] {
                 val newBody =
                   replace(
                     modifiedVars.zipWithIndex.map{ case (v, i) => 
-                      (v.toVariable, TupleSelect(newRes.toVariable, i+2)): (Expr, Expr)}.toMap + 
+                      (v.toVariable, TupleSelect(newRes.toVariable, i+2)): (Expr, Expr)}.toMap ++
+                    modifiedVars.zip(freshNames).map{ case (ov, nv) => 
+                      (Old(ov), nv.toVariable)}.toMap +
                     (res.toVariable -> TupleSelect(newRes.toVariable, 1)),
                   postBody)
                 Lambda(Seq(newRes), newBody).setPos(post)
diff --git a/src/test/resources/regression/verification/xlang/valid/ArrayNested2.scala b/src/test/resources/regression/verification/xlang/valid/ArrayNested2.scala
index fb1a778b8922be1ad8bd5836c5a56740af930374..a8935ab8c1d4eec6980b85f171e695071f2a9442 100644
--- a/src/test/resources/regression/verification/xlang/valid/ArrayNested2.scala
+++ b/src/test/resources/regression/verification/xlang/valid/ArrayNested2.scala
@@ -4,7 +4,7 @@ object ArrayNested2 {
 
   def test(): Int = {
 
-    var a = Array(1, 2, 0)
+    val a = Array(1, 2, 0)
 
     def nested(): Unit = {
       require(a.length == 3)
diff --git a/src/test/resources/regression/verification/xlang/valid/NestedOld1.scala b/src/test/resources/regression/verification/xlang/valid/NestedOld1.scala
new file mode 100644
index 0000000000000000000000000000000000000000..903dfd63aca5105c9366c459552865646139033e
--- /dev/null
+++ b/src/test/resources/regression/verification/xlang/valid/NestedOld1.scala
@@ -0,0 +1,16 @@
+import leon.lang._
+
+object NestedOld1 {
+
+  def test(): Int = {
+    var counter = 0
+
+    def inc(): Unit = {
+      counter += 1
+    } ensuring(_ => counter == old(counter) + 1)
+
+    inc()
+    counter
+  } ensuring(_ == 1)
+
+}
diff --git a/src/test/resources/regression/verification/xlang/valid/NestedOld2.scala b/src/test/resources/regression/verification/xlang/valid/NestedOld2.scala
new file mode 100644
index 0000000000000000000000000000000000000000..fe6143ecf623c295251ca2b9d75d6474d422fd4f
--- /dev/null
+++ b/src/test/resources/regression/verification/xlang/valid/NestedOld2.scala
@@ -0,0 +1,24 @@
+import leon.lang._
+
+object NestedOld2 {
+
+  def test(): Int = {
+    var counterPrev = 0
+    var counterNext = 1
+
+    def step(): Unit = {
+      require(counterNext == counterPrev + 1)
+      counterPrev = counterNext
+      counterNext = counterNext+1
+    } ensuring(_ => {
+      counterPrev == old(counterNext) && 
+      counterNext == old(counterNext) + 1 &&
+      counterPrev == old(counterPrev) + 1
+    })
+
+    step()
+    step()
+    counterNext
+  } ensuring(_ == 3)
+
+}