From c7719514498b76a561e6f628456f28c34fc7e5cc Mon Sep 17 00:00:00 2001
From: ravi <ravi.kandhadai@epfl.ch>
Date: Thu, 4 Feb 2016 18:29:50 +0100
Subject: [PATCH] Changing some parameters and minor changes

---
 library/annotation/package.scala              |  6 +++
 .../invariant/engine/InferenceContext.scala   |  2 +-
 .../invariant/engine/RefinementEngine.scala   | 45 ++++++++++---------
 .../invariant/structure/FunctionUtils.scala   |  1 +
 .../templateSolvers/NLTemplateSolver.scala    |  4 +-
 .../laziness/LazinessEliminationPhase.scala   |  7 +--
 .../leon/laziness/LazyClosureConverter.scala  |  6 +--
 .../leon/laziness/LazyClosureFactory.scala    |  3 +-
 .../withOrb/RealTimeQueue.scala               | 15 +++----
 9 files changed, 49 insertions(+), 40 deletions(-)

diff --git a/library/annotation/package.scala b/library/annotation/package.scala
index 94c4adb7d..14a770b4d 100644
--- a/library/annotation/package.scala
+++ b/library/annotation/package.scala
@@ -17,6 +17,8 @@ package object annotation {
   class extern     extends StaticAnnotation
   @ignore
   class inline     extends StaticAnnotation
+
+  // Orb annotations
   @ignore
   class monotonic  extends StaticAnnotation
   @ignore
@@ -27,4 +29,8 @@ package object annotation {
   class invstate extends StaticAnnotation
   @ignore
   class memoize extends StaticAnnotation
+  @ignore
+  class invisibleBody extends StaticAnnotation // do not unfold the body of the function
+  @ignore
+  class unfoldFactor(f: Int=0) extends StaticAnnotation // 0 implies no bound on unfolding
 }
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/engine/InferenceContext.scala b/src/main/scala/leon/invariant/engine/InferenceContext.scala
index 966a79dc6..96603581a 100644
--- a/src/main/scala/leon/invariant/engine/InferenceContext.scala
+++ b/src/main/scala/leon/invariant/engine/InferenceContext.scala
@@ -36,7 +36,7 @@ class InferenceContext(val initProgram: Program, val leonContext: LeonContext) {
   val dumpStats = false
 
   // the following options have default values
-  val vcTimeout = leonContext.findOption(optVCTimeout).getOrElse(15L) // in secs
+  val vcTimeout = leonContext.findOption(optVCTimeout).getOrElse(30L) // in secs
   val nlTimeout = leonContext.findOption(optNLTimeout).getOrElse(15L)
   val totalTimeout = leonContext.findOption(SharedOptions.optTimeout) // in secs
   val functionsToInfer = leonContext.findOption(SharedOptions.optFunctions)
diff --git a/src/main/scala/leon/invariant/engine/RefinementEngine.scala b/src/main/scala/leon/invariant/engine/RefinementEngine.scala
index 4175ef57a..786a66b25 100644
--- a/src/main/scala/leon/invariant/engine/RefinementEngine.scala
+++ b/src/main/scala/leon/invariant/engine/RefinementEngine.scala
@@ -70,7 +70,6 @@ class RefinementEngine(ctx: InferenceContext, prog: Program, ctrTracker: Constra
 
       //unroll each call in the head pointers and in toRefineCalls
       val callsToProcess = if (toRefineCalls.isDefined) {
-
         //pick only those calls that have been least unrolled
         val relevCalls = allheads.intersect(toRefineCalls.get)
         var minCalls = Set[Call]()
@@ -86,14 +85,12 @@ class RefinementEngine(ctx: InferenceContext, prog: Program, ctrTracker: Constra
           }
         })
         minCalls
-
       } else allheads
 
       if (verbose)
         reporter.info("Unrolling: " + callsToProcess.size + "/" + allheads.size)
 
       val unrolls = callsToProcess.foldLeft(Set[Call]())((acc, call) => {
-
         val calldata = formula.callData(call)
         val recInvokes = calldata.parents.count(_ == call.fi.tfd.fd)
         //if the call is not a recursive call, unroll it unconditionally
@@ -110,7 +107,7 @@ class RefinementEngine(ctx: InferenceContext, prog: Program, ctrTracker: Constra
             acc
           }
         }
-        //TODO: are there better ways of unrolling ??
+        //TODO: are there better ways of unrolling ?? Yes. Akask Lal "dag Inlining". Implement that!
       })
 
       //update the head functions
