diff options
Diffstat (limited to 'Source/VCGeneration/Check.cs')
-rw-r--r-- | Source/VCGeneration/Check.cs | 1381 |
1 files changed, 694 insertions, 687 deletions
diff --git a/Source/VCGeneration/Check.cs b/Source/VCGeneration/Check.cs index da8624e9..7bda0022 100644 --- a/Source/VCGeneration/Check.cs +++ b/Source/VCGeneration/Check.cs @@ -1,687 +1,694 @@ -//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Linq;
-using System.Collections;
-using System.Collections.Generic;
-using System.Threading;
-using System.IO;
-using System.Text.RegularExpressions;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie.AbstractInterpretation;
-using Microsoft.Boogie.VCExprAST;
-using Microsoft.Basetypes;
-using System.Threading.Tasks;
-
-namespace Microsoft.Boogie {
-
- enum CheckerStatus
- {
- Idle,
- Ready,
- Busy,
- Closed
- }
-
- /// <summary>
- /// Interface to the theorem prover specialized to Boogie.
- ///
- /// This class creates the appropriate background axioms. There
- /// should be one instance per BoogiePL program.
- /// </summary>
- public sealed class Checker {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(gen != null);
- Contract.Invariant(thmProver != null);
- }
-
- private readonly VCExpressionGenerator gen;
-
- private ProverInterface thmProver;
- private int timeout;
-
- // state for the async interface
- private volatile ProverInterface.Outcome outcome;
- private volatile bool hasOutput;
- private volatile UnexpectedProverOutputException outputExn;
- private DateTime proverStart;
- private TimeSpan proverRunTime;
- private volatile ProverInterface.ErrorHandler handler;
- private volatile CheckerStatus status;
- public volatile Program Program;
-
- public void GetReady()
- {
- Contract.Requires(IsIdle);
-
- status = CheckerStatus.Ready;
- }
-
- public void GoBackToIdle()
- {
- Contract.Requires(IsBusy);
-
- status = CheckerStatus.Idle;
- }
-
- public Task ProverTask { get; set; }
-
- public bool WillingToHandle(int timeout, Program prog) {
- return status == CheckerStatus.Idle && timeout == this.timeout && (prog == null || Program == prog);
- }
-
- public VCExpressionGenerator VCExprGen {
- get {
- Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null);
- return this.gen;
- }
- }
- public ProverInterface TheoremProver {
- get {
- Contract.Ensures(Contract.Result<ProverInterface>() != null);
- return this.thmProver;
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // We share context information for the same program between different Checkers
-
- private struct ContextCacheKey {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(program != null);
- }
-
- public readonly Program program;
-
- public ContextCacheKey(Program prog) {
- Contract.Requires(prog != null);
- this.program = prog;
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (that is ContextCacheKey) {
- ContextCacheKey thatKey = (ContextCacheKey)that;
- return this.program.Equals(thatKey.program);
- }
- return false;
- }
-
- [Pure]
- public override int GetHashCode() {
- return this.program.GetHashCode();
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// Constructor. Initialize a checker with the program and log file.
- /// Optionally, use prover context provided by parameter "ctx".
- /// </summary>
- public Checker(VC.ConditionGeneration vcgen, Program prog, string/*?*/ logFilePath, bool appendLogFile, int timeout, ProverContext ctx = null) {
- Contract.Requires(vcgen != null);
- Contract.Requires(prog != null);
- this.timeout = timeout;
- this.Program = prog;
-
- ProverOptions options = cce.NonNull(CommandLineOptions.Clo.TheProverFactory).BlankProverOptions();
-
- if (logFilePath != null) {
- options.LogFilename = logFilePath;
- if (appendLogFile)
- options.AppendLogFile = appendLogFile;
- }
-
- if (timeout > 0) {
- options.TimeLimit = timeout * 1000;
- }
-
- options.Parse(CommandLineOptions.Clo.ProverOptions);
-
- ContextCacheKey key = new ContextCacheKey(prog);
- ProverInterface prover;
-
- if (vcgen.CheckerCommonState == null) {
- vcgen.CheckerCommonState = new Dictionary<ContextCacheKey, ProverContext>();
- }
- IDictionary<ContextCacheKey, ProverContext>/*!>!*/ cachedContexts = (IDictionary<ContextCacheKey, ProverContext/*!*/>)vcgen.CheckerCommonState;
-
- if (ctx == null && cachedContexts.TryGetValue(key, out ctx))
- {
- ctx = (ProverContext)cce.NonNull(ctx).Clone();
- prover = (ProverInterface)
- CommandLineOptions.Clo.TheProverFactory.SpawnProver(options, ctx);
- } else {
- if (ctx == null) ctx = (ProverContext)CommandLineOptions.Clo.TheProverFactory.NewProverContext(options);
-
- Setup(prog, ctx);
-
- // we first generate the prover and then store a clone of the
- // context in the cache, so that the prover can setup stuff in
- // the context to be cached
- prover = (ProverInterface)
- CommandLineOptions.Clo.TheProverFactory.SpawnProver(options, ctx);
- cachedContexts.Add(key, cce.NonNull((ProverContext)ctx.Clone()));
- }
-
- this.thmProver = prover;
- this.gen = prover.VCExprGen;
- }
-
- public void Retarget(Program prog, ProverContext ctx, int timeout = 0)
- {
- lock (this)
- {
- hasOutput = default(bool);
- outcome = default(ProverInterface.Outcome);
- outputExn = default(UnexpectedProverOutputException);
- handler = default(ProverInterface.ErrorHandler);
- TheoremProver.FullReset(gen);
- ctx.Reset();
- Setup(prog, ctx);
- this.timeout = timeout;
- SetTimeout();
- }
- }
-
- public void RetargetWithoutReset(Program prog, ProverContext ctx)
- {
- ctx.Clear();
- Setup(prog, ctx);
- }
-
-
- public void SetTimeout()
- {
- if (0 < timeout)
- {
- TheoremProver.SetTimeOut(timeout * 1000);
- }
- else
- {
- TheoremProver.SetTimeOut(0);
- }
- }
-
- /// <summary>
- /// Set up the context.
- /// </summary>
- private void Setup(Program prog, ProverContext ctx)
- {
- Program = prog;
- lock (Program.TopLevelDeclarations)
- {
- foreach (Declaration decl in Program.TopLevelDeclarations)
- {
- Contract.Assert(decl != null);
- var typeDecl = decl as TypeCtorDecl;
- var constDecl = decl as Constant;
- var funDecl = decl as Function;
- var axiomDecl = decl as Axiom;
- var glVarDecl = decl as GlobalVariable;
- if (typeDecl != null)
- {
- ctx.DeclareType(typeDecl, null);
- }
- else if (constDecl != null)
- {
- ctx.DeclareConstant(constDecl, constDecl.Unique, null);
- }
- else if (funDecl != null)
- {
- ctx.DeclareFunction(funDecl, null);
- }
- else if (axiomDecl != null)
- {
- ctx.AddAxiom(axiomDecl, null);
- }
- else if (glVarDecl != null)
- {
- ctx.DeclareGlobalVariable(glVarDecl, null);
- }
- }
- }
- }
-
- /// <summary>
- /// Clean-up.
- /// </summary>
- public void Close() {
- thmProver.Close();
- status = CheckerStatus.Closed;
- }
-
- /// <summary>
- /// Push a Verification Condition as an Axiom
- /// (Required for Doomed Program Point detection)
- /// </summary>
- public void PushVCExpr(VCExpr vc) {
- Contract.Requires(vc != null);
- //thmProver.Context.AddAxiom(vc);
- thmProver.PushVCExpression(vc);
- }
-
- public bool IsBusy {
- get {
- return status == CheckerStatus.Busy;
- }
- }
-
- public bool IsReady
- {
- get
- {
- return status == CheckerStatus.Ready;
- }
- }
-
- public bool IsClosed {
- get {
- return status == CheckerStatus.Closed;
- }
- }
-
- public bool IsIdle
- {
- get
- {
- return status == CheckerStatus.Idle;
- }
- }
-
- public bool HasOutput {
- get {
- return hasOutput;
- }
- }
-
- public TimeSpan ProverRunTime {
- get {
- return proverRunTime;
- }
- }
-
- private void WaitForOutput(object dummy) {
- lock (this)
- {
- try
- {
- outcome = thmProver.CheckOutcome(cce.NonNull(handler));
- }
- catch (UnexpectedProverOutputException e)
- {
- outputExn = e;
- }
-
- switch (outcome)
- {
- case ProverInterface.Outcome.Valid:
- thmProver.LogComment("Valid");
- break;
- case ProverInterface.Outcome.Invalid:
- thmProver.LogComment("Invalid");
- break;
- case ProverInterface.Outcome.TimeOut:
- thmProver.LogComment("Timed out");
- break;
- case ProverInterface.Outcome.OutOfMemory:
- thmProver.LogComment("Out of memory");
- break;
- case ProverInterface.Outcome.Undetermined:
- thmProver.LogComment("Undetermined");
- break;
- }
-
- hasOutput = true;
- proverRunTime = DateTime.UtcNow - proverStart;
- }
- }
-
- public void BeginCheck(string descriptiveName, VCExpr vc, ProverInterface.ErrorHandler handler) {
- Contract.Requires(descriptiveName != null);
- Contract.Requires(vc != null);
- Contract.Requires(handler != null);
- Contract.Requires(IsReady);
-
- status = CheckerStatus.Busy;
- hasOutput = false;
- outputExn = null;
- this.handler = handler;
-
- thmProver.Reset(gen);
- SetTimeout();
- proverStart = DateTime.UtcNow;
- thmProver.BeginCheck(descriptiveName, vc, handler);
- // gen.ClearSharedFormulas(); PR: don't know yet what to do with this guy
-
- ProverTask = Task.Factory.StartNew(() => { WaitForOutput(null); } , TaskCreationOptions.LongRunning);
- }
-
- public ProverInterface.Outcome ReadOutcome() {
- Contract.Requires(IsBusy);
- Contract.Requires(HasOutput);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
-
- hasOutput = false;
-
- if (outputExn != null) {
- throw outputExn;
- }
-
- return outcome;
- }
- }
-
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
- // -----------------------------------------------------------------------------------------------
-
- public abstract class ProverInterface {
- public static ProverInterface CreateProver(Program prog, string/*?*/ logFilePath, bool appendLogFile, int timeout, int taskID = -1) {
- Contract.Requires(prog != null);
-
- ProverOptions options = cce.NonNull(CommandLineOptions.Clo.TheProverFactory).BlankProverOptions();
-
- if (logFilePath != null) {
- options.LogFilename = logFilePath;
- if (appendLogFile)
- options.AppendLogFile = appendLogFile;
- }
-
- if (timeout > 0) {
- options.TimeLimit = timeout * 1000;
- }
-
- if (taskID >= 0) {
- options.Parse(CommandLineOptions.Clo.Cho[taskID].ProverOptions);
- } else {
- options.Parse(CommandLineOptions.Clo.ProverOptions);
- }
-
- ProverContext ctx = (ProverContext)CommandLineOptions.Clo.TheProverFactory.NewProverContext(options);
-
- // set up the context
- foreach (Declaration decl in prog.TopLevelDeclarations) {
- Contract.Assert(decl != null);
- TypeCtorDecl t = decl as TypeCtorDecl;
- if (t != null) {
- ctx.DeclareType(t, null);
- }
- }
- foreach (Declaration decl in prog.TopLevelDeclarations) {
- Contract.Assert(decl != null);
- Constant c = decl as Constant;
- if (c != null) {
- ctx.DeclareConstant(c, c.Unique, null);
- }
- else {
- Function f = decl as Function;
- if (f != null) {
- ctx.DeclareFunction(f, null);
- }
- }
- }
- foreach (var ax in prog.Axioms) {
- ctx.AddAxiom(ax, null);
- }
- foreach (Declaration decl in prog.TopLevelDeclarations) {
- Contract.Assert(decl != null);
- GlobalVariable v = decl as GlobalVariable;
- if (v != null) {
- ctx.DeclareGlobalVariable(v, null);
- }
- }
-
- return (ProverInterface)CommandLineOptions.Clo.TheProverFactory.SpawnProver(options, ctx);
- }
-
- public enum Outcome {
- Valid,
- Invalid,
- TimeOut,
- OutOfMemory,
- Undetermined
- }
- public class ErrorHandler {
- // Used in CheckOutcomeCore
- public virtual int StartingProcId()
- {
- return 0;
- }
-
- public virtual void OnModel(IList<string> labels, Model model, Outcome proverOutcome) {
- Contract.Requires(cce.NonNullElements(labels));
- }
-
- public virtual void OnResourceExceeded(string message) {
- Contract.Requires(message != null);
- }
-
- public virtual void OnProverWarning(string message)
- {
- Contract.Requires(message != null);
- switch (CommandLineOptions.Clo.PrintProverWarnings) {
- case CommandLineOptions.ProverWarnings.None:
- break;
- case CommandLineOptions.ProverWarnings.Stdout:
- Console.WriteLine("Prover warning: " + message);
- break;
- case CommandLineOptions.ProverWarnings.Stderr:
- Console.Error.WriteLine("Prover warning: " + message);
- break;
- default:
- Contract.Assume(false);
- throw new cce.UnreachableException(); // unexpected case
- }
- }
-
- public virtual Absy Label2Absy(string label) {
- Contract.Requires(label != null);
- Contract.Ensures(Contract.Result<Absy>() != null);
-
- throw new System.NotImplementedException();
- }
- }
- public abstract void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler);
-
- public virtual Outcome CheckRPFP(string descriptiveName, RPFP vc, ErrorHandler handler,
- out RPFP.Node cex,
- Dictionary<int, Dictionary<string, string>> varSubst, Dictionary<string,int> extra_bound = null)
- {
- throw new System.NotImplementedException();
- }
- [NoDefaultContract]
- public abstract Outcome CheckOutcome(ErrorHandler handler, int taskID = -1);
- public virtual string[] CalculatePath(int controlFlowConstant) {
- throw new System.NotImplementedException();
- }
- public virtual void LogComment(string comment) {
- Contract.Requires(comment != null);
- }
- public virtual void Close() {
- }
-
- public abstract void Reset(VCExpressionGenerator gen);
-
- public abstract void FullReset(VCExpressionGenerator gen);
-
- /// <summary>
- /// MSchaef: Allows to Push a VCExpression as Axiom on the prover stack (beta)
- /// for now it is only implemented by ProcessTheoremProver and still requires some
- /// testing
- /// </summary>
- public virtual void PushVCExpression(VCExpr vc) {
- Contract.Requires(vc != null);
- throw new NotImplementedException();
- }
- public virtual string VCExpressionToString(VCExpr vc) {
- Contract.Requires(vc != null);
- Contract.Ensures(Contract.Result<string>() != null);
- throw new NotImplementedException();
- }
- public virtual void Pop() {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- throw new NotImplementedException();
- }
- public virtual int NumAxiomsPushed() {
- throw new NotImplementedException();
- }
- public virtual int FlushAxiomsToTheoremProver() {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- throw new NotImplementedException();
- }
-
- // (assert vc)
- public virtual void Assert(VCExpr vc, bool polarity)
- {
- throw new NotImplementedException();
- }
-
- // (assert implicit-axioms)
- public virtual void AssertAxioms()
- {
- throw new NotImplementedException();
- }
-
- // (check-sat)
- public virtual void Check()
- {
- throw new NotImplementedException();
- }
-
- // (check-sat + get-unsat-core + checkOutcome)
- public virtual Outcome CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore, ErrorHandler handler)
- {
- throw new NotImplementedException();
- }
-
- public virtual Outcome CheckAssumptions(List<VCExpr> hardAssumptions, List<VCExpr> softAssumptions, out List<int> unsatisfiedSoftAssumptions, ErrorHandler handler) {
- throw new NotImplementedException();
- }
-
- public virtual Outcome CheckOutcomeCore(ErrorHandler handler, int taskID = -1)
- {
- throw new NotImplementedException();
- }
-
- // (push 1)
- public virtual void Push()
- {
- throw new NotImplementedException();
- }
-
- // Set theorem prover timeout for the next "check-sat"
- public virtual void SetTimeOut(int ms)
- { }
-
- public abstract ProverContext Context {
- get;
- }
-
- public abstract VCExpressionGenerator VCExprGen {
- get;
- }
-
- public virtual void DefineMacro(Macro fun, VCExpr vc) {
- throw new NotImplementedException();
- }
-
- public class VCExprEvaluationException : Exception
- {
-
- }
-
- public virtual object Evaluate(VCExpr expr)
- {
- throw new NotImplementedException();
- }
-
- //////////////////////
- // For interpolation queries
- //////////////////////
-
- // Assert vc tagged with a name
- public virtual void AssertNamed(VCExpr vc, bool polarity, string name)
- {
- throw new NotImplementedException();
- }
-
- // Returns Interpolant(A,B)
- public virtual VCExpr ComputeInterpolant(VCExpr A, VCExpr B)
- {
- throw new NotImplementedException();
- }
-
- // Returns for each l, Interpolant(root + (leaves - l), l)
- // Preconditions:
- // leaves cannot have subformulas with same variable names
- // Both root and leaves should have been previously named via AssertNamed
- public virtual List<VCExpr> GetTreeInterpolant(List<string> root, List<string> leaves)
- {
- throw new NotImplementedException();
- }
-
- }
-
- public class ProverInterfaceContracts : ProverInterface {
- public override ProverContext Context {
- get {
- Contract.Ensures(Contract.Result<ProverContext>() != null);
-
- throw new NotImplementedException();
- }
- }
- public override VCExpressionGenerator VCExprGen {
- get {
- Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null);
-
- throw new NotImplementedException();
- }
- }
- public override void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler) {/*Contract.Requires(descriptiveName != null);*/
- //Contract.Requires(vc != null);
- //Contract.Requires(handler != null);
- throw new NotImplementedException();
- }
- [NoDefaultContract]
- public override Outcome CheckOutcome(ErrorHandler handler, int taskID = -1) {
- //Contract.Requires(handler != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
- throw new NotImplementedException();
- }
-
- public override void Reset(VCExpressionGenerator gen)
- {
- throw new NotImplementedException();
- }
-
- public override void FullReset(VCExpressionGenerator gen)
- {
- throw new NotImplementedException();
- }
- }
-
- public class ProverException : Exception {
- public ProverException(string s)
- : base(s) {
- }
- }
- public class UnexpectedProverOutputException : ProverException {
- public UnexpectedProverOutputException(string s)
- : base(s) {
- }
- }
- public class ProverDiedException : UnexpectedProverOutputException {
- public ProverDiedException()
- : base("Prover died with no further output, perhaps it ran out of memory or was killed.") {
- }
- }
-}
+//----------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- +using System; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using System.Threading; +using System.IO; +using System.Text.RegularExpressions; +using System.Diagnostics; +using System.Diagnostics.Contracts; +using Microsoft.Boogie.AbstractInterpretation; +using Microsoft.Boogie.VCExprAST; +using Microsoft.Basetypes; +using System.Threading.Tasks; + +namespace Microsoft.Boogie { + + enum CheckerStatus + { + Idle, + Ready, + Busy, + Closed + } + + /// <summary> + /// Interface to the theorem prover specialized to Boogie. + /// + /// This class creates the appropriate background axioms. There + /// should be one instance per BoogiePL program. + /// </summary> + public sealed class Checker { + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(gen != null); + Contract.Invariant(thmProver != null); + } + + private readonly VCExpressionGenerator gen; + + private ProverInterface thmProver; + private int timeout; + + // state for the async interface + private volatile ProverInterface.Outcome outcome; + private volatile bool hasOutput; + private volatile UnexpectedProverOutputException outputExn; + private DateTime proverStart; + private TimeSpan proverRunTime; + private volatile ProverInterface.ErrorHandler handler; + private volatile CheckerStatus status; + public volatile Program Program; + + public void GetReady() + { + Contract.Requires(IsIdle); + + status = CheckerStatus.Ready; + } + + public void GoBackToIdle() + { + Contract.Requires(IsBusy); + + status = CheckerStatus.Idle; + } + + public Task ProverTask { get; set; } + + public bool WillingToHandle(int timeout, Program prog) { + return status == CheckerStatus.Idle && timeout == this.timeout && (prog == null || Program == prog); + } + + public VCExpressionGenerator VCExprGen { + get { + Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null); + return this.gen; + } + } + public ProverInterface TheoremProver { + get { + Contract.Ensures(Contract.Result<ProverInterface>() != null); + return this.thmProver; + } + } + + ///////////////////////////////////////////////////////////////////////////////// + // We share context information for the same program between different Checkers + + private struct ContextCacheKey { + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(program != null); + } + + public readonly Program program; + + public ContextCacheKey(Program prog) { + Contract.Requires(prog != null); + this.program = prog; + } + + [Pure] + [Reads(ReadsAttribute.Reads.Nothing)] + public override bool Equals(object that) { + if (that is ContextCacheKey) { + ContextCacheKey thatKey = (ContextCacheKey)that; + return this.program.Equals(thatKey.program); + } + return false; + } + + [Pure] + public override int GetHashCode() { + return this.program.GetHashCode(); + } + } + + ///////////////////////////////////////////////////////////////////////////////// + + /// <summary> + /// Constructor. Initialize a checker with the program and log file. + /// Optionally, use prover context provided by parameter "ctx". + /// </summary> + public Checker(VC.ConditionGeneration vcgen, Program prog, string/*?*/ logFilePath, bool appendLogFile, int timeout, ProverContext ctx = null) { + Contract.Requires(vcgen != null); + Contract.Requires(prog != null); + this.timeout = timeout; + this.Program = prog; + + ProverOptions options = cce.NonNull(CommandLineOptions.Clo.TheProverFactory).BlankProverOptions(); + + if (logFilePath != null) { + options.LogFilename = logFilePath; + if (appendLogFile) + options.AppendLogFile = appendLogFile; + } + + if (timeout > 0) { + options.TimeLimit = timeout * 1000; + } + + options.Parse(CommandLineOptions.Clo.ProverOptions); + + ContextCacheKey key = new ContextCacheKey(prog); + ProverInterface prover; + + if (vcgen.CheckerCommonState == null) { + vcgen.CheckerCommonState = new Dictionary<ContextCacheKey, ProverContext>(); + } + IDictionary<ContextCacheKey, ProverContext>/*!>!*/ cachedContexts = (IDictionary<ContextCacheKey, ProverContext/*!*/>)vcgen.CheckerCommonState; + + if (ctx == null && cachedContexts.TryGetValue(key, out ctx)) + { + ctx = (ProverContext)cce.NonNull(ctx).Clone(); + prover = (ProverInterface) + CommandLineOptions.Clo.TheProverFactory.SpawnProver(options, ctx); + } else { + if (ctx == null) ctx = (ProverContext)CommandLineOptions.Clo.TheProverFactory.NewProverContext(options); + + Setup(prog, ctx); + + // we first generate the prover and then store a clone of the + // context in the cache, so that the prover can setup stuff in + // the context to be cached + prover = (ProverInterface) + CommandLineOptions.Clo.TheProverFactory.SpawnProver(options, ctx); + cachedContexts.Add(key, cce.NonNull((ProverContext)ctx.Clone())); + } + + this.thmProver = prover; + this.gen = prover.VCExprGen; + } + + public void Retarget(Program prog, ProverContext ctx, int timeout = 0) + { + lock (this) + { + hasOutput = default(bool); + outcome = default(ProverInterface.Outcome); + outputExn = default(UnexpectedProverOutputException); + handler = default(ProverInterface.ErrorHandler); + TheoremProver.FullReset(gen); + ctx.Reset(); + Setup(prog, ctx); + this.timeout = timeout; + SetTimeout(); + } + } + + public void RetargetWithoutReset(Program prog, ProverContext ctx) + { + ctx.Clear(); + Setup(prog, ctx); + } + + + public void SetTimeout() + { + if (0 < timeout) + { + TheoremProver.SetTimeOut(timeout * 1000); + } + else + { + TheoremProver.SetTimeOut(0); + } + } + + /// <summary> + /// Set up the context. + /// </summary> + private void Setup(Program prog, ProverContext ctx) + { + Program = prog; + // TODO(wuestholz): Is this lock necessary? + lock (Program.TopLevelDeclarations) + { + foreach (Declaration decl in Program.TopLevelDeclarations) + { + Contract.Assert(decl != null); + var typeDecl = decl as TypeCtorDecl; + var constDecl = decl as Constant; + var funDecl = decl as Function; + var axiomDecl = decl as Axiom; + var glVarDecl = decl as GlobalVariable; + if (typeDecl != null) + { + ctx.DeclareType(typeDecl, null); + } + else if (constDecl != null) + { + ctx.DeclareConstant(constDecl, constDecl.Unique, null); + } + else if (funDecl != null) + { + ctx.DeclareFunction(funDecl, null); + } + else if (axiomDecl != null) + { + ctx.AddAxiom(axiomDecl, null); + } + else if (glVarDecl != null) + { + ctx.DeclareGlobalVariable(glVarDecl, null); + } + } + } + } + + /// <summary> + /// Clean-up. + /// </summary> + public void Close() { + thmProver.Close(); + status = CheckerStatus.Closed; + } + + /// <summary> + /// Push a Verification Condition as an Axiom + /// (Required for Doomed Program Point detection) + /// </summary> + public void PushVCExpr(VCExpr vc) { + Contract.Requires(vc != null); + //thmProver.Context.AddAxiom(vc); + thmProver.PushVCExpression(vc); + } + + public bool IsBusy { + get { + return status == CheckerStatus.Busy; + } + } + + public bool IsReady + { + get + { + return status == CheckerStatus.Ready; + } + } + + public bool IsClosed { + get { + return status == CheckerStatus.Closed; + } + } + + public bool IsIdle + { + get + { + return status == CheckerStatus.Idle; + } + } + + public bool HasOutput { + get { + return hasOutput; + } + } + + public TimeSpan ProverRunTime { + get { + return proverRunTime; + } + } + + private void WaitForOutput(object dummy) { + lock (this) + { + try + { + outcome = thmProver.CheckOutcome(cce.NonNull(handler)); + } + catch (UnexpectedProverOutputException e) + { + outputExn = e; + } + + switch (outcome) + { + case ProverInterface.Outcome.Valid: + thmProver.LogComment("Valid"); + break; + case ProverInterface.Outcome.Invalid: + thmProver.LogComment("Invalid"); + break; + case ProverInterface.Outcome.TimeOut: + thmProver.LogComment("Timed out"); + break; + case ProverInterface.Outcome.OutOfMemory: + thmProver.LogComment("Out of memory"); + break; + case ProverInterface.Outcome.Undetermined: + thmProver.LogComment("Undetermined"); + break; + } + + hasOutput = true; + proverRunTime = DateTime.UtcNow - proverStart; + } + } + + public void BeginCheck(string descriptiveName, VCExpr vc, ProverInterface.ErrorHandler handler) { + Contract.Requires(descriptiveName != null); + Contract.Requires(vc != null); + Contract.Requires(handler != null); + Contract.Requires(IsReady); + + status = CheckerStatus.Busy; + hasOutput = false; + outputExn = null; + this.handler = handler; + + thmProver.Reset(gen); + SetTimeout(); + proverStart = DateTime.UtcNow; + thmProver.BeginCheck(descriptiveName, vc, handler); + // gen.ClearSharedFormulas(); PR: don't know yet what to do with this guy + + ProverTask = Task.Factory.StartNew(() => { WaitForOutput(null); }, TaskCreationOptions.LongRunning); + } + + public ProverInterface.Outcome ReadOutcome() { + Contract.Requires(IsBusy); + Contract.Requires(HasOutput); + Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true); + + hasOutput = false; + + if (outputExn != null) { + throw outputExn; + } + + return outcome; + } + } + + // ----------------------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------------------- + + public abstract class ProverInterface { + + public static ProverInterface CreateProver(Program prog, string/*?*/ logFilePath, bool appendLogFile, int timeout, int taskID = -1) { + Contract.Requires(prog != null); + + ProverOptions options = cce.NonNull(CommandLineOptions.Clo.TheProverFactory).BlankProverOptions(); + + if (logFilePath != null) { + options.LogFilename = logFilePath; + if (appendLogFile) + options.AppendLogFile = appendLogFile; + } + + if (timeout > 0) { + options.TimeLimit = timeout * 1000; + } + + if (taskID >= 0) { + options.Parse(CommandLineOptions.Clo.Cho[taskID].ProverOptions); + } else { + options.Parse(CommandLineOptions.Clo.ProverOptions); + } + + ProverContext ctx = (ProverContext)CommandLineOptions.Clo.TheProverFactory.NewProverContext(options); + + // set up the context + foreach (Declaration decl in prog.TopLevelDeclarations) { + Contract.Assert(decl != null); + TypeCtorDecl t = decl as TypeCtorDecl; + if (t != null) { + ctx.DeclareType(t, null); + } + } + foreach (Declaration decl in prog.TopLevelDeclarations) { + Contract.Assert(decl != null); + Constant c = decl as Constant; + if (c != null) { + ctx.DeclareConstant(c, c.Unique, null); + } + else { + Function f = decl as Function; + if (f != null) { + ctx.DeclareFunction(f, null); + } + } + } + foreach (var ax in prog.Axioms) { + ctx.AddAxiom(ax, null); + } + foreach (Declaration decl in prog.TopLevelDeclarations) { + Contract.Assert(decl != null); + GlobalVariable v = decl as GlobalVariable; + if (v != null) { + ctx.DeclareGlobalVariable(v, null); + } + } + + return (ProverInterface)CommandLineOptions.Clo.TheProverFactory.SpawnProver(options, ctx); + } + + public enum Outcome { + Valid, + Invalid, + TimeOut, + OutOfMemory, + Undetermined, + Bounded + } + + public readonly ISet<VCExprVar> NamedAssumes = new HashSet<VCExprVar>(); + public ISet<string> UsedNamedAssumes { get; protected set; } + + public class ErrorHandler { + // Used in CheckOutcomeCore + public virtual int StartingProcId() + { + return 0; + } + + public virtual void OnModel(IList<string> labels, Model model, Outcome proverOutcome) { + Contract.Requires(cce.NonNullElements(labels)); + } + + public virtual void OnResourceExceeded(string message, IEnumerable<Tuple<AssertCmd, TransferCmd>> assertCmds = null) { + Contract.Requires(message != null); + } + + public virtual void OnProverWarning(string message) + { + Contract.Requires(message != null); + switch (CommandLineOptions.Clo.PrintProverWarnings) { + case CommandLineOptions.ProverWarnings.None: + break; + case CommandLineOptions.ProverWarnings.Stdout: + Console.WriteLine("Prover warning: " + message); + break; + case CommandLineOptions.ProverWarnings.Stderr: + Console.Error.WriteLine("Prover warning: " + message); + break; + default: + Contract.Assume(false); + throw new cce.UnreachableException(); // unexpected case + } + } + + public virtual Absy Label2Absy(string label) { + Contract.Requires(label != null); + Contract.Ensures(Contract.Result<Absy>() != null); + + throw new System.NotImplementedException(); + } + } + public abstract void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler); + + public virtual Outcome CheckRPFP(string descriptiveName, RPFP vc, ErrorHandler handler, + out RPFP.Node cex, + Dictionary<int, Dictionary<string, string>> varSubst, Dictionary<string,int> extra_bound = null) + { + throw new System.NotImplementedException(); + } + [NoDefaultContract] + public abstract Outcome CheckOutcome(ErrorHandler handler, int taskID = -1); + public virtual string[] CalculatePath(int controlFlowConstant) { + throw new System.NotImplementedException(); + } + public virtual void LogComment(string comment) { + Contract.Requires(comment != null); + } + public virtual void Close() { + } + + public abstract void Reset(VCExpressionGenerator gen); + + public abstract void FullReset(VCExpressionGenerator gen); + + /// <summary> + /// MSchaef: Allows to Push a VCExpression as Axiom on the prover stack (beta) + /// for now it is only implemented by ProcessTheoremProver and still requires some + /// testing + /// </summary> + public virtual void PushVCExpression(VCExpr vc) { + Contract.Requires(vc != null); + throw new NotImplementedException(); + } + public virtual string VCExpressionToString(VCExpr vc) { + Contract.Requires(vc != null); + Contract.Ensures(Contract.Result<string>() != null); + throw new NotImplementedException(); + } + public virtual void Pop() { + Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true); + throw new NotImplementedException(); + } + public virtual int NumAxiomsPushed() { + throw new NotImplementedException(); + } + public virtual int FlushAxiomsToTheoremProver() { + Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true); + throw new NotImplementedException(); + } + + // (assert vc) + public virtual void Assert(VCExpr vc, bool polarity, bool isSoft = false, int weight = 1) + { + throw new NotImplementedException(); + } + + // (assert implicit-axioms) + public virtual void AssertAxioms() + { + throw new NotImplementedException(); + } + + // (check-sat) + public virtual void Check() + { + throw new NotImplementedException(); + } + + // (check-sat + get-unsat-core + checkOutcome) + public virtual Outcome CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore, ErrorHandler handler) + { + throw new NotImplementedException(); + } + + public virtual Outcome CheckAssumptions(List<VCExpr> hardAssumptions, List<VCExpr> softAssumptions, out List<int> unsatisfiedSoftAssumptions, ErrorHandler handler) { + throw new NotImplementedException(); + } + + public virtual Outcome CheckOutcomeCore(ErrorHandler handler, int taskID = -1) + { + throw new NotImplementedException(); + } + + // (push 1) + public virtual void Push() + { + throw new NotImplementedException(); + } + + // Set theorem prover timeout for the next "check-sat" + public virtual void SetTimeOut(int ms) + { } + + public abstract ProverContext Context { + get; + } + + public abstract VCExpressionGenerator VCExprGen { + get; + } + + public virtual void DefineMacro(Macro fun, VCExpr vc) { + throw new NotImplementedException(); + } + + public class VCExprEvaluationException : Exception + { + + } + + public virtual object Evaluate(VCExpr expr) + { + throw new NotImplementedException(); + } + + ////////////////////// + // For interpolation queries + ////////////////////// + + // Assert vc tagged with a name + public virtual void AssertNamed(VCExpr vc, bool polarity, string name) + { + throw new NotImplementedException(); + } + + // Returns Interpolant(A,B) + public virtual VCExpr ComputeInterpolant(VCExpr A, VCExpr B) + { + throw new NotImplementedException(); + } + + // Returns for each l, Interpolant(root + (leaves - l), l) + // Preconditions: + // leaves cannot have subformulas with same variable names + // Both root and leaves should have been previously named via AssertNamed + public virtual List<VCExpr> GetTreeInterpolant(List<string> root, List<string> leaves) + { + throw new NotImplementedException(); + } + + } + + public class ProverInterfaceContracts : ProverInterface { + public override ProverContext Context { + get { + Contract.Ensures(Contract.Result<ProverContext>() != null); + + throw new NotImplementedException(); + } + } + public override VCExpressionGenerator VCExprGen { + get { + Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null); + + throw new NotImplementedException(); + } + } + public override void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler) {/*Contract.Requires(descriptiveName != null);*/ + //Contract.Requires(vc != null); + //Contract.Requires(handler != null); + throw new NotImplementedException(); + } + [NoDefaultContract] + public override Outcome CheckOutcome(ErrorHandler handler, int taskID = -1) { + //Contract.Requires(handler != null); + Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true); + throw new NotImplementedException(); + } + + public override void Reset(VCExpressionGenerator gen) + { + throw new NotImplementedException(); + } + + public override void FullReset(VCExpressionGenerator gen) + { + throw new NotImplementedException(); + } + } + + public class ProverException : Exception { + public ProverException(string s) + : base(s) { + } + } + public class UnexpectedProverOutputException : ProverException { + public UnexpectedProverOutputException(string s) + : base(s) { + } + } + public class ProverDiedException : UnexpectedProverOutputException { + public ProverDiedException() + : base("Prover died with no further output, perhaps it ran out of memory or was killed.") { + } + } +} |