Skip to content
Snippets Groups Projects
Commit e445f6d3 authored by Manos Koukoutos's avatar Manos Koukoutos
Browse files

SMTLIB-CVC4 with define-funs-rec

parent 4be1df0c
No related branches found
No related tags found
No related merge requests found
...@@ -2,6 +2,7 @@ package leon.purescala ...@@ -2,6 +2,7 @@ package leon.purescala
import Definitions._ import Definitions._
import Expressions._ import Expressions._
import ExprOps.{preMap, postMap, functionCallsOf}
object DefOps { object DefOps {
...@@ -262,11 +263,7 @@ object DefOps { ...@@ -262,11 +263,7 @@ object DefOps {
} }
import Expressions.Expr
import ExprOps.{preMap, postMap}
/* /*
* Apply an expression operation on all expressions contained in a FunDef * Apply an expression operation on all expressions contained in a FunDef
*/ */
...@@ -385,4 +382,21 @@ object DefOps { ...@@ -385,4 +382,21 @@ object DefOps {
}(e) }(e)
} }
} /**
* Returns a call graph starting from the given sources, taking into account
* instantiations of function type parameters,
* If given limit of explored nodes reached, it returns a partial set of reached TypedFunDefs
* and the boolean set to "false".
* Otherwise, it returns the full set of reachable TypedFunDefs and "true"
*/
def typedTransitiveCallees(sources: Set[TypedFunDef], limit: Option[Int] = None): (Set[TypedFunDef], Boolean) = {
import leon.utils.SearchSpace.reachable
reachable(
sources,
(tfd: TypedFunDef) => functionCallsOf(tfd.fd.fullBody) map { _.tfd },
limit
)
}
}
\ No newline at end of file
...@@ -437,6 +437,8 @@ object Definitions { ...@@ -437,6 +437,8 @@ object Definitions {
TypedFunDef(this, tparams.map(_.tp)) TypedFunDef(this, tparams.map(_.tp))
} }
def isRecursive(p: Program) = p.callGraph.transitiveCallees(this) contains this
setSubDefOwners() setSubDefOwners()
// Deprecated, old API // Deprecated, old API
@deprecated("Use .body instead", "2.3") @deprecated("Use .body instead", "2.3")
......
...@@ -1955,6 +1955,7 @@ object ExprOps { ...@@ -1955,6 +1955,7 @@ object ExprOps {
case _ => None case _ => None
} }
/** /**
* Deprecated API * Deprecated API
* ======== * ========
......
...@@ -19,7 +19,7 @@ object SolverFactory { ...@@ -19,7 +19,7 @@ object SolverFactory {
} }
} }
val definedSolvers = Set("fairz3", "unrollz3", "enum", "smt", "smt-z3", "smt-cvc4") val definedSolvers = Set("fairz3", "unrollz3", "enum", "smt", "smt-z3", "smt-cvc4", "smt-2.5-cvc4")
def getFromSettings[S](ctx: LeonContext, program: Program): SolverFactory[TimeoutSolver] = { def getFromSettings[S](ctx: LeonContext, program: Program): SolverFactory[TimeoutSolver] = {
import combinators._ import combinators._
...@@ -42,6 +42,9 @@ object SolverFactory { ...@@ -42,6 +42,9 @@ object SolverFactory {
case "smt-cvc4" => case "smt-cvc4" =>
SolverFactory(() => new UnrollingSolver(ctx, program, new SMTLIBSolver(ctx, program) with SMTLIBCVC4Target) with TimeoutSolver) SolverFactory(() => new UnrollingSolver(ctx, program, new SMTLIBSolver(ctx, program) with SMTLIBCVC4Target) with TimeoutSolver)
case "smt-2.5-cvc4" =>
SolverFactory(() => new SMTLIBSolver(ctx, program) with SMTLIBUnrollingCVC4Target with TimeoutSolver)
case _ => case _ =>
ctx.reporter.fatalError("Unknown solver "+name) ctx.reporter.fatalError("Unknown solver "+name)
} }
......
/* Copyright 2009-2015 EPFL, Lausanne */
package leon
package solvers.smtlib
import purescala.Definitions.TypedFunDef
import purescala.DefOps.typedTransitiveCallees
import purescala.ExprOps.matchToIfThenElse
import smtlib.parser.Commands._
import smtlib.parser.Terms._
trait SMTLIBUnrollingCVC4Target extends SMTLIBCVC4Target {
this: SMTLIBSolver =>
private val typedFunDefExplorationLimit = 10000
override def targetName = "2.5-cvc4"
override def declareFunction(tfd: TypedFunDef): SSymbol = {
if (tfd.params.isEmpty) {
super[SMTLIBCVC4Target].declareFunction(tfd)
} else {
val (funs, exploredAll) = typedTransitiveCallees(Set(tfd), Some(typedFunDefExplorationLimit))
if (!exploredAll) {
reporter.warning(
s"Did not manage to explore the space of typed functions called from ${tfd.id}. The solver may fail"
)
}
val (smtFunDecls, smtBodies) = funs.toSeq.collect {
case tfd if !functions.containsA(tfd) && tfd.params.nonEmpty =>
val id = if (tfd.tps.isEmpty) {
tfd.id
} else {
tfd.id.freshen
}
val sym = id2sym(id)
functions +=(tfd, sym)
(
FunDec(
sym,
tfd.params map { p => SortedVar(id2sym(p.id), declareSort(p.getType)) },
declareSort(tfd.returnType)
),
toSMT(matchToIfThenElse(tfd.body.get))(tfd.params.map { p =>
(p.id, id2sym(p.id): Term)
}.toMap)
)
}.unzip
if (smtFunDecls.nonEmpty) sendCommand(DefineFunsRec(smtFunDecls, smtBodies))
functions.toB(tfd)
}
}
}
package leon.utils
object SearchSpace {
def reachable[A](sources: Set[A], generateNeighbors: A => Set[A], limit: Option[Int] = None): (Set[A], Boolean) = {
require(limit forall(_ >= 0))
def rec(seen: Set[A], toSee: Set[A], limit: Option[Int]): (Set[A], Boolean) = {
(toSee.headOption, limit) match {
case (None, _) =>
(seen, true)
case (_, Some(0)) =>
(seen, false)
case (Some(hd), _) =>
val neighbors = generateNeighbors(hd)
rec(seen + hd, toSee ++ neighbors -- (seen + hd), limit map {_ - 1})
}
}
rec(Set(), sources, limit)
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment