Skip to content
Snippets Groups Projects
Commit 2abdb481 authored by Emmanouil (Manos) Koukoutos's avatar Emmanouil (Manos) Koukoutos Committed by Etienne Kneuss
Browse files

Focus on conditions

parent fd347c51
No related branches found
No related tags found
No related merge requests found
package leon.repair
import leon.purescala._
import Definitions._
import Trees._
import TypeTrees._
import TreeOps.postMap
import Constructors.not
import leon.LeonContext
import leon.evaluators.DefaultEvaluator
import scala.util.Try
// This evaluator treats the condition cond non-deterministically in the following sense:
// If a function invocation fails or violates a postcondition for cond,
// it backtracks and gets executed again for !cond
class RepairNDEvaluator(ctx: LeonContext, prog: Program, fd : FunDef, cond: Expr) extends DefaultEvaluator(ctx, prog) {
override def e(expr: Expr)(implicit rctx: RC, gctx: GC): Expr = expr match {
case FunctionInvocation(tfd, args) if tfd.fd == fd =>
if (gctx.stepsLeft < 0) {
throw RuntimeError("Exceeded number of allocated methods calls ("+gctx.maxSteps+")")
}
gctx.stepsLeft -= 1
val evArgs = args.map(a => e(a))
// build a mapping for the function...
val frame = rctx.withVars((tfd.params.map(_.id) zip evArgs).toMap)
if(tfd.hasPrecondition) {
e(tfd.precondition.get)(frame, gctx) match {
case BooleanLiteral(true) =>
case BooleanLiteral(false) =>
throw RuntimeError("Precondition violation for " + tfd.id.name + " reached in evaluation.: " + tfd.precondition.get)
case other =>
throw RuntimeError(typeErrorMsg(other, BooleanType))
}
}
if(!tfd.hasBody && !rctx.mappings.isDefinedAt(tfd.id)) {
throw EvalError("Evaluation of function with unknown implementation.")
}
val body = tfd.body.getOrElse(rctx.mappings(tfd.id))
def treat(subst : Expr => Expr) = {
val callResult = e(subst(body))(frame, gctx)
if(tfd.hasPostcondition) {
val (id, post) = tfd.postcondition.get
e(subst(post))(frame.withNewVar(id, callResult), gctx) match {
case BooleanLiteral(true) =>
case BooleanLiteral(false) => throw RuntimeError("Postcondition violation for " + tfd.id.name + " reached in evaluation.")
case other => throw EvalError(typeErrorMsg(other, BooleanType))
}
}
callResult
}
Try {
treat(e => e)
}.getOrElse {
treat( postMap{
// Use reference equality, just in case cond appears again in the program
case c if c eq cond => Some(not(cond))
case _ => None
} _)
}
case _ => super.e(expr)
}
}
\ No newline at end of file
...@@ -136,7 +136,7 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout ...@@ -136,7 +136,7 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout
)) diff Seq(ADTInduction, TEGIS, IntegerInequalities, IntegerEquation) )) diff Seq(ADTInduction, TEGIS, IntegerInequalities, IntegerEquation)
); );
// extract chooses from nfd // extract chooses from fd
val Seq(ci) = ChooseInfo.extractFromFunction(ctx, program, fd, soptions) val Seq(ci) = ChooseInfo.extractFromFunction(ctx, program, fd, soptions)
val nci = ci.copy(pc = and(ci.pc, guide)) val nci = ci.copy(pc = and(ci.pc, guide))
...@@ -181,6 +181,15 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout ...@@ -181,6 +181,15 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout
} }
val test2Tests : Map[FI, Set[FI]] = testEval.fullCallGraph val test2Tests : Map[FI, Set[FI]] = testEval.fullCallGraph
/*println("About to print")
for{
(test, tests) <-test2Tests
if (test._1 == fd)
} {
println(test._2 mkString ", ")
println(new ExamplesTable("", tests.toSeq.filter{_._1 == fd}.map{ x => InExample(x._2)}).toString)
}*/
def isFailing(fi : FI) = !testEval.fiStatus(fi) && (fi._1 == fd) def isFailing(fi : FI) = !testEval.fiStatus(fi) && (fi._1 == fd)
val failing = test2Tests filter { case (from, to) => val failing = test2Tests filter { case (from, to) =>
...@@ -198,75 +207,102 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout ...@@ -198,75 +207,102 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout
// - returns Some(true) if for all tests e evaluates to true // - returns Some(true) if for all tests e evaluates to true
// - returns Some(false) if for all tests e evaluates to false // - returns Some(false) if for all tests e evaluates to false
// - returns None otherwise // - returns None otherwise
def forAllTests(e: Expr, env: Map[Identifier, Expr]): Option[Boolean] = { def forAllTests(e: Expr, env: Map[Identifier, Expr], evaluator: Evaluator): Option[Boolean] = {
val results = minimalFailingTests.map { ex => var soFar : Option[Boolean] = None
minimalFailingTests.foreach { ex =>
val ins = ex.ins val ins = ex.ins
evaluator.eval(e, env ++ (args zip ins)) match { evaluator.eval(e, env ++ (args zip ins)) match {
case EvaluationResults.Successful(BooleanLiteral(true)) => Some(true) case EvaluationResults.Successful(BooleanLiteral(b)) =>
case EvaluationResults.Successful(BooleanLiteral(false)) => Some(false) soFar match {
case e => None case None =>
soFar = Some(b)
case Some(`b`) =>
case _ =>
return None
}
case e =>
return None
} }
} }
if (results.size == 1) { soFar
results.head
} else {
None
}
} }
def focus(expr: Expr, env: Map[Identifier, Expr]): (Expr, Expr) = expr match { def focus(expr: Expr, env: Map[Identifier, Expr])(implicit spec: Expr, out: Identifier): (Expr, Expr) = {
case me @ MatchExpr(scrut, cases) => val choose = Choose(List(out), spec)
var res: Option[(Expr, Expr)] = None expr match {
case me @ MatchExpr(scrut, cases) =>
// in case scrut is an non-variable expr, we simplify to a variable + inject in env var res: Option[(Expr, Expr)] = None
for (c <- cases if res.isEmpty) {
val cond = and(conditionForPattern(scrut, c.pattern, includeBinders = false), // in case scrut is an non-variable expr, we simplify to a variable + inject in env
c.optGuard.getOrElse(BooleanLiteral(true))) for (c <- cases if res.isEmpty) {
val map = mapForPattern(scrut, c.pattern) val cond = and(conditionForPattern(scrut, c.pattern, includeBinders = false),
c.optGuard.getOrElse(BooleanLiteral(true)))
val map = mapForPattern(scrut, c.pattern)
forAllTests(cond, env ++ map) match {
forAllTests(cond, env ++ map, evaluator) match {
case Some(true) =>
val (b, r) = focus(c.rhs, env ++ map)
res = Some((MatchExpr(scrut, cases.map { c2 =>
if (c2 eq c) {
c2.copy(rhs = b)
} else {
c2
}
}), r))
case Some(false) =>
// continue until next case
case None =>
res = Some((choose, expr))
}
}
res.getOrElse((choose, expr))
case Let(id, value, body) =>
val (b, r) = focus(body, env + (id -> value))
(Let(id, value, b), r)
case ite @ IfExpr(c, thn, els) =>
forAllTests(
spec,
env + (out -> IfExpr(not(c), thn, els)),
new RepairNDEvaluator(ctx,program,fd,c)
) match {
case Some(true) => case Some(true) =>
val (b, r) = focus(c.rhs, env ++ map) // If all failing tests succeed with the condition reversed,
res = Some((MatchExpr(scrut, cases.map { c2 => // we focus on the condition
if (c2 eq c) { val newOut = FreshIdentifier("cond", true).setType(BooleanType)
c2.copy(rhs = b) val newSpec = Let(
} else { out,
c2 IfExpr(Variable(newOut), thn, els),
} spec
}), r)) )
val (b, r) = focus(c, env)(newSpec, newOut)
case Some(false) => (IfExpr(b, thn, els), r)
// continue until next case case _ =>
case None => // Try to focus on branches
res = Some((choose, expr)) forAllTests(c, env, evaluator) match {
case Some(true) =>
val (b, r) = focus(thn, env)
(IfExpr(c, b, els), r)
case Some(false) =>
val (b, r) = focus(els, env)
(IfExpr(c, thn, b), r)
case None =>
// We cannot focus any further
(choose, expr)
}
} }
}
res.getOrElse((choose, expr))
case Let(id, value, body) =>
val (b, r) = focus(body, env + (id -> value))
(Let(id, value, b), r)
case IfExpr(c, thn, els) =>
forAllTests(c, env) match {
case Some(true) =>
val (b, r) = focus(thn, env)
(IfExpr(c, b, els), r)
case Some(false) =>
val (b, r) = focus(els, env)
(IfExpr(c, thn, b), r)
case None =>
(choose, expr)
}
case _ => case _ =>
(choose, expr) (choose, expr)
}
} }
focus(body, Map()) focus(body, Map())(spec, out)
} }
def getVerificationCounterExamples(fd: FunDef, prog: Program): Option[Seq[InExample]] = { def getVerificationCounterExamples(fd: FunDef, prog: Program): Option[Seq[InExample]] = {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment