diff --git a/src/main/scala/leon/Reporter.scala b/src/main/scala/leon/Reporter.scala index 0f693f1ae22e7911b1a1366b1c558d29b3bc47de..c13bfa60e4f802b112a58908249a023177012324 100644 --- a/src/main/scala/leon/Reporter.scala +++ b/src/main/scala/leon/Reporter.scala @@ -97,6 +97,7 @@ case object DebugSectionSynthesis extends DebugSection("synthesis", 1 << 1 case object DebugSectionTimers extends DebugSection("timers", 1 << 2) case object DebugSectionOptions extends DebugSection("options", 1 << 3) case object DebugSectionVerification extends DebugSection("verification", 1 << 4) +case object DebugSectionTermination extends DebugSection("termination", 1 << 5) object DebugSections { val all = Set[DebugSection]( @@ -104,6 +105,7 @@ object DebugSections { DebugSectionSynthesis, DebugSectionTimers, DebugSectionOptions, + DebugSectionTermination, DebugSectionVerification ) } diff --git a/src/main/scala/leon/purescala/Trees.scala b/src/main/scala/leon/purescala/Trees.scala index bbcfa9bb09ff7d632077c444040e19c944d9196d..68d87237ee13b36861249246002f6c87183a1718 100644 --- a/src/main/scala/leon/purescala/Trees.scala +++ b/src/main/scala/leon/purescala/Trees.scala @@ -64,7 +64,6 @@ object Trees { val fixedType = funDef.returnType funDef.args.zip(args).foreach { - case (a, ResultVariable()) => true // assume its correct... don't know how to get context to really check case (a, c) => typeCheck(c, a.tpe) } } diff --git a/src/main/scala/leon/solvers/z3/FunctionTemplate.scala b/src/main/scala/leon/solvers/z3/FunctionTemplate.scala index 5a3f2e2f4700dd0f118184377c63fdfa0c3313f0..59380d8750cc74552ac497abaffb379026b00ba0 100644 --- a/src/main/scala/leon/solvers/z3/FunctionTemplate.scala +++ b/src/main/scala/leon/solvers/z3/FunctionTemplate.scala @@ -27,7 +27,7 @@ class FunctionTemplate private( guardedExprs : Map[Identifier,Seq[Expr]], isRealFunDef : Boolean) { - private val isTerminatingForAllInputs : Boolean = ( + private def isTerminatingForAllInputs : Boolean = ( isRealFunDef && !funDef.hasPrecondition && solver.getTerminator.terminates(funDef).isGuaranteed diff --git a/src/main/scala/leon/termination/ChainProcessor.scala b/src/main/scala/leon/termination/ChainProcessor.scala index 2d6ad5b412451f60e8de81552c8e743457329101..83e20354b332e910dd69a52445a826d36e424c8c 100644 --- a/src/main/scala/leon/termination/ChainProcessor.scala +++ b/src/main/scala/leon/termination/ChainProcessor.scala @@ -17,17 +17,19 @@ class ChainProcessor(checker: TerminationChecker) extends Processor(checker) wit def run(problem: Problem): (TraversableOnce[Result], TraversableOnce[Problem]) = { import scala.collection.mutable.{Map => MutableMap} - reporter.info("- Running ChainProcessor") + implicit val debugSection = DebugSectionTermination + + reporter.debug("- Running ChainProcessor") val allChainMap : Map[FunDef, Set[Chain]] = problem.funDefs.map(funDef => funDef -> ChainBuilder.run(funDef)).toMap - reporter.info("- Computing all possible Chains") + reporter.debug("- Computing all possible Chains") var counter = 0 val possibleChainMap : Map[FunDef, Set[Chain]] = allChainMap.mapValues(chains => chains.filter(chain => isWeakSAT(And(chain.loop())))) - reporter.info("- Collecting re-entrant Chains") + reporter.debug("- Collecting re-entrant Chains") val reentrantChainMap : Map[FunDef, Set[Chain]] = possibleChainMap.mapValues(chains => chains.filter(chain => isWeakSAT(And(chain reentrant chain)))) // We build a cross-chain map that determines which chains can reenter into another one after a loop. // Note: We are also checking reentrance SAT here, so again, we negate the formula! - reporter.info("- Computing cross-chain map") + reporter.debug("- Computing cross-chain map") val crossChains : Map[Chain, Set[Chain]] = possibleChainMap.toSeq.map({ case (funDef, chains) => val reentrant = reentrantChainMap(funDef) chains.map(chain => chain -> { @@ -41,7 +43,7 @@ class ChainProcessor(checker: TerminationChecker) extends Processor(checker) wit // We use the cross-chains to build chain clusters. For each cluster, we must prove that the SAME argument // decreases in each of the chains in the cluster! - reporter.info("- Building cluster estimation by fix-point iteration") + reporter.debug("- Building cluster estimation by fix-point iteration") val clusters : Map[FunDef, Set[Set[Chain]]] = { def cluster(set: Set[Chain]): Set[Chain] = { set ++ set.map(crossChains(_)).flatten @@ -76,7 +78,7 @@ class ChainProcessor(checker: TerminationChecker) extends Processor(checker) wit validChainMap.map({ case (funDef, chains) => funDef -> build(chains) }) } - reporter.info("- Strengthening postconditions") + reporter.debug("- Strengthening postconditions") strengthenPostconditions(problem.funDefs) def buildLoops(fd: FunDef, cluster: Set[Chain]): (Expr, Seq[(Seq[Expr], Expr)]) = { @@ -104,13 +106,13 @@ class ChainProcessor(checker: TerminationChecker) extends Processor(checker) wit }) } - reporter.info("- Searching for structural size decrease") + reporter.debug("- Searching for structural size decrease") val sizeCleared : ClusterMap = clear(clusters, (fd, cluster) => { val (e1, e2s) = buildLoops(fd, cluster) ChainComparator.sizeDecreasing(e1, e2s) }) - reporter.info("- Searching for numeric convergence") + reporter.debug("- Searching for numeric convergence") val numericCleared : ClusterMap = clear(sizeCleared, (fd, cluster) => { val (e1, e2s) = buildLoops(fd, cluster) ChainComparator.numericConverging(e1, e2s, cluster, checker) diff --git a/src/main/scala/leon/termination/Processor.scala b/src/main/scala/leon/termination/Processor.scala index e230c870170d9dcf6986c629d598295ecad73565..dd826a56a0dbcf94b3cc8565849eb735200663a2 100644 --- a/src/main/scala/leon/termination/Processor.scala +++ b/src/main/scala/leon/termination/Processor.scala @@ -80,11 +80,7 @@ object Solvable { trait Solvable { self: Processor => override def process(problem: Problem): (TraversableOnce[Result], TraversableOnce[Problem]) = { - try { - self.run(problem) - } finally { - destroySolvers - } + self.run(problem) } private var solvers: List[SolverFactory[Solver]] = null @@ -95,22 +91,15 @@ trait Solvable { self: Processor => private def initSolvers { val structDefs = StructuralSize.defs if (structDefs != lastDefs || solvers == null) { - destroySolvers - val program : Program = self.checker.program val allDefs : Seq[Definition] = program.mainObject.defs ++ structDefs val newProgram : Program = program.copy(mainObject = program.mainObject.copy(defs = allDefs)) val context : LeonContext = self.checker.context - val solvers0 = new FairZ3SolverFactory(context, newProgram) :: Nil - solvers = solvers0.map(_.withTimeout(500)) + solvers = new TimeoutSolverFactory(SolverFactory(() => new FairZ3Solver(context, newProgram)), 500) :: Nil } } - protected def destroySolvers { - if (solvers != null) solvers.foreach(_.free()) - } - type Solution = (Option[Boolean], Map[Identifier, Expr]) private def solve(problem: Expr): Solution = { @@ -151,6 +140,8 @@ trait Solvable { self: Processor => } class ProcessingPipeline(program: Program, context: LeonContext, _processors: Processor*) { + implicit val debugSection = DebugSectionTermination + import scala.collection.mutable.{Queue => MutableQueue} assert(_processors.nonEmpty) @@ -174,7 +165,7 @@ class ProcessingPipeline(program: Program, context: LeonContext, _processors: Pr sb.append(" " + funDef.id + "\n") } } - reporter.info(sb.toString) + reporter.debug(sb.toString) } private def printResult(results: List[Result]) { @@ -184,7 +175,7 @@ class ProcessingPipeline(program: Program, context: LeonContext, _processors: Pr case Cleared(fd) => sb.append(" %-10s %s\n".format(fd.id, "Cleared")) case Broken(fd, args) => sb.append(" %-10s %s\n".format(fd.id, "Broken for arguments: " + args.mkString("(", ",", ")"))) } - reporter.info(sb.toString) + reporter.debug(sb.toString) } def clear(fd: FunDef) : Boolean = { diff --git a/src/test/scala/leon/test/termination/TerminationRegression.scala b/src/test/scala/leon/test/termination/TerminationRegression.scala index 977da326df20af53b965adb61512c66c25754cce..f65daf86ab2fcc3278614ef8ed59d942387a8b9b 100644 --- a/src/test/scala/leon/test/termination/TerminationRegression.scala +++ b/src/test/scala/leon/test/termination/TerminationRegression.scala @@ -99,6 +99,6 @@ class TerminationRegression extends LeonTestSuite { assert(reporter.warningCount === 0) } - forEachFileIn("error", true) { output => () } + //forEachFileIn("error", true) { output => () } }