From a59cd852f2a8536ae4e0358506595ea391821620 Mon Sep 17 00:00:00 2001
From: ravi <ravi.kandhadai@epfl.ch>
Date: Tue, 6 Oct 2015 18:25:17 +0200
Subject: [PATCH] Supporting resource verification of lazy programs

---
 .../util/LetTupleSimplifications.scala        |  12 +-
 .../laziness/LazinessEliminationPhase.scala   |  43 +-
 .../scala/leon/laziness/LazinessUtil.scala    |  11 +-
 .../leon/laziness/LazyClosureConverter.scala  |   3 +-
 .../leon/laziness/LazyInstrumenter.scala      |  62 +++
 .../solvers/templates/TemplateGenerator.scala |   2 +-
 .../SerialInstrumentationPhase.scala          | 499 +++++++++---------
 .../RealTimeQueue-transformed.scala           | 265 +++++-----
 .../lazy-datastructures/RealTimeQueue.scala   |  28 +-
 9 files changed, 496 insertions(+), 429 deletions(-)
 create mode 100644 src/main/scala/leon/laziness/LazyInstrumenter.scala

diff --git a/src/main/scala/leon/invariant/util/LetTupleSimplifications.scala b/src/main/scala/leon/invariant/util/LetTupleSimplifications.scala
index c89eae941..c62437405 100644
--- a/src/main/scala/leon/invariant/util/LetTupleSimplifications.scala
+++ b/src/main/scala/leon/invariant/util/LetTupleSimplifications.scala
@@ -99,13 +99,10 @@ object LetTupleSimplification {
           postMap(replaceMap.lift, true)(e) //perform recursive replacements to handle nested tuple selects
         //replaceMap(ts) //replace tuple-selects in the map with the new identifier
 
-        case t: Terminal => t
-
-        /*case UnaryOperator(sube, op) =>
-          op(recSimplify(sube, replaceMap))
+        case ts @ TupleSelect(Tuple(subes), i) =>
+          subes(i - 1)
 
-        case BinaryOperator(e1, e2, op) =>
-          op(recSimplify(e1, replaceMap), recSimplify(e2, replaceMap))*/
+        case t: Terminal => t
 
         case Operator(subes, op) =>
           op(subes.map(recSimplify(_, replaceMap)))
@@ -383,6 +380,9 @@ object LetTupleSimplification {
             }
           }
         }
+        // also perform a tuple simplification
+        case ts @ TupleSelect(Tuple(subes), i) =>
+          Some(subes(i - 1))
         case _ => None
       }
       res
diff --git a/src/main/scala/leon/laziness/LazinessEliminationPhase.scala b/src/main/scala/leon/laziness/LazinessEliminationPhase.scala
index defad548c..39d2e95ce 100644
--- a/src/main/scala/leon/laziness/LazinessEliminationPhase.scala
+++ b/src/main/scala/leon/laziness/LazinessEliminationPhase.scala
@@ -32,12 +32,13 @@ object LazinessEliminationPhase extends TransformationPhase {
   val debugLifting = false
   val dumpProgramWithClosures = false
   val dumpTypeCorrectProg = false
-  val dumpFinalProg = false
+  val dumpProgWithPreAsserts = false
+  val dumpInstrumentedProgram = false
   val debugSolvers = false
-  
+
   val skipVerification = false
   val prettyPrint = true
-  
+
   val name = "Laziness Elimination Phase"
   val description = "Coverts a program that uses lazy construct" +
     " to a program that does not use lazy constructs"
@@ -50,28 +51,33 @@ object LazinessEliminationPhase extends TransformationPhase {
    */
   def apply(ctx: LeonContext, prog: Program): Program = {
 
-    val nprog = liftLazyExpressions(prog)        
+    val nprog = liftLazyExpressions(prog)
     val progWithClosures = (new LazyClosureConverter(nprog, new LazyClosureFactory(nprog))).apply
     if (dumpProgramWithClosures)
-      println("After closure conversion: \n" + ScalaPrinter.apply(progWithClosures))    
-      
-    //Rectify type parameters and local types      
+      println("After closure conversion: \n" + ScalaPrinter.apply(progWithClosures))
+
+    //Rectify type parameters and local types
     val typeCorrectProg = (new TypeRectifier(progWithClosures, tp => tp.id.name.endsWith("@"))).apply
     if (dumpTypeCorrectProg)
       println("After rectifying types: \n" + ScalaPrinter.apply(typeCorrectProg))
-      
-    val transProg = (new ClosurePreAsserter(typeCorrectProg)).apply
-    if (dumpFinalProg)
-      println("After asserting closure preconditions: \n" + ScalaPrinter.apply(transProg))      
-  
+
+    val progWithPre = (new ClosurePreAsserter(typeCorrectProg)).apply
+    if (dumpProgWithPreAsserts)
+      println("After asserting closure preconditions: \n" + ScalaPrinter.apply(progWithPre))
+
+    // instrument the program for resources
+    val instProg = (new LazyInstrumenter(progWithPre)).apply
+    if(dumpInstrumentedProgram)
+      println("After instrumentation: \n" + ScalaPrinter.apply(instProg))
+
     // check specifications (to be moved to a different phase)
     if (!skipVerification)
-      checkSpecifications(transProg)
+      checkSpecifications(instProg)
     if (prettyPrint)
-      prettyPrintProgramToFile(transProg, ctx)
-    transProg
-  }  
-  
+      prettyPrintProgramToFile(instProg, ctx)
+    instProg
+  }
+
   /**
    * convert the argument of every lazy constructors to a procedure
    */
@@ -128,7 +134,7 @@ object LazinessEliminationPhase extends TransformationPhase {
     prog.definedFunctions.foreach { fd =>
       if (fd.annotations.contains("axiom"))
         fd.addFlag(Annotation("library", Seq()))
-    }    
+    }
     val functions = Seq() // Seq("--functions=Rotate@rotateLem")
     val solverOptions = if(debugSolvers) Seq("--debug=solver") else Seq()
     val ctx = Main.processOptions(Seq("--solvers=smt-cvc4") ++ solverOptions ++ functions)
@@ -232,4 +238,3 @@ object LazinessEliminationPhase extends TransformationPhase {
     invFuns
   }*/
 }
-
diff --git a/src/main/scala/leon/laziness/LazinessUtil.scala b/src/main/scala/leon/laziness/LazinessUtil.scala
index dd65f2df4..eb32ac937 100644
--- a/src/main/scala/leon/laziness/LazinessUtil.scala
+++ b/src/main/scala/leon/laziness/LazinessUtil.scala
@@ -57,7 +57,7 @@ object LazinessUtil {
       }
     }
     ctx.reporter.info("Output written on " + outputFolder)
