diff --git a/src/main/scala/leon/Reporter.scala b/src/main/scala/leon/Reporter.scala index 03512770fc9c84d9d11a41b2124fafdc6683e506..814c4352a321f41a0f75bac34ad20643d69b6c7b 100644 --- a/src/main/scala/leon/Reporter.scala +++ b/src/main/scala/leon/Reporter.scala @@ -27,10 +27,7 @@ class DefaultReporter extends Reporter { protected val infoPfx = "[ Info ] " protected val fatalPfx = "[ Fatal ] " - def output(msg: String) : Unit = { - if(!Settings.simpleOutput) - println(msg) - } + def output(msg: String) : Unit = println(msg) protected def reline(pfx: String, msg: String) : String = { val color = if(pfx == errorPfx || pfx == warningPfx || pfx == fatalPfx) { diff --git a/src/main/scala/leon/Settings.scala b/src/main/scala/leon/Settings.scala index f4ff31f49292dcd90d911c28b88aee516d048561..04ed6bc41df6aa410879b2492aeb9f5580ab93a9 100644 --- a/src/main/scala/leon/Settings.scala +++ b/src/main/scala/leon/Settings.scala @@ -26,7 +26,6 @@ object Settings { var bitvectorBitwidth : Option[Int] = None var debugLevel: Int = 0 var debugTags: Set[String] = Set.empty - var simpleOutput: Boolean = false var synthesis: Boolean = false var transformProgram: Boolean = true var stopAfterExtraction: Boolean = false diff --git a/src/main/scala/leon/plugin/AnalysisComponent.scala b/src/main/scala/leon/plugin/AnalysisComponent.scala index 77c058a6fa5335cbc5092b545c453d9ef0396cf0..1cc1cde07699255945ffab7a42dba0c52e586a98 100644 --- a/src/main/scala/leon/plugin/AnalysisComponent.scala +++ b/src/main/scala/leon/plugin/AnalysisComponent.scala @@ -24,10 +24,7 @@ class AnalysisComponent(val global: Global, val pluginInstance: LeonPlugin) protected def stopIfErrors: Unit = { if(reporter.hasErrors) { - if(Settings.simpleOutput) - println("error") sys.exit(1) - //throw new Exception("There were errors.") } } diff --git a/src/main/scala/leon/plugin/LeonPlugin.scala b/src/main/scala/leon/plugin/LeonPlugin.scala index 13542da332745a4db94d34e09bb107a5f4d75e3b..afc5fa35d441c099da969c2e5789ea48ea229643 100644 --- a/src/main/scala/leon/plugin/LeonPlugin.scala +++ b/src/main/scala/leon/plugin/LeonPlugin.scala @@ -63,7 +63,6 @@ class LeonPlugin(val global: PluginRunner) extends Plugin { case "cores" => leon.Settings.useCores = true case "quickcheck" => leon.Settings.useQuickCheck = true case "parallel" => leon.Settings.useParallel = true - case "oneline" => leon.Settings.simpleOutput = true case "noLuckyTests" => leon.Settings.luckyTest = false case "noverifymodel" => leon.Settings.verifyModel = false case "imperative" => leon.Settings.synthesis = false; diff --git a/src/main/scala/leon/verification/Analysis.scala b/src/main/scala/leon/verification/Analysis.scala index b6786f30c973734d9b3e2b648c00957e63bd3aaf..1521ad8e1e3fa4ad42d36664d76d27a5fed4966c 100644 --- a/src/main/scala/leon/verification/Analysis.scala +++ b/src/main/scala/leon/verification/Analysis.scala @@ -40,13 +40,12 @@ class Analysis(val program : Program, val reporter: Reporter) { FunctionTemplate.mkTemplate(funDef) } - if(solverExtensions.size > 1) { + val report = if(solverExtensions.size > 1) { reporter.info("Running verification condition generation...") - - val list = generateVerificationConditions - checkVerificationConditions(list : _*) + checkVerificationConditions(generateVerificationConditions) } else { reporter.warning("No solver specified. Cannot test verification conditions.") + VerificationReport.emptyReport } analysisExtensions.foreach(ae => { @@ -54,7 +53,7 @@ class Analysis(val program : Program, val reporter: Reporter) { ae.analyse(program) }) - new VerificationReport + report } private def generateVerificationConditions : List[VerificationCondition] = { @@ -91,8 +90,7 @@ class Analysis(val program : Program, val reporter: Reporter) { allVCs.toList } - def checkVerificationCondition(vc: VerificationCondition) : Unit = checkVerificationConditions(vc) - def checkVerificationConditions(vcs: VerificationCondition*) : Unit = { + private def checkVerificationConditions(vcs: Seq[VerificationCondition]) : VerificationReport = { for(vcInfo <- vcs) { val funDef = vcInfo.funDef val vc = vcInfo.condition @@ -152,73 +150,8 @@ class Analysis(val program : Program, val reporter: Reporter) { } - if(vcs.size > 0) { - val summaryString = ( - VerificationCondition.infoHeader + - vcs.map(_.infoLine).mkString("\n", "\n", "\n") + - VerificationCondition.infoFooter - ) - reporter.info(summaryString) - - if(Settings.simpleOutput) { - val outStr = - if(vcs.forall(_.status == "valid")) "valid" - else if(vcs.exists(_.status == "invalid")) "invalid" - else "unknown" - println(outStr) - } - - // Printing summary for the evaluation section of paper: - val writeSummary = false - if (writeSummary) { - def writeToFile(filename: String, content: String) : Unit = { - try { - val fw = new java.io.FileWriter(filename) - fw.write(content) - fw.close - } catch { - case e => reporter.error("There was an error while generating the test file" + filename) - } - } - - var toWrite: String = "" - val functionVCs = vcs groupBy (_.funDef) - val vcsByPostcond = functionVCs groupBy - (_._2 exists ((vc: VerificationCondition) => vc.kind == VCKind.Postcondition)) - def functionInfoLine(id: String, funVCs: Traversable[VerificationCondition]) = { - val vcsByKind = funVCs groupBy (_.kind) - val nbPrecond = vcsByKind.get(VCKind.Precondition).getOrElse(Nil).size - val nbMatch = vcsByKind.get(VCKind.ExhaustiveMatch).getOrElse(Nil).size - val totalTime = - (funVCs.foldLeft(0.0)((a, b) => a + b.time.getOrElse(0.0))) - val validStr = "ok" - val invalidStr = "err" - val status = if (funVCs.forall(_.status == "valid")) validStr else invalidStr - val timeStr = if (totalTime < 0.01) "< 0.01" else ("%-3.2f" format totalTime) - - val toRet = - "%-25s %-3s %-3s %-9s %6s" format (id, nbPrecond, nbMatch, status, timeStr) - toRet - } - for ((withPostcond, functionsByPostcond) <- vcsByPostcond) { - if (withPostcond) - toWrite += "with postcondition:\n" - else - toWrite += "without postcondition:\n" - for ((funDef, funVCs) <- functionsByPostcond.toList.sortWith((p1, p2) => p1._1 < p2._1)) { - toWrite += functionInfoLine(funDef.id.toString, funVCs) + "\n" - } - } - - val fileName = program.mainObject.id.toString + "-evaluation.txt" - val folderName = "summary" - - new java.io.File(folderName).mkdir() - - writeToFile(folderName + "/" + fileName, toWrite) - } - } else { - reporter.info("No verification conditions were analyzed.") - } + val report = new VerificationReport(vcs) + reporter.info(report.summaryString) + report } } diff --git a/src/main/scala/leon/verification/VerificationCondition.scala b/src/main/scala/leon/verification/VerificationCondition.scala index ac972d50cbf1d3754900db64c38741b572be2324..217eb94b70287d8f74de5a98a1370c0068c831ac 100644 --- a/src/main/scala/leon/verification/VerificationCondition.scala +++ b/src/main/scala/leon/verification/VerificationCondition.scala @@ -21,28 +21,16 @@ class VerificationCondition(val condition: Expr, val funDef: FunDef, val kind: V case Some(false) => "invalid" } - private def tacticStr = tactic.shortDescription match { + def tacticStr = tactic.shortDescription match { case "default" => "" case s => s } - private def solverStr = solvedWith match { + def solverStr = solvedWith match { case Some(s) => s.shortDescription case None => "" } - private def timeStr = time.map(t => "%-3.3f".format(t)).getOrElse("") - - def infoLine : String = { - "║ %-25s %-9s %9s %-8s %-10s %-7s %7s ║" format (funDef.id.toString, kind, posInfo, status, tacticStr, solverStr, timeStr) - } -} - -object VerificationCondition { - val infoFooter : String = "╚" + ("═" * 83) + "╝" - val infoHeader : String = ". ┌─────────┐\n" + - "╔═╡ Summary ╞" + ("═" * 71) + "╗\n" + - "║ └─────────┘" + (" " * 71) + "║" } object VCKind extends Enumeration { diff --git a/src/main/scala/leon/verification/VerificationReport.scala b/src/main/scala/leon/verification/VerificationReport.scala index 2b82dfcee0d00581075985630da40bff71c1ee0b..16b6516241c806005605ec8ce0a56cc178eb3035 100644 --- a/src/main/scala/leon/verification/VerificationReport.scala +++ b/src/main/scala/leon/verification/VerificationReport.scala @@ -1,3 +1,48 @@ package leon.verification -class VerificationReport +class VerificationReport(val conditions : Seq[VerificationCondition]) { + lazy val totalConditions : Int = conditions.size + + lazy val totalTime : Double = conditions.foldLeft(0.0d)((t,c) => t + c.time.getOrElse(0.0d)) + + lazy val totalValid : Int = conditions.count(_.value == Some(true)) + + lazy val totalInvalid : Int = conditions.count(_.value == Some(false)) + + lazy val totalUnknown : Int = conditions.count(_.value == None) + + def summaryString : String = if(totalConditions >= 0) { + VerificationReport.infoHeader + + conditions.map(VerificationReport.infoLine).mkString("\n", "\n", "\n") + + VerificationReport.infoSep + + ("║ total: %-4d valid: %-4d invalid: %-4d unknown %-4d " + + (" " * 18) + + " %-3.3f ║\n").format(totalConditions, totalValid, totalInvalid, totalUnknown, totalTime) + + VerificationReport.infoFooter + } else { + "No verification conditions were analyzed." + } +} + +object VerificationReport { + def emptyReport : VerificationReport = new VerificationReport(Nil) + + private val infoSep : String = "╟" + ("┄" * 83) + "╢\n" + private val infoFooter : String = "╚" + ("═" * 83) + "╝" + private val infoHeader : String = ". ┌─────────┐\n" + + "╔═╡ Summary ╞" + ("═" * 71) + "╗\n" + + "║ └─────────┘" + (" " * 71) + "║" + + private def infoLine(vc : VerificationCondition) : String = { + val timeStr = vc.time.map(t => "%-3.3f".format(t)).getOrElse("") + + "║ %-25s %-9s %9s %-8s %-10s %-7s %7s ║".format( + vc.funDef.id.toString, + vc.kind, + vc.posInfo, + vc.status, + vc.tacticStr, + vc.solverStr, + timeStr) + } +} diff --git a/src/test/scala/leon/test/ValidPrograms.scala b/src/test/scala/leon/test/ValidPrograms.scala index 426e78fb27f2422d9f86952d9995374b1917202f..37df60f224e91b9a23f030b4653ad725db9fad72 100644 --- a/src/test/scala/leon/test/ValidPrograms.scala +++ b/src/test/scala/leon/test/ValidPrograms.scala @@ -43,5 +43,6 @@ class ValidPrograms extends FunSuite { } } - mkTest("/home/psuter/Test.scala") + // Sorry for leaving this there... + // mkTest("/home/psuter/Test.scala") }