diff --git a/src/main/scala/inox/solvers/smtlib/SMTLIBSolver.scala b/src/main/scala/inox/solvers/smtlib/SMTLIBSolver.scala index 2dd091e005a64ead80677e77069be4d01a865e52..a93526a0f76a3018c5f9c2ce7a6eff3cff79af30 100644 --- a/src/main/scala/inox/solvers/smtlib/SMTLIBSolver.scala +++ b/src/main/scala/inox/solvers/smtlib/SMTLIBSolver.scala @@ -28,21 +28,23 @@ trait SMTLIBSolver extends Solver with SMTLIBTarget { } /* Public solver interface */ - def assertCnstr(expr: Expr): Unit = if (!hasError) { - try { - variablesOf(expr).foreach(declareVariable) - - val term = toSMT(expr)(Map()) - emit(Assert(term)) - } catch { - case _ : SolverUnsupportedError => - // Store that there was an error. Now all following check() - // invocations will return None - addError() - } + def assertCnstr(expr: Expr): Unit = { + variablesOf(expr).foreach(declareVariable) + + val term = toSMT(expr)(Map()) + emit(Assert(term)) } override def reset() = { + adtManager.reset() + constructors.clear() + selectors.clear() + testers.clear() + variables.clear() + sorts.clear() + lambdas.clear() + functions.clear() + emit(Reset(), rawOut = true) match { case Error(msg) => reporter.warning(s"Failed to reset $name: $msg") @@ -51,63 +53,70 @@ trait SMTLIBSolver extends Solver with SMTLIBTarget { } } - override def check(config: Configuration): config.Response[Model, Cores] = config.cast { - if (hasError) Unknown else { - emit(CheckSat()) match { - case CheckSatStatus(SatStatus) => - config match { - case All | Model => - val syms = variables.aSet.map(variables.aToB) - emit(GetModel()) match { - case GetModelResponseSuccess(smodel) => - // first-pass to gather functions - val modelFunDefs = smodel.collect { - case me @ DefineFun(SMTFunDef(a, args, _, _)) if args.nonEmpty => - a -> me - }.toMap - - val model = smodel.flatMap { - case DefineFun(SMTFunDef(s, _, _, e)) if syms(s) => - try { - val v = variables.toA(s) - val value = fromSMT(e, v.getType)(Map(), modelFunDefs) - Some(v.toVal -> value) - } catch { - case _: Unsupported => - None - } - case _ => None - }.toMap - - SatWithModel(model) - - case _ => - Unknown - } + private def extractResponse(config: Configuration, res: SExpr): config.Response[Model, Cores] = + config.cast(res match { + case CheckSatStatus(SatStatus) => + if (config.withModel) { + val syms = variables.aSet.map(variables.aToB) + emit(GetModel()) match { + case GetModelResponseSuccess(smodel) => + // first-pass to gather functions + val modelFunDefs = smodel.collect { + case me @ DefineFun(SMTFunDef(a, args, _, _)) if args.nonEmpty => + a -> me + }.toMap + + val model = smodel.flatMap { + case DefineFun(SMTFunDef(s, _, _, e)) if syms(s) => + try { + val v = variables.toA(s) + val value = fromSMT(e, v.getType)(Map(), modelFunDefs) + Some(v.toVal -> value) + } catch { + case _: Unsupported => + None + } + case _ => None + }.toMap + + SatWithModel(model) + case _ => - Sat + Unknown } - case CheckSatStatus(UnsatStatus) => - config match { - case All | Cores => - emit(GetUnsatCore()) match { - case GetUnsatCoreResponseSuccess(syms) => - UnsatWithCores(Set.empty) // FIXME - case _ => - UnsatWithCores(Set.empty) - } + } else { + Sat + } + case CheckSatStatus(UnsatStatus) => + if (config.withCores) { + emit(GetUnsatCore()) match { + case GetUnsatCoreResponseSuccess(syms) => + UnsatWithCores(Set.empty) // FIXME case _ => - Unsat + UnsatWithCores(Set.empty) } - case CheckSatStatus(UnknownStatus) => Unknown - case e => Unknown - } + } else { + Unsat + } + case CheckSatStatus(UnknownStatus) => Unknown + case e => Unknown + }) + + def check(config: Configuration): config.Response[Model, Cores] = + extractResponse(config, emit(CheckSat())) + + def checkAssumptions(config: Configuration)(assumptions: Set[Expr]): config.Response[Model, Cores] = { + val props = assumptions.toSeq.map { + case Not(v: Variable) => PropLiteral(variables.toB(v), false) + case v: Variable => PropLiteral(variables.toB(v), true) + case t => unsupported(t, "Assumptions must be either variables or their negation") } - } - def checkAssumptions(config: Configuration)(assumptions: Set[Trees]): config.Response[Model, Cores] = ??? //TODO + extractResponse(config, emit(CheckSatAssuming(props))) + } def push(): Unit = { + adtManager.push() constructors.push() selectors.push() testers.push() @@ -115,12 +124,12 @@ trait SMTLIBSolver extends Solver with SMTLIBTarget { sorts.push() lambdas.push() functions.push() - errors.push() emit(Push(1)) } def pop(): Unit = { + adtManager.pop() constructors.pop() selectors.pop() testers.pop() @@ -128,7 +137,6 @@ trait SMTLIBSolver extends Solver with SMTLIBTarget { sorts.pop() lambdas.pop() functions.pop() - errors.pop() emit(Pop(1)) } diff --git a/src/main/scala/inox/solvers/smtlib/SMTLIBTarget.scala b/src/main/scala/inox/solvers/smtlib/SMTLIBTarget.scala index 9077286e73b6e6f1b89f5f802cb4f5e0eb88d064..c8a1731586bcd2a2b50107f8311ee5e5aa2abb47 100644 --- a/src/main/scala/inox/solvers/smtlib/SMTLIBTarget.scala +++ b/src/main/scala/inox/solvers/smtlib/SMTLIBTarget.scala @@ -90,13 +90,8 @@ trait SMTLIBTarget extends Interruptible with ADTManagers { o.flush() } interpreter.eval(cmd) match { - case err @ Error(msg) if !hasError && !interrupted && !rawOut => - ctx.reporter.warning(s"Unexpected error from $targetName solver: $msg") - //println(Thread.currentThread().getStackTrace.map(_.toString).take(10).mkString("\n")) - // Store that there was an error. Now all following check() - // invocations will return None - addError() - err + case err @ Error(msg) if !interrupted && !rawOut => + ctx.reporter.fatalError(s"Unexpected error from $targetName solver: $msg") case res => res } @@ -142,9 +137,6 @@ trait SMTLIBTarget extends Interruptible with ADTManagers { protected val sorts = new IncrementalBijection[Type, Sort]() protected val functions = new IncrementalBijection[TypedFunDef, SSymbol]() protected val lambdas = new IncrementalBijection[FunctionType, SSymbol]() - protected val errors = new IncrementalBijection[Unit, Boolean]() - protected def hasError = errors.getB(()) contains true - protected def addError() = errors += () -> true /* Helper functions */