-  }  
+  }
 
   def isLazyInvocation(e: Expr)(implicit p: Program): Boolean = e match {
     case FunctionInvocation(TypedFunDef(fd, _), Seq(_)) =>
@@ -134,6 +134,14 @@ object LazinessUtil {
     fd.id.name.startsWith("new@")
   }
 
+  def evalFunctionName(absTypeName: String) = {
+    "eval@" + absTypeName
+  }
+
+  def isEvalFunction(fd: FunDef) = {
+    fd.id.name.startsWith("eval@")
+  }
+
   /**
    * Returns all functions that 'need' states to be passed in
    * and those that return a new state.
@@ -163,4 +171,3 @@ object LazinessUtil {
     (funsNeedStates, funsRetStates)
   }
 }
-
diff --git a/src/main/scala/leon/laziness/LazyClosureConverter.scala b/src/main/scala/leon/laziness/LazyClosureConverter.scala
index 6b11c654c..a54835407 100644
--- a/src/main/scala/leon/laziness/LazyClosureConverter.scala
+++ b/src/main/scala/leon/laziness/LazyClosureConverter.scala
@@ -134,7 +134,7 @@ class LazyClosureConverter(p: Program, closureFactory: LazyClosureFactory) {
     val retType = TupleType(Seq(tpe, stType))
 
     // create a eval function
-    val dfun = new FunDef(FreshIdentifier("eval" + absdef.id.name, Untyped),
+    val dfun = new FunDef(FreshIdentifier(evalFunctionName(absdef.id.name), Untyped),
       tparamDefs, retType, Seq(ValDef(param1), ValDef(param2)))
 
     // assign body of the eval fucntion
@@ -523,4 +523,3 @@ class LazyClosureConverter(p: Program, closureFactory: LazyClosureFactory) {
         evalFunctions.values ++ computeFunctions.values, anchor)
   }
 }
-
diff --git a/src/main/scala/leon/laziness/LazyInstrumenter.scala b/src/main/scala/leon/laziness/LazyInstrumenter.scala
new file mode 100644
index 000000000..65bff6d22
--- /dev/null
+++ b/src/main/scala/leon/laziness/LazyInstrumenter.scala
@@ -0,0 +1,62 @@
+package leon
+package laziness
+
+import invariant.factories._
+import invariant.util.Util._
+import invariant.util._
+import invariant.structure.FunctionUtils._
+import purescala.ScalaPrinter
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.DefOps._
+import purescala.Extractors._
+import purescala.Types._
+import leon.invariant.util.TypeUtil._
+import leon.invariant.util.LetTupleSimplification._
+import leon.verification.AnalysisPhase
+import java.io.File
+import java.io.FileWriter
+import java.io.BufferedWriter
+import scala.util.matching.Regex
+import leon.purescala.PrettyPrinter
+import leon.LeonContext
+import leon.LeonOptionDef
+import leon.Main
+import leon.transformations._
+import LazinessUtil._
+
+class LazyInstrumenter(p: Program) {
+
+  def apply: Program = {
+    val exprInstFactory = (x: Map[FunDef, FunDef], y: SerialInstrumenter, z: FunDef) =>
+      new LazyExprInstrumenter(x, y)(z)
+    (new SerialInstrumenter(p, Some(exprInstFactory))).apply
+  }
+
+  class LazyExprInstrumenter(funMap: Map[FunDef, FunDef], serialInst: SerialInstrumenter)(implicit currFun: FunDef)
+      extends ExprInstrumenter(funMap, serialInst)(currFun) {
+
+    val costOfMemoization: Map[Instrumentation, Int] =
+      Map(Time -> 1, Stack -> 1, Rec -> 1, TPR -> 1, Depth -> 1)
+
+    override def apply(e: Expr): Expr = {
+      if (isEvalFunction(currFun)) {
+        val closureParam = currFun.params(0).id.toVariable
+        val stateParam = currFun.params(1).id.toVariable
+        val nbody = super.apply(e)
+        val bodyId = FreshIdentifier("bd", nbody.getType, true)
+        val instExprs = instrumenters map { m =>
+          IfExpr(ElementOfSet(closureParam, stateParam),
+              //SubsetOf(FiniteSet(Set(closureParam), closureParam.getType), stateParam),
+            InfiniteIntegerLiteral(costOfMemoization(m.inst)),
+            selectInst(bodyId.toVariable, m.inst))
+        }
+        Let(bodyId, nbody,
+          Tuple(TupleSelect(bodyId.toVariable, 1) +: instExprs))
+
+      } else super.apply(e)
+    }
+  }
+}
diff --git a/src/main/scala/leon/solvers/templates/TemplateGenerator.scala b/src/main/scala/leon/solvers/templates/TemplateGenerator.scala
index f6484ff7b..1ecc2c9cd 100644
--- a/src/main/scala/leon/solvers/templates/TemplateGenerator.scala
+++ b/src/main/scala/leon/solvers/templates/TemplateGenerator.scala
@@ -95,7 +95,7 @@ class TemplateGenerator[T](val encoder: TemplateEncoder[T],
           }
 
         val (postConds, postExprs, postGuarded, postLambdas, postQuantifications) = mkClauses(start, postHolds, substMap)
-        val allGuarded = (bodyGuarded.keys ++ postGuarded.keys).map { k => 
+        val allGuarded = (bodyGuarded.keys ++ postGuarded.keys).map { k =>
           k -> (bodyGuarded.getOrElse(k, Seq.empty) ++ postGuarded.getOrElse(k, Seq.empty))
         }.toMap
 
diff --git a/src/main/scala/leon/transformations/SerialInstrumentationPhase.scala b/src/main/scala/leon/transformations/SerialInstrumentationPhase.scala
index 20e3aa0e2..fba97a85b 100644
--- a/src/main/scala/leon/transformations/SerialInstrumentationPhase.scala
+++ b/src/main/scala/leon/transformations/SerialInstrumentationPhase.scala
@@ -12,7 +12,7 @@ import leon.utils._
 import invariant.util._
 import invariant.util.CallGraphUtil
 import invariant.structure.FunctionUtils._
-import scala.collection.mutable.{Map => MutableMap}
+import scala.collection.mutable.{ Map => MutableMap }
 
 /**
  * An instrumentation phase that performs a sequence of instrumentations
@@ -23,14 +23,16 @@ object InstrumentationPhase extends TransformationPhase {
   val description = "Instruments the program for all counters needed"
 
   def apply(ctx: LeonContext, program: Program): Program = {
-    val instprog = new SerialInstrumenter(ctx, program)
+    val instprog = new SerialInstrumenter(program)
     instprog.apply
   }
 }
 
-class SerialInstrumenter(ctx: LeonContext, program: Program) {
+class SerialInstrumenter(program: Program,
+    exprInstOpt : Option[(Map[FunDef, FunDef], SerialInstrumenter, FunDef) => ExprInstrumenter] = None) {
   val debugInstrumentation = false
 
+  val exprInstFactory = exprInstOpt.getOrElse((x: Map[FunDef, FunDef], y : SerialInstrumenter, z: FunDef) => new ExprInstrumenter(x, y)(z))
   val instToInstrumenter: Map[Instrumentation, Instrumenter] =
     Map(Time -> new TimeInstrumenter(program, this),
       Depth -> new DepthInstrumenter(program, this),
@@ -40,15 +42,17 @@ class SerialInstrumenter(ctx: LeonContext, program: Program) {
 
   // a map from functions to the list of instrumentations to be performed for the function
   lazy val funcInsts = {
-    var emap = MutableMap[FunDef,List[Instrumentation]]()
+    var emap = MutableMap[FunDef, List[Instrumentation]]()
     def update(fd: FunDef, inst: Instrumentation) {
       if (emap.contains(fd))
         emap(fd) = (emap(fd) :+ inst).distinct
       else emap.update(fd, List(inst))
     }
-    instToInstrumenter.values.foreach{ m =>
-      m.functionsToInstrument.foreach({ case (fd, instsToPerform) =>
-        instsToPerform.foreach(instToPerform => update(fd, instToPerform)) })
+    instToInstrumenter.values.foreach { m =>
+      m.functionsToInstrument.foreach({
+        case (fd, instsToPerform) =>
+          instsToPerform.foreach(instToPerform => update(fd, instToPerform))
+      })
     }
     emap.toMap
   }
@@ -100,7 +104,8 @@ class SerialInstrumenter(ctx: LeonContext, program: Program) {
 
     def mapBody(body: Expr, from: FunDef, to: FunDef) = {
       val res = if (instFuncs.contains(from)) {
-        (new ExprInstrumenter(funMap)(from)(body))
+        //(new ExprInstrumenter(funMap, this)(from)(body))
+        exprInstFactory(funMap, this, from)(body)
       } else
         mapExpr(body)
       res
@@ -154,16 +159,17 @@ class SerialInstrumenter(ctx: LeonContext, program: Program) {
       }
     }
 
-    val additionalFuncs = funMap.flatMap{ case (k, _) =>
-       if (instFuncs(k))
-        instrumenters(k).flatMap(_.additionalfunctionsToAdd)
-      else List()
+    val additionalFuncs = funMap.flatMap {
+      case (k, _) =>
+        if (instFuncs(k))
+          instrumenters(k).flatMap(_.additionalfunctionsToAdd)
+        else List()
     }.toList.distinct
 
     val newprog = Util.copyProgram(program, (defs: Seq[Definition]) =>
       defs.map {
         case fd: FunDef if funMap.contains(fd) =>
-           funMap(fd)
+          funMap(fd)
         case d => d
       } ++ additionalFuncs)
     if (debugInstrumentation)
@@ -172,269 +178,269 @@ class SerialInstrumenter(ctx: LeonContext, program: Program) {
     ProgramSimplifier(newprog)
   }
 
-  class ExprInstrumenter(funMap: Map[FunDef, FunDef])(implicit currFun: FunDef) {
-    val retainMatches = true
-
-    val insts = funcInsts(currFun)
-    val instrumenters = SerialInstrumenter.this.instrumenters(currFun)
-    val instIndex = SerialInstrumenter.this.instIndex(currFun) _
-    val selectInst = SerialInstrumenter.this.selectInst(currFun) _
-    val instTypes = SerialInstrumenter.this.instTypes(currFun)
-
-    // Should be called only if 'expr' has to be instrumented
-    // Returned Expr is always an expr of type tuple (Expr, Int)
-    def tupleify(e: Expr, subs: Seq[Expr], recons: Seq[Expr] => Expr)(implicit letIdMap: Map[Identifier, Identifier]): Expr = {
-      // When called for:
-      // Op(n1,n2,n3)
-      // e      = Op(n1,n2,n3)
-      // subs   = Seq(n1,n2,n3)
-      // recons = { Seq(newn1,newn2,newn3) => Op(newn1, newn2, newn3) }
-      //
-      // This transformation should return, informally:
-      //
-      // LetTuple((e1,t1), transform(n1),
-      //   LetTuple((e2,t2), transform(n2),
-      //    ...
-      //      Tuple(recons(e1, e2, ...), t1 + t2 + ... costOfExpr(Op)
-      //    ...
-      //   )
-      // )
-      //
-      // You will have to handle FunctionInvocation specially here!
-      tupleifyRecur(e, subs, recons, List(), Map())
-    }
+}
 
-    def tupleifyRecur(e: Expr, subs: Seq[Expr], recons: Seq[Expr] => Expr, subeVals: List[Expr],
-      subeInsts: Map[Instrumentation, List[Expr]])(implicit letIdMap: Map[Identifier, Identifier]): Expr = {
-      //note: subs.size should be zero if e is a terminal
-      if (subs.size == 0) {
-        e match {
-          case v @ Variable(id) =>
-            val valPart = if (letIdMap.contains(id)) {
-              TupleSelect(letIdMap(id).toVariable, 1) //this takes care of replacement
-            } else v
-            val instPart = instrumenters map (_.instrument(v, Seq()))
-            Tuple(valPart +: instPart)
-
-          case t: Terminal =>
-            val instPart = instrumenters map (_.instrument(t, Seq()))
-            val finalRes = Tuple(t +: instPart)
-            finalRes
-
-          case f @ FunctionInvocation(tfd, args) if tfd.fd.isRealFunction =>
-            val newfd = funMap(tfd.fd)
-            val newFunInv = FunctionInvocation(TypedFunDef(newfd, tfd.tps), subeVals)
-            //create a variables to store the result of function invocation
-            if (instFuncs(tfd.fd)) {
-              //this function is also instrumented
-              val resvar = Variable(FreshIdentifier("e", newfd.returnType, true))
-              val valexpr = TupleSelect(resvar, 1)
-              val instexprs = instrumenters.map { m =>
-                val calleeInst = if (funcInsts(tfd.fd).contains(m.inst)) {
-                  List(SerialInstrumenter.this.selectInst(tfd.fd)(resvar, m.inst))
-                } else List()
-                //Note we need to ensure that the last element of list is the instval of the finv
-                m.instrument(e, subeInsts.getOrElse(m.inst, List()) ++ calleeInst, Some(resvar))
-              }
-              Let(resvar.id, newFunInv, Tuple(valexpr +: instexprs))
-            } else {
-              val resvar = Variable(FreshIdentifier("e", tfd.fd.returnType, true))
-              val instexprs = instrumenters.map { m =>
-                m.instrument(e, subeInsts.getOrElse(m.inst, List()))
-              }
-              Let(resvar.id, newFunInv, Tuple(resvar +: instexprs))
-            }
+class ExprInstrumenter(funMap: Map[FunDef, FunDef], serialInst: SerialInstrumenter)(implicit currFun: FunDef) {
+  val retainMatches = true
+
+  val insts = serialInst.funcInsts(currFun)
+  val instrumenters = serialInst.instrumenters(currFun)
+  val instIndex = serialInst.instIndex(currFun) _
+  val selectInst = serialInst.selectInst(currFun) _
+  val instTypes = serialInst.instTypes(currFun)
+
+  // Should be called only if 'expr' has to be instrumented
+  // Returned Expr is always an expr of type tuple (Expr, Int)
+  def tupleify(e: Expr, subs: Seq[Expr], recons: Seq[Expr] => Expr)(implicit letIdMap: Map[Identifier, Identifier]): Expr = {
+    // When called for:
+    // Op(n1,n2,n3)
+    // e      = Op(n1,n2,n3)
+    // subs   = Seq(n1,n2,n3)
+    // recons = { Seq(newn1,newn2,newn3) => Op(newn1, newn2, newn3) }
+    //
+    // This transformation should return, informally:
+    //
+    // LetTuple((e1,t1), transform(n1),
+    //   LetTuple((e2,t2), transform(n2),
+    //    ...
+    //      Tuple(recons(e1, e2, ...), t1 + t2 + ... costOfExpr(Op)
+    //    ...
+    //   )
+    // )
+    //
+    // You will have to handle FunctionInvocation specially here!
+    tupleifyRecur(e, subs, recons, List(), Map())
+  }
 
-          // This case will be taken if the function invocation is actually a val (lazy or otherwise) in the class
-          case f @ FunctionInvocation(tfd, args) =>
-            val resvar = Variable(FreshIdentifier("e", tfd.fd.returnType, true))
-            val instPart = instrumenters map (_.instrument(f, Seq()))
-            val finalRes = Tuple(f +: instPart)
-            finalRes
-
-          case _ =>
-            val exprPart = recons(subeVals)
-            val instexprs = instrumenters.zipWithIndex.map {
-              case (menter, i) => menter.instrument(e, subeInsts.getOrElse(menter.inst, List()))
+  def tupleifyRecur(e: Expr, subs: Seq[Expr], recons: Seq[Expr] => Expr, subeVals: List[Expr],
+                    subeInsts: Map[Instrumentation, List[Expr]])(implicit letIdMap: Map[Identifier, Identifier]): Expr = {
+    //note: subs.size should be zero if e is a terminal
+    if (subs.size == 0) {
+      e match {
+        case v @ Variable(id) =>
+          val valPart = if (letIdMap.contains(id)) {
+            TupleSelect(letIdMap(id).toVariable, 1) //this takes care of replacement
+          } else v
+          val instPart = instrumenters map (_.instrument(v, Seq()))
+          Tuple(valPart +: instPart)
+
+        case t: Terminal =>
+          val instPart = instrumenters map (_.instrument(t, Seq()))
+          val finalRes = Tuple(t +: instPart)
+          finalRes
+
+        case f @ FunctionInvocation(tfd, args) if tfd.fd.isRealFunction =>
+          val newfd = TypedFunDef(funMap(tfd.fd), tfd.tps)
+          val newFunInv = FunctionInvocation(newfd, subeVals)
+          //create a variables to store the result of function invocation
+          if (serialInst.instFuncs(tfd.fd)) {
+            //this function is also instrumented
+            val resvar = Variable(FreshIdentifier("e", newfd.returnType, true))
+            val valexpr = TupleSelect(resvar, 1)
+            val instexprs = instrumenters.map { m =>
+              val calleeInst = if (serialInst.funcInsts(tfd.fd).contains(m.inst)) {
+                List(serialInst.selectInst(tfd.fd)(resvar, m.inst))
+              } else List()
+              //Note we need to ensure that the last element of list is the instval of the finv
+              m.instrument(e, subeInsts.getOrElse(m.inst, List()) ++ calleeInst, Some(resvar))
             }
-            Tuple(exprPart +: instexprs)
-        }
-      } else {
-        val currExp = subs.head
-        val resvar = Variable(FreshIdentifier("e", TupleType(currExp.getType +: instTypes), true))
-        val eval = TupleSelect(resvar, 1)
-        val instMap = insts.map { inst =>
-          (inst -> (subeInsts.getOrElse(inst, List()) :+ selectInst(resvar, inst)))
-        }.toMap
-        //process the remaining arguments
-        val recRes = tupleifyRecur(e, subs.tail, recons, subeVals :+ eval, instMap)
-        //transform the current expression
-        val newCurrExpr = transform(currExp)
-        Let(resvar.id, newCurrExpr, recRes)
+            Let(resvar.id, newFunInv, Tuple(valexpr +: instexprs))
+          } else {
+            val resvar = Variable(FreshIdentifier("e", newFunInv.getType, true))
+            val instexprs = instrumenters.map { m =>
+              m.instrument(e, subeInsts.getOrElse(m.inst, List()))
+            }
+            Let(resvar.id, newFunInv, Tuple(resvar +: instexprs))
+          }
+
+        // This case will be taken if the function invocation is actually a val (lazy or otherwise) in the class
+        case f @ FunctionInvocation(tfd, args) =>
+          val resvar = Variable(FreshIdentifier("e", tfd.fd.returnType, true))
+          val instPart = instrumenters map (_.instrument(f, Seq()))
+          val finalRes = Tuple(f +: instPart)
+          finalRes
+
+        case _ =>
+          val exprPart = recons(subeVals)
+          val instexprs = instrumenters.zipWithIndex.map {
+            case (menter, i) => menter.instrument(e, subeInsts.getOrElse(menter.inst, List()))
+          }
+          Tuple(exprPart +: instexprs)
       }
+    } else {
+      val currExp = subs.head
+      val resvar = Variable(FreshIdentifier("e", TupleType(currExp.getType +: instTypes), true))
+      val eval = TupleSelect(resvar, 1)
+      val instMap = insts.map { inst =>
+        (inst -> (subeInsts.getOrElse(inst, List()) :+ selectInst(resvar, inst)))
+      }.toMap
+      //process the remaining arguments
+      val recRes = tupleifyRecur(e, subs.tail, recons, subeVals :+ eval, instMap)
+      //transform the current expression
+      val newCurrExpr = transform(currExp)
+      Let(resvar.id, newCurrExpr, recRes)
     }
+  }
 
-    /**
-     * TODO: need to handle new expression trees
-     * Match statements without guards are now instrumented directly
-     */
-    def transform(e: Expr)(implicit letIdMap: Map[Identifier, Identifier]): Expr = e match {
-      // Assume that none of the matchcases has a guard. It has already been converted into an if then else
-      case me @ MatchExpr(scrutinee, matchCases) =>
-        val containsGuard = matchCases.exists(currCase => currCase.optGuard.isDefined)
-        if (containsGuard) {
-          def rewritePM(me: MatchExpr): Option[Expr] = {
-            val MatchExpr(scrut, cases) = me
-            val condsAndRhs = for (cse <- cases) yield {
-              val map = mapForPattern(scrut, cse.pattern)
-              val patCond = conditionForPattern(scrut, cse.pattern, includeBinders = false)
-              val realCond = cse.optGuard match {
-                case Some(g) => And(patCond, replaceFromIDs(map, g))
-                case None => patCond
-              }
-              val newRhs = replaceFromIDs(map, cse.rhs)
-              (realCond, newRhs)
+  /**
+   * TODO: need to handle new expression trees
+   * Match statements without guards are now instrumented directly
+   */
+  def transform(e: Expr)(implicit letIdMap: Map[Identifier, Identifier]): Expr = e match {
+    // Assume that none of the matchcases has a guard. It has already been converted into an if then else
+    case me @ MatchExpr(scrutinee, matchCases) =>
+      val containsGuard = matchCases.exists(currCase => currCase.optGuard.isDefined)
+      if (containsGuard) {
+        def rewritePM(me: MatchExpr): Option[Expr] = {
+          val MatchExpr(scrut, cases) = me
+          val condsAndRhs = for (cse <- cases) yield {
+            val map = mapForPattern(scrut, cse.pattern)
+            val patCond = conditionForPattern(scrut, cse.pattern, includeBinders = false)
+            val realCond = cse.optGuard match {
+              case Some(g) => And(patCond, replaceFromIDs(map, g))
+              case None    => patCond
             }
-            val bigIte = condsAndRhs.foldRight[Expr](
-              Error(me.getType, "Match is non-exhaustive").copiedFrom(me))((p1, ex) => {
-                if (p1._1 == BooleanLiteral(true)) {
-                  p1._2
-                } else {
-                  IfExpr(p1._1, p1._2, ex)
-                }
-              })
-            Some(bigIte)
+            val newRhs = replaceFromIDs(map, cse.rhs)
+            (realCond, newRhs)
           }
-          transform(rewritePM(me).get)
-        } else {
-          val instScrutinee =
-            Variable(FreshIdentifier("scr", TupleType(scrutinee.getType +: instTypes), true))
-
-          def transformMatchCaseList(mCases: Seq[MatchCase]): Seq[MatchCase] = {
-            def transformMatchCase(mCase: MatchCase) = {
-              val MatchCase(pattern, guard, expr) = mCase
-              val newExpr = {
-                val exprVal =
-                  Variable(FreshIdentifier("expr", TupleType(expr.getType +: instTypes), true))
-                val newExpr = transform(expr)
-                val instExprs = instrumenters map { m =>
-                  m.instrumentMatchCase(me, mCase, selectInst(exprVal, m.inst),
-                    selectInst(instScrutinee, m.inst))
-                }
-                val letBody = Tuple(TupleSelect(exprVal, 1) +: instExprs)
-                Let(exprVal.id, newExpr, letBody)
+          val bigIte = condsAndRhs.foldRight[Expr](
+            Error(me.getType, "Match is non-exhaustive").copiedFrom(me))((p1, ex) => {
+              if (p1._1 == BooleanLiteral(true)) {
+                p1._2
+              } else {
+                IfExpr(p1._1, p1._2, ex)
               }
-              MatchCase(pattern, guard, newExpr)
-            }
-            if (mCases.length == 0) Seq[MatchCase]()
-            else {
-              transformMatchCase(mCases.head) +: transformMatchCaseList(mCases.tail)
+            })
+          Some(bigIte)
+        }
+        transform(rewritePM(me).get)
+      } else {
+        val instScrutinee =
+          Variable(FreshIdentifier("scr", TupleType(scrutinee.getType +: instTypes), true))
+
+        def transformMatchCaseList(mCases: Seq[MatchCase]): Seq[MatchCase] = {
+          def transformMatchCase(mCase: MatchCase) = {
+            val MatchCase(pattern, guard, expr) = mCase
+            val newExpr = {
+              val exprVal =
+                Variable(FreshIdentifier("expr", TupleType(expr.getType +: instTypes), true))
+              val newExpr = transform(expr)
+              val instExprs = instrumenters map { m =>
+                m.instrumentMatchCase(me, mCase, selectInst(exprVal, m.inst),
+                  selectInst(instScrutinee, m.inst))
+              }
+              val letBody = Tuple(TupleSelect(exprVal, 1) +: instExprs)
+              Let(exprVal.id, newExpr, letBody)
             }
+            MatchCase(pattern, guard, newExpr)
+          }
+          if (mCases.length == 0) Seq[MatchCase]()
+          else {
+            transformMatchCase(mCases.head) +: transformMatchCaseList(mCases.tail)
           }
-          val matchExpr = MatchExpr(TupleSelect(instScrutinee, 1),
-            transformMatchCaseList(matchCases))
-          Let(instScrutinee.id, transform(scrutinee), matchExpr)
         }
+        val matchExpr = MatchExpr(TupleSelect(instScrutinee, 1),
+          transformMatchCaseList(matchCases))
+        Let(instScrutinee.id, transform(scrutinee), matchExpr)
+      }
 
-      case Let(i, v, b) => {
-        val (ni, nv) = {
-          val ir = Variable(FreshIdentifier("ir", TupleType(v.getType +: instTypes), true))
-          val transv = transform(v)
-          (ir, transv)
-        }
-        val r = Variable(FreshIdentifier("r", TupleType(b.getType +: instTypes), true))
-        val transformedBody = transform(b)(letIdMap + (i -> ni.id))
-        val instexprs = instrumenters map { m =>
-          m.instrument(e, List(selectInst(ni, m.inst), selectInst(r, m.inst)))
-        }
-        Let(ni.id, nv,
-          Let(r.id, transformedBody, Tuple(TupleSelect(r, 1) +: instexprs)))
+    case Let(i, v, b) => {
+      val (ni, nv) = {
+        val ir = Variable(FreshIdentifier("ir", TupleType(v.getType +: instTypes), true))
+        val transv = transform(v)
+        (ir, transv)
+      }
+      val r = Variable(FreshIdentifier("r", TupleType(b.getType +: instTypes), true))
+      val transformedBody = transform(b)(letIdMap + (i -> ni.id))
+      val instexprs = instrumenters map { m =>
+        m.instrument(e, List(selectInst(ni, m.inst), selectInst(r, m.inst)))
       }
+      Let(ni.id, nv,
+        Let(r.id, transformedBody, Tuple(TupleSelect(r, 1) +: instexprs)))
+    }
 
-      case ife @ IfExpr(cond, th, elze) => {
-        val (nifCons, condInsts) = {
-          val rescond = Variable(FreshIdentifier("c", TupleType(cond.getType +: instTypes), true))
-          val condInstPart = insts.map { inst => (inst -> selectInst(rescond, inst)) }.toMap
-          val recons = (e1: Expr, e2: Expr) => {
-            Let(rescond.id, transform(cond), IfExpr(TupleSelect(rescond, 1), e1, e2))
-          }
-          (recons, condInstPart)
-        }
-        val (nthenCons, thenInsts) = {
-          val resthen = Variable(FreshIdentifier("th", TupleType(th.getType +: instTypes), true))
-          val thInstPart = insts.map { inst => (inst -> selectInst(resthen, inst)) }.toMap
-          val recons = (theninsts: List[Expr]) => {
-            Let(resthen.id, transform(th), Tuple(TupleSelect(resthen, 1) +: theninsts))
-          }
-          (recons, thInstPart)
+    case ife @ IfExpr(cond, th, elze) => {
+      val (nifCons, condInsts) = {
+        val rescond = Variable(FreshIdentifier("c", TupleType(cond.getType +: instTypes), true))
+        val condInstPart = insts.map { inst => (inst -> selectInst(rescond, inst)) }.toMap
+        val recons = (e1: Expr, e2: Expr) => {
+          Let(rescond.id, transform(cond), IfExpr(TupleSelect(rescond, 1), e1, e2))
         }
-        val (nelseCons, elseInsts) = {
-          val reselse = Variable(FreshIdentifier("el", TupleType(elze.getType +: instTypes), true))
-          val elInstPart = insts.map { inst => (inst -> selectInst(reselse, inst)) }.toMap
-          val recons = (einsts: List[Expr]) => {
-            Let(reselse.id, transform(elze), Tuple(TupleSelect(reselse, 1) +: einsts))
-          }
-          (recons, elInstPart)
+        (recons, condInstPart)
+      }
+      val (nthenCons, thenInsts) = {
+        val resthen = Variable(FreshIdentifier("th", TupleType(th.getType +: instTypes), true))
+        val thInstPart = insts.map { inst => (inst -> selectInst(resthen, inst)) }.toMap
+        val recons = (theninsts: List[Expr]) => {
+          Let(resthen.id, transform(th), Tuple(TupleSelect(resthen, 1) +: theninsts))
         }
-        val (finalThInsts, finalElInsts) = instrumenters.foldLeft((List[Expr](), List[Expr]())) {
-          case ((thinsts, elinsts), menter) =>
-            val inst = menter.inst
-            val (thinst, elinst) = menter.instrumentIfThenElseExpr(ife,
-              Some(condInsts(inst)), Some(thenInsts(inst)), Some(elseInsts(inst)))
-            (thinsts :+ thinst, elinsts :+ elinst)
+        (recons, thInstPart)
+      }
+      val (nelseCons, elseInsts) = {
+        val reselse = Variable(FreshIdentifier("el", TupleType(elze.getType +: instTypes), true))
+        val elInstPart = insts.map { inst => (inst -> selectInst(reselse, inst)) }.toMap
+        val recons = (einsts: List[Expr]) => {
+          Let(reselse.id, transform(elze), Tuple(TupleSelect(reselse, 1) +: einsts))
         }
-        val nthen = nthenCons(finalThInsts)
-        val nelse = nelseCons(finalElInsts)
-        nifCons(nthen, nelse)
+        (recons, elInstPart)
       }
+      val (finalThInsts, finalElInsts) = instrumenters.foldLeft((List[Expr](), List[Expr]())) {
+        case ((thinsts, elinsts), menter) =>
+          val inst = menter.inst
+          val (thinst, elinst) = menter.instrumentIfThenElseExpr(ife,
+            Some(condInsts(inst)), Some(thenInsts(inst)), Some(elseInsts(inst)))
+          (thinsts :+ thinst, elinsts :+ elinst)
+      }
+      val nthen = nthenCons(finalThInsts)
+      val nelse = nelseCons(finalElInsts)
+      nifCons(nthen, nelse)
+    }
 
-      // For all other operations, we go through a common tupleifier.
-      case n @ Operator(ss, recons) =>
-        tupleify(e, ss, recons)
+    // For all other operations, we go through a common tupleifier.
+    case n @ Operator(ss, recons) =>
+      tupleify(e, ss, recons)
 
-/*      case b @ BinaryOperator(s1, s2, recons) =>
+    /*      case b @ BinaryOperator(s1, s2, recons) =>
         tupleify(e, Seq(s1, s2), { case Seq(s1, s2) => recons(s1, s2) })
 
       case u @ UnaryOperator(s, recons) =>
         tupleify(e, Seq(s), { case Seq(s) => recons(s) })
 */
-      case t: Terminal =>
-        tupleify(e, Seq(), { case Seq() => t })
-    }
-
-    def apply(e: Expr): Expr = {
-      // Apply transformations
-      val newe =
-        if (retainMatches) e
-        else matchToIfThenElse(liftExprInMatch(e))
-      val transformed = transform(newe)(Map())
-      val bodyId = FreshIdentifier("bd", transformed.getType, true)
-      val instExprs = instrumenters map { m =>
-        m.instrumentBody(newe,
-          selectInst(bodyId.toVariable, m.inst))
+    case t: Terminal =>
+      tupleify(e, Seq(), { case Seq() => t })
+  }
 
-      }
-      Let(bodyId, transformed,
-        Tuple(TupleSelect(bodyId.toVariable, 1) +: instExprs))
+  def apply(e: Expr): Expr = {
+    // Apply transformations
+    val newe =
+      if (retainMatches) e
+      else matchToIfThenElse(liftExprInMatch(e))
+    val transformed = transform(newe)(Map())
+    val bodyId = FreshIdentifier("bd", transformed.getType, true)
+    val instExprs = instrumenters map { m =>
+      m.instrumentBody(newe,
+        selectInst(bodyId.toVariable, m.inst))
     }
+    Let(bodyId, transformed,
+      Tuple(TupleSelect(bodyId.toVariable, 1) +: instExprs))
+  }
 
-    def liftExprInMatch(ine: Expr): Expr = {
-      def helper(e: Expr): Expr = {
-        e match {
-          case MatchExpr(strut, cases) => strut match {
-            case t: Terminal => e
-            case _ => {
-              val freshid = FreshIdentifier("m", strut.getType, true)
-              Let(freshid, strut, MatchExpr(freshid.toVariable, cases))
-            }
+  def liftExprInMatch(ine: Expr): Expr = {
+    def helper(e: Expr): Expr = {
+      e match {
+        case MatchExpr(strut, cases) => strut match {
+          case t: Terminal => e
+          case _ => {
+            val freshid = FreshIdentifier("m", strut.getType, true)
+            Let(freshid, strut, MatchExpr(freshid.toVariable, cases))
           }
-          case _ => e
         }
+        case _ => e
       }
-
-      if (retainMatches) helper(ine)
-      else simplePostTransform(helper)(ine)
     }
+
+    if (retainMatches) helper(ine)
+    else simplePostTransform(helper)(ine)
   }
 }
 
@@ -467,14 +473,13 @@ abstract class Instrumenter(program: Program, si: SerialInstrumenter) {
    * by Expression Extractors.
    * fd is the function containing the expression `e`
    */
-  def instrument(e: Expr, subInsts: Seq[Expr], funInvResVar: Option[Variable] = None)
-    (implicit fd: FunDef, letIdMap: Map[Identifier, Identifier]): Expr
+  def instrument(e: Expr, subInsts: Seq[Expr], funInvResVar: Option[Variable] = None)(implicit fd: FunDef, letIdMap: Map[Identifier, Identifier]): Expr
 
   /**
    * Instrument procedure specialized for if-then-else
    */
   def instrumentIfThenElseExpr(e: IfExpr, condInst: Option[Expr],
-    thenInst: Option[Expr], elzeInst: Option[Expr]): (Expr, Expr)
+                               thenInst: Option[Expr], elzeInst: Option[Expr]): (Expr, Expr)
 
   /**
    * This function is expected to combine the cost of the scrutinee,
@@ -485,5 +490,5 @@ abstract class Instrumenter(program: Program, si: SerialInstrumenter) {
    * matching across match statements and ifThenElse statements is consistent
    */
   def instrumentMatchCase(me: MatchExpr, mc: MatchCase,
-    caseExprCost: Expr, scrutineeCost: Expr): Expr
+                          caseExprCost: Expr, scrutineeCost: Expr): Expr
 }
\ No newline at end of file
diff --git a/testcases/lazy-datastructures/RealTimeQueue-transformed.scala b/testcases/lazy-datastructures/RealTimeQueue-transformed.scala
index d416dacb0..f690cc86b 100644
--- a/testcases/lazy-datastructures/RealTimeQueue-transformed.scala
+++ b/testcases/lazy-datastructures/RealTimeQueue-transformed.scala
@@ -1,12 +1,13 @@
 //import leon.lazyeval._
-import leon.lang._
-import leon.annotation._
-import leon.collection._
+package leon
+import lang._
+import annotation._
+import collection._
 
 object RealTimeQueue {
   abstract class LList[T]
-  
-  def LList$isEmpty[T]($this : LList[T]): Boolean = {
+
+  def LList$isEmpty[T]($this: LList[T]): Boolean = {
     $this match {
       case SNil() =>
         true
@@ -14,8 +15,8 @@ object RealTimeQueue {
         false
     }
   }
-  
-  def LList$isCons[T]($this : LList[T]): Boolean = {
+
+  def LList$isCons[T]($this: LList[T]): Boolean = {
     $this match {
       case SCons(_, _) =>
         true
@@ -23,8 +24,8 @@ object RealTimeQueue {
         false
     }
   }
-  
-  def LList$size[T]($this : LList[T]): BigInt = {    
+
+  def LList$size[T]($this: LList[T]): BigInt = {
     $this match {
       case SNil() =>
         BigInt(0)
@@ -32,31 +33,30 @@ object RealTimeQueue {
         BigInt(1) + ssize[T](t)
     }
   } ensuring {
-    (x$1 : BigInt) => (x$1 >= BigInt(0))
+    (x$1: BigInt) => (x$1 >= BigInt(0))
   }
-  
-  case class SCons[T](x : T, tail : LazyLList[T]) extends LList[T]
-  
+
+  case class SCons[T](x: T, tail: LazyLList[T]) extends LList[T]
+
   case class SNil[T]() extends LList[T]
-  
+
   // TODO: closures are not ADTs since two closures with same arguments are not necessarily equal but 
   // ADTs are equal. This creates a bit of problem in checking if a closure belongs to a set or not.
   // However, currently we are assuming that such problems do not happen. 
   // A solution is to pass around a dummy id that is unique for each closure.
   abstract class LazyLList[T]
-  
-  case class Rotate[T](f : LazyLList[T], r : List[T], a : LazyLList[T], res: LList[T]) extends LazyLList[T]
-  
-  case class Lazyarg[T](newa : LList[T]) extends LazyLList[T]
 
+  case class Rotate[T](f: LazyLList[T], r: List[T], a: LazyLList[T], res: LList[T]) extends LazyLList[T]
+
+  case class Lazyarg[T](newa: LList[T]) extends LazyLList[T]
 
-  def ssize[T](l : LazyLList[T]): BigInt = {    
+  def ssize[T](l: LazyLList[T]): BigInt = {
     val clist = evalLazyLList[T](l, Set[LazyLList[T]]())._1
     LList$size[T](clist)
 
-  } ensuring(res => res >= 0)
+  } ensuring (res => res >= 0)
 
-  def isConcrete[T](l : LazyLList[T], st : Set[LazyLList[T]]): Boolean = {
+  def isConcrete[T](l: LazyLList[T], st: Set[LazyLList[T]]): Boolean = {
     Set[LazyLList[T]](l).subsetOf(st) && (evalLazyLList[T](l, st)._1 match {
       case SCons(_, tail) =>
         isConcrete[T](tail, st)
@@ -64,28 +64,20 @@ object RealTimeQueue {
         true
     }) || LList$isEmpty[T](evalLazyLList[T](l, st)._1)
   }
-  
-  // an assertion: closures created by evaluating a closure will result in unevaluated closure
+
+  // an assertion: closures created by evaluating a closure will result in unevaluated closure  
   @library
-  def lemmaLazy[T](l : LazyLList[T], st : Set[LazyLList[T]]) : Boolean = {
-    Set[LazyLList[T]](l).subsetOf(st) || {     
+  def lemmaLazy[T](l: LazyLList[T], st: Set[LazyLList[T]]): Boolean = {
+    Set[LazyLList[T]](l).subsetOf(st) || {
       evalLazyLList[T](l, Set[LazyLList[T]]())._1 match {
-	case SCons(_, tail) => 
-	  l != tail && !Set[LazyLList[T]](tail).subsetOf(st)
-	case _ => true
+        case SCons(_, tail) =>
+          l != tail && !Set[LazyLList[T]](tail).subsetOf(st)
+        case _ => true
       }
     }
-//     Set[LazyLList[T]](l).subsetOf(st) || {
-//       val (nval, nst, _) = evalLazyLList[T](l, st)
-//       nval match {
-// 	case SCons(_, tail) => 
-// 	  !Set[LazyLList[T]](tail).subsetOf(nst)
-// 	case _ => true
-//       }
-//     }
   } holds
-    
-  def firstUnevaluated[T](l : LazyLList[T], st : Set[LazyLList[T]]): LazyLList[T] = {
+
+  def firstUnevaluated[T](l: LazyLList[T], st: Set[LazyLList[T]]): LazyLList[T] = {
     if (Set[LazyLList[T]](l).subsetOf(st)) {
       evalLazyLList[T](l, st)._1 match {
         case SCons(_, tail) =>
@@ -96,71 +88,70 @@ object RealTimeQueue {
     } else {
       l
     }
-  } ensuring(res => (!LList$isEmpty[T](evalLazyLList[T](res, st)._1) || isConcrete[T](l, st)) && 
-	      (LList$isEmpty[T](evalLazyLList[T](res, st)._1) || !Set[LazyLList[T]](res).subsetOf(st)) && 	      
-	      { val (nval, nst, _) = evalLazyLList[T](res, st)
-		nval match {
-		  case SCons(_, tail) => 
-		      firstUnevaluated(l, nst) == tail		      		      
-		  case _ => true
-		}
-	      } && 
-	      lemmaLazy(res, st)
-	    )  
-  
+  } ensuring (res => (!LList$isEmpty[T](evalLazyLList[T](res, st)._1) || isConcrete[T](l, st)) &&
+    (LList$isEmpty[T](evalLazyLList[T](res, st)._1) || !Set[LazyLList[T]](res).subsetOf(st)) &&
+    {
+      val (nval, nst, _) = evalLazyLList[T](res, st)
+      nval match {
+        case SCons(_, tail) =>
+          firstUnevaluated(l, nst) == tail
+        case _ => true
+      }
+    } &&
+    lemmaLazy(res, st))
+
   @library
-  def evalLazyLList[T](cl : LazyLList[T], st : Set[LazyLList[T]]): (LList[T], Set[LazyLList[T]], BigInt) = {    
+  def evalLazyLList[T](cl: LazyLList[T], st: Set[LazyLList[T]]): (LList[T], Set[LazyLList[T]], BigInt) = {
     cl match {
-      case t : Rotate[T] =>
+      case t: Rotate[T] =>
         val (rres, _, rtime) = rotate(t.f, t.r, t.a, st)
         val tset = Set[LazyLList[T]](t)
-	val tme = 
-	  if(tset.subsetOf(st))
-	    BigInt(1)
-	  else // time of rotate
-	    rtime
+        val tme =
+          if (tset.subsetOf(st))
+            BigInt(1)
+          else // time of rotate
+            rtime
         (rotate(t.f, t.r, t.a, Set[LazyLList[T]]())._1, st ++ tset, tme)
 
-      case t : Lazyarg[T] =>
+      case t: Lazyarg[T] =>
         (lazyarg(t.newa), st ++ Set[LazyLList[T]](t), BigInt(1))
     }
-  } ensuring(res => (cl match {
-      case t : Rotate[T] => 
-        LList$size(res._1) == ssize(t.f) + t.r.size + ssize(t.a) && 
-	      res._1 != SNil[T]() && 
-	     res._3 <= 4
-      case _ => true
-     }) 
-    // && 
-    //   (res._1 match {
-	   //       case SCons(_, tail) => 
-	   //         Set[LazyLList[T]](cl).subsetOf(st) || !Set[LazyLList[T]](tail).subsetOf(res._2)
-	   //       case _ => true
-    //   })
-    )
-  
+  } ensuring (res => (cl match {
+    case t: Rotate[T] =>
+      LList$size(res._1) == ssize(t.f) + t.r.size + ssize(t.a) &&
+        res._1 != SNil[T]() &&
+        res._3 <= 4
+    case _ => true
+  }) // && 
+  //   (res._1 match {
+  //       case SCons(_, tail) => 
+  //         Set[LazyLList[T]](cl).subsetOf(st) || !Set[LazyLList[T]](tail).subsetOf(res._2)
+  //       case _ => true
+  //   })
+  )
+
   @extern
-  def rotate2[T](f : LazyLList[T], r : List[T], a : LazyLList[T], st : Set[LazyLList[T]]): (LList[T], Set[LazyLList[T]], BigInt) = ???
-  
-  def lazyarg[T](newa : LList[T]): LList[T] = {
+  def rotate2[T](f: LazyLList[T], r: List[T], a: LazyLList[T], st: Set[LazyLList[T]]): (LList[T], Set[LazyLList[T]], BigInt) = ???
+
+  def lazyarg[T](newa: LList[T]): LList[T] = {
     newa
-  } 
-  
-  def streamScheduleProperty[T](s : LazyLList[T], sch : LazyLList[T], st : Set[LazyLList[T]]): Boolean = {
+  }
+
+  def streamScheduleProperty[T](s: LazyLList[T], sch: LazyLList[T], st: Set[LazyLList[T]]): Boolean = {
     firstUnevaluated[T](s, st) == sch
   }
-  
-  case class Queue[T](f : LazyLList[T], r : List[T], s : LazyLList[T])
-  
-  def Queue$isEmpty[T]($this : Queue[T], st : Set[LazyLList[T]]): Boolean = {    
+
+  case class Queue[T](f: LazyLList[T], r: List[T], s: LazyLList[T])
+
+  def Queue$isEmpty[T]($this: Queue[T], st: Set[LazyLList[T]]): Boolean = {
     LList$isEmpty[T](evalLazyLList[T]($this.f, st)._1)
   }
-  
-  def Queue$valid[T]($this : Queue[T], st : Set[LazyLList[T]]): Boolean = {
-    streamScheduleProperty[T]($this.f, $this.s, st) && 
+
+  def Queue$valid[T]($this: Queue[T], st: Set[LazyLList[T]]): Boolean = {
+    streamScheduleProperty[T]($this.f, $this.s, st) &&
       ssize[T]($this.s) == ssize[T]($this.f) - $this.r.size
   }
-  
+
   // things to prove:
   // (a0) prove that pre implies post for 'rotate' (this depends on the assumption on eval)
   // (a) Rotate closure creations satisfy the preconditions of 'rotate' (or)    
@@ -172,66 +163,67 @@ object RealTimeQueue {
   // Note: using both captured and calling context is possible but is more involved
   // (c) Assume that 'eval' ensures the postcondition of 'rotate'
   // (d) Moreover we can also assume that the preconditons of rotate hold whenever we use a closure
-  
+
   // proof of (a)
   // (i) for stateless invariants this can be proven by treating lazy eager, 
   // so not doing this here
-  
+
   // monotonicity of isConcrete
-  def lemmaConcreteMonotone[T](f : LazyLList[T], st1 : Set[LazyLList[T]], st2 : Set[LazyLList[T]]) : Boolean = {    
+  def lemmaConcreteMonotone[T](f: LazyLList[T], st1: Set[LazyLList[T]], st2: Set[LazyLList[T]]): Boolean = {
     (evalLazyLList[T](f, st1)._1 match {
       case SCons(_, tail) =>
-	      lemmaConcreteMonotone(tail, st1, st2)        
+        lemmaConcreteMonotone(tail, st1, st2)
       case _ =>
         true
-    }) &&   
+    }) &&
       !(st1.subsetOf(st2) && isConcrete(f, st1)) || isConcrete(f, st2)
   } holds
- 
+
   // proof that the precondition isConcrete(f, st) holds for closure creation in 'rotate' function
-  def rotateClosureLemma1[T](f : LazyLList[T], st : Set[LazyLList[T]]): Boolean = {
-    require(isConcrete(f, st)) 
+  def rotateClosureLemma1[T](f: LazyLList[T], st: Set[LazyLList[T]]): Boolean = {
+    require(isConcrete(f, st))
     val dres = evalLazyLList[T](f, st);
-    dres._1 match {      
-      case SCons(x, tail) =>        
+    dres._1 match {
+      case SCons(x, tail) =>
         isConcrete(tail, st)
       case _ => true
     }
   } holds
-  
+
   // proof that the precondition isConcrete(f, st) holds for closure creation in 'createQueue' function
-  def rotateClosureLemma2[T](f : LazyLList[T], sch : LazyLList[T], st : Set[LazyLList[T]]): Boolean = {    
+  // @ important use and instantiate monotonicity of 
+  def rotateClosureLemma2[T](f: LazyLList[T], sch: LazyLList[T], st: Set[LazyLList[T]]): Boolean = {
     require(streamScheduleProperty[T](f, sch, st)) // && ssize[T](sch) == (ssize[T](f) - r.size) + BigInt(1))
     val dres4 = evalLazyLList[T](sch, st);
-    dres4._1 match {      
+    dres4._1 match {
       case SNil() =>
         //isConcrete(f, dres4._2)
-        isConcrete(f, st)  // the above is implied by the monotonicity of 'isConcrete'
-      case _ => true        
-    }  
+        isConcrete(f, st) // the above is implied by the monotonicity of 'isConcrete'
+      case _ => true
+    }
   } holds
-  
+
   // proof that the precondition isConcrete(f, st) holds for closure creation in 'dequeue' function
-  def rotateClosureLemma3[T](q : Queue[T], st : Set[LazyLList[T]]): Boolean = {
-    require(!Queue$isEmpty[T](q, st) && Queue$valid[T](q, st))    
+  def rotateClosureLemma3[T](q: Queue[T], st: Set[LazyLList[T]]): Boolean = {
+    require(!Queue$isEmpty[T](q, st) && Queue$valid[T](q, st))
     val dres7 = evalLazyLList[T](q.f, st);
-    val SCons(x, nf) = dres7._1    
+    val SCons(x, nf) = dres7._1
     val dres8 = evalLazyLList[T](q.s, dres7._2);
-    dres8._1 match {      
+    dres8._1 match {
       case SNil() =>
-        isConcrete(nf, st)         
-        // the above would imply: isConcrete(nf, dres8._2) by monotonicity
+        isConcrete(nf, st)
+      // the above would imply: isConcrete(nf, dres8._2) by monotonicity
       case _ => true
     }
   } holds
-  
+
   // part(c) assume postconditon of 'rotate' in closure invocation time and also 
   // the preconditions of 'rotate' if necesssary, and prove the properties of the 
   // methods that invoke closures     
-    
+
   // proving specifications of 'rotate' (only state specifications are interesting)  
-  def rotate[T](f : LazyLList[T], r : List[T], a : LazyLList[T], st : Set[LazyLList[T]]): (LList[T], Set[LazyLList[T]], BigInt) = {
-    require(r.size == ssize[T](f) + BigInt(1) && isConcrete(f, st))      
+  def rotate[T](f: LazyLList[T], r: List[T], a: LazyLList[T], st: Set[LazyLList[T]]): (LList[T], Set[LazyLList[T]], BigInt) = {
+    require(r.size == ssize[T](f) + BigInt(1) && isConcrete(f, st))
     val dres = evalLazyLList[T](f, st);
     (dres._1, r) match {
       case (SNil(), Cons(y, _)) =>
@@ -240,45 +232,44 @@ object RealTimeQueue {
         val na = Lazyarg[T](SCons[T](y, a))
         (SCons[T](x, Rotate[T](tail, r1, na, SNil[T]())), dres._2, dres._3 + 3)
     }
-  } ensuring(res => LList$size(res._1) == ssize(f) + r.size + ssize(a) &&
-		    res._1 != SNil[T]() &&
-		    res._3 <= 4)  
-  
-   
+  } ensuring (res => LList$size(res._1) == ssize(f) + r.size + ssize(a) &&
+    res._1 != SNil[T]() &&
+    res._3 <= 4)
+
   // a stub for creating new closure (ensures that the new closures do not belong to the old state)
   // Note: this could result in inconsistency since we are associating unique ids with closures
   @library
-  def newclosure[T](rt: Rotate[T], st: Set[LazyLList[T]])  = {
+  def newclosure[T](rt: Rotate[T], st: Set[LazyLList[T]]) = {
     (rt, st)
-  } ensuring(res => !Set[LazyLList[T]](res._1).subsetOf(st))
-  
+  } ensuring (res => !Set[LazyLList[T]](res._1).subsetOf(st))
+
   // proving specifications of 'createQueue' (only state specifications are interesting)
-  def createQueue[T](f : LazyLList[T], r : List[T], sch : LazyLList[T], st : Set[LazyLList[T]]): (Queue[T], Set[LazyLList[T]], BigInt) = {
-    require(streamScheduleProperty[T](f, sch, st) && 
+  def createQueue[T](f: LazyLList[T], r: List[T], sch: LazyLList[T], st: Set[LazyLList[T]]): (Queue[T], Set[LazyLList[T]], BigInt) = {
+    require(streamScheduleProperty[T](f, sch, st) &&
       ssize[T](sch) == (ssize[T](f) - r.size) + BigInt(1))
     val dres4 = evalLazyLList[T](sch, st);
     dres4._1 match {
       case SCons(_, tail) =>
         (Queue[T](f, r, tail), dres4._2, dres4._3 + 2)
-      case SNil() =>       
+      case SNil() =>
         val rotres1 = newclosure(Rotate[T](f, r, Lazyarg[T](SNil[T]()), SNil[T]()), dres4._2); // can also directly call rotate here
         (Queue[T](rotres1._1, List[T](), rotres1._1), dres4._2, dres4._3 + 3)
     }
-  } ensuring(res => Queue$valid[T](res._1, res._2) && 
-		    res._3 <= 7)  
-  
+  } ensuring (res => Queue$valid[T](res._1, res._2) &&
+    res._3 <= 7)
+
   // proving specifications of 'enqueue'
-  def enqueue[T](x : T, q : Queue[T], st : Set[LazyLList[T]]): (Queue[T], Set[LazyLList[T]], BigInt) = {
+  def enqueue[T](x: T, q: Queue[T], st: Set[LazyLList[T]]): (Queue[T], Set[LazyLList[T]], BigInt) = {
     require(Queue$valid[T](q, st))
     createQueue[T](q.f, Cons[T](x, q.r), q.s, st)
-  } ensuring (res => Queue$valid[T](res._1, res._2) && 
-		      res._3 <= 7)  
-  
+  } ensuring (res => Queue$valid[T](res._1, res._2) &&
+    res._3 <= 7)
+
   // proving specifications of 'dequeue'
-  def dequeue[T](q : Queue[T], st : Set[LazyLList[T]]): (Queue[T], Set[LazyLList[T]], BigInt) = {
-    require(!Queue$isEmpty[T](q, st) && Queue$valid[T](q, st))    
+  def dequeue[T](q: Queue[T], st: Set[LazyLList[T]]): (Queue[T], Set[LazyLList[T]], BigInt) = {
+    require(!Queue$isEmpty[T](q, st) && Queue$valid[T](q, st))
     val dres7 = evalLazyLList[T](q.f, st);
-    val SCons(x, nf) = dres7._1    
+    val SCons(x, nf) = dres7._1
     val dres8 = evalLazyLList[T](q.s, dres7._2);
     dres8._1 match {
       case SCons(_, nsch) =>
@@ -287,6 +278,6 @@ object RealTimeQueue {
         val rotres3 = newclosure(Rotate[T](nf, q.r, Lazyarg[T](SNil[T]()), SNil[T]()), dres8._2);
         (Queue[T](rotres3._1, List[T](), rotres3._1), dres8._2, dres7._3 + dres8._3 + 4)
     }
-  } ensuring(res => Queue$valid[T](res._1, res._2) && 
-		    res._3 <= 12)  
+  } ensuring (res => Queue$valid[T](res._1, res._2) &&
+    res._3 <= 12)
 }
diff --git a/testcases/lazy-datastructures/RealTimeQueue.scala b/testcases/lazy-datastructures/RealTimeQueue.scala
index a058163be..e3f4618cf 100644
--- a/testcases/lazy-datastructures/RealTimeQueue.scala
+++ b/testcases/lazy-datastructures/RealTimeQueue.scala
@@ -2,6 +2,7 @@ import leon.lazyeval._
 import leon.lang._
 import leon.annotation._
 import leon.collection._
+import leon.instrumentation._
 
 object RealTimeQueue {
 
@@ -9,20 +10,20 @@ object RealTimeQueue {
     def isEmpty: Boolean = {
       this match {
         case SNil() => true
-        case _ => false
+        case _      => false
       }
     }
 
     def isCons: Boolean = {
       this match {
         case SCons(_, _) => true
-        case _ => false
+        case _           => false
       }
     }
 
     def size: BigInt = {
       this match {
-        case SNil() => BigInt(0)
+        case SNil()      => BigInt(0)
         case SCons(x, t) => 1 + ssize(t)
       }
     } ensuring (_ >= 0)
@@ -64,11 +65,10 @@ object RealTimeQueue {
     ((res*).isEmpty || !res.isEvaluated) && // if the return value is not a Nil closure then it would not have been evaluated
     streamLemma(res) &&
     (res.value match {
-      case SCons(_, tail) =>        
+      case SCons(_, tail) =>
         firstUnevaluated(l) == tail // after evaluating the firstUnevaluated closure in 'l' we get the next unevaluated closure
       case _ => true
-    })
-  )
+    }))
 
   def streamScheduleProperty[T](s: $[LList[T]], sch: $[LList[T]]) = {
     firstUnevaluated(s) == sch
@@ -82,9 +82,8 @@ object RealTimeQueue {
     }
   }
 
-  //@lazyproc
   def rotate[T](f: $[LList[T]], r: List[T], a: $[LList[T]]): LList[T] = {
-    require(r.size == ssize(f) + 1) // isConcrete(f) // size invariant between 'f' and 'r' holds
+    require(r.size == ssize(f) + 1 && isConcrete(f)) // size invariant between 'f' and 'r' holds
     (f.value, r) match {
       case (SNil(), Cons(y, _)) => //in this case 'y' is the only element in 'r'
         SCons[T](y, a)
@@ -93,13 +92,13 @@ object RealTimeQueue {
         val rot = $(rotate(tail, r1, $(newa))) //this creates a lazy rotate operation
         SCons[T](x, rot)
     }
-  } ensuring (res => res.size == ssize(f) + r.size + ssize(a) && res.isCons)
-  //&&  res._2 <= O(1) //time bound) 
+  } ensuring (res => res.size == ssize(f) + r.size + ssize(a) && res.isCons &&  
+                     time <= 30)
 
   // TODO: make newa into sch to avoid a different closure category
   def createQueue[T](f: $[LList[T]], r: List[T], sch: $[LList[T]]): Queue[T] = {
     require(streamScheduleProperty(f, sch) &&
-      ssize(sch) == ssize(f) - r.size + 1) //size invariant holds              
+      ssize(sch) == ssize(f) - r.size + 1) //size invariant holds
     sch.value match { // evaluate the schedule if it is not evaluated
       case SCons(_, tail) =>
         Queue(f, r, tail)
@@ -108,12 +107,12 @@ object RealTimeQueue {
         val rotres = $(rotate(f, r, $(newa)))
         Queue(rotres, Nil[T](), rotres)
     }
-  } ensuring (res => res.valid)
+  } ensuring (res => res.valid && time <= 50)
 
   def enqueue[T](x: T, q: Queue[T]): Queue[T] = {
     require(q.valid)
     createQueue(q.f, Cons[T](x, q.r), q.s)
-  } ensuring (res => res.valid)
+  } ensuring (res => res.valid && time <= 60)
 
   def dequeue[T](q: Queue[T]): Queue[T] = {
     require(!q.isEmpty && q.valid)
@@ -128,6 +127,5 @@ object RealTimeQueue {
             Queue(rotres, Nil[T](), rotres)
         }
     }
-  } ensuring (res => res.valid)
+  } ensuring (res => time <= 120) //res.valid && )
 }
-  
\ No newline at end of file
-- 
GitLab