@@ -189,25 +186,29 @@ class RefinementEngine(ctx: InferenceContext, prog: Program, ctrTracker: Constra
   }
 
   def inilineCall(call: Call, formula: Formula) = {
-    //here inline the body and conjoin it with the guard
     val tfd = call.fi.tfd
     val callee = tfd.fd
-
-    //Important: make sure we use a fresh body expression here, and freshenlocals
-    val tparamMap = (callee.tparams zip tfd.tps).toMap
-    val newbody = freshenLocals(matchToIfThenElse(callee.body.get))
-    val freshBody = instantiateType(newbody, tparamMap, Map())
-    val calleeSummary =
-      Equals(getFunctionReturnVariable(callee), freshBody)
-    val argmap1 = formalToActual(call)
-    val inlinedSummary = ExpressionTransformer.normalizeExpr(replace(argmap1, calleeSummary), ctx.multOp)
-
-    if (this.dumpInlinedSummary)
-      println("Inlined Summary: " + inlinedSummary)
-
-    //conjoin the summary with the disjunct corresponding to the 'guard'
-    //note: the parents of the summary are the parents of the call plus the callee function
-    val calldata = formula.callData(call)
-    formula.conjoinWithDisjunct(calldata.guard, inlinedSummary, (callee +: calldata.parents))
+    if (callee.isBodyVisible) {
+      //here inline the body and conjoin it with the guard
+      //Important: make sure we use a fresh body expression here, and freshenlocals
+      val tparamMap = (callee.tparams zip tfd.tps).toMap
+      val newbody = freshenLocals(matchToIfThenElse(callee.body.get))
+      val freshBody = instantiateType(newbody, tparamMap, Map())
+      val calleeSummary =
+        Equals(getFunctionReturnVariable(callee), freshBody)
+      val argmap1 = formalToActual(call)
+      val inlinedSummary = ExpressionTransformer.normalizeExpr(replace(argmap1, calleeSummary), ctx.multOp)
+
+      if (this.dumpInlinedSummary)
+        println("Inlined Summary: " + inlinedSummary)
+
+      //conjoin the summary with the disjunct corresponding to the 'guard'
+      //note: the parents of the summary are the parents of the call plus the callee function
+      val calldata = formula.callData(call)
+      formula.conjoinWithDisjunct(calldata.guard, inlinedSummary, (callee +: calldata.parents))
+    } else {
+      if (verbose)
+        reporter.info(s"Not inlining ${call.fi}: body invisible!")
+    }
   }
 }
diff --git a/src/main/scala/leon/invariant/structure/FunctionUtils.scala b/src/main/scala/leon/invariant/structure/FunctionUtils.scala
index dc77b9447..fa9597e70 100644
--- a/src/main/scala/leon/invariant/structure/FunctionUtils.scala
+++ b/src/main/scala/leon/invariant/structure/FunctionUtils.scala
@@ -27,6 +27,7 @@ object FunctionUtils {
     lazy val compose = fd.annotations.contains("compose")
     lazy val isLibrary = fd.annotations.contains("library")
     lazy val isExtern = fd.annotations.contains("extern")
+    lazy val isBodyVisible =  !fd.annotations.contains("invisibleBody")
     lazy val hasFieldFlag = fd.flags.contains(IsField(false))
     lazy val hasLazyFieldFlag = fd.flags.contains(IsField(true))
     lazy val isUserFunction = !hasFieldFlag && !hasLazyFieldFlag
diff --git a/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolver.scala b/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolver.scala
index f4e63e0c0..1194695b9 100644
--- a/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolver.scala
+++ b/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolver.scala
@@ -45,7 +45,7 @@ class NLTemplateSolver(ctx: InferenceContext, program: Program,
   val trackUnpackedVCCTime = false
 
   //print flags
-  val verbose = true
+  val verbose = false
   val printCounterExample = false
   val printPathToConsole = false
   val dumpPathAsSMTLIB = false
@@ -59,7 +59,7 @@ class NLTemplateSolver(ctx: InferenceContext, program: Program,
   private val farkasSolver = new FarkasLemmaSolver(ctx, program)
   private val startFromEarlierModel = true
   private val disableCegis = true
-  private val useIncrementalSolvingForVCs = true
+  private val useIncrementalSolvingForVCs = false
   private val useCVCToCheckVCs = true
   private val usePortfolio = false // portfolio has a bug in incremental solving
 
diff --git a/src/main/scala/leon/laziness/LazinessEliminationPhase.scala b/src/main/scala/leon/laziness/LazinessEliminationPhase.scala
index c40e38a9c..ef1a5415e 100644
--- a/src/main/scala/leon/laziness/LazinessEliminationPhase.scala
+++ b/src/main/scala/leon/laziness/LazinessEliminationPhase.scala
@@ -37,6 +37,7 @@ import leon.verification._
 import PredicateUtil._
 import leon.invariant.engine._
 import LazyVerificationPhase._
+import utils._
 /**
  * TODO: Function names are assumed to be small case. Fix this!!
  */
@@ -93,14 +94,14 @@ object LazinessEliminationPhase extends TransformationPhase {
     if (dumpTypeCorrectProg)
       println("After rectifying types: \n" + ScalaPrinter.apply(typeCorrectProg))
 
-    val progWithPre = (new ClosurePreAsserter(typeCorrectProg)).apply
+    val progWithPre =  (new ClosurePreAsserter(typeCorrectProg)).apply
     if (dumpProgWithPreAsserts) {
       //println("After asserting closure preconditions: \n" + ScalaPrinter.apply(progWithPre))
       prettyPrintProgramToFile(progWithPre, ctx, "-withpre", uniqueIds = true)
     }
 
     // verify the contracts that do not use resources
-    val progWOInstSpecs = removeInstrumentationSpecs(progWithPre)
+    val progWOInstSpecs = InliningPhase.apply(ctx, removeInstrumentationSpecs(progWithPre))
     if (dumpProgWOInstSpecs) {
       //println("After removing instrumentation specs: \n" + ScalaPrinter.apply(progWOInstSpecs))
       prettyPrintProgramToFile(progWOInstSpecs, ctx, "-woinst")
@@ -110,7 +111,7 @@ object LazinessEliminationPhase extends TransformationPhase {
       checkSpecifications(progWOInstSpecs, checkCtx)
 
     // instrument the program for resources (note: we avoid checking preconditions again here)
-    val instrumenter = new LazyInstrumenter(typeCorrectProg, closureFactory)
+    val instrumenter = new LazyInstrumenter(InliningPhase.apply(ctx, typeCorrectProg), closureFactory)
     val instProg = instrumenter.apply
     if (dumpInstrumentedProgram) {
       //println("After instrumentation: \n" + ScalaPrinter.apply(instProg))
diff --git a/src/main/scala/leon/laziness/LazyClosureConverter.scala b/src/main/scala/leon/laziness/LazyClosureConverter.scala
index 365babd1b..404f968f6 100644
--- a/src/main/scala/leon/laziness/LazyClosureConverter.scala
+++ b/src/main/scala/leon/laziness/LazyClosureConverter.scala
@@ -251,8 +251,6 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
 
   /**
    * These are evalFunctions that do not affect the state.
-   * TODO: here we can avoid creating two calls to the function one
-   * with uninterpreted state and other with input state (since here both are equal)
    */
   val computeFunctions = evalFunctions.map {
     case (tname, evalfd) =>
@@ -267,6 +265,7 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
       val invoke = FunctionInvocation(TypedFunDef(evalfd, evalfd.tparams.map(_.tp)),
         Seq(param1.id.toVariable, uiState))
       fun.body = Some(TupleSelect(invoke, 1))
+      fun.addFlag(IsInlined)
       (tname -> fun)
   }.toMap
 
@@ -286,7 +285,8 @@ class LazyClosureConverter(p: Program, ctx: LeonContext,
     val fun = new FunDef(FreshIdentifier(closureConsName(tname)), tparamdefs,
       Seq(ValDef(param1), ValDef(param2)), param1Type)
     fun.body = Some(param1.toVariable)
-    // assert that the closure in unevaluated if useRefEquality is enabled
+    fun.addFlag(IsInlined)
+    // assert that the closure in unevaluated if useRefEquality is enabled! is this needed ?
     // not supported as of now
     /*if (refEq) {
       val resid = FreshIdentifier("res", param1Type)
diff --git a/src/main/scala/leon/laziness/LazyClosureFactory.scala b/src/main/scala/leon/laziness/LazyClosureFactory.scala
index 49151ed15..921119154 100644
--- a/src/main/scala/leon/laziness/LazyClosureFactory.scala
+++ b/src/main/scala/leon/laziness/LazyClosureFactory.scala
@@ -207,7 +207,6 @@ class LazyClosureFactory(p: Program) {
       val SetType(baseT) = stType.classDef.fields.find { fld => fld.id.name == fldname }.get.getType
       val param2 = FreshIdentifier("cl", baseT)
 
-      // TODO: as an optimization we can mark all these functions as inline and inline them at their callees
       val updateFun = new FunDef(FreshIdentifier("updState" + tn),
         state.tparams, Seq(ValDef(param1), ValDef(param2)), stType)
       // create a body for the updateFun:
@@ -221,6 +220,8 @@ class LazyClosureFactory(p: Program) {
       }
       val nst = CaseClass(stType, nargs)
       updateFun.body = Some(nst)
+      // add inline annotation of optimization
+      updateFun.addFlag(IsInlined)
       (tn -> updateFun)
     }.toMap
 }
diff --git a/testcases/lazy-datastructures/withOrb/RealTimeQueue.scala b/testcases/lazy-datastructures/withOrb/RealTimeQueue.scala
index 7a3b07008..f0a78b4f2 100644
--- a/testcases/lazy-datastructures/withOrb/RealTimeQueue.scala
+++ b/testcases/lazy-datastructures/withOrb/RealTimeQueue.scala
@@ -28,15 +28,13 @@ object RealTimeQueue {
     def size: BigInt = {
       this match {
         case SNil()      => BigInt(0)
-        case SCons(x, t) => 1 + ssize(t)
+        case SCons(x, t) => 1 + (t*).size
       }
     } ensuring (_ >= 0)
   }
   case class SCons[T](x: T, tail: $[Stream[T]]) extends Stream[T]
   case class SNil[T]() extends Stream[T]
 
-  def ssize[T](l: $[Stream[T]]): BigInt = (l*).size
-
   def isConcrete[T](l: $[Stream[T]]): Boolean = {
     l.isEvaluated && (l* match {
       case SCons(_, tail) =>
@@ -45,9 +43,10 @@ object RealTimeQueue {
     })
   }
 
-   @invstate
+  @invisibleBody
+  @invstate
   def rotate[T](f: $[Stream[T]], r: List[T], a: $[Stream[T]]): Stream[T] = { // doesn't change state
-    require(r.size == ssize(f) + 1 && isConcrete(f))
+    require(r.size == (f*).size + 1 && isConcrete(f))
     (f.value, r) match {
       case (SNil(), Cons(y, _)) => //in this case 'y' is the only element in 'r'
         SCons[T](y, a)
@@ -82,7 +81,7 @@ object RealTimeQueue {
     def isEmpty = (f*).isEmpty
     def valid = {
       (firstUnevaluated(f) == firstUnevaluated(s)) &&
-        ssize(s) == ssize(f) - r.size //invariant: |s| = |f| - |r|
+        (s*).size == (f*).size - r.size //invariant: |s| = |f| - |r|
     }
   }
 
@@ -102,11 +101,11 @@ object RealTimeQueue {
     createQ(q.f, Cons(x, q.r), q.s)
   } ensuring (res => res.valid && time <= ?)
 
-  /*def dequeue[T](q: Queue[T]): Queue[T] = {
+  def dequeue[T](q: Queue[T]): Queue[T] = {
     require(!q.isEmpty && q.valid)
     q.f.value match {
       case SCons(x, nf) =>
         createQ(nf, q.r, q.s)
     }
-  } ensuring (res => res.valid && time <= ?)*/
+  } ensuring (res => res.valid && time <= ?)
 }
-- 
GitLab