From 1be039deb78eef7ea9265a7d84625f454cc21cc4 Mon Sep 17 00:00:00 2001 From: Etienne Kneuss <colder@php.net> Date: Mon, 10 Feb 2014 13:04:04 +0100 Subject: [PATCH] Improve debugging for trees. asString now preferred over toString. --- src/main/scala/leon/LeonOption.scala | 2 +- src/main/scala/leon/Reporter.scala | 23 ++------------- src/main/scala/leon/Settings.scala | 2 ++ .../codegen/runtime/ChooseEntryPoint.scala | 2 +- .../leon/evaluators/RecursiveEvaluator.scala | 4 +-- src/main/scala/leon/purescala/Common.scala | 6 ++++ .../scala/leon/purescala/Definitions.scala | 10 ------- .../scala/leon/purescala/PrettyPrinter.scala | 5 ++++ .../scala/leon/purescala/PrinterOptions.scala | 19 +++++++++++- src/main/scala/leon/purescala/Trees.scala | 4 +-- src/main/scala/leon/purescala/TypeTrees.scala | 4 +-- src/main/scala/leon/solvers/Solver.scala | 2 ++ .../leon/solvers/combinators/DNFSolver.scala | 6 ++-- .../solvers/combinators/UnrollingSolver.scala | 2 +- src/main/scala/leon/synthesis/Rules.scala | 2 +- .../scala/leon/synthesis/rules/Cegis.scala | 2 +- .../leon/termination/ChainProcessor.scala | 2 +- .../scala/leon/termination/Processor.scala | 2 ++ src/main/scala/leon/utils/DebugSections.scala | 29 +++++++++++++++++++ .../leon/verification/AnalysisPhase.scala | 4 +-- 20 files changed, 81 insertions(+), 51 deletions(-) create mode 100644 src/main/scala/leon/utils/DebugSections.scala diff --git a/src/main/scala/leon/LeonOption.scala b/src/main/scala/leon/LeonOption.scala index d1379cf38..a40f2d4c7 100644 --- a/src/main/scala/leon/LeonOption.scala +++ b/src/main/scala/leon/LeonOption.scala @@ -56,7 +56,7 @@ object ListValue { if (value == "off") { None } else { - Some(value.split(':').map(_.trim).filter(!_.isEmpty)) + Some(value.split("[:,]").map(_.trim).filter(!_.isEmpty)) } } } diff --git a/src/main/scala/leon/Reporter.scala b/src/main/scala/leon/Reporter.scala index 1cd2585a0..dc8669399 100644 --- a/src/main/scala/leon/Reporter.scala +++ b/src/main/scala/leon/Reporter.scala @@ -2,6 +2,8 @@ package leon +import utils._ + import purescala.Definitions.Definition import purescala.Trees.Expr import purescala.PrettyPrinter @@ -88,24 +90,3 @@ class DefaultReporter(settings: Settings) extends Reporter(settings) { throw LeonFatalError(msg.toString) } } - -@implicitNotFound("No implicit debug section found in scope. You need define an implicit DebugSection to use debug/ifDebug") -sealed abstract class DebugSection(val name: String, val mask: Int) - -case object DebugSectionSolver extends DebugSection("solver", 1 << 0) -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]( - DebugSectionSolver, - DebugSectionSynthesis, - DebugSectionTimers, - DebugSectionOptions, - DebugSectionTermination, - DebugSectionVerification - ) -} diff --git a/src/main/scala/leon/Settings.scala b/src/main/scala/leon/Settings.scala index d280e6344..63f116d7c 100644 --- a/src/main/scala/leon/Settings.scala +++ b/src/main/scala/leon/Settings.scala @@ -2,6 +2,8 @@ package leon +import utils.DebugSection + case class Settings( val strictCompilation: Boolean = true, // Terminates Leon in case an error occured during extraction val debugSections: Set[DebugSection] = Set(), // Enables debug message for the following sections diff --git a/src/main/scala/leon/codegen/runtime/ChooseEntryPoint.scala b/src/main/scala/leon/codegen/runtime/ChooseEntryPoint.scala index 0316953f1..cf6a7ac28 100644 --- a/src/main/scala/leon/codegen/runtime/ChooseEntryPoint.scala +++ b/src/main/scala/leon/codegen/runtime/ChooseEntryPoint.scala @@ -68,7 +68,7 @@ object ChooseEntryPoint { val total = System.currentTimeMillis-tStart; ctx.reporter.debug("Synthesis took "+total+"ms") - ctx.reporter.debug("Finished synthesis with "+leonRes) + ctx.reporter.debug("Finished synthesis with "+leonRes.asString(ctx)) unit.exprToJVM(leonRes) case Some(false) => diff --git a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala index 246e7f654..d644dc234 100644 --- a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala +++ b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala @@ -367,7 +367,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program) extends Evalu import solvers.z3.FairZ3Solver import purescala.TreeOps.simplestValue - implicit val debugSection = DebugSectionSynthesis + implicit val debugSection = utils.DebugSectionSynthesis val p = synthesis.Problem.fromChoose(choose) @@ -401,7 +401,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program) extends Evalu val total = System.currentTimeMillis-tStart; ctx.reporter.debug("Synthesis took "+total+"ms") - ctx.reporter.debug("Finished synthesis with "+leonRes) + ctx.reporter.debug("Finished synthesis with "+leonRes.asString(ctx)) leonRes case Some(false) => diff --git a/src/main/scala/leon/purescala/Common.scala b/src/main/scala/leon/purescala/Common.scala index 89fc30674..ca6b4fc0f 100644 --- a/src/main/scala/leon/purescala/Common.scala +++ b/src/main/scala/leon/purescala/Common.scala @@ -19,6 +19,12 @@ object Common { } this } + + override def toString: String = PrettyPrinter(this) + + def asString(implicit ctx: LeonContext): String = { + ScalaPrinter(this, ctx) + } } // the type is left blank (Untyped) for Identifiers that are not variables diff --git a/src/main/scala/leon/purescala/Definitions.scala b/src/main/scala/leon/purescala/Definitions.scala index 832c514ab..c5bcead22 100644 --- a/src/main/scala/leon/purescala/Definitions.scala +++ b/src/main/scala/leon/purescala/Definitions.scala @@ -13,7 +13,6 @@ object Definitions { sealed abstract class Definition extends Tree { val id: Identifier - override def toString: String = PrettyPrinter(this) override def hashCode : Int = id.hashCode override def equals(that : Any) : Boolean = that match { case t : Definition => t.id == this.id @@ -56,15 +55,6 @@ object Definitions { def isRecursive(f1: FunDef) = mainModule.isRecursive(f1) def caseClassDef(name: String) = mainModule.caseClassDef(name) - def writeScalaFile(filename: String) { - import java.io.FileWriter - import java.io.BufferedWriter - val fstream = new FileWriter(filename) - val out = new BufferedWriter(fstream) - out.write(ScalaPrinter(this)) - out.close - } - def duplicate = { copy(mainModule = mainModule.copy(defs = mainModule.defs.collect { case fd: FunDef => fd.duplicate diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala index 98345cba1..562ea2500 100644 --- a/src/main/scala/leon/purescala/PrettyPrinter.scala +++ b/src/main/scala/leon/purescala/PrettyPrinter.scala @@ -531,6 +531,11 @@ abstract class PrettyPrinterFactory { printer.pp(tree, None)(opts.baseIndent) printer.toString } + + def apply(tree: Tree, ctx: LeonContext): String = { + val opts = PrinterOptions.fromContext(ctx) + apply(tree, opts) + } } object PrettyPrinter extends PrettyPrinterFactory { diff --git a/src/main/scala/leon/purescala/PrinterOptions.scala b/src/main/scala/leon/purescala/PrinterOptions.scala index 597c15c68..65c4017e0 100644 --- a/src/main/scala/leon/purescala/PrinterOptions.scala +++ b/src/main/scala/leon/purescala/PrinterOptions.scala @@ -1,4 +1,7 @@ -package leon.purescala +package leon +package purescala + +import utils._ case class PrinterOptions ( baseIndent: Int = 0, @@ -6,3 +9,17 @@ case class PrinterOptions ( printTypes: Boolean = false, printUniqueIds: Boolean = false ) + +object PrinterOptions { + def fromContext(ctx: LeonContext): PrinterOptions = { + val debugTrees = ctx.settings.debugSections contains DebugSectionTrees + val debugPositions = ctx.settings.debugSections contains DebugSectionPositions + + PrinterOptions( + baseIndent = 0, + printPositions = debugPositions, + printTypes = debugTrees, + printUniqueIds = debugTrees + ) + } +} diff --git a/src/main/scala/leon/purescala/Trees.scala b/src/main/scala/leon/purescala/Trees.scala index 2052034fa..938ff8407 100644 --- a/src/main/scala/leon/purescala/Trees.scala +++ b/src/main/scala/leon/purescala/Trees.scala @@ -15,9 +15,7 @@ object Trees { /* EXPRESSIONS */ - abstract class Expr extends Tree with Typed with Serializable { - override def toString: String = PrettyPrinter(this) - } + abstract class Expr extends Tree with Typed with Serializable trait Terminal { self: Expr => diff --git a/src/main/scala/leon/purescala/TypeTrees.scala b/src/main/scala/leon/purescala/TypeTrees.scala index 61918e5a2..cd83cd8eb 100644 --- a/src/main/scala/leon/purescala/TypeTrees.scala +++ b/src/main/scala/leon/purescala/TypeTrees.scala @@ -49,9 +49,7 @@ object TypeTrees { } - sealed abstract class TypeTree extends Tree { - override def toString: String = PrettyPrinter(this) - } + sealed abstract class TypeTree extends Tree // returns the number of distinct values that inhabit a type sealed abstract class TypeSize extends Serializable diff --git a/src/main/scala/leon/solvers/Solver.scala b/src/main/scala/leon/solvers/Solver.scala index b4edadedb..be9b144c5 100644 --- a/src/main/scala/leon/solvers/Solver.scala +++ b/src/main/scala/leon/solvers/Solver.scala @@ -12,6 +12,8 @@ trait Solver { def name: String val context: LeonContext + implicit lazy val leonContext = context + def assertCnstr(expression: Expr): Unit def check: Option[Boolean] diff --git a/src/main/scala/leon/solvers/combinators/DNFSolver.scala b/src/main/scala/leon/solvers/combinators/DNFSolver.scala index 507106bd1..9a36612b1 100644 --- a/src/main/scala/leon/solvers/combinators/DNFSolver.scala +++ b/src/main/scala/leon/solvers/combinators/DNFSolver.scala @@ -33,15 +33,15 @@ class DNFSolver(val context: LeonContext, var result : Option[Boolean] = None - debugS("Before NNF:\n" + expr) + debugS("Before NNF:\n" + expr.asString) val nnfed = nnf(expr, false) - debugS("After NNF:\n" + nnfed) + debugS("After NNF:\n" + nnfed.asString) val dnfed = dnf(nnfed) - debugS("After DNF:\n" + dnfed) + debugS("After DNF:\n" + dnfed.asString) val candidates : Seq[Expr] = dnfed match { case Or(es) => es diff --git a/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala b/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala index 301260440..17dbabe8f 100644 --- a/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala +++ b/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala @@ -38,7 +38,7 @@ class UnrollingSolver(val context: LeonContext, underlyings: SolverFactory[Incre def check : Option[Boolean] = theConstraint.map { expr => val solver = underlyings.getNewSolver//SimpleSolverAPI(underlyings) - debugS("Check called on " + expr + "...") + debugS("Check called on " + expr.asString + "...") val template = getTemplate(expr) diff --git a/src/main/scala/leon/synthesis/Rules.scala b/src/main/scala/leon/synthesis/Rules.scala index 619d8926b..bede19443 100644 --- a/src/main/scala/leon/synthesis/Rules.scala +++ b/src/main/scala/leon/synthesis/Rules.scala @@ -85,7 +85,7 @@ abstract class Rule(val name: String) { def subst(what: Tuple2[Identifier, Expr], in: Expr): Expr = replace(Map(Variable(what._1) -> what._2), in) def substAll(what: Map[Identifier, Expr], in: Expr): Expr = replace(what.map(w => Variable(w._1) -> w._2), in) - implicit val debugSection = DebugSectionSynthesis + implicit val debugSection = leon.utils.DebugSectionSynthesis val forward: List[Solution] => Option[Solution] = { case List(s) => diff --git a/src/main/scala/leon/synthesis/rules/Cegis.scala b/src/main/scala/leon/synthesis/rules/Cegis.scala index b588357fc..3bb6d950f 100644 --- a/src/main/scala/leon/synthesis/rules/Cegis.scala +++ b/src/main/scala/leon/synthesis/rules/Cegis.scala @@ -559,7 +559,7 @@ case object CEGIS extends Rule("CEGIS") { sctx.reporter.ifDebug { debug => debug("UNROLLING: ") for (c <- clauses) { - debug(" - " + c) + debug(" - " + c.asString(sctx.context)) } debug("CLOSED Bs "+closedBs) } diff --git a/src/main/scala/leon/termination/ChainProcessor.scala b/src/main/scala/leon/termination/ChainProcessor.scala index 6ac33d59b..8b4b69dde 100644 --- a/src/main/scala/leon/termination/ChainProcessor.scala +++ b/src/main/scala/leon/termination/ChainProcessor.scala @@ -18,7 +18,7 @@ class ChainProcessor(checker: TerminationChecker, val chainComparator = new ChainComparator(structuralSize) def run(problem: Problem): (TraversableOnce[Result], TraversableOnce[Problem]) = { - implicit val debugSection = DebugSectionTermination + implicit val debugSection = utils.DebugSectionTermination reporter.debug("- Running ChainProcessor") val allChainMap : Map[FunDef, Set[Chain]] = problem.funDefs.map(funDef => funDef -> chainBuilder.run(funDef)).toMap diff --git a/src/main/scala/leon/termination/Processor.scala b/src/main/scala/leon/termination/Processor.scala index 8b3a8e36e..c26879a16 100644 --- a/src/main/scala/leon/termination/Processor.scala +++ b/src/main/scala/leon/termination/Processor.scala @@ -1,6 +1,8 @@ package leon package termination +import utils._ + import purescala.Trees._ import purescala.TreeOps._ import purescala.Common._ diff --git a/src/main/scala/leon/utils/DebugSections.scala b/src/main/scala/leon/utils/DebugSections.scala new file mode 100644 index 000000000..b399a19d9 --- /dev/null +++ b/src/main/scala/leon/utils/DebugSections.scala @@ -0,0 +1,29 @@ +package leon +package utils + +import scala.annotation.implicitNotFound + +@implicitNotFound("No implicit debug section found in scope. You need define an implicit DebugSection to use debug/ifDebug") +sealed abstract class DebugSection(val name: String, val mask: Int) + +case object DebugSectionSolver extends DebugSection("solver", 1 << 0) +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) +case object DebugSectionTrees extends DebugSection("trees", 1 << 6) +case object DebugSectionPositions extends DebugSection("positions", 1 << 7) + +object DebugSections { + val all = Set[DebugSection]( + DebugSectionSolver, + DebugSectionSynthesis, + DebugSectionTimers, + DebugSectionOptions, + DebugSectionVerification, + DebugSectionTermination, + DebugSectionTrees, + DebugSectionPositions + ) +} diff --git a/src/main/scala/leon/verification/AnalysisPhase.scala b/src/main/scala/leon/verification/AnalysisPhase.scala index dc67963e7..42d952565 100644 --- a/src/main/scala/leon/verification/AnalysisPhase.scala +++ b/src/main/scala/leon/verification/AnalysisPhase.scala @@ -19,7 +19,7 @@ object AnalysisPhase extends LeonPhase[Program,VerificationReport] { val name = "Analysis" val description = "Leon Verification" - implicit val debugSection = DebugSectionVerification + implicit val debugSection = utils.DebugSectionVerification override val definedOptions : Set[LeonOptionDef] = Set( LeonValueOptionDef("functions", "--functions=f1:f2", "Limit verification to f1,f2,..."), @@ -72,7 +72,7 @@ object AnalysisPhase extends LeonPhase[Program,VerificationReport] { reporter.info("Now considering '" + vcInfo.kind + "' VC for " + funDef.id + "...") reporter.debug("Verification condition (" + vcInfo.kind + ") for ==== " + funDef.id + " ====") - reporter.debug(simplifyLets(vc)) + reporter.debug(simplifyLets(vc).asString(vctx.context)) // try all solvers until one returns a meaningful answer solvers.find(sf => { -- GitLab