diff options
Diffstat (limited to 'Source/Provers/SMTLib')
-rw-r--r-- | Source/Provers/SMTLib/CVC4.cs | 142 | ||||
-rw-r--r-- | Source/Provers/SMTLib/Inspector.cs | 314 | ||||
-rw-r--r-- | Source/Provers/SMTLib/ProverInterface.cs | 5176 | ||||
-rw-r--r-- | Source/Provers/SMTLib/SExpr.cs | 526 | ||||
-rw-r--r-- | Source/Provers/SMTLib/SMTLib.csproj | 474 | ||||
-rw-r--r-- | Source/Provers/SMTLib/SMTLibLineariser.cs | 1702 | ||||
-rw-r--r-- | Source/Provers/SMTLib/SMTLibNamer.cs | 294 | ||||
-rw-r--r-- | Source/Provers/SMTLib/SMTLibProverOptions.cs | 316 | ||||
-rw-r--r-- | Source/Provers/SMTLib/TypeDeclCollector.cs | 790 | ||||
-rw-r--r-- | Source/Provers/SMTLib/Z3.cs | 774 | ||||
-rw-r--r-- | Source/Provers/SMTLib/cce.cs | 384 |
11 files changed, 5446 insertions, 5446 deletions
diff --git a/Source/Provers/SMTLib/CVC4.cs b/Source/Provers/SMTLib/CVC4.cs index 0ac2ec20..999ac7b5 100644 --- a/Source/Provers/SMTLib/CVC4.cs +++ b/Source/Provers/SMTLib/CVC4.cs @@ -1,71 +1,71 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics.Contracts;
-using System.IO;
-using System.Text.RegularExpressions;
-
-namespace Microsoft.Boogie.SMTLib
-{
- class CVC4
- {
- static string _proverPath;
-
- static string CodebaseString()
- {
- Contract.Ensures(Contract.Result<string>() != null);
- return Path.GetDirectoryName(cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location));
- }
-
- public static string ExecutablePath()
- {
- if (_proverPath == null)
- FindExecutable();
- return _proverPath;
- }
-
- static void FindExecutable()
- // throws ProverException, System.IO.FileNotFoundException;
- {
- Contract.Ensures(_proverPath != null);
-
- // Command line option 'cvc4exe' always has priority if set
- if (CommandLineOptions.Clo.CVC4ExecutablePath != null)
- {
- _proverPath = CommandLineOptions.Clo.CVC4ExecutablePath;
- if (!File.Exists(_proverPath))
- {
- throw new ProverException("Cannot find prover specified with cvc4exe: " + _proverPath);
- }
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("[TRACE] Using prover: " + _proverPath);
- }
- return;
- }
-
- var proverExe = "cvc4.exe";
-
- if (_proverPath == null)
- {
- // Initialize '_proverPath'
- _proverPath = Path.Combine(CodebaseString(), proverExe);
- string firstTry = _proverPath;
-
- if (File.Exists(firstTry))
- {
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("[TRACE] Using prover: " + _proverPath);
- }
- return;
- }
- else
- {
- throw new ProverException("Cannot find executable: " + firstTry);
- }
- }
- }
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics.Contracts; +using System.IO; +using System.Text.RegularExpressions; + +namespace Microsoft.Boogie.SMTLib +{ + class CVC4 + { + static string _proverPath; + + static string CodebaseString() + { + Contract.Ensures(Contract.Result<string>() != null); + return Path.GetDirectoryName(cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location)); + } + + public static string ExecutablePath() + { + if (_proverPath == null) + FindExecutable(); + return _proverPath; + } + + static void FindExecutable() + // throws ProverException, System.IO.FileNotFoundException; + { + Contract.Ensures(_proverPath != null); + + // Command line option 'cvc4exe' always has priority if set + if (CommandLineOptions.Clo.CVC4ExecutablePath != null) + { + _proverPath = CommandLineOptions.Clo.CVC4ExecutablePath; + if (!File.Exists(_proverPath)) + { + throw new ProverException("Cannot find prover specified with cvc4exe: " + _proverPath); + } + if (CommandLineOptions.Clo.Trace) + { + Console.WriteLine("[TRACE] Using prover: " + _proverPath); + } + return; + } + + var proverExe = "cvc4.exe"; + + if (_proverPath == null) + { + // Initialize '_proverPath' + _proverPath = Path.Combine(CodebaseString(), proverExe); + string firstTry = _proverPath; + + if (File.Exists(firstTry)) + { + if (CommandLineOptions.Clo.Trace) + { + Console.WriteLine("[TRACE] Using prover: " + _proverPath); + } + return; + } + else + { + throw new ProverException("Cannot find executable: " + firstTry); + } + } + } + } +} diff --git a/Source/Provers/SMTLib/Inspector.cs b/Source/Provers/SMTLib/Inspector.cs index 362502f3..13a2076e 100644 --- a/Source/Provers/SMTLib/Inspector.cs +++ b/Source/Provers/SMTLib/Inspector.cs @@ -1,157 +1,157 @@ -//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.IO;
-using System.Diagnostics;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-//using util;
-using Microsoft.Boogie;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-namespace Microsoft.Boogie.SMTLib
-{
- internal class FindLabelsVisitor : TraversingVCExprVisitor<bool, bool> {
- public HashSet<string/*!*/>/*!*/ Labels = new HashSet<string/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNull(Labels));
- }
-
-
- public static HashSet<string/*!*/>/*!*/ FindLabels(VCExpr/*!*/ expr) {
- Contract.Requires(expr != null);
- Contract.Ensures(cce.NonNull(Contract.Result<HashSet<string/*!*/>/*!*/>()));
-
- FindLabelsVisitor visitor = new FindLabelsVisitor();
- visitor.Traverse(expr, true);
- return visitor.Labels;
- }
-
- protected override bool StandardResult(VCExpr node, bool arg) {
- //Contract.Requires(node!=null);
- VCExprNAry nary = node as VCExprNAry;
- if (nary != null) {
- VCExprLabelOp lab = nary.Op as VCExprLabelOp;
- if (lab != null) {
- Labels.Add(lab.label);
- }
- }
- return true;
- }
- }
-
- internal class Inspector {
- [Rep] protected readonly Process inspector;
- [Rep] readonly TextReader fromInspector;
- [Rep] readonly TextWriter toInspector;
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(inspector!=null);
- Contract.Invariant(fromInspector!=null);
- Contract.Invariant(toInspector != null);
- }
-
-
- public Inspector(SMTLibProverOptions opts)
- {
- Contract.Requires(opts != null);
- ProcessStartInfo psi = new ProcessStartInfo(opts.Inspector);
- Contract.Assert(psi!=null);
- psi.CreateNoWindow = true;
- psi.UseShellExecute = false;
- psi.RedirectStandardInput = true;
- psi.RedirectStandardOutput = true;
- psi.RedirectStandardError = false;
-
- try
- {
- Process inspector = Process.Start(psi);
- this.inspector = inspector;
- fromInspector = inspector.StandardOutput;
- toInspector = inspector.StandardInput;
- }
- catch (System.ComponentModel.Win32Exception e)
- {
- throw new Exception(string.Format("Unable to start the inspector process {0}: {1}", opts.Inspector, e.Message));
- }
- }
-
- public void NewProblem(string descriptiveName, VCExpr vc, ProverInterface.ErrorHandler handler)
- {
- Contract.Requires(descriptiveName != null);
- Contract.Requires(vc != null);
- Contract.Requires(handler != null);
- HashSet<string/*!*/>/*!*/ labels = FindLabelsVisitor.FindLabels(vc);
- Contract.Assert(labels!=null);
- toInspector.WriteLine("PROBLEM " + descriptiveName);
- toInspector.WriteLine("TOKEN BEGIN");
- foreach (string lab in labels) {
- Contract.Assert(lab!=null);
- string no = lab.Substring(1);
- Absy absy = handler.Label2Absy(no);
-
- IToken tok = absy.tok;
- AssertCmd assrt = absy as AssertCmd;
- Block blk = absy as Block;
- string val = tok.val; // might require computation, so cache it
- if (val == "foo" || tok.filename == null) continue; // no token
-
- toInspector.Write("TOKEN ");
- toInspector.Write(lab);
- toInspector.Write(" ");
-
- if (assrt != null) {
- toInspector.Write("ASSERT");
- string errData = assrt.ErrorData as string;
- if (errData != null) {
- val = errData;
- } else if (assrt.ErrorMessage != null) {
- val = assrt.ErrorMessage;
- }
- } else if (blk != null) {
- toInspector.Write("BLOCK ");
- toInspector.Write(blk.Label);
- } else {
- Contract.Assume( false);
- }
- if (val == null || val == "assert" || val == "ensures") { val = ""; }
-
- if (absy is LoopInitAssertCmd) {
- val += " (loop entry)";
- } else if (absy is LoopInvMaintainedAssertCmd) {
- val += " (loop body)";
- } else if (val.IndexOf("#VCCERR") >= 0) {
- // skip further transformations
- } else if (absy is AssertRequiresCmd) {
- AssertRequiresCmd req = (AssertRequiresCmd)absy;
- IToken t2 = req.Requires.tok;
- string tval = t2.val;
- if (tval == "requires")
- tval = string.Format("{0}({1},{2}))", t2.filename, t2.line, t2.col);
- string call = "";
- if (val != "call") call = " in call to " + val;
- val = string.Format("precondition {0}{1}", tval, call);
- }
-
- val = val.Replace("\r", "").Replace("\n", " ");
-
- toInspector.WriteLine(string.Format(" {0} {1} :@:{2}:@:{3}", tok.line, tok.col, tok.filename, val));
- }
- toInspector.WriteLine("TOKEN END");
- }
-
- public void StatsLine(string line)
- {
- Contract.Requires(line != null);
- toInspector.WriteLine(line);
- toInspector.Flush();
- }
- }
-}
+//----------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- +using System; +using System.IO; +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +//using util; +using Microsoft.Boogie; +using Microsoft.Basetypes; +using Microsoft.Boogie.VCExprAST; + +namespace Microsoft.Boogie.SMTLib +{ + internal class FindLabelsVisitor : TraversingVCExprVisitor<bool, bool> { + public HashSet<string/*!*/>/*!*/ Labels = new HashSet<string/*!*/>(); + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(cce.NonNull(Labels)); + } + + + public static HashSet<string/*!*/>/*!*/ FindLabels(VCExpr/*!*/ expr) { + Contract.Requires(expr != null); + Contract.Ensures(cce.NonNull(Contract.Result<HashSet<string/*!*/>/*!*/>())); + + FindLabelsVisitor visitor = new FindLabelsVisitor(); + visitor.Traverse(expr, true); + return visitor.Labels; + } + + protected override bool StandardResult(VCExpr node, bool arg) { + //Contract.Requires(node!=null); + VCExprNAry nary = node as VCExprNAry; + if (nary != null) { + VCExprLabelOp lab = nary.Op as VCExprLabelOp; + if (lab != null) { + Labels.Add(lab.label); + } + } + return true; + } + } + + internal class Inspector { + [Rep] protected readonly Process inspector; + [Rep] readonly TextReader fromInspector; + [Rep] readonly TextWriter toInspector; + [ContractInvariantMethod] + void ObjectInvariant() + { + Contract.Invariant(inspector!=null); + Contract.Invariant(fromInspector!=null); + Contract.Invariant(toInspector != null); + } + + + public Inspector(SMTLibProverOptions opts) + { + Contract.Requires(opts != null); + ProcessStartInfo psi = new ProcessStartInfo(opts.Inspector); + Contract.Assert(psi!=null); + psi.CreateNoWindow = true; + psi.UseShellExecute = false; + psi.RedirectStandardInput = true; + psi.RedirectStandardOutput = true; + psi.RedirectStandardError = false; + + try + { + Process inspector = Process.Start(psi); + this.inspector = inspector; + fromInspector = inspector.StandardOutput; + toInspector = inspector.StandardInput; + } + catch (System.ComponentModel.Win32Exception e) + { + throw new Exception(string.Format("Unable to start the inspector process {0}: {1}", opts.Inspector, e.Message)); + } + } + + public void NewProblem(string descriptiveName, VCExpr vc, ProverInterface.ErrorHandler handler) + { + Contract.Requires(descriptiveName != null); + Contract.Requires(vc != null); + Contract.Requires(handler != null); + HashSet<string/*!*/>/*!*/ labels = FindLabelsVisitor.FindLabels(vc); + Contract.Assert(labels!=null); + toInspector.WriteLine("PROBLEM " + descriptiveName); + toInspector.WriteLine("TOKEN BEGIN"); + foreach (string lab in labels) { + Contract.Assert(lab!=null); + string no = lab.Substring(1); + Absy absy = handler.Label2Absy(no); + + IToken tok = absy.tok; + AssertCmd assrt = absy as AssertCmd; + Block blk = absy as Block; + string val = tok.val; // might require computation, so cache it + if (val == "foo" || tok.filename == null) continue; // no token + + toInspector.Write("TOKEN "); + toInspector.Write(lab); + toInspector.Write(" "); + + if (assrt != null) { + toInspector.Write("ASSERT"); + string errData = assrt.ErrorData as string; + if (errData != null) { + val = errData; + } else if (assrt.ErrorMessage != null) { + val = assrt.ErrorMessage; + } + } else if (blk != null) { + toInspector.Write("BLOCK "); + toInspector.Write(blk.Label); + } else { + Contract.Assume( false); + } + if (val == null || val == "assert" || val == "ensures") { val = ""; } + + if (absy is LoopInitAssertCmd) { + val += " (loop entry)"; + } else if (absy is LoopInvMaintainedAssertCmd) { + val += " (loop body)"; + } else if (val.IndexOf("#VCCERR") >= 0) { + // skip further transformations + } else if (absy is AssertRequiresCmd) { + AssertRequiresCmd req = (AssertRequiresCmd)absy; + IToken t2 = req.Requires.tok; + string tval = t2.val; + if (tval == "requires") + tval = string.Format("{0}({1},{2}))", t2.filename, t2.line, t2.col); + string call = ""; + if (val != "call") call = " in call to " + val; + val = string.Format("precondition {0}{1}", tval, call); + } + + val = val.Replace("\r", "").Replace("\n", " "); + + toInspector.WriteLine(string.Format(" {0} {1} :@:{2}:@:{3}", tok.line, tok.col, tok.filename, val)); + } + toInspector.WriteLine("TOKEN END"); + } + + public void StatsLine(string line) + { + Contract.Requires(line != null); + toInspector.WriteLine(line); + toInspector.Flush(); + } + } +} diff --git a/Source/Provers/SMTLib/ProverInterface.cs b/Source/Provers/SMTLib/ProverInterface.cs index 8ded5f10..e93ecee9 100644 --- a/Source/Provers/SMTLib/ProverInterface.cs +++ b/Source/Provers/SMTLib/ProverInterface.cs @@ -1,2588 +1,2588 @@ -//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Threading;
-using System.IO;
-//using ExternalProver;
-using System.Linq;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie.AbstractInterpretation;
-using Microsoft.Boogie;
-using Microsoft.Boogie.VCExprAST;
-using Microsoft.Boogie.Clustering;
-using Microsoft.Boogie.TypeErasure;
-using System.Text;
-
-using RPFP = Microsoft.Boogie.RPFP;
-
-namespace Microsoft.Boogie.SMTLib
-{
- public class SMTLibProcessTheoremProver : ProverInterface
- {
- private readonly SMTLibProverContext ctx;
- private VCExpressionGenerator gen;
- private readonly SMTLibProverOptions options;
- private bool usingUnsatCore;
- private RPFP rpfp = null;
-
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(ctx != null);
- Contract.Invariant(AxBuilder != null);
- Contract.Invariant(Namer != null);
- Contract.Invariant(DeclCollector != null);
- Contract.Invariant(cce.NonNullElements(Axioms));
- Contract.Invariant(cce.NonNullElements(TypeDecls));
- Contract.Invariant(_backgroundPredicates != null);
-
- }
-
-
- [NotDelayed]
- public SMTLibProcessTheoremProver(ProverOptions options, VCExpressionGenerator gen,
- SMTLibProverContext ctx)
- {
- Contract.Requires(options != null);
- Contract.Requires(gen != null);
- Contract.Requires(ctx != null);
-
- InitializeGlobalInformation();
-
- this.options = (SMTLibProverOptions)options;
- this.ctx = ctx;
- this.gen = gen;
- this.usingUnsatCore = false;
-
- SetupAxiomBuilder(gen);
-
- Namer = new SMTLibNamer();
- ctx.parent = this;
- this.DeclCollector = new TypeDeclCollector((SMTLibProverOptions)options, Namer);
-
- if (CommandLineOptions.Clo.PrintFixedPoint != null || CommandLineOptions.Clo.PrintConjectures != null)
- {
- declHandler = new MyDeclHandler();
- DeclCollector.SetDeclHandler(declHandler);
- }
-
- SetupProcess();
-
- if (CommandLineOptions.Clo.StratifiedInlining > 0 || CommandLineOptions.Clo.ContractInfer
- || CommandLineOptions.Clo.SecureVcGen != null)
- {
- // Prepare for ApiChecker usage
- if (options.LogFilename != null && currentLogFile == null)
- {
- currentLogFile = OpenOutputFile("");
- }
- PrepareCommon();
- }
- }
-
- private void SetupAxiomBuilder(VCExpressionGenerator gen)
- {
- switch (CommandLineOptions.Clo.TypeEncodingMethod)
- {
- case CommandLineOptions.TypeEncoding.Arguments:
- AxBuilder = new TypeAxiomBuilderArguments(gen);
- AxBuilder.Setup();
- break;
- case CommandLineOptions.TypeEncoding.Monomorphic:
- AxBuilder = new TypeAxiomBuilderPremisses(gen);
- break;
- default:
- AxBuilder = new TypeAxiomBuilderPremisses(gen);
- AxBuilder.Setup();
- break;
- }
- }
-
- ProcessStartInfo ComputeProcessStartInfo()
- {
- var path = this.options.ProverPath;
- switch (options.Solver) {
- case SolverKind.Z3:
- if (path == null)
- path = Z3.ExecutablePath();
- return SMTLibProcess.ComputerProcessStartInfo(path, "AUTO_CONFIG=false -smt2 -in");
- case SolverKind.CVC4:
- if (path == null)
- path = CVC4.ExecutablePath();
- return SMTLibProcess.ComputerProcessStartInfo(path, "--lang=smt --no-strict-parsing --no-condense-function-values --incremental");
- default:
- Debug.Assert(false);
- return null;
- }
- }
-
- void SetupProcess()
- {
- if (Process != null) return;
-
- var psi = ComputeProcessStartInfo();
- Process = new SMTLibProcess(psi, this.options);
- Process.ErrorHandler += this.HandleProverError;
- }
-
-
- void PossiblyRestart()
- {
- if (Process != null && Process.NeedsRestart) {
- Process.Close();
- Process = null;
- SetupProcess();
- Process.Send(common.ToString());
- }
- }
-
- public override ProverContext Context
- {
- get
- {
- Contract.Ensures(Contract.Result<ProverContext>() != null);
-
- return ctx;
- }
- }
-
- internal TypeAxiomBuilder AxBuilder { get; private set; }
- internal readonly UniqueNamer Namer;
- readonly TypeDeclCollector DeclCollector;
- protected SMTLibProcess Process;
- readonly List<string> proverErrors = new List<string>();
- readonly List<string> proverWarnings = new List<string>();
- readonly StringBuilder common = new StringBuilder();
- protected TextWriter currentLogFile;
- protected volatile ErrorHandler currentErrorHandler;
-
- private void FeedTypeDeclsToProver()
- {
- foreach (string s in DeclCollector.GetNewDeclarations()) {
- Contract.Assert(s != null);
- AddTypeDecl(s);
- }
- }
-
- private string Sanitize(string msg)
- {
- var idx = msg.IndexOf('\n');
- if (idx > 0)
- msg = msg.Replace("\r", "").Replace("\n", "\r\n");
- return msg;
- }
-
- public override void LogComment(string comment)
- {
- SendCommon("; " + comment);
- }
-
- private void SendCommon(string s)
- {
- Send(s, true);
- }
-
- protected void SendThisVC(string s)
- {
- Send(s, false);
- }
-
- private void Send(string s, bool isCommon)
- {
- s = Sanitize(s);
-
- if (isCommon)
- common.Append(s).Append("\r\n");
-
- if (Process != null)
- Process.Send(s);
- if (currentLogFile != null) {
- currentLogFile.WriteLine(s);
- currentLogFile.Flush();
- }
- }
-
- private void FindDependentTypes(Type type, List<CtorType> dependentTypes)
- {
- MapType mapType = type as MapType;
- if (mapType != null)
- {
- foreach (Type t in mapType.Arguments)
- {
- FindDependentTypes(t, dependentTypes);
- }
- FindDependentTypes(mapType.Result, dependentTypes);
- }
- CtorType ctorType = type as CtorType;
- if (ctorType != null && ctx.KnownDatatypeConstructors.ContainsKey(ctorType))
- {
- dependentTypes.Add(ctorType);
- }
- }
-
- private void PrepareCommon()
- {
- if (common.Length == 0)
- {
- SendCommon("(set-option :print-success false)");
- SendCommon("(set-info :smt-lib-version 2.0)");
- if (options.ProduceModel())
- SendCommon("(set-option :produce-models true)");
- foreach (var opt in options.SmtOptions)
- {
- SendCommon("(set-option :" + opt.Option + " " + opt.Value + ")");
- }
-
- if (!string.IsNullOrEmpty(options.Logic))
- {
- SendCommon("(set-logic " + options.Logic + ")");
- }
-
- // Set produce-unsat-cores last. It seems there's a bug in Z3 where if we set it earlier its value
- // gets reset by other set-option commands ( https://z3.codeplex.com/workitem/188 )
- if (CommandLineOptions.Clo.ContractInfer && (CommandLineOptions.Clo.UseUnsatCoreForContractInfer || CommandLineOptions.Clo.ExplainHoudini))
- {
- SendThisVC("(set-option :produce-unsat-cores true)");
- this.usingUnsatCore = true;
- }
-
- SendCommon("; done setting options\n");
- SendCommon(_backgroundPredicates);
-
- if (options.UseTickleBool)
- {
- SendCommon("(declare-fun tickleBool (Bool) Bool)");
- SendCommon("(assert (and (tickleBool true) (tickleBool false)))");
- }
-
- if (CommandLineOptions.Clo.RunDiagnosticsOnTimeout)
- {
- SendCommon("(declare-fun timeoutDiagnostics (Int) Bool)");
- }
-
- if (ctx.KnownDatatypeConstructors.Count > 0)
- {
- GraphUtil.Graph<CtorType> dependencyGraph = new GraphUtil.Graph<CtorType>();
- foreach (CtorType datatype in ctx.KnownDatatypeConstructors.Keys)
- {
- dependencyGraph.AddSource(datatype);
- foreach (Function f in ctx.KnownDatatypeConstructors[datatype])
- {
- List<CtorType> dependentTypes = new List<CtorType>();
- foreach (Variable v in f.InParams)
- {
- FindDependentTypes(v.TypedIdent.Type, dependentTypes);
- }
- foreach (CtorType result in dependentTypes)
- {
- dependencyGraph.AddEdge(datatype, result);
- }
- }
- }
- GraphUtil.StronglyConnectedComponents<CtorType> sccs = new GraphUtil.StronglyConnectedComponents<CtorType>(dependencyGraph.Nodes, dependencyGraph.Predecessors, dependencyGraph.Successors);
- sccs.Compute();
- foreach (GraphUtil.SCC<CtorType> scc in sccs)
- {
- string datatypeString = "";
- foreach (CtorType datatype in scc)
- {
- datatypeString += "(" + SMTLibExprLineariser.TypeToString(datatype) + " ";
- foreach (Function f in ctx.KnownDatatypeConstructors[datatype])
- {
- string quotedConstructorName = Namer.GetQuotedName(f, f.Name);
- if (f.InParams.Count == 0)
- {
- datatypeString += quotedConstructorName + " ";
- }
- else
- {
- datatypeString += "(" + quotedConstructorName + " ";
- foreach (Variable v in f.InParams)
- {
- string quotedSelectorName = Namer.GetQuotedName(v, v.Name + "#" + f.Name);
- datatypeString += "(" + quotedSelectorName + " " + DeclCollector.TypeToStringReg(v.TypedIdent.Type) + ") ";
- }
- datatypeString += ") ";
- }
- }
- datatypeString += ") ";
- }
- List<string> decls = DeclCollector.GetNewDeclarations();
- foreach (string decl in decls)
- {
- SendCommon(decl);
- }
- SendCommon("(declare-datatypes () (" + datatypeString + "))");
- }
- }
- if (CommandLineOptions.Clo.ProverPreamble != null)
- SendCommon("(include \"" + CommandLineOptions.Clo.ProverPreamble + "\")");
- }
-
- if (!AxiomsAreSetup)
- {
- var axioms = ctx.Axioms;
- var nary = axioms as VCExprNAry;
- if (nary != null && nary.Op == VCExpressionGenerator.AndOp)
- foreach (var expr in nary.UniformArguments)
- {
- var str = VCExpr2String(expr, -1);
- if (str != "true")
- AddAxiom(str);
- }
- else
- AddAxiom(VCExpr2String(axioms, -1));
- AxiomsAreSetup = true;
- }
- }
-
- public override int FlushAxiomsToTheoremProver()
- {
- // we feed the axioms when begincheck is called.
- return 0;
- }
-
- private void FlushAxioms()
- {
- TypeDecls.Iter(SendCommon);
- TypeDecls.Clear();
- foreach (string s in Axioms) {
- Contract.Assert(s != null);
- if (s != "true")
- SendCommon("(assert " + s + ")");
- }
- Axioms.Clear();
- //FlushPushedAssertions();
- }
-
- private void CloseLogFile()
- {
- if (currentLogFile != null) {
- currentLogFile.Close();
- currentLogFile = null;
- }
- }
-
- private void FlushLogFile()
- {
- if (currentLogFile != null) {
- currentLogFile.Flush();
- }
- }
-
- public override void Close()
- {
- base.Close();
- CloseLogFile();
- if (Process != null)
- Process.Close();
- }
-
- public override void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler)
- {
- //Contract.Requires(descriptiveName != null);
- //Contract.Requires(vc != null);
- //Contract.Requires(handler != null);
- rpfp = null;
-
- if (options.SeparateLogFiles) CloseLogFile(); // shouldn't really happen
-
- if (options.LogFilename != null && currentLogFile == null)
- {
- currentLogFile = OpenOutputFile(descriptiveName);
- currentLogFile.Write(common.ToString());
- }
-
- PrepareCommon();
-
- string vcString = "(assert (not\n" + VCExpr2String(vc, 1) + "\n))";
- FlushAxioms();
-
- PossiblyRestart();
-
- SendThisVC("(push 1)");
- SendThisVC("(set-info :boogie-vc-id " + SMTLibNamer.QuoteId(descriptiveName) + ")");
- SendThisVC(vcString);
- FlushLogFile();
-
- if (Process != null) {
- Process.PingPong(); // flush any errors
-
- if (Process.Inspector != null)
- Process.Inspector.NewProblem(descriptiveName, vc, handler);
- }
-
- SendThisVC("(check-sat)");
- FlushLogFile();
- }
-
- public override void Reset(VCExpressionGenerator gen)
- {
- if (options.Solver == SolverKind.Z3)
- {
- this.gen = gen;
- SendThisVC("(reset)");
-
- if (0 < common.Length)
- {
- var c = common.ToString();
- Process.Send(c);
- if (currentLogFile != null)
- {
- currentLogFile.WriteLine(c);
- }
- }
- }
- }
-
- public override void FullReset(VCExpressionGenerator gen)
- {
- if (options.Solver == SolverKind.Z3)
- {
- this.gen = gen;
- Namer.Reset();
- common.Clear();
- SetupAxiomBuilder(gen);
- Axioms.Clear();
- TypeDecls.Clear();
- AxiomsAreSetup = false;
- ctx.Reset();
- ctx.KnownDatatypeConstructors.Clear();
- ctx.parent = this;
- DeclCollector.Reset();
- SendThisVC("; did a full reset");
- }
- }
-
-
-
- private string StripCruft(string name){
- if(name.Contains("@@"))
- return name.Remove(name.LastIndexOf ("@@"));
- return name;
- }
-
- private class BadExprFromProver : Exception
- {
- };
-
- private delegate VCExpr ArgGetter (int pos);
-
- private delegate VCExpr[] ArgsGetter ();
-
- private delegate VCExprVar[] VarsGetter ();
-
- private VCExprOp VCStringToVCOp (string op)
- {
- switch (op) {
- case "+" :
- return VCExpressionGenerator.AddIOp;
- case "-" :
- return VCExpressionGenerator.SubIOp;
- case "*" :
- return VCExpressionGenerator.MulIOp;
- case "div" :
- return VCExpressionGenerator.DivIOp;
- case "=" :
- return VCExpressionGenerator.EqOp;
- case "<=" :
- return VCExpressionGenerator.LeOp;
- case "<" :
- return VCExpressionGenerator.LtOp;
- case ">=" :
- return VCExpressionGenerator.GeOp;
- case ">" :
- return VCExpressionGenerator.GtOp;
- case "and" :
- return VCExpressionGenerator.AndOp;
- case "or" :
- return VCExpressionGenerator.OrOp;
- case "not" :
- return VCExpressionGenerator.NotOp;
- case "ite" :
- return VCExpressionGenerator.IfThenElseOp;
- default:
- return null;
- }
- }
-
- private class MyDeclHandler : TypeDeclCollector.DeclHandler {
- public Dictionary<string,VCExprVar> var_map = new Dictionary<string, VCExprVar>();
- public Dictionary<string,Function> func_map = new Dictionary<string, Function>();
- public override void VarDecl(VCExprVar v){
- var_map[v.Name] = v;
- }
- public override void FuncDecl(Function f){
- func_map[f.Name] = f;
- }
- public MyDeclHandler() {
- }
- }
-
- private MyDeclHandler declHandler = null;
-
- private VCExprVar SExprToVar (SExpr e)
- {
- if(e.Arguments.Count() != 1){
- HandleProverError ("Prover error: bad quantifier syntax");
- throw new BadExprFromProver ();
- }
- string vname = StripCruft(e.Name);
- SExpr vtype = e[0];
- switch(vtype.Name){
- case "Int":
- return gen.Variable(vname,Type.Int);
- case "Bool":
- return gen.Variable (vname,Type.Bool);
- case "Array":{
- // TODO: handle more general array types
- var idxType = Type.Int; // well, could be something else
- var valueType =
- (vtype.Arguments[1].Name == "Int") ? Type.Int : Type.Bool;
- var types = new List<Type>();
- types.Add(idxType);
- return gen.Variable (vname, new MapType(Token.NoToken,new List<TypeVariable>(),types,valueType));
- }
- default: {
- HandleProverError ("Prover error: bad type: " + vtype.Name);
- throw new BadExprFromProver ();
- }
- }
- }
-
- private VCExpr MakeBinary(VCExprOp op, VCExpr [] args)
- {
- if (args.Count() == 0)
- {
- // with zero args we need the identity of the op
- if (op == VCExpressionGenerator.AndOp)
- return VCExpressionGenerator.True;
- if (op == VCExpressionGenerator.OrOp)
- return VCExpressionGenerator.False;
- if (op == VCExpressionGenerator.AddIOp)
- {
- Microsoft.Basetypes.BigNum x = Microsoft.Basetypes.BigNum.ZERO;
- return gen.Integer(x);
- }
- HandleProverError("Prover error: bad expression ");
- throw new BadExprFromProver();
- }
- var temp = args[0];
- for (int i = 1; i < args.Count(); i++)
- temp = gen.Function(op, temp, args[i]);
- return temp;
- }
-
- protected VCExpr SExprToVCExpr (SExpr e, Dictionary<string,VCExpr> bound)
- {
- if (e.Arguments.Count() == 0) {
- var name = StripCruft(e.Name);
- if (name [0] >= '0' && name [0] <= '9') {
- Microsoft.Basetypes.BigNum x = Microsoft.Basetypes.BigNum.FromString(name);
- return gen.Integer (x);
- }
- if (bound.ContainsKey (name)) {
- return bound [name];
- }
- if(name == "true")
- return VCExpressionGenerator.True;
- if(name == "false")
- return VCExpressionGenerator.False;
- if(declHandler.var_map.ContainsKey(name))
- return declHandler.var_map[name];
- HandleProverError ("Prover error: unknown symbol:" + name);
- //throw new BadExprFromProver ();
- var v = gen.Variable(name, Type.Int);
- bound.Add(name, v);
- return v;
- }
- ArgGetter g = i => SExprToVCExpr (e [i], bound);
- ArgsGetter ga = () => e.Arguments.Select (x => SExprToVCExpr (x, bound)).ToArray ();
- VarsGetter gb = () => e [0].Arguments.Select (x => SExprToVar (x)).ToArray ();
- switch (e.Name) {
- case "select" :
- return gen.Select (ga ());
- case "store" :
- return gen.Store (ga ());
- case "forall":
- case "exists":
- {
- var binds = e.Arguments[0];
- var vcbinds = new List<VCExprVar>();
- var bound_copy = new Dictionary<string, VCExpr>(bound);
- for (int i = 0; i < binds.Arguments.Count(); i++)
- {
- var bind = binds.Arguments[i];
- var symb = StripCruft(bind.Name);
- var vcv = SExprToVar(bind);
- vcbinds.Add(vcv);
- bound[symb] = vcv;
- }
- var body = g(1);
- if (e.Name == "forall")
- body = gen.Forall(vcbinds, new List<VCTrigger>(), body);
- else
- body = gen.Exists(vcbinds, new List<VCTrigger>(), body);
- bound = bound_copy;
- return body;
- }
- case "-" : // have to deal with unary case
- {
- if(e.ArgCount == 1){
- var args = new VCExpr[2];
- args[0] = gen.Integer (Microsoft.Basetypes.BigNum.ZERO);
- args[1] = g(0);
- return gen.Function(VCStringToVCOp("-"),args);
- }
- return gen.Function(VCStringToVCOp("-"),ga());
- }
- case "!" : // this is commentary
- return g(0);
- case "let" : {
- // we expand lets exponentially since there is no let binding in Boogie surface syntax
- bool expand_lets = true;
- var binds = e.Arguments[0];
- var vcbinds = new List<VCExprLetBinding>();
- var bound_copy = new Dictionary<string, VCExpr>(bound);
- for(int i = 0; i < binds.Arguments.Count(); i++){
- var bind = binds.Arguments[i];
- var symb = bind.Name;
- var def = bind.Arguments[0];
- var vce = SExprToVCExpr(def, bound);
- var vcv = gen.Variable(symb,vce.Type);
- var vcb = gen.LetBinding(vcv,vce);
- vcbinds.Add (vcb);
- bound[symb] = expand_lets ? vce : vcv;
- }
- var body = g(1);
- if(!expand_lets)
- body = gen.Let(vcbinds,body);
- bound = bound_copy;
- return body;
- }
-
- default: {
- var op = VCStringToVCOp (e.Name);
- if (op == null) {
- var name = StripCruft(e.Name);
- if(declHandler.func_map.ContainsKey(name)){
- Function f = declHandler.func_map[name];
- return gen.Function (f, ga());
- }
- HandleProverError ("Prover error: unknown operator:" + e.Name);
- throw new BadExprFromProver ();
- }
- if(op.Arity == 2)
- return MakeBinary (op, ga ());
- return gen.Function(op, ga());
- }
- }
- }
-
- private void SExprToSoln (SExpr resp,
- Dictionary<int,Dictionary<string,string>> varSubst)
- {
- Dictionary<string, RPFP.Node> pmap = new Dictionary<string,RPFP.Node> ();
-
- foreach (var node in rpfp.nodes)
- pmap.Add ((node.Name as VCExprBoogieFunctionOp).Func.Name, node);
-
- var lines = resp.Arguments;
-
- // get all the predicate definitions
- for (int i = 0; i < lines.Length; i++) {
- var line = lines [i];
- string pname;
- RPFP.Transformer annot;
- GetDefun(line, out pname, out annot);
-
- if(pmap.ContainsKey(pname)){
- var node = pmap[pname];
- node.Annotation = annot;
- }
- else if(pname[0] != '@'){ // if not an internal symbol
- HandleProverError ("Prover error: got unknown predicate:" + pname);
- throw new BadExprFromProver ();
- }
- }
-
- }
-
- private void GetDefun(SExpr line, out string pname, out RPFP.Transformer annot)
- {
- if (line.Name != "define-fun")
- {
- HandleProverError("Prover error: expected define-fun but got:" + line.Name);
- throw new BadExprFromProver();
- }
- if (line.ArgCount != 4)
- {
- HandleProverError("Prover error: define-fun has wrong number of arguments");
- throw new BadExprFromProver();
- }
- pname = StripCruft(line.Arguments[0].Name);
- var pvars = line.Arguments[1];
- var pbody = line.Arguments[3]; // range has to be Bool
- var binding = new Dictionary<string, VCExpr>();
- var pvs = new List<VCExpr>();
- foreach (var b in pvars.Arguments)
- {
- var e = SExprToVar(b);
- pvs.Add(e);
- binding.Add(StripCruft(b.Name), e);
- }
- VCExpr bexpr = SExprToVCExpr(pbody, binding);
-
- annot = rpfp.CreateRelation(pvs.ToArray(), bexpr);
- }
-
- private RPFP.Node SExprToCex(SExpr resp, ErrorHandler handler,
- Dictionary<int,Dictionary<string,string>> varSubst)
- {
- Dictionary<string, RPFP.Node> nmap = new Dictionary<string,RPFP.Node>();
- Dictionary<string, RPFP.Node> pmap = new Dictionary<string,RPFP.Node>();
-
- foreach(var node in rpfp.nodes)
- pmap.Add((node.Name as VCExprBoogieFunctionOp).Func.Name,node);
-
- RPFP.Node topnode = null;
- var lines = resp.Arguments;
-
- // last line of derivation is from query, skip it
- for (int i = 0; i < lines.Length-1; i++)
- {
- var line = lines[i];
- if (line.ArgCount != 6)
- {
- HandleProverError("bad derivation line from prover: " + line.ToString());
- return null;
- }
- var name = line[0];
- var conseq = line[1];
- var rule = line[2];
- var subst = line[3];
- var labs = line[4];
- var refs = line[5];
- var predName = conseq.Name;
- {
- string spacer = "@@"; // Hack! UniqueNamer is adding these and I can't stop it!
- int pos = predName.LastIndexOf(spacer);
- if (pos >= 0)
- predName = predName.Substring(0, pos);
- }
- RPFP.Node node = null;
- if (!pmap.TryGetValue(predName, out node))
- {
- HandleProverError("unknown predicate from prover: " + predName.ToString());
- return null;
- }
- RPFP.Node cexnode = rpfp.CloneNode(node);
- cexnode.map = node;
- nmap.Add(name.Name, cexnode);
- List<RPFP.Node> Chs = new List<RPFP.Node>();
-
- if (refs.Name != "ref")
- {
- HandleProverError("bad references from prover: " + refs.ToString());
- return null;
- }
- foreach (var c in refs.Arguments)
- {
- if (c.Name == "true")
- Chs.Add(null);
- else
- {
- RPFP.Node ch = null;
- if (!nmap.TryGetValue(c.Name, out ch))
- {
- HandleProverError("unknown reference from prover: " + c.ToString());
- return null;
- }
- Chs.Add(ch);
- }
- }
-
- if (!rule.Name.StartsWith("rule!"))
- {
- HandleProverError("bad rule name from prover: " + refs.ToString());
- return null;
- }
- int ruleNum = Convert.ToInt32(rule.Name.Substring(5)) - 1;
- if (ruleNum < 0 || ruleNum > rpfp.edges.Count)
- {
- HandleProverError("bad rule name from prover: " + refs.ToString());
- return null;
- }
- RPFP.Edge orig_edge = rpfp.edges[ruleNum];
- RPFP.Edge e = rpfp.CreateEdge(cexnode, orig_edge.F, Chs.ToArray());
- e.map = orig_edge;
- topnode = cexnode;
-
- if (labs.Name != "labels")
- {
- HandleProverError("bad labels from prover: " + labs.ToString());
- return null;
- }
- e.labels = new HashSet<string>();
- foreach (var l in labs.Arguments)
- e.labels.Add(l.Name);
-
- if (subst.Name != "subst")
- {
- HandleProverError("bad subst from prover: " + subst.ToString());
- return null;
- }
- Dictionary<string, string> dict = new Dictionary<string, string>();
- varSubst[e.number] = dict;
- foreach (var s in subst.Arguments)
- {
- if (s.Name != "=" || s.Arguments.Length != 2)
- {
- HandleProverError("bad equation from prover: " + s.ToString());
- return null;
- }
- string uniqueName = s.Arguments[0].Name;
- string spacer = "@@"; // Hack! UniqueNamer is adding these and I can't stop it!
- int pos = uniqueName.LastIndexOf(spacer);
- if (pos >= 0)
- uniqueName = uniqueName.Substring(0, pos);
- dict.Add(uniqueName, s.Arguments[1].ToString());
- }
-
- }
- if (topnode == null)
- {
- HandleProverError("empty derivation from prover: " + resp.ToString());
- }
- return topnode;
- }
-
- private Model SExprToModel(SExpr resp, ErrorHandler handler)
- {
- // Concatenate all the arguments
- string modelString = resp[0].Name;
- // modelString = modelString.Substring(7, modelString.Length - 8); // remove "(model " and final ")"
- var models = Model.ParseModels(new StringReader("Error model: \n" + modelString));
- if (models == null || models.Count == 0)
- {
- HandleProverError("no model from prover: " + resp.ToString());
- }
- return models[0];
- }
-
- private string QuantifiedVCExpr2String(VCExpr x)
- {
- return VCExpr2String(x, 1);
-#if false
- if (!(x is VCExprQuantifier))
- return VCExpr2String(x, 1);
- VCExprQuantifier node = (x as VCExprQuantifier);
- if(node.BoundVars.Count == 0)
- return VCExpr2String(x, 1);
-
- StringWriter wr = new StringWriter();
-
- string kind = node.Quan == Quantifier.ALL ? "forall" : "exists";
- wr.Write("({0} (", kind);
-
- for (int i = 0; i < node.BoundVars.Count; i++)
- {
- VCExprVar var = node.BoundVars[i];
- Contract.Assert(var != null);
- string printedName = Namer.GetQuotedName(var, var.Name);
- Contract.Assert(printedName != null);
- wr.Write("({0} {1}) ", printedName, SMTLibExprLineariser.TypeToString(var.Type));
- }
-
- wr.Write(") ");
- wr.Write(VCExpr2String(node.Body, 1));
- wr.Write(")");
- string res = wr.ToString();
- return res;
-#endif
- }
-
- public override Outcome CheckRPFP(string descriptiveName, RPFP _rpfp, ErrorHandler handler,
- out RPFP.Node cex,
- Dictionary<int, Dictionary<string, string>> varSubst,
- Dictionary<string, int> extra_bound)
- {
- //Contract.Requires(descriptiveName != null);
- //Contract.Requires(vc != null);
- //Contract.Requires(handler != null);
- rpfp = _rpfp;
- cex = null;
-
-
- if (options.SeparateLogFiles) CloseLogFile(); // shouldn't really happen
-
- if (options.LogFilename != null && currentLogFile == null)
- {
- currentLogFile = OpenOutputFile(descriptiveName);
- currentLogFile.Write(common.ToString());
- }
-
- PrepareCommon();
-
- Push();
- SendThisVC("(fixedpoint-push)");
- foreach (var node in rpfp.nodes)
- {
- DeclCollector.RegisterRelation((node.Name as VCExprBoogieFunctionOp).Func);
- }
-
- LineariserOptions.Default.LabelsBelowQuantifiers = true;
- List<string> ruleStrings = new List<string>();
- var recursion_bound = CommandLineOptions.Clo.RecursionBound;
- foreach (var edge in rpfp.edges)
- {
- string node_name = (edge.Parent.Name as VCExprBoogieFunctionOp).Func.Name;
- string rule_name = "rule_" + edge.number.ToString();
- string rec_bound = "";
- if(extra_bound != null && extra_bound.ContainsKey(node_name))
- rec_bound = (recursion_bound + extra_bound[node_name]).ToString();
- string ruleString = "(rule " + QuantifiedVCExpr2String(rpfp.GetRule(edge)) + " " + rule_name + " " + rec_bound + "\n)";
- ruleStrings.Add(ruleString);
- }
- string queryString = "(query " + QuantifiedVCExpr2String(rpfp.GetQuery()) + "\n :engine duality\n :print-certificate true\n";
-
-#if true
- if (CommandLineOptions.Clo.StratifiedInlining != 0)
- queryString += " :stratified-inlining true\n";
- if (CommandLineOptions.Clo.RecursionBound > 0)
- queryString += " :recursion-bound " + Convert.ToString(CommandLineOptions.Clo.RecursionBound) + "\n";
-#endif
- queryString += ")";
- LineariserOptions.Default.LabelsBelowQuantifiers = false;
- FlushAxioms();
-
- PossiblyRestart();
-
- SendThisVC("(set-info :boogie-vc-id " + SMTLibNamer.QuoteId(descriptiveName) + ")");
- foreach(var rs in ruleStrings)
- SendThisVC(rs);
- FlushLogFile();
-
- if (Process != null)
- {
- Process.PingPong(); // flush any errors
-
-#if false
- // TODO: this is not going to work
- if (Process.Inspector != null)
- Process.Inspector.NewProblem(descriptiveName, vc, handler);
-#endif
- }
-
- SendThisVC(queryString);
- FlushLogFile();
-
- var result = Outcome.Undetermined;
-
- if (Process != null)
- {
-
- var resp = Process.GetProverResponse();
-
- if (proverErrors.Count > 0)
- {
- result = Outcome.Undetermined;
- foreach (var err in proverErrors)
- {
- if (err.Contains("canceled"))
- {
- result = Outcome.TimeOut;
- }
- }
- }
- else if(resp == null)
- HandleProverError("Prover did not respond");
- else switch (resp.Name)
- {
- case "unsat":
- result = Outcome.Valid;
- break;
- case "sat":
- result = Outcome.Invalid;
- break;
- case "unknown":
- result = Outcome.Invalid;
- break;
- case "bounded":
- result = Outcome.Bounded;
- break;
- case "error":
- if (resp.ArgCount > 0 && resp.Arguments[0].Name.Contains("canceled"))
- {
- result = Outcome.TimeOut;
- }
- else
- {
- HandleProverError("Prover error: " + resp.Arguments[0]);
- result = Outcome.Undetermined;
- }
- break;
- default:
- HandleProverError("Unexpected prover response: " + resp.ToString());
- break;
- }
-
- switch (result)
- {
- case Outcome.Invalid:
- {
- resp = Process.GetProverResponse();
- if (resp.Name == "derivation")
- {
- cex = SExprToCex(resp, handler,varSubst);
- }
- else
- HandleProverError("Unexpected prover response: " + resp.ToString());
- resp = Process.GetProverResponse();
- if (resp.Name == "model")
- {
- var model = SExprToModel(resp, handler);
- cex.owner.SetBackgroundModel(model);
- }
- else
- HandleProverError("Unexpected prover response: " + resp.ToString());
- break;
- }
- case Outcome.Valid:
- case Outcome.Bounded:
- {
- resp = Process.GetProverResponse();
- if (resp.Name == "fixedpoint")
- {
- // only get the response if we need it
- if(CommandLineOptions.Clo.PrintFixedPoint != null)
- SExprToSoln(resp, varSubst);
- }
- else
- HandleProverError("Unexpected prover response: " + resp.ToString());
- break;
- }
- default:
- break;
- }
-
-#if false
- while (true)
- {
- resp = Process.GetProverResponse();
- if (resp == null || Process.IsPong(resp))
- break;
- HandleProverError("Unexpected prover response: " + resp.ToString());
- }
-#endif
- }
- SendThisVC("(fixedpoint-pop)");
- Pop();
- AxiomsAreSetup = false;
-
- if (CommandLineOptions.Clo.PrintConjectures != null)
- {
- ReadConjectures(CommandLineOptions.Clo.PrintConjectures);
- }
-
- return result;
- }
-
- class MyFileParser : SExpr.Parser
- {
- SMTLibProcessTheoremProver parent;
-
- public MyFileParser(System.IO.StreamReader _sr, SMTLibProcessTheoremProver _parent)
- : base(_sr)
- {
- parent = _parent;
- }
- public override void ParseError(string msg)
- {
- parent.HandleProverError("Error in conjecture file from prover: " + msg);
- }
- }
-
- void ReadConjectures(string filename)
- {
- try
- {
- System.IO.StreamReader sr = new StreamReader(filename + ".tmp");
- SExpr.Parser p = new MyFileParser(sr, this);
- var sexps = p.ParseSExprs(false);
- Dictionary<string, RPFP.Node> pmap = GetNodeMap();
- foreach (var e in sexps)
- {
- string pname;
- RPFP.Transformer annot;
- GetDefun(e, out pname, out annot);
-
- if (pmap.ContainsKey(pname))
- {
- var c = new RPFP.Conjecture();
- c.node = pmap[pname];
- c.bound = annot;
- rpfp.conjectures.Add(c);
- }
- else if (pname[0] != '@')
- { // if not an internal symbol
- HandleProverError("Prover error: got unknown predicate:" + pname);
- throw new BadExprFromProver();
- }
- }
- sr.Close();
- }
- catch (Exception)
- {
- HandleProverError("No conjecture file from prover");
- throw new BadExprFromProver();
- }
- }
-
- private Dictionary<string, RPFP.Node> GetNodeMap()
- {
- Dictionary<string, RPFP.Node> pmap = new Dictionary<string, RPFP.Node>();
- foreach (var node in rpfp.nodes)
- pmap.Add((node.Name as VCExprBoogieFunctionOp).Func.Name, node);
- return pmap;
- }
-
- private static HashSet<string> usedLogNames = new HashSet<string>();
-
- private TextWriter OpenOutputFile(string descriptiveName)
- {
- Contract.Requires(descriptiveName != null);
- Contract.Ensures(Contract.Result<TextWriter>() != null);
-
- string filename = options.LogFilename;
- filename = Helpers.SubstituteAtPROC(descriptiveName, cce.NonNull(filename));
- var curFilename = filename;
-
- lock (usedLogNames) {
- int n = 1;
- while (usedLogNames.Contains(curFilename)) {
- curFilename = filename + "." + n++;
- }
- usedLogNames.Add(curFilename);
- }
-
- return new StreamWriter(curFilename, false);
- }
-
- private void FlushProverWarnings()
- {
- var handler = currentErrorHandler;
- if (handler != null) {
- lock (proverWarnings) {
- proverWarnings.Iter(handler.OnProverWarning);
- proverWarnings.Clear();
- }
- }
- }
-
- protected void HandleProverError(string s)
- {
- s = s.Replace("\r", "");
- lock (proverWarnings) {
- while (s.StartsWith("WARNING: ")) {
- var idx = s.IndexOf('\n');
- var warn = s;
- if (idx > 0) {
- warn = s.Substring(0, idx);
- s = s.Substring(idx + 1);
- } else {
- s = "";
- }
- warn = warn.Substring(9);
- proverWarnings.Add(warn);
- }
- }
-
- FlushProverWarnings();
-
- if (s == "") return;
-
- lock (proverErrors) {
- proverErrors.Add(s);
- Console.WriteLine("Prover error: " + s);
- }
- }
-
- [NoDefaultContract]
- public override Outcome CheckOutcome(ErrorHandler handler, int taskID = -1)
- {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
-
- var result = CheckOutcomeCore(handler, taskID: taskID);
- SendThisVC("(pop 1)");
- FlushLogFile();
-
- return result;
- }
-
- [NoDefaultContract]
- public override Outcome CheckOutcomeCore(ErrorHandler handler, int taskID = -1)
- {
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
-
- var result = Outcome.Undetermined;
-
- if (Process == null)
- return result;
-
- try {
- currentErrorHandler = handler;
- FlushProverWarnings();
-
- int errorLimit;
- if (CommandLineOptions.Clo.ConcurrentHoudini) {
- Contract.Assert(taskID >= 0);
- errorLimit = CommandLineOptions.Clo.Cho[taskID].ProverCCLimit;
- } else {
- errorLimit = CommandLineOptions.Clo.ProverCCLimit;
- }
-
- if (errorLimit < 1)
- errorLimit = 1;
-
- int errorsLeft = errorLimit;
-
- var globalResult = Outcome.Undetermined;
-
- while (true) {
- string[] labels = null;
- bool popLater = false;
-
- try {
- errorsLeft--;
-
- result = GetResponse();
-
- if (CommandLineOptions.Clo.RunDiagnosticsOnTimeout && result == Outcome.TimeOut)
- {
- #region Run timeout diagnostics
-
- if (CommandLineOptions.Clo.TraceDiagnosticsOnTimeout)
- {
- Console.Out.WriteLine("Starting timeout diagnostics with initial time limit {0}.", options.TimeLimit);
- }
-
- SendThisVC("; begin timeout diagnostics");
-
- var start = DateTime.UtcNow;
- var unverified = new SortedSet<int>(ctx.TimeoutDiagnosticIDToAssertion.Keys);
- var timedOut = new SortedSet<int>();
- int frac = 2;
- int queries = 0;
- int timeLimitPerAssertion = 0 < options.TimeLimit ? (options.TimeLimit / 100) * CommandLineOptions.Clo.TimeLimitPerAssertionInPercent : 1000;
- while (true)
- {
- int rem = unverified.Count;
- if (rem == 0)
- {
- if (0 < timedOut.Count)
- {
- result = CheckSplit(timedOut, ref popLater, options.TimeLimit, timeLimitPerAssertion, ref queries);
- if (result == Outcome.Valid)
- {
- timedOut.Clear();
- }
- else if (result == Outcome.TimeOut)
- {
- // Give up and report which assertions were not verified.
- var cmds = timedOut.Select(id => ctx.TimeoutDiagnosticIDToAssertion[id]);
-
- if (cmds.Any())
- {
- handler.OnResourceExceeded("timeout after running diagnostics", cmds);
- }
- }
- }
- else
- {
- result = Outcome.Valid;
- }
- break;
- }
-
- // TODO(wuestholz): Try out different ways for splitting up the work (e.g., randomly).
- var cnt = Math.Max(1, rem / frac);
- // It seems like assertions later in the control flow have smaller indexes.
- var split = new SortedSet<int>(unverified.Where((val, idx) => (rem - idx - 1) < cnt));
- Contract.Assert(0 < split.Count);
- var splitRes = CheckSplit(split, ref popLater, timeLimitPerAssertion, timeLimitPerAssertion, ref queries);
- if (splitRes == Outcome.Valid)
- {
- unverified.ExceptWith(split);
- frac = 1;
- }
- else if (splitRes == Outcome.Invalid)
- {
- result = splitRes;
- break;
- }
- else if (splitRes == Outcome.TimeOut)
- {
- if (2 <= frac && (4 <= (rem / frac)))
- {
- frac *= 4;
- }
- else if (2 <= (rem / frac))
- {
- frac *= 2;
- }
- else
- {
- timedOut.UnionWith(split);
- unverified.ExceptWith(split);
- frac = 1;
- }
- }
- else
- {
- break;
- }
- }
-
- unverified.UnionWith(timedOut);
-
- var end = DateTime.UtcNow;
-
- SendThisVC("; end timeout diagnostics");
-
- if (CommandLineOptions.Clo.TraceDiagnosticsOnTimeout)
- {
- Console.Out.WriteLine("Terminated timeout diagnostics after {0:F0} ms and {1} prover queries.", end.Subtract(start).TotalMilliseconds, queries);
- Console.Out.WriteLine("Outcome: {0}", result);
- Console.Out.WriteLine("Unverified assertions: {0} (of {1})", unverified.Count, ctx.TimeoutDiagnosticIDToAssertion.Keys.Count);
-
- string filename = "unknown";
- var assertion = ctx.TimeoutDiagnosticIDToAssertion.Values.Select(t => t.Item1).FirstOrDefault(a => a.tok != null && a.tok != Token.NoToken && a.tok.filename != null);
- if (assertion != null)
- {
- filename = assertion.tok.filename;
- }
- File.AppendAllText("timeouts.csv", string.Format(";{0};{1};{2:F0};{3};{4};{5};{6}\n", filename, options.TimeLimit, end.Subtract(start).TotalMilliseconds, queries, result, unverified.Count, ctx.TimeoutDiagnosticIDToAssertion.Keys.Count));
- }
-
- #endregion
- }
-
- if (globalResult == Outcome.Undetermined)
- globalResult = result;
-
- if (result == Outcome.Invalid || result == Outcome.TimeOut || result == Outcome.OutOfMemory) {
- IList<string> xlabels;
- if (CommandLineOptions.Clo.UseLabels) {
- labels = GetLabelsInfo();
- if (labels == null)
- {
- xlabels = new string[] { };
- }
- else
- {
- xlabels = labels.Select(a => a.Replace("@", "").Replace("+", "")).ToList();
- }
- }
- else if(CommandLineOptions.Clo.SIBoolControlVC) {
- labels = new string[0];
- xlabels = labels;
- } else {
- labels = CalculatePath(handler.StartingProcId());
- xlabels = labels;
- }
- Model model = (result == Outcome.TimeOut || result == Outcome.OutOfMemory) ? null :
- GetErrorModel();
- handler.OnModel(xlabels, model, result);
- }
-
- if (labels == null || !labels.Any() || errorsLeft == 0) break;
- } finally {
- if (popLater)
- {
- SendThisVC("(pop 1)");
- }
- }
-
- if (CommandLineOptions.Clo.UseLabels) {
- var negLabels = labels.Where(l => l.StartsWith("@")).ToArray();
- var posLabels = labels.Where(l => !l.StartsWith("@"));
- Func<string, string> lbl = (s) => SMTLibNamer.QuoteId(SMTLibNamer.LabelVar(s));
- if (!options.MultiTraces)
- posLabels = Enumerable.Empty<string>();
- var conjuncts = posLabels.Select(s => "(not " + lbl(s) + ")").Concat(negLabels.Select(lbl)).ToArray();
- string expr = conjuncts.Length == 1 ? conjuncts[0] : ("(or " + conjuncts.Concat(" ") + ")"); ;
- if (!conjuncts.Any())
- {
- expr = "false";
- }
- SendThisVC("(assert " + expr + ")");
- SendThisVC("(check-sat)");
- }
- else {
- string source = labels[labels.Length - 2];
- string target = labels[labels.Length - 1];
- SendThisVC("(assert (not (= (ControlFlow 0 " + source + ") (- " + target + "))))");
- SendThisVC("(check-sat)");
- }
- }
-
- FlushLogFile();
-
- if (CommandLineOptions.Clo.RestartProverPerVC && Process != null)
- Process.NeedsRestart = true;
-
- return globalResult;
-
- } finally {
- currentErrorHandler = null;
- }
- }
-
- private Outcome CheckSplit(SortedSet<int> split, ref bool popLater, int timeLimit, int timeLimitPerAssertion, ref int queries)
- {
- var tla = timeLimitPerAssertion * split.Count;
-
- if (popLater)
- {
- SendThisVC("(pop 1)");
- }
-
- SendThisVC("(push 1)");
- SendThisVC(string.Format("(set-option :{0} {1})", Z3.SetTimeoutOption(), (0 < tla && tla < timeLimit) ? tla : timeLimit));
- popLater = true;
-
- SendThisVC(string.Format("; checking split VC with {0} unverified assertions", split.Count));
- var expr = VCExpressionGenerator.True;
- foreach (var i in ctx.TimeoutDiagnosticIDToAssertion.Keys)
- {
- var lit = VCExprGen.Function(VCExpressionGenerator.TimeoutDiagnosticsOp, VCExprGen.Integer(Microsoft.Basetypes.BigNum.FromInt(i)));
- if (split.Contains(i)) {
- lit = VCExprGen.Not(lit);
- }
- expr = VCExprGen.AndSimp(expr, lit);
- }
- SendThisVC("(assert " + VCExpr2String(expr, 1) + ")");
- if (options.Solver == SolverKind.Z3)
- {
- SendThisVC("(apply (then (using-params propagate-values :max_rounds 1) simplify) :print false)");
- }
- FlushLogFile();
- SendThisVC("(check-sat)");
- queries++;
- return GetResponse();
- }
-
- public override string[] CalculatePath(int controlFlowConstant) {
- SendThisVC("(get-value ((ControlFlow " + controlFlowConstant + " 0)))");
- var path = new List<string>();
- while (true) {
- var resp = Process.GetProverResponse();
- if (resp == null) break;
- if (!(resp.Name == "" && resp.ArgCount == 1)) break;
- resp = resp.Arguments[0];
- if (!(resp.Name == "" && resp.ArgCount == 2)) break;
- resp = resp.Arguments[1];
- var v = resp.Name;
- if (v == "-" && resp.ArgCount == 1) {
- v = resp.Arguments[0].Name;
- path.Add(v);
- break;
- }
- else if (resp.ArgCount != 0)
- break;
- path.Add(v);
- SendThisVC("(get-value ((ControlFlow " + controlFlowConstant + " " + v + ")))");
- }
- return path.ToArray();
- }
-
-
- private class SMTErrorModelConverter {
- private struct SMTDataType {
- public string Constructor;
- public List<SExpr> Types;
- }
-
- private List<SExpr> ErrorModelTodo;
- private SMTLibProcessTheoremProver Parent;
- private StringBuilder ErrorModel = new StringBuilder();
- private HashSet<SExpr> TopLevelProcessed = new HashSet<SExpr>();
- private int NumNewArrays = 0;
- private Dictionary<string, int> SortSet = new Dictionary<string, int>();
- private Dictionary<string, SMTDataType> DataTypes = new Dictionary<string, SMTDataType>();
- private Dictionary<string, SExpr> Functions = new Dictionary<string, SExpr>();
-
- public SMTErrorModelConverter(SExpr _ErrorModel, SMTLibProcessTheoremProver _Parent) {
- ErrorModelTodo = _ErrorModel.Arguments.ToList();;
- Parent = _Parent;
- }
-
- public string Convert() {
- ConvertErrorModel(ErrorModel);
- return ErrorModel.ToString();
- }
-
- bool isConstArray(SExpr element, SExpr type) {
- if (type.Name != "Array")
- return false;
-
- if (element.Name == "__array_store_all__") // CVC4 1.4
- return true;
- else if (element.Name == "" && element[0].Name == "as" &&
- element[0][0].Name == "const") // CVC4 > 1.4
- return true;
-
- return false;
- }
-
- SExpr getConstArrayElement(SExpr element) {
- if (element.Name == "__array_store_all__") // CVC4 1.4
- return element[1];
- else if (element.Name == "" && element[0].Name == "as" &&
- element[0][0].Name == "const") // CVC4 > 1.4
- return element[1];
-
- Parent.HandleProverError("Unexpected value: " + element);
- throw new BadExprFromProver ();
- }
-
- void ConstructComplexValue(SExpr element, SExpr type, StringBuilder m) {
- if (type.Name == "Array") {
- if (element.Name == "store" || isConstArray(element, type)) {
- NumNewArrays++;
- m.Append("as-array[k!" + NumNewArrays + ']');
- SExpr[] args = {new SExpr("k!" + NumNewArrays), new SExpr(""), type, element};
- var newElement = new SExpr("define-fun", args);
- TopLevelProcessed.Add(newElement);
- ErrorModelTodo.Add(newElement);
- return;
- }
- }
-
- ConstructSimpleValue(element, type, m);
- }
-
- void ConstructSimpleValue(SExpr element, SExpr type, StringBuilder m) {
- if (type.Name == "Bool" && element.ArgCount == 0) {
- m.Append(element.ToString());
- return;
- }
-
- if (type.Name == "Int") {
- if (element.ArgCount == 0) {
- m.Append(element.ToString());
- return;
- } else if (element.Name == "-" && element.ArgCount == 1) {
- m.Append(element.ToString());
- return;
- }
- }
-
- if (type.Name == "_" && type.ArgCount == 2 && type[0].Name == "BitVec") {
- if (element.Name == "_" && element.ArgCount == 2 &&
- element[0].Name.StartsWith("bv") && element[0].ArgCount == 0 &&
- element[1].Name == type.Arguments[1].Name && element[1].ArgCount == 0) {
- m.Append(element[0].Name + '[' + element[1].Name + ']');
- return;
- }
- }
-
- if (type.Name == "Array") {
- while (element.Name == "store") {
- ConstructComplexValue(element[1], type[0], m);
- m.Append(" -> ");
- ConstructComplexValue(element[2], type[1], m);
- m.Append("\n ");
- if (element[0].Name != "store") {
- m.Append("else -> ");
- }
- element = element[0];
- }
-
- if (isConstArray(element, type)) {
- ConstructComplexValue(getConstArrayElement(element), type[1], m);
- return;
- } else if (element.Name == "_" && element.ArgCount == 2 &&
- element[0].Name == "as-array") {
- m.Append("as-array[" + element[1].Name + ']');
- return;
- }
- }
-
- if (SortSet.ContainsKey(type.Name) && SortSet[type.Name] == 0) {
- var prefix = "@uc_T_" + type.Name.Substring(2) + "_";
- if (element.Name.StartsWith(prefix)) {
- m.Append(type.Name + "!val!" + element.Name.Substring(prefix.Length));
- return;
- }
- }
-
- if (Functions.ContainsKey(element.Name) &&
- type.Name == Functions[element.Name].Name) {
- m.Append(element.Name);
- return;
- }
-
- if (DataTypes.ContainsKey(type.Name) &&
- DataTypes[type.Name].Constructor == element.Name &&
- element.ArgCount == DataTypes[type.Name].Types.Count) {
- m.Append("(" + element.Name);
- for (int i = 0; i < element.ArgCount; ++i) {
- m.Append(" ");
- ConstructComplexValue(element[i], DataTypes[type.Name].Types[i], m);
- }
- m.Append(")");
- return;
- }
-
- Parent.HandleProverError("Unexpected value: " + element);
- throw new BadExprFromProver ();
- }
-
- void ConstructFunctionArguments(SExpr arguments, List<SExpr> argTypes, StringBuilder[] argValues) {
- if (arguments.Name == "and") {
- ConstructFunctionArguments(arguments[0], argTypes, argValues);
- ConstructFunctionArguments(arguments[1], argTypes, argValues);
- } else if (arguments.Name == "=" &&
- (arguments[0].Name.StartsWith("_ufmt_") || arguments[0].Name.StartsWith("x!"))) {
- int argNum;
- if (arguments[0].Name.StartsWith("_ufmt_"))
- argNum = System.Convert.ToInt32(arguments[0].Name.Substring("_uftm_".Length)) - 1;
- else /* if (arguments[0].Name.StartsWith("x!")) */
- argNum = System.Convert.ToInt32(arguments[0].Name.Substring("x!".Length)) - 1;
- if (argNum < 0 || argNum >= argTypes.Count) {
- Parent.HandleProverError("Unexpected function argument: " + arguments[0]);
- throw new BadExprFromProver ();
- }
- if (argValues[argNum] != null) {
- Parent.HandleProverError("Function argument defined multiple times: " + arguments[0]);
- throw new BadExprFromProver ();
- }
- argValues[argNum] = new StringBuilder();
- ConstructComplexValue(arguments[1], argTypes[argNum], argValues[argNum]);
- } else {
- Parent.HandleProverError("Unexpected function argument: " + arguments);
- throw new BadExprFromProver ();
- }
- }
-
- void ConstructFunctionElements(SExpr element, List<SExpr> argTypes, SExpr outType, StringBuilder m) {
- while (element.Name == "ite") {
- StringBuilder[] argValues = new StringBuilder[argTypes.Count];
- ConstructFunctionArguments(element[0], argTypes, argValues);
- foreach (var s in argValues)
- m.Append(s + " ");
- m.Append("-> ");
- ConstructComplexValue(element[1], outType, m);
- m.Append("\n ");
- if (element[2].Name != "ite")
- m.Append("else -> ");
- element = element[2];
- }
-
- ConstructComplexValue(element, outType, m);
- }
-
- void ConstructFunction(SExpr element, SExpr inType, SExpr outType, StringBuilder m) {
- List<SExpr> argTypes = new List<SExpr>();
-
- for (int i = 0; i < inType.ArgCount; ++i) {
- if (inType[i].Name != "_ufmt_" + (i + 1) && inType[i].Name != "x!" + (i + 1) &&
- !inType[i].Name.StartsWith("BOUND_VARIABLE_")) {
- Parent.HandleProverError("Unexpected function argument: " + inType[i].Name);
- throw new BadExprFromProver ();
- }
- argTypes.Add(inType[i][0]);
- }
-
- ConstructFunctionElements(element, argTypes, outType, m);
- }
-
- void ConstructDefine(SExpr element, StringBuilder m) {
- Debug.Assert(element.Name == "define-fun");
-
- if (element[1].ArgCount != 0)
- TopLevelProcessed.Add(element);
-
- m.Append(element[0] + " -> ");
- if (TopLevelProcessed.Contains(element))
- m.Append("{\n ");
-
- if (element[1].ArgCount == 0 && element[2].Name == "Array" && !TopLevelProcessed.Contains(element)) {
- ConstructComplexValue(element[3], element[2], m);
- } else if (element[1].ArgCount == 0) {
- ConstructSimpleValue(element[3], element[2], m);
- } else {
- ConstructFunction(element[3], element[1], element[2], m);
- }
-
- if (TopLevelProcessed.Contains(element))
- m.Append("\n}");
- m.Append("\n");
- }
-
- void ExtractDataType(SExpr datatypes) {
- Debug.Assert(datatypes.Name == "declare-datatypes");
-
- if (datatypes[0].Name != "" || datatypes[1].Name != "" || datatypes[1].ArgCount != 1) {
- Parent.HandleProverError("Unexpected datatype: " + datatypes);
- throw new BadExprFromProver ();
- }
-
- SMTDataType dt = new SMTDataType();
- SExpr typeDef = datatypes[1][0];
-
- if (typeDef.ArgCount != 1) {
- Parent.HandleProverError("Unexpected datatype: " + datatypes);
- throw new BadExprFromProver ();
- }
-
- dt.Constructor = typeDef[0].Name;
- dt.Types = new List<SExpr>();
-
- for (int i = 0; i < typeDef[0].ArgCount; ++i) {
- if (typeDef[0][i].ArgCount != 1) {
- Parent.HandleProverError("Unexpected datatype constructor: " + typeDef[0]);
- throw new BadExprFromProver ();
- }
- dt.Types.Add(typeDef[0][i][0]);
- }
-
- DataTypes[typeDef.Name] = dt;
- }
-
- private void ConvertErrorModel(StringBuilder m) {
- if (Parent.options.Solver == SolverKind.Z3) {
- // Datatype declarations are not returned by Z3, so parse common
- // instead. This is not very efficient, but currently not an issue,
- // as this not the normal way of interfacing with Z3.
- var ms = new MemoryStream(Encoding.ASCII.GetBytes(Parent.common.ToString()));
- var sr = new StreamReader(ms);
- SExpr.Parser p = new MyFileParser(sr, null);
- var sexprs = p.ParseSExprs(false);
- foreach (var e in sexprs) {
- switch (e.Name) {
- case "declare-datatypes":
- ExtractDataType(e);
- break;
- }
- }
- }
-
- while (ErrorModelTodo.Count > 0) {
- var e = ErrorModelTodo[0];
- ErrorModelTodo.RemoveAt(0);
-
- switch (e.Name) {
- case "define-fun":
- ConstructDefine(e, m);
- break;
- case "declare-sort":
- SortSet[e[0].Name] = System.Convert.ToInt32(e[1].Name);
- break;
- case "declare-datatypes":
- ExtractDataType(e);
- break;
- case "declare-fun":
- if (e[1].Name != "" || e[1].ArgCount > 0 || e[2].ArgCount > 0 ||
- e[2].Name == "Bool" || e[2].Name == "Int") {
- Parent.HandleProverError("Unexpected top level model element: " + e.Name);
- throw new BadExprFromProver ();
- }
- Functions[e[0].Name] = e[2];
- break;
- case "forall":
- // ignore
- break;
- default:
- Parent.HandleProverError("Unexpected top level model element: " + e.Name);
- throw new BadExprFromProver ();
- }
- }
- }
- }
-
- private Model GetErrorModel() {
- if (!options.ExpectingModel())
- return null;
- SendThisVC("(get-model)");
- Process.Ping();
- Model theModel = null;
- while (true) {
- var resp = Process.GetProverResponse();
- if (resp == null || Process.IsPong(resp))
- break;
- if (theModel != null)
- HandleProverError("Expecting only one model but got many");
-
- string modelStr = null;
- if (resp.Name == "model" && resp.ArgCount >= 1) {
- var converter = new SMTErrorModelConverter(resp, this);
- modelStr = converter.Convert();
- }
- else if (resp.ArgCount == 0 && resp.Name.Contains("->")) {
- modelStr = resp.Name;
- }
- else {
- HandleProverError("Unexpected prover response getting model: " + resp.ToString());
- }
-
- List<Model> models = null;
- try {
- switch (options.Solver) {
- case SolverKind.Z3:
- case SolverKind.CVC4:
- models = Model.ParseModels(new StringReader("Error model: \n" + modelStr));
- break;
- default:
- Debug.Assert(false);
- return null;
- }
- }
- catch (ArgumentException exn) {
- HandleProverError("Model parsing error: " + exn.Message);
- }
- if (models == null)
- HandleProverError("Could not parse any models");
- else if (models.Count == 0)
- HandleProverError("Could not parse any models");
- else if (models.Count > 1)
- HandleProverError("Expecting only one model but got many");
- else
- theModel = models[0];
- }
- return theModel;
- }
-
- private string[] GetLabelsInfo()
- {
- SendThisVC("(labels)");
- Process.Ping();
-
- string[] res = null;
- while (true) {
- var resp = Process.GetProverResponse();
- if (resp == null || Process.IsPong(resp))
- break;
- if (res != null)
- HandleProverError("Expecting only one sequence of labels but got many");
- if (resp.Name == "labels" && resp.ArgCount >= 1) {
- res = resp.Arguments.Select(a => a.Name.Replace("|", "")).ToArray();
- }
- else {
- HandleProverError("Unexpected prover response getting labels: " + resp.ToString());
- }
- }
- return res;
- }
-
- private Outcome GetResponse()
- {
- var result = Outcome.Undetermined;
- var wasUnknown = false;
-
- Process.Ping();
-
- while (true) {
- var resp = Process.GetProverResponse();
- if (resp == null || Process.IsPong(resp))
- break;
-
- switch (resp.Name) {
- case "unsat":
- result = Outcome.Valid;
- break;
- case "sat":
- result = Outcome.Invalid;
- break;
- case "unknown":
- result = Outcome.Invalid;
- wasUnknown = true;
- break;
- default:
- HandleProverError("Unexpected prover response: " + resp.ToString());
- break;
- }
- }
-
- if (wasUnknown) {
- SendThisVC("(get-info :reason-unknown)");
- Process.Ping();
- while (true) {
- var resp = Process.GetProverResponse();
- if (resp == null || Process.IsPong(resp))
- break;
-
- if (resp.ArgCount == 1 && resp.Name == ":reason-unknown") {
- switch (resp[0].Name) {
- case "memout":
- currentErrorHandler.OnResourceExceeded("memory");
- result = Outcome.OutOfMemory;
- Process.NeedsRestart = true;
- break;
- case "timeout": case "canceled":
- currentErrorHandler.OnResourceExceeded("timeout");
- result = Outcome.TimeOut;
- break;
- default:
- break;
- }
- } else {
- HandleProverError("Unexpected prover response (getting info about 'unknown' response): " + resp.ToString());
- }
- }
-
- }
-
- return result;
- }
-
- protected string VCExpr2String(VCExpr expr, int polarity)
- {
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- lock (gen)
- {
- DateTime start = DateTime.UtcNow;
- //if (CommandLineOptions.Clo.Trace)
- // Console.Write("Linearising ... ");
-
- // handle the types in the VCExpr
- TypeEraser eraser;
- switch (CommandLineOptions.Clo.TypeEncodingMethod)
- {
- case CommandLineOptions.TypeEncoding.Arguments:
- eraser = new TypeEraserArguments((TypeAxiomBuilderArguments)AxBuilder, gen);
- break;
- case CommandLineOptions.TypeEncoding.Monomorphic:
- eraser = null;
- break;
- default:
- eraser = new TypeEraserPremisses((TypeAxiomBuilderPremisses)AxBuilder, gen);
- break;
- }
- VCExpr exprWithoutTypes = eraser == null ? expr : eraser.Erase(expr, polarity);
- Contract.Assert(exprWithoutTypes != null);
-
- LetBindingSorter letSorter = new LetBindingSorter(gen);
- Contract.Assert(letSorter != null);
- VCExpr sortedExpr = letSorter.Mutate(exprWithoutTypes, true);
- Contract.Assert(sortedExpr != null);
- VCExpr sortedAxioms = letSorter.Mutate(AxBuilder.GetNewAxioms(), true);
- Contract.Assert(sortedAxioms != null);
-
- DeclCollector.Collect(sortedAxioms);
- DeclCollector.Collect(sortedExpr);
- FeedTypeDeclsToProver();
-
-
-
- AddAxiom(SMTLibExprLineariser.ToString(sortedAxioms, Namer, options));
- string res = SMTLibExprLineariser.ToString(sortedExpr, Namer, options);
- Contract.Assert(res != null);
-
- if (CommandLineOptions.Clo.Trace)
- {
- DateTime end = DateTime.UtcNow;
- TimeSpan elapsed = end - start;
- if (elapsed.TotalSeconds > 0.5)
- Console.WriteLine("Linearising [{0} s]", elapsed.TotalSeconds);
- }
- return res;
- }
- }
-
- // the list of all known axioms, where have to be included in each
- // verification condition
- private readonly List<string/*!>!*/> Axioms = new List<string/*!*/>();
- private bool AxiomsAreSetup = false;
-
-
-
-
- // similarly, a list of function/predicate declarations
- private readonly List<string/*!>!*/> TypeDecls = new List<string/*!*/>();
-
- protected void AddAxiom(string axiom)
- {
- Contract.Requires(axiom != null);
- Axioms.Add(axiom);
- // if (thmProver != null) {
- // LogActivity(":assume " + axiom);
- // thmProver.AddAxioms(axiom);
- // }
- }
-
- protected void AddTypeDecl(string decl)
- {
- Contract.Requires(decl != null);
- TypeDecls.Add(decl);
- // if (thmProver != null) {
- // LogActivity(decl);
- // thmProver.Feed(decl, 0);
- // }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- private static string _backgroundPredicates;
-
- static void InitializeGlobalInformation()
- {
- Contract.Ensures(_backgroundPredicates != null);
- //throws ProverException, System.IO.FileNotFoundException;
- if (_backgroundPredicates == null) {
- if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.Monomorphic)
- {
- _backgroundPredicates = "";
- }
- else
- {
- _backgroundPredicates = @"
-(set-info :category ""industrial"")
-(declare-sort |T@U| 0)
-(declare-sort |T@T| 0)
-(declare-fun real_pow (Real Real) Real)
-(declare-fun UOrdering2 (|T@U| |T@U|) Bool)
-(declare-fun UOrdering3 (|T@T| |T@U| |T@U|) Bool)";
- }
- }
- }
-
- public override VCExpressionGenerator VCExprGen
- {
- get { return this.gen; }
- }
-
- //// Push/pop interface
-
- //List<string> pushedAssertions = new List<string>();
- //int numRealPushes;
- public override string VCExpressionToString(VCExpr vc)
- {
- return VCExpr2String(vc, 1);
- }
-
- public override void PushVCExpression(VCExpr vc)
- {
- throw new NotImplementedException();
-
- }
-
- public override void Pop()
- {
- SendThisVC("(pop 1)");
- DeclCollector.Pop();
- }
-
- public override int NumAxiomsPushed()
- {
- throw new NotImplementedException();
- //return numRealPushes + pushedAssertions.Count;
- }
-
- private void FlushPushedAssertions()
- {
- throw new NotImplementedException();
- }
-
- public override void Assert(VCExpr vc, bool polarity)
- {
- string a = "";
- if (polarity)
- {
- a = "(assert " + VCExpr2String(vc, 1) + ")";
- }
- else
- {
- a = "(assert (not\n" + VCExpr2String(vc, 1) + "\n))";
- }
- AssertAxioms();
- SendThisVC(a);
- }
-
- public override void DefineMacro(Macro f, VCExpr vc) {
- DeclCollector.AddFunction(f);
- string printedName = Namer.GetQuotedName(f, f.Name);
- var argTypes = f.InParams.Cast<Variable>().MapConcat(p => DeclCollector.TypeToStringReg(p.TypedIdent.Type), " ");
- string decl = "(define-fun " + printedName + " (" + argTypes + ") " + DeclCollector.TypeToStringReg(f.OutParams[0].TypedIdent.Type) + " " + VCExpr2String(vc, 1) + ")";
- AssertAxioms();
- SendThisVC(decl);
- }
-
- public override void AssertAxioms()
- {
- FlushAxioms();
- }
-
- public override void Check()
- {
- PrepareCommon();
- SendThisVC("(check-sat)");
- FlushLogFile();
- }
-
- public override void SetTimeOut(int ms)
- {
- if (options.Solver == SolverKind.Z3) {
- var name = Z3.SetTimeoutOption();
- var value = ms.ToString();
- options.TimeLimit = ms;
- options.SmtOptions.RemoveAll(ov => ov.Option == name);
- options.AddSmtOption(name, value);
- SendThisVC(string.Format("(set-option :{0} {1})", name, value));
- }
- }
-
- public override object Evaluate(VCExpr expr)
- {
- string vcString = VCExpr2String(expr, 1);
- SendThisVC("(get-value (" + vcString + "))");
- var resp = Process.GetProverResponse();
- if (resp == null) throw new VCExprEvaluationException();
- if (!(resp.Name == "" && resp.ArgCount == 1)) throw new VCExprEvaluationException();
- resp = resp.Arguments[0];
- if (resp.Name == "")
- {
- // evaluating an expression
- if (resp.ArgCount == 2)
- resp = resp.Arguments[1];
- else
- throw new VCExprEvaluationException();
- }
- else
- {
- // evaluating a variable
- if (resp.ArgCount == 1)
- resp = resp.Arguments[0];
- else
- throw new VCExprEvaluationException();
- }
- if (resp.Name == "-" && resp.ArgCount == 1) // negative int
- return Microsoft.Basetypes.BigNum.FromString("-" + resp.Arguments[0].Name);
- if (resp.Name == "_" && resp.ArgCount == 2 && resp.Arguments[0].Name.StartsWith("bv")) // bitvector
- return new BvConst(Microsoft.Basetypes.BigNum.FromString(resp.Arguments[0].Name.Substring("bv".Length)),
- int.Parse(resp.Arguments[1].Name));
- if (resp.ArgCount != 0)
- throw new VCExprEvaluationException();
- if (expr.Type.Equals(Boogie.Type.Bool))
- return bool.Parse(resp.Name);
- else if (expr.Type.Equals(Boogie.Type.Int))
- return Microsoft.Basetypes.BigNum.FromString(resp.Name);
- else
- return resp.Name;
- }
-
- /// <summary>
- /// Extra state for ApiChecker (used by stratifiedInlining)
- /// </summary>
- static int nameCounter = 0;
-
- public override Outcome CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore, ErrorHandler handler)
- {
- unsatCore = new List<int>();
-
- Push();
- // Name the assumptions
- var nameToAssumption = new Dictionary<string, int>();
- int i = 0;
- foreach (var vc in assumptions)
- {
- var name = "a" + nameCounter.ToString();
- nameCounter++;
- nameToAssumption.Add(name, i);
-
- string vcString = VCExpr2String(vc, 1);
- AssertAxioms();
- SendThisVC(string.Format("(assert (! {0} :named {1}))", vcString, name));
- i++;
- }
- Check();
-
- var outcome = CheckOutcomeCore(handler);
-
- if (outcome != Outcome.Valid) {
- Pop();
- return outcome;
- }
-
- Contract.Assert(usingUnsatCore, "SMTLib prover not setup for computing unsat cores");
- SendThisVC("(get-unsat-core)");
- var resp = Process.GetProverResponse();
- unsatCore = new List<int>();
- if (resp.Name != "") unsatCore.Add(nameToAssumption[resp.Name]);
- foreach (var s in resp.Arguments) unsatCore.Add(nameToAssumption[s.Name]);
-
- FlushLogFile();
- Pop();
- return outcome;
- }
-
- public override void Push()
- {
- SendThisVC("(push 1)");
- DeclCollector.Push();
- }
-
- public override Outcome CheckAssumptions(List<VCExpr> hardAssumptions, List<VCExpr> softAssumptions, out List<int> unsatisfiedSoftAssumptions, ErrorHandler handler) {
- unsatisfiedSoftAssumptions = new List<int>();
-
- // First, convert both hard and soft assumptions to SMTLIB strings
- List<string> hardAssumptionStrings = new List<string>();
- foreach (var a in hardAssumptions) {
- hardAssumptionStrings.Add(VCExpr2String(a, 1));
- }
- List<string> currAssumptionStrings = new List<string>();
- foreach (var a in softAssumptions) {
- currAssumptionStrings.Add(VCExpr2String(a, 1));
- }
-
- Push();
- AssertAxioms();
- foreach (var a in hardAssumptionStrings) {
- SendThisVC("(assert " + a + ")");
- }
- Check();
- Outcome outcome = GetResponse();
- if (outcome != Outcome.Invalid) {
- Pop();
- return outcome;
- }
-
- int k = 0;
- List<string> relaxVars = new List<string>();
- while (true) {
- Push();
- foreach (var a in currAssumptionStrings) {
- SendThisVC("(assert " + a + ")");
- }
- Check();
- outcome = CheckOutcomeCore(handler);
- if (outcome != Outcome.Valid)
- break;
- Pop();
- string relaxVar = "relax_" + k;
- relaxVars.Add(relaxVar);
- SendThisVC("(declare-fun " + relaxVar + " () Int)");
- List<string> nextAssumptionStrings = new List<string>();
- for (int i = 0; i < currAssumptionStrings.Count; i++) {
- string constraint = "(= " + relaxVar + " " + i + ")";
- nextAssumptionStrings.Add("(or " + currAssumptionStrings[i] + " " + constraint + ")");
- }
- currAssumptionStrings = nextAssumptionStrings;
- k++;
- }
-
- if (outcome == Outcome.Invalid) {
- foreach (var relaxVar in relaxVars) {
- SendThisVC("(get-value (" + relaxVar + "))");
- FlushLogFile();
- var resp = Process.GetProverResponse();
- if (resp == null) break;
- if (!(resp.Name == "" && resp.ArgCount == 1)) break;
- resp = resp.Arguments[0];
- if (!(resp.Name != "" && resp.ArgCount == 1)) break;
- resp = resp.Arguments[0];
- if (resp.ArgCount != 0)
- break;
- int v;
- if (int.TryParse(resp.Name, out v))
- unsatisfiedSoftAssumptions.Add(v);
- else
- break;
- }
- Pop();
- }
-
- Pop();
- return outcome;
- }
- }
-
- public class SMTLibInterpolatingProcessTheoremProver : SMTLibProcessTheoremProver
- {
- public SMTLibInterpolatingProcessTheoremProver(ProverOptions options, VCExpressionGenerator gen,
- SMTLibProverContext ctx)
- : base(AddInterpOption(options), gen, ctx)
- {
-
- }
-
- private static ProverOptions AddInterpOption(ProverOptions options)
- {
- var opts = (SMTLibProverOptions)options;
- opts.AddSmtOption("produce-interpolants", "true");
- if (CommandLineOptions.Clo.PrintFixedPoint == null)
- CommandLineOptions.Clo.PrintFixedPoint = "itp.fixedpoint.bpl";
- return opts;
- }
-
- public override void AssertNamed(VCExpr vc, bool polarity, string name)
- {
- string vcString;
- if (polarity)
- {
- vcString = VCExpr2String(vc, 1);
- }
- else
- {
- vcString = "(not " + VCExpr2String(vc, 1) + ")";
- }
- AssertAxioms();
- SendThisVC(string.Format("(assert (! {0} :named {1}))", vcString, name));
- }
-
- public override VCExpr ComputeInterpolant(VCExpr A, VCExpr B)
- {
- string A_str = VCExpr2String(A, 1);
- string B_str = VCExpr2String(B, 1);
-
- AssertAxioms();
- SendThisVC("(compute-interpolant " + A_str + " " + B_str + ")");
-
- SExpr interpolant;
- Outcome result = GetInterpolantResponse(out interpolant);
-
- if (result != Outcome.Valid)
- return null;
-
- VCExpr interpolantVC = SExprToVCExpr(interpolant, new Dictionary<string, VCExpr>());
- return interpolantVC;
- }
-
- private Outcome GetInterpolantResponse(out SExpr interpolant)
- {
- var result = Outcome.Undetermined;
- var wasUnknown = false;
- interpolant = null;
-
- Process.Ping();
- bool onlyOnce = false;
-
- while (true)
- {
- var resp = Process.GetProverResponse();
- if (resp == null || Process.IsPong(resp))
- break;
-
- switch (resp.Name)
- {
- case "unsat":
- result = Outcome.Valid;
- break;
- case "sat":
- result = Outcome.Invalid;
- break;
- case "unknown":
- result = Outcome.Invalid;
- wasUnknown = true;
- break;
- default:
- if (result == Outcome.Valid)
- {
- interpolant = resp as SExpr;
-
- Contract.Assert(onlyOnce == false);
- onlyOnce = true;
- continue;
- }
- HandleProverError("Unexpected prover response: " + resp.ToString());
- break;
- }
- }
-
- if (wasUnknown)
- {
- SendThisVC("(get-info :reason-unknown)");
- Process.Ping();
-
- while (true)
- {
- var resp = Process.GetProverResponse();
- if (resp == null || Process.IsPong(resp))
- break;
-
- if (resp.ArgCount == 1 && resp.Name == ":reason-unknown")
- {
- switch (resp[0].Name)
- {
- case "memout":
- currentErrorHandler.OnResourceExceeded("memory");
- result = Outcome.OutOfMemory;
- Process.NeedsRestart = true;
- break;
- case "timeout":
- case "canceled":
- currentErrorHandler.OnResourceExceeded("timeout");
- result = Outcome.TimeOut;
- break;
- default:
- break;
- }
- }
- else
- {
- HandleProverError("Unexpected prover response (getting info about 'unknown' response): " + resp.ToString());
- }
- }
- }
-
- return result;
- }
-
- public override List<VCExpr> GetTreeInterpolant(List<string> root, List<string> leaves)
- {
- List<VCExpr> result = new List<VCExpr>();
-
- string vcStr = "true";
- foreach (string str in root)
- vcStr = vcStr + " " + str;
- foreach (string str in leaves)
- vcStr = vcStr + "\r\n (interp " + str + ")";
-
- vcStr = "(get-interpolant (and\r\n" + vcStr + "\r\n))";
- SendThisVC(vcStr);
- if(currentLogFile != null) currentLogFile.Flush();
-
- List<SExpr> interpolantList;
- GetTreeInterpolantResponse(out interpolantList);
-
- Dictionary<string, VCExpr> bound = new Dictionary<string, VCExpr>();
- foreach (SExpr sexpr in interpolantList)
- {
- VCExpr interpolantVC = SExprToVCExpr(sexpr, bound);
- result.Add(interpolantVC);
- }
-
- return result;
- }
-
- private void GetTreeInterpolantResponse(out List<SExpr> interpolantList)
- {
- interpolantList = new List<SExpr>();
-
- Process.Ping();
-
- while (true)
- {
- var resp = Process.GetProverResponse();
- if (resp == null || Process.IsPong(resp))
- break;
-
- SExpr interpolant = resp as SExpr;
- if(interpolant == null)
- HandleProverError("Unexpected prover response: got null for interpolant!");
- interpolantList.Add(interpolant);
- }
- }
- }
-
- public class SMTLibProverContext : DeclFreeProverContext
- {
- internal SMTLibProcessTheoremProver parent;
-
- public readonly Dictionary<CtorType, List<Function>> KnownDatatypeConstructors = new Dictionary<CtorType, List<Function>>();
-
- public SMTLibProverContext(VCExpressionGenerator gen,
- VCGenerationOptions genOptions)
- : base(gen, genOptions)
- {
- }
-
- protected SMTLibProverContext(SMTLibProverContext par)
- : base(par)
- {
- }
-
- public override object Clone()
- {
- return new SMTLibProverContext(this);
- }
-
- public override string Lookup(VCExprVar var)
- {
- VCExprVar v = parent.AxBuilder.TryTyped2Untyped(var);
- if (v != null) {
- var = v;
- }
- return parent.Namer.Lookup(var);
- }
-
- public override void DeclareFunction(Function f, string attributes) {
- if (f is DatatypeConstructor) {
- CtorType datatype = (CtorType) f.OutParams[0].TypedIdent.Type;
- if (!KnownDatatypeConstructors.ContainsKey(datatype))
- KnownDatatypeConstructors[datatype] = new List<Function>();
- KnownDatatypeConstructors[datatype].Add(f);
- }
- base.DeclareFunction(f, attributes);
- }
- }
-
- public class Factory : ProverFactory
- {
- // Set programmatically
- public static bool UseInterpolation = false;
-
- public override object SpawnProver(ProverOptions options, object ctxt)
- {
- //Contract.Requires(ctxt != null);
- //Contract.Requires(options != null);
- Contract.Ensures(Contract.Result<object>() != null);
-
- return this.SpawnProver(options,
- cce.NonNull((SMTLibProverContext)ctxt).ExprGen,
- cce.NonNull((SMTLibProverContext)ctxt));
- }
-
- public override object NewProverContext(ProverOptions options)
- {
- //Contract.Requires(options != null);
- Contract.Ensures(Contract.Result<object>() != null);
-
- VCExpressionGenerator gen = new VCExpressionGenerator();
- List<string>/*!>!*/ proverCommands = new List<string/*!*/>();
- proverCommands.Add("smtlib");
- var opts = (SMTLibProverOptions)options ;
- if (opts.Solver == SolverKind.Z3)
- proverCommands.Add("z3");
- else
- proverCommands.Add("external");
- VCGenerationOptions genOptions = new VCGenerationOptions(proverCommands);
- return new SMTLibProverContext(gen, genOptions);
- }
-
- public override ProverOptions BlankProverOptions()
- {
- return new SMTLibProverOptions();
- }
-
- protected virtual SMTLibProcessTheoremProver SpawnProver(ProverOptions options,
- VCExpressionGenerator gen,
- SMTLibProverContext ctx)
- {
- Contract.Requires(options != null);
- Contract.Requires(gen != null);
- Contract.Requires(ctx != null);
- Contract.Ensures(Contract.Result<SMTLibProcessTheoremProver>() != null);
-
- if (UseInterpolation)
- return new SMTLibInterpolatingProcessTheoremProver(options, gen, ctx);
-
- return new SMTLibProcessTheoremProver(options, gen, ctx);
- }
-
- public override bool SupportsLabels(ProverOptions options)
- {
- return ((SMTLibProverOptions)options).SupportsLabels;
- }
- }
-}
+//----------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading; +using System.IO; +//using ExternalProver; +using System.Linq; +using System.Diagnostics; +using System.Diagnostics.Contracts; +using Microsoft.Boogie.AbstractInterpretation; +using Microsoft.Boogie; +using Microsoft.Boogie.VCExprAST; +using Microsoft.Boogie.Clustering; +using Microsoft.Boogie.TypeErasure; +using System.Text; + +using RPFP = Microsoft.Boogie.RPFP; + +namespace Microsoft.Boogie.SMTLib +{ + public class SMTLibProcessTheoremProver : ProverInterface + { + private readonly SMTLibProverContext ctx; + private VCExpressionGenerator gen; + private readonly SMTLibProverOptions options; + private bool usingUnsatCore; + private RPFP rpfp = null; + + [ContractInvariantMethod] + void ObjectInvariant() + { + Contract.Invariant(ctx != null); + Contract.Invariant(AxBuilder != null); + Contract.Invariant(Namer != null); + Contract.Invariant(DeclCollector != null); + Contract.Invariant(cce.NonNullElements(Axioms)); + Contract.Invariant(cce.NonNullElements(TypeDecls)); + Contract.Invariant(_backgroundPredicates != null); + + } + + + [NotDelayed] + public SMTLibProcessTheoremProver(ProverOptions options, VCExpressionGenerator gen, + SMTLibProverContext ctx) + { + Contract.Requires(options != null); + Contract.Requires(gen != null); + Contract.Requires(ctx != null); + + InitializeGlobalInformation(); + + this.options = (SMTLibProverOptions)options; + this.ctx = ctx; + this.gen = gen; + this.usingUnsatCore = false; + + SetupAxiomBuilder(gen); + + Namer = new SMTLibNamer(); + ctx.parent = this; + this.DeclCollector = new TypeDeclCollector((SMTLibProverOptions)options, Namer); + + if (CommandLineOptions.Clo.PrintFixedPoint != null || CommandLineOptions.Clo.PrintConjectures != null) + { + declHandler = new MyDeclHandler(); + DeclCollector.SetDeclHandler(declHandler); + } + + SetupProcess(); + + if (CommandLineOptions.Clo.StratifiedInlining > 0 || CommandLineOptions.Clo.ContractInfer + || CommandLineOptions.Clo.SecureVcGen != null) + { + // Prepare for ApiChecker usage + if (options.LogFilename != null && currentLogFile == null) + { + currentLogFile = OpenOutputFile(""); + } + PrepareCommon(); + } + } + + private void SetupAxiomBuilder(VCExpressionGenerator gen) + { + switch (CommandLineOptions.Clo.TypeEncodingMethod) + { + case CommandLineOptions.TypeEncoding.Arguments: + AxBuilder = new TypeAxiomBuilderArguments(gen); + AxBuilder.Setup(); + break; + case CommandLineOptions.TypeEncoding.Monomorphic: + AxBuilder = new TypeAxiomBuilderPremisses(gen); + break; + default: + AxBuilder = new TypeAxiomBuilderPremisses(gen); + AxBuilder.Setup(); + break; + } + } + + ProcessStartInfo ComputeProcessStartInfo() + { + var path = this.options.ProverPath; + switch (options.Solver) { + case SolverKind.Z3: + if (path == null) + path = Z3.ExecutablePath(); + return SMTLibProcess.ComputerProcessStartInfo(path, "AUTO_CONFIG=false -smt2 -in"); + case SolverKind.CVC4: + if (path == null) + path = CVC4.ExecutablePath(); + return SMTLibProcess.ComputerProcessStartInfo(path, "--lang=smt --no-strict-parsing --no-condense-function-values --incremental"); + default: + Debug.Assert(false); + return null; + } + } + + void SetupProcess() + { + if (Process != null) return; + + var psi = ComputeProcessStartInfo(); + Process = new SMTLibProcess(psi, this.options); + Process.ErrorHandler += this.HandleProverError; + } + + + void PossiblyRestart() + { + if (Process != null && Process.NeedsRestart) { + Process.Close(); + Process = null; + SetupProcess(); + Process.Send(common.ToString()); + } + } + + public override ProverContext Context + { + get + { + Contract.Ensures(Contract.Result<ProverContext>() != null); + + return ctx; + } + } + + internal TypeAxiomBuilder AxBuilder { get; private set; } + internal readonly UniqueNamer Namer; + readonly TypeDeclCollector DeclCollector; + protected SMTLibProcess Process; + readonly List<string> proverErrors = new List<string>(); + readonly List<string> proverWarnings = new List<string>(); + readonly StringBuilder common = new StringBuilder(); + protected TextWriter currentLogFile; + protected volatile ErrorHandler currentErrorHandler; + + private void FeedTypeDeclsToProver() + { + foreach (string s in DeclCollector.GetNewDeclarations()) { + Contract.Assert(s != null); + AddTypeDecl(s); + } + } + + private string Sanitize(string msg) + { + var idx = msg.IndexOf('\n'); + if (idx > 0) + msg = msg.Replace("\r", "").Replace("\n", "\r\n"); + return msg; + } + + public override void LogComment(string comment) + { + SendCommon("; " + comment); + } + + private void SendCommon(string s) + { + Send(s, true); + } + + protected void SendThisVC(string s) + { + Send(s, false); + } + + private void Send(string s, bool isCommon) + { + s = Sanitize(s); + + if (isCommon) + common.Append(s).Append("\r\n"); + + if (Process != null) + Process.Send(s); + if (currentLogFile != null) { + currentLogFile.WriteLine(s); + currentLogFile.Flush(); + } + } + + private void FindDependentTypes(Type type, List<CtorType> dependentTypes) + { + MapType mapType = type as MapType; + if (mapType != null) + { + foreach (Type t in mapType.Arguments) + { + FindDependentTypes(t, dependentTypes); + } + FindDependentTypes(mapType.Result, dependentTypes); + } + CtorType ctorType = type as CtorType; + if (ctorType != null && ctx.KnownDatatypeConstructors.ContainsKey(ctorType)) + { + dependentTypes.Add(ctorType); + } + } + + private void PrepareCommon() + { + if (common.Length == 0) + { + SendCommon("(set-option :print-success false)"); + SendCommon("(set-info :smt-lib-version 2.0)"); + if (options.ProduceModel()) + SendCommon("(set-option :produce-models true)"); + foreach (var opt in options.SmtOptions) + { + SendCommon("(set-option :" + opt.Option + " " + opt.Value + ")"); + } + + if (!string.IsNullOrEmpty(options.Logic)) + { + SendCommon("(set-logic " + options.Logic + ")"); + } + + // Set produce-unsat-cores last. It seems there's a bug in Z3 where if we set it earlier its value + // gets reset by other set-option commands ( https://z3.codeplex.com/workitem/188 ) + if (CommandLineOptions.Clo.ContractInfer && (CommandLineOptions.Clo.UseUnsatCoreForContractInfer || CommandLineOptions.Clo.ExplainHoudini)) + { + SendThisVC("(set-option :produce-unsat-cores true)"); + this.usingUnsatCore = true; + } + + SendCommon("; done setting options\n"); + SendCommon(_backgroundPredicates); + + if (options.UseTickleBool) + { + SendCommon("(declare-fun tickleBool (Bool) Bool)"); + SendCommon("(assert (and (tickleBool true) (tickleBool false)))"); + } + + if (CommandLineOptions.Clo.RunDiagnosticsOnTimeout) + { + SendCommon("(declare-fun timeoutDiagnostics (Int) Bool)"); + } + + if (ctx.KnownDatatypeConstructors.Count > 0) + { + GraphUtil.Graph<CtorType> dependencyGraph = new GraphUtil.Graph<CtorType>(); + foreach (CtorType datatype in ctx.KnownDatatypeConstructors.Keys) + { + dependencyGraph.AddSource(datatype); + foreach (Function f in ctx.KnownDatatypeConstructors[datatype]) + { + List<CtorType> dependentTypes = new List<CtorType>(); + foreach (Variable v in f.InParams) + { + FindDependentTypes(v.TypedIdent.Type, dependentTypes); + } + foreach (CtorType result in dependentTypes) + { + dependencyGraph.AddEdge(datatype, result); + } + } + } + GraphUtil.StronglyConnectedComponents<CtorType> sccs = new GraphUtil.StronglyConnectedComponents<CtorType>(dependencyGraph.Nodes, dependencyGraph.Predecessors, dependencyGraph.Successors); + sccs.Compute(); + foreach (GraphUtil.SCC<CtorType> scc in sccs) + { + string datatypeString = ""; + foreach (CtorType datatype in scc) + { + datatypeString += "(" + SMTLibExprLineariser.TypeToString(datatype) + " "; + foreach (Function f in ctx.KnownDatatypeConstructors[datatype]) + { + string quotedConstructorName = Namer.GetQuotedName(f, f.Name); + if (f.InParams.Count == 0) + { + datatypeString += quotedConstructorName + " "; + } + else + { + datatypeString += "(" + quotedConstructorName + " "; + foreach (Variable v in f.InParams) + { + string quotedSelectorName = Namer.GetQuotedName(v, v.Name + "#" + f.Name); + datatypeString += "(" + quotedSelectorName + " " + DeclCollector.TypeToStringReg(v.TypedIdent.Type) + ") "; + } + datatypeString += ") "; + } + } + datatypeString += ") "; + } + List<string> decls = DeclCollector.GetNewDeclarations(); + foreach (string decl in decls) + { + SendCommon(decl); + } + SendCommon("(declare-datatypes () (" + datatypeString + "))"); + } + } + if (CommandLineOptions.Clo.ProverPreamble != null) + SendCommon("(include \"" + CommandLineOptions.Clo.ProverPreamble + "\")"); + } + + if (!AxiomsAreSetup) + { + var axioms = ctx.Axioms; + var nary = axioms as VCExprNAry; + if (nary != null && nary.Op == VCExpressionGenerator.AndOp) + foreach (var expr in nary.UniformArguments) + { + var str = VCExpr2String(expr, -1); + if (str != "true") + AddAxiom(str); + } + else + AddAxiom(VCExpr2String(axioms, -1)); + AxiomsAreSetup = true; + } + } + + public override int FlushAxiomsToTheoremProver() + { + // we feed the axioms when begincheck is called. + return 0; + } + + private void FlushAxioms() + { + TypeDecls.Iter(SendCommon); + TypeDecls.Clear(); + foreach (string s in Axioms) { + Contract.Assert(s != null); + if (s != "true") + SendCommon("(assert " + s + ")"); + } + Axioms.Clear(); + //FlushPushedAssertions(); + } + + private void CloseLogFile() + { + if (currentLogFile != null) { + currentLogFile.Close(); + currentLogFile = null; + } + } + + private void FlushLogFile() + { + if (currentLogFile != null) { + currentLogFile.Flush(); + } + } + + public override void Close() + { + base.Close(); + CloseLogFile(); + if (Process != null) + Process.Close(); + } + + public override void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler) + { + //Contract.Requires(descriptiveName != null); + //Contract.Requires(vc != null); + //Contract.Requires(handler != null); + rpfp = null; + + if (options.SeparateLogFiles) CloseLogFile(); // shouldn't really happen + + if (options.LogFilename != null && currentLogFile == null) + { + currentLogFile = OpenOutputFile(descriptiveName); + currentLogFile.Write(common.ToString()); + } + + PrepareCommon(); + + string vcString = "(assert (not\n" + VCExpr2String(vc, 1) + "\n))"; + FlushAxioms(); + + PossiblyRestart(); + + SendThisVC("(push 1)"); + SendThisVC("(set-info :boogie-vc-id " + SMTLibNamer.QuoteId(descriptiveName) + ")"); + SendThisVC(vcString); + FlushLogFile(); + + if (Process != null) { + Process.PingPong(); // flush any errors + + if (Process.Inspector != null) + Process.Inspector.NewProblem(descriptiveName, vc, handler); + } + + SendThisVC("(check-sat)"); + FlushLogFile(); + } + + public override void Reset(VCExpressionGenerator gen) + { + if (options.Solver == SolverKind.Z3) + { + this.gen = gen; + SendThisVC("(reset)"); + + if (0 < common.Length) + { + var c = common.ToString(); + Process.Send(c); + if (currentLogFile != null) + { + currentLogFile.WriteLine(c); + } + } + } + } + + public override void FullReset(VCExpressionGenerator gen) + { + if (options.Solver == SolverKind.Z3) + { + this.gen = gen; + Namer.Reset(); + common.Clear(); + SetupAxiomBuilder(gen); + Axioms.Clear(); + TypeDecls.Clear(); + AxiomsAreSetup = false; + ctx.Reset(); + ctx.KnownDatatypeConstructors.Clear(); + ctx.parent = this; + DeclCollector.Reset(); + SendThisVC("; did a full reset"); + } + } + + + + private string StripCruft(string name){ + if(name.Contains("@@")) + return name.Remove(name.LastIndexOf ("@@")); + return name; + } + + private class BadExprFromProver : Exception + { + }; + + private delegate VCExpr ArgGetter (int pos); + + private delegate VCExpr[] ArgsGetter (); + + private delegate VCExprVar[] VarsGetter (); + + private VCExprOp VCStringToVCOp (string op) + { + switch (op) { + case "+" : + return VCExpressionGenerator.AddIOp; + case "-" : + return VCExpressionGenerator.SubIOp; + case "*" : + return VCExpressionGenerator.MulIOp; + case "div" : + return VCExpressionGenerator.DivIOp; + case "=" : + return VCExpressionGenerator.EqOp; + case "<=" : + return VCExpressionGenerator.LeOp; + case "<" : + return VCExpressionGenerator.LtOp; + case ">=" : + return VCExpressionGenerator.GeOp; + case ">" : + return VCExpressionGenerator.GtOp; + case "and" : + return VCExpressionGenerator.AndOp; + case "or" : + return VCExpressionGenerator.OrOp; + case "not" : + return VCExpressionGenerator.NotOp; + case "ite" : + return VCExpressionGenerator.IfThenElseOp; + default: + return null; + } + } + + private class MyDeclHandler : TypeDeclCollector.DeclHandler { + public Dictionary<string,VCExprVar> var_map = new Dictionary<string, VCExprVar>(); + public Dictionary<string,Function> func_map = new Dictionary<string, Function>(); + public override void VarDecl(VCExprVar v){ + var_map[v.Name] = v; + } + public override void FuncDecl(Function f){ + func_map[f.Name] = f; + } + public MyDeclHandler() { + } + } + + private MyDeclHandler declHandler = null; + + private VCExprVar SExprToVar (SExpr e) + { + if(e.Arguments.Count() != 1){ + HandleProverError ("Prover error: bad quantifier syntax"); + throw new BadExprFromProver (); + } + string vname = StripCruft(e.Name); + SExpr vtype = e[0]; + switch(vtype.Name){ + case "Int": + return gen.Variable(vname,Type.Int); + case "Bool": + return gen.Variable (vname,Type.Bool); + case "Array":{ + // TODO: handle more general array types + var idxType = Type.Int; // well, could be something else + var valueType = + (vtype.Arguments[1].Name == "Int") ? Type.Int : Type.Bool; + var types = new List<Type>(); + types.Add(idxType); + return gen.Variable (vname, new MapType(Token.NoToken,new List<TypeVariable>(),types,valueType)); + } + default: { + HandleProverError ("Prover error: bad type: " + vtype.Name); + throw new BadExprFromProver (); + } + } + } + + private VCExpr MakeBinary(VCExprOp op, VCExpr [] args) + { + if (args.Count() == 0) + { + // with zero args we need the identity of the op + if (op == VCExpressionGenerator.AndOp) + return VCExpressionGenerator.True; + if (op == VCExpressionGenerator.OrOp) + return VCExpressionGenerator.False; + if (op == VCExpressionGenerator.AddIOp) + { + Microsoft.Basetypes.BigNum x = Microsoft.Basetypes.BigNum.ZERO; + return gen.Integer(x); + } + HandleProverError("Prover error: bad expression "); + throw new BadExprFromProver(); + } + var temp = args[0]; + for (int i = 1; i < args.Count(); i++) + temp = gen.Function(op, temp, args[i]); + return temp; + } + + protected VCExpr SExprToVCExpr (SExpr e, Dictionary<string,VCExpr> bound) + { + if (e.Arguments.Count() == 0) { + var name = StripCruft(e.Name); + if (name [0] >= '0' && name [0] <= '9') { + Microsoft.Basetypes.BigNum x = Microsoft.Basetypes.BigNum.FromString(name); + return gen.Integer (x); + } + if (bound.ContainsKey (name)) { + return bound [name]; + } + if(name == "true") + return VCExpressionGenerator.True; + if(name == "false") + return VCExpressionGenerator.False; + if(declHandler.var_map.ContainsKey(name)) + return declHandler.var_map[name]; + HandleProverError ("Prover error: unknown symbol:" + name); + //throw new BadExprFromProver (); + var v = gen.Variable(name, Type.Int); + bound.Add(name, v); + return v; + } + ArgGetter g = i => SExprToVCExpr (e [i], bound); + ArgsGetter ga = () => e.Arguments.Select (x => SExprToVCExpr (x, bound)).ToArray (); + VarsGetter gb = () => e [0].Arguments.Select (x => SExprToVar (x)).ToArray (); + switch (e.Name) { + case "select" : + return gen.Select (ga ()); + case "store" : + return gen.Store (ga ()); + case "forall": + case "exists": + { + var binds = e.Arguments[0]; + var vcbinds = new List<VCExprVar>(); + var bound_copy = new Dictionary<string, VCExpr>(bound); + for (int i = 0; i < binds.Arguments.Count(); i++) + { + var bind = binds.Arguments[i]; + var symb = StripCruft(bind.Name); + var vcv = SExprToVar(bind); + vcbinds.Add(vcv); + bound[symb] = vcv; + } + var body = g(1); + if (e.Name == "forall") + body = gen.Forall(vcbinds, new List<VCTrigger>(), body); + else + body = gen.Exists(vcbinds, new List<VCTrigger>(), body); + bound = bound_copy; + return body; + } + case "-" : // have to deal with unary case + { + if(e.ArgCount == 1){ + var args = new VCExpr[2]; + args[0] = gen.Integer (Microsoft.Basetypes.BigNum.ZERO); + args[1] = g(0); + return gen.Function(VCStringToVCOp("-"),args); + } + return gen.Function(VCStringToVCOp("-"),ga()); + } + case "!" : // this is commentary + return g(0); + case "let" : { + // we expand lets exponentially since there is no let binding in Boogie surface syntax + bool expand_lets = true; + var binds = e.Arguments[0]; + var vcbinds = new List<VCExprLetBinding>(); + var bound_copy = new Dictionary<string, VCExpr>(bound); + for(int i = 0; i < binds.Arguments.Count(); i++){ + var bind = binds.Arguments[i]; + var symb = bind.Name; + var def = bind.Arguments[0]; + var vce = SExprToVCExpr(def, bound); + var vcv = gen.Variable(symb,vce.Type); + var vcb = gen.LetBinding(vcv,vce); + vcbinds.Add (vcb); + bound[symb] = expand_lets ? vce : vcv; + } + var body = g(1); + if(!expand_lets) + body = gen.Let(vcbinds,body); + bound = bound_copy; + return body; + } + + default: { + var op = VCStringToVCOp (e.Name); + if (op == null) { + var name = StripCruft(e.Name); + if(declHandler.func_map.ContainsKey(name)){ + Function f = declHandler.func_map[name]; + return gen.Function (f, ga()); + } + HandleProverError ("Prover error: unknown operator:" + e.Name); + throw new BadExprFromProver (); + } + if(op.Arity == 2) + return MakeBinary (op, ga ()); + return gen.Function(op, ga()); + } + } + } + + private void SExprToSoln (SExpr resp, + Dictionary<int,Dictionary<string,string>> varSubst) + { + Dictionary<string, RPFP.Node> pmap = new Dictionary<string,RPFP.Node> (); + + foreach (var node in rpfp.nodes) + pmap.Add ((node.Name as VCExprBoogieFunctionOp).Func.Name, node); + + var lines = resp.Arguments; + + // get all the predicate definitions + for (int i = 0; i < lines.Length; i++) { + var line = lines [i]; + string pname; + RPFP.Transformer annot; + GetDefun(line, out pname, out annot); + + if(pmap.ContainsKey(pname)){ + var node = pmap[pname]; + node.Annotation = annot; + } + else if(pname[0] != '@'){ // if not an internal symbol + HandleProverError ("Prover error: got unknown predicate:" + pname); + throw new BadExprFromProver (); + } + } + + } + + private void GetDefun(SExpr line, out string pname, out RPFP.Transformer annot) + { + if (line.Name != "define-fun") + { + HandleProverError("Prover error: expected define-fun but got:" + line.Name); + throw new BadExprFromProver(); + } + if (line.ArgCount != 4) + { + HandleProverError("Prover error: define-fun has wrong number of arguments"); + throw new BadExprFromProver(); + } + pname = StripCruft(line.Arguments[0].Name); + var pvars = line.Arguments[1]; + var pbody = line.Arguments[3]; // range has to be Bool + var binding = new Dictionary<string, VCExpr>(); + var pvs = new List<VCExpr>(); + foreach (var b in pvars.Arguments) + { + var e = SExprToVar(b); + pvs.Add(e); + binding.Add(StripCruft(b.Name), e); + } + VCExpr bexpr = SExprToVCExpr(pbody, binding); + + annot = rpfp.CreateRelation(pvs.ToArray(), bexpr); + } + + private RPFP.Node SExprToCex(SExpr resp, ErrorHandler handler, + Dictionary<int,Dictionary<string,string>> varSubst) + { + Dictionary<string, RPFP.Node> nmap = new Dictionary<string,RPFP.Node>(); + Dictionary<string, RPFP.Node> pmap = new Dictionary<string,RPFP.Node>(); + + foreach(var node in rpfp.nodes) + pmap.Add((node.Name as VCExprBoogieFunctionOp).Func.Name,node); + + RPFP.Node topnode = null; + var lines = resp.Arguments; + + // last line of derivation is from query, skip it + for (int i = 0; i < lines.Length-1; i++) + { + var line = lines[i]; + if (line.ArgCount != 6) + { + HandleProverError("bad derivation line from prover: " + line.ToString()); + return null; + } + var name = line[0]; + var conseq = line[1]; + var rule = line[2]; + var subst = line[3]; + var labs = line[4]; + var refs = line[5]; + var predName = conseq.Name; + { + string spacer = "@@"; // Hack! UniqueNamer is adding these and I can't stop it! + int pos = predName.LastIndexOf(spacer); + if (pos >= 0) + predName = predName.Substring(0, pos); + } + RPFP.Node node = null; + if (!pmap.TryGetValue(predName, out node)) + { + HandleProverError("unknown predicate from prover: " + predName.ToString()); + return null; + } + RPFP.Node cexnode = rpfp.CloneNode(node); + cexnode.map = node; + nmap.Add(name.Name, cexnode); + List<RPFP.Node> Chs = new List<RPFP.Node>(); + + if (refs.Name != "ref") + { + HandleProverError("bad references from prover: " + refs.ToString()); + return null; + } + foreach (var c in refs.Arguments) + { + if (c.Name == "true") + Chs.Add(null); + else + { + RPFP.Node ch = null; + if (!nmap.TryGetValue(c.Name, out ch)) + { + HandleProverError("unknown reference from prover: " + c.ToString()); + return null; + } + Chs.Add(ch); + } + } + + if (!rule.Name.StartsWith("rule!")) + { + HandleProverError("bad rule name from prover: " + refs.ToString()); + return null; + } + int ruleNum = Convert.ToInt32(rule.Name.Substring(5)) - 1; + if (ruleNum < 0 || ruleNum > rpfp.edges.Count) + { + HandleProverError("bad rule name from prover: " + refs.ToString()); + return null; + } + RPFP.Edge orig_edge = rpfp.edges[ruleNum]; + RPFP.Edge e = rpfp.CreateEdge(cexnode, orig_edge.F, Chs.ToArray()); + e.map = orig_edge; + topnode = cexnode; + + if (labs.Name != "labels") + { + HandleProverError("bad labels from prover: " + labs.ToString()); + return null; + } + e.labels = new HashSet<string>(); + foreach (var l in labs.Arguments) + e.labels.Add(l.Name); + + if (subst.Name != "subst") + { + HandleProverError("bad subst from prover: " + subst.ToString()); + return null; + } + Dictionary<string, string> dict = new Dictionary<string, string>(); + varSubst[e.number] = dict; + foreach (var s in subst.Arguments) + { + if (s.Name != "=" || s.Arguments.Length != 2) + { + HandleProverError("bad equation from prover: " + s.ToString()); + return null; + } + string uniqueName = s.Arguments[0].Name; + string spacer = "@@"; // Hack! UniqueNamer is adding these and I can't stop it! + int pos = uniqueName.LastIndexOf(spacer); + if (pos >= 0) + uniqueName = uniqueName.Substring(0, pos); + dict.Add(uniqueName, s.Arguments[1].ToString()); + } + + } + if (topnode == null) + { + HandleProverError("empty derivation from prover: " + resp.ToString()); + } + return topnode; + } + + private Model SExprToModel(SExpr resp, ErrorHandler handler) + { + // Concatenate all the arguments + string modelString = resp[0].Name; + // modelString = modelString.Substring(7, modelString.Length - 8); // remove "(model " and final ")" + var models = Model.ParseModels(new StringReader("Error model: \n" + modelString)); + if (models == null || models.Count == 0) + { + HandleProverError("no model from prover: " + resp.ToString()); + } + return models[0]; + } + + private string QuantifiedVCExpr2String(VCExpr x) + { + return VCExpr2String(x, 1); +#if false + if (!(x is VCExprQuantifier)) + return VCExpr2String(x, 1); + VCExprQuantifier node = (x as VCExprQuantifier); + if(node.BoundVars.Count == 0) + return VCExpr2String(x, 1); + + StringWriter wr = new StringWriter(); + + string kind = node.Quan == Quantifier.ALL ? "forall" : "exists"; + wr.Write("({0} (", kind); + + for (int i = 0; i < node.BoundVars.Count; i++) + { + VCExprVar var = node.BoundVars[i]; + Contract.Assert(var != null); + string printedName = Namer.GetQuotedName(var, var.Name); + Contract.Assert(printedName != null); + wr.Write("({0} {1}) ", printedName, SMTLibExprLineariser.TypeToString(var.Type)); + } + + wr.Write(") "); + wr.Write(VCExpr2String(node.Body, 1)); + wr.Write(")"); + string res = wr.ToString(); + return res; +#endif + } + + public override Outcome CheckRPFP(string descriptiveName, RPFP _rpfp, ErrorHandler handler, + out RPFP.Node cex, + Dictionary<int, Dictionary<string, string>> varSubst, + Dictionary<string, int> extra_bound) + { + //Contract.Requires(descriptiveName != null); + //Contract.Requires(vc != null); + //Contract.Requires(handler != null); + rpfp = _rpfp; + cex = null; + + + if (options.SeparateLogFiles) CloseLogFile(); // shouldn't really happen + + if (options.LogFilename != null && currentLogFile == null) + { + currentLogFile = OpenOutputFile(descriptiveName); + currentLogFile.Write(common.ToString()); + } + + PrepareCommon(); + + Push(); + SendThisVC("(fixedpoint-push)"); + foreach (var node in rpfp.nodes) + { + DeclCollector.RegisterRelation((node.Name as VCExprBoogieFunctionOp).Func); + } + + LineariserOptions.Default.LabelsBelowQuantifiers = true; + List<string> ruleStrings = new List<string>(); + var recursion_bound = CommandLineOptions.Clo.RecursionBound; + foreach (var edge in rpfp.edges) + { + string node_name = (edge.Parent.Name as VCExprBoogieFunctionOp).Func.Name; + string rule_name = "rule_" + edge.number.ToString(); + string rec_bound = ""; + if(extra_bound != null && extra_bound.ContainsKey(node_name)) + rec_bound = (recursion_bound + extra_bound[node_name]).ToString(); + string ruleString = "(rule " + QuantifiedVCExpr2String(rpfp.GetRule(edge)) + " " + rule_name + " " + rec_bound + "\n)"; + ruleStrings.Add(ruleString); + } + string queryString = "(query " + QuantifiedVCExpr2String(rpfp.GetQuery()) + "\n :engine duality\n :print-certificate true\n"; + +#if true + if (CommandLineOptions.Clo.StratifiedInlining != 0) + queryString += " :stratified-inlining true\n"; + if (CommandLineOptions.Clo.RecursionBound > 0) + queryString += " :recursion-bound " + Convert.ToString(CommandLineOptions.Clo.RecursionBound) + "\n"; +#endif + queryString += ")"; + LineariserOptions.Default.LabelsBelowQuantifiers = false; + FlushAxioms(); + + PossiblyRestart(); + + SendThisVC("(set-info :boogie-vc-id " + SMTLibNamer.QuoteId(descriptiveName) + ")"); + foreach(var rs in ruleStrings) + SendThisVC(rs); + FlushLogFile(); + + if (Process != null) + { + Process.PingPong(); // flush any errors + +#if false + // TODO: this is not going to work + if (Process.Inspector != null) + Process.Inspector.NewProblem(descriptiveName, vc, handler); +#endif + } + + SendThisVC(queryString); + FlushLogFile(); + + var result = Outcome.Undetermined; + + if (Process != null) + { + + var resp = Process.GetProverResponse(); + + if (proverErrors.Count > 0) + { + result = Outcome.Undetermined; + foreach (var err in proverErrors) + { + if (err.Contains("canceled")) + { + result = Outcome.TimeOut; + } + } + } + else if(resp == null) + HandleProverError("Prover did not respond"); + else switch (resp.Name) + { + case "unsat": + result = Outcome.Valid; + break; + case "sat": + result = Outcome.Invalid; + break; + case "unknown": + result = Outcome.Invalid; + break; + case "bounded": + result = Outcome.Bounded; + break; + case "error": + if (resp.ArgCount > 0 && resp.Arguments[0].Name.Contains("canceled")) + { + result = Outcome.TimeOut; + } + else + { + HandleProverError("Prover error: " + resp.Arguments[0]); + result = Outcome.Undetermined; + } + break; + default: + HandleProverError("Unexpected prover response: " + resp.ToString()); + break; + } + + switch (result) + { + case Outcome.Invalid: + { + resp = Process.GetProverResponse(); + if (resp.Name == "derivation") + { + cex = SExprToCex(resp, handler,varSubst); + } + else + HandleProverError("Unexpected prover response: " + resp.ToString()); + resp = Process.GetProverResponse(); + if (resp.Name == "model") + { + var model = SExprToModel(resp, handler); + cex.owner.SetBackgroundModel(model); + } + else + HandleProverError("Unexpected prover response: " + resp.ToString()); + break; + } + case Outcome.Valid: + case Outcome.Bounded: + { + resp = Process.GetProverResponse(); + if (resp.Name == "fixedpoint") + { + // only get the response if we need it + if(CommandLineOptions.Clo.PrintFixedPoint != null) + SExprToSoln(resp, varSubst); + } + else + HandleProverError("Unexpected prover response: " + resp.ToString()); + break; + } + default: + break; + } + +#if false + while (true) + { + resp = Process.GetProverResponse(); + if (resp == null || Process.IsPong(resp)) + break; + HandleProverError("Unexpected prover response: " + resp.ToString()); + } +#endif + } + SendThisVC("(fixedpoint-pop)"); + Pop(); + AxiomsAreSetup = false; + + if (CommandLineOptions.Clo.PrintConjectures != null) + { + ReadConjectures(CommandLineOptions.Clo.PrintConjectures); + } + + return result; + } + + class MyFileParser : SExpr.Parser + { + SMTLibProcessTheoremProver parent; + + public MyFileParser(System.IO.StreamReader _sr, SMTLibProcessTheoremProver _parent) + : base(_sr) + { + parent = _parent; + } + public override void ParseError(string msg) + { + parent.HandleProverError("Error in conjecture file from prover: " + msg); + } + } + + void ReadConjectures(string filename) + { + try + { + System.IO.StreamReader sr = new StreamReader(filename + ".tmp"); + SExpr.Parser p = new MyFileParser(sr, this); + var sexps = p.ParseSExprs(false); + Dictionary<string, RPFP.Node> pmap = GetNodeMap(); + foreach (var e in sexps) + { + string pname; + RPFP.Transformer annot; + GetDefun(e, out pname, out annot); + + if (pmap.ContainsKey(pname)) + { + var c = new RPFP.Conjecture(); + c.node = pmap[pname]; + c.bound = annot; + rpfp.conjectures.Add(c); + } + else if (pname[0] != '@') + { // if not an internal symbol + HandleProverError("Prover error: got unknown predicate:" + pname); + throw new BadExprFromProver(); + } + } + sr.Close(); + } + catch (Exception) + { + HandleProverError("No conjecture file from prover"); + throw new BadExprFromProver(); + } + } + + private Dictionary<string, RPFP.Node> GetNodeMap() + { + Dictionary<string, RPFP.Node> pmap = new Dictionary<string, RPFP.Node>(); + foreach (var node in rpfp.nodes) + pmap.Add((node.Name as VCExprBoogieFunctionOp).Func.Name, node); + return pmap; + } + + private static HashSet<string> usedLogNames = new HashSet<string>(); + + private TextWriter OpenOutputFile(string descriptiveName) + { + Contract.Requires(descriptiveName != null); + Contract.Ensures(Contract.Result<TextWriter>() != null); + + string filename = options.LogFilename; + filename = Helpers.SubstituteAtPROC(descriptiveName, cce.NonNull(filename)); + var curFilename = filename; + + lock (usedLogNames) { + int n = 1; + while (usedLogNames.Contains(curFilename)) { + curFilename = filename + "." + n++; + } + usedLogNames.Add(curFilename); + } + + return new StreamWriter(curFilename, false); + } + + private void FlushProverWarnings() + { + var handler = currentErrorHandler; + if (handler != null) { + lock (proverWarnings) { + proverWarnings.Iter(handler.OnProverWarning); + proverWarnings.Clear(); + } + } + } + + protected void HandleProverError(string s) + { + s = s.Replace("\r", ""); + lock (proverWarnings) { + while (s.StartsWith("WARNING: ")) { + var idx = s.IndexOf('\n'); + var warn = s; + if (idx > 0) { + warn = s.Substring(0, idx); + s = s.Substring(idx + 1); + } else { + s = ""; + } + warn = warn.Substring(9); + proverWarnings.Add(warn); + } + } + + FlushProverWarnings(); + + if (s == "") return; + + lock (proverErrors) { + proverErrors.Add(s); + Console.WriteLine("Prover error: " + s); + } + } + + [NoDefaultContract] + public override Outcome CheckOutcome(ErrorHandler handler, int taskID = -1) + { + Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true); + + var result = CheckOutcomeCore(handler, taskID: taskID); + SendThisVC("(pop 1)"); + FlushLogFile(); + + return result; + } + + [NoDefaultContract] + public override Outcome CheckOutcomeCore(ErrorHandler handler, int taskID = -1) + { + Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true); + + var result = Outcome.Undetermined; + + if (Process == null) + return result; + + try { + currentErrorHandler = handler; + FlushProverWarnings(); + + int errorLimit; + if (CommandLineOptions.Clo.ConcurrentHoudini) { + Contract.Assert(taskID >= 0); + errorLimit = CommandLineOptions.Clo.Cho[taskID].ProverCCLimit; + } else { + errorLimit = CommandLineOptions.Clo.ProverCCLimit; + } + + if (errorLimit < 1) + errorLimit = 1; + + int errorsLeft = errorLimit; + + var globalResult = Outcome.Undetermined; + + while (true) { + string[] labels = null; + bool popLater = false; + + try { + errorsLeft--; + + result = GetResponse(); + + if (CommandLineOptions.Clo.RunDiagnosticsOnTimeout && result == Outcome.TimeOut) + { + #region Run timeout diagnostics + + if (CommandLineOptions.Clo.TraceDiagnosticsOnTimeout) + { + Console.Out.WriteLine("Starting timeout diagnostics with initial time limit {0}.", options.TimeLimit); + } + + SendThisVC("; begin timeout diagnostics"); + + var start = DateTime.UtcNow; + var unverified = new SortedSet<int>(ctx.TimeoutDiagnosticIDToAssertion.Keys); + var timedOut = new SortedSet<int>(); + int frac = 2; + int queries = 0; + int timeLimitPerAssertion = 0 < options.TimeLimit ? (options.TimeLimit / 100) * CommandLineOptions.Clo.TimeLimitPerAssertionInPercent : 1000; + while (true) + { + int rem = unverified.Count; + if (rem == 0) + { + if (0 < timedOut.Count) + { + result = CheckSplit(timedOut, ref popLater, options.TimeLimit, timeLimitPerAssertion, ref queries); + if (result == Outcome.Valid) + { + timedOut.Clear(); + } + else if (result == Outcome.TimeOut) + { + // Give up and report which assertions were not verified. + var cmds = timedOut.Select(id => ctx.TimeoutDiagnosticIDToAssertion[id]); + + if (cmds.Any()) + { + handler.OnResourceExceeded("timeout after running diagnostics", cmds); + } + } + } + else + { + result = Outcome.Valid; + } + break; + } + + // TODO(wuestholz): Try out different ways for splitting up the work (e.g., randomly). + var cnt = Math.Max(1, rem / frac); + // It seems like assertions later in the control flow have smaller indexes. + var split = new SortedSet<int>(unverified.Where((val, idx) => (rem - idx - 1) < cnt)); + Contract.Assert(0 < split.Count); + var splitRes = CheckSplit(split, ref popLater, timeLimitPerAssertion, timeLimitPerAssertion, ref queries); + if (splitRes == Outcome.Valid) + { + unverified.ExceptWith(split); + frac = 1; + } + else if (splitRes == Outcome.Invalid) + { + result = splitRes; + break; + } + else if (splitRes == Outcome.TimeOut) + { + if (2 <= frac && (4 <= (rem / frac))) + { + frac *= 4; + } + else if (2 <= (rem / frac)) + { + frac *= 2; + } + else + { + timedOut.UnionWith(split); + unverified.ExceptWith(split); + frac = 1; + } + } + else + { + break; + } + } + + unverified.UnionWith(timedOut); + + var end = DateTime.UtcNow; + + SendThisVC("; end timeout diagnostics"); + + if (CommandLineOptions.Clo.TraceDiagnosticsOnTimeout) + { + Console.Out.WriteLine("Terminated timeout diagnostics after {0:F0} ms and {1} prover queries.", end.Subtract(start).TotalMilliseconds, queries); + Console.Out.WriteLine("Outcome: {0}", result); + Console.Out.WriteLine("Unverified assertions: {0} (of {1})", unverified.Count, ctx.TimeoutDiagnosticIDToAssertion.Keys.Count); + + string filename = "unknown"; + var assertion = ctx.TimeoutDiagnosticIDToAssertion.Values.Select(t => t.Item1).FirstOrDefault(a => a.tok != null && a.tok != Token.NoToken && a.tok.filename != null); + if (assertion != null) + { + filename = assertion.tok.filename; + } + File.AppendAllText("timeouts.csv", string.Format(";{0};{1};{2:F0};{3};{4};{5};{6}\n", filename, options.TimeLimit, end.Subtract(start).TotalMilliseconds, queries, result, unverified.Count, ctx.TimeoutDiagnosticIDToAssertion.Keys.Count)); + } + + #endregion + } + + if (globalResult == Outcome.Undetermined) + globalResult = result; + + if (result == Outcome.Invalid || result == Outcome.TimeOut || result == Outcome.OutOfMemory) { + IList<string> xlabels; + if (CommandLineOptions.Clo.UseLabels) { + labels = GetLabelsInfo(); + if (labels == null) + { + xlabels = new string[] { }; + } + else + { + xlabels = labels.Select(a => a.Replace("@", "").Replace("+", "")).ToList(); + } + } + else if(CommandLineOptions.Clo.SIBoolControlVC) { + labels = new string[0]; + xlabels = labels; + } else { + labels = CalculatePath(handler.StartingProcId()); + xlabels = labels; + } + Model model = (result == Outcome.TimeOut || result == Outcome.OutOfMemory) ? null : + GetErrorModel(); + handler.OnModel(xlabels, model, result); + } + + if (labels == null || !labels.Any() || errorsLeft == 0) break; + } finally { + if (popLater) + { + SendThisVC("(pop 1)"); + } + } + + if (CommandLineOptions.Clo.UseLabels) { + var negLabels = labels.Where(l => l.StartsWith("@")).ToArray(); + var posLabels = labels.Where(l => !l.StartsWith("@")); + Func<string, string> lbl = (s) => SMTLibNamer.QuoteId(SMTLibNamer.LabelVar(s)); + if (!options.MultiTraces) + posLabels = Enumerable.Empty<string>(); + var conjuncts = posLabels.Select(s => "(not " + lbl(s) + ")").Concat(negLabels.Select(lbl)).ToArray(); + string expr = conjuncts.Length == 1 ? conjuncts[0] : ("(or " + conjuncts.Concat(" ") + ")"); ; + if (!conjuncts.Any()) + { + expr = "false"; + } + SendThisVC("(assert " + expr + ")"); + SendThisVC("(check-sat)"); + } + else { + string source = labels[labels.Length - 2]; + string target = labels[labels.Length - 1]; + SendThisVC("(assert (not (= (ControlFlow 0 " + source + ") (- " + target + "))))"); + SendThisVC("(check-sat)"); + } + } + + FlushLogFile(); + + if (CommandLineOptions.Clo.RestartProverPerVC && Process != null) + Process.NeedsRestart = true; + + return globalResult; + + } finally { + currentErrorHandler = null; + } + } + + private Outcome CheckSplit(SortedSet<int> split, ref bool popLater, int timeLimit, int timeLimitPerAssertion, ref int queries) + { + var tla = timeLimitPerAssertion * split.Count; + + if (popLater) + { + SendThisVC("(pop 1)"); + } + + SendThisVC("(push 1)"); + SendThisVC(string.Format("(set-option :{0} {1})", Z3.SetTimeoutOption(), (0 < tla && tla < timeLimit) ? tla : timeLimit)); + popLater = true; + + SendThisVC(string.Format("; checking split VC with {0} unverified assertions", split.Count)); + var expr = VCExpressionGenerator.True; + foreach (var i in ctx.TimeoutDiagnosticIDToAssertion.Keys) + { + var lit = VCExprGen.Function(VCExpressionGenerator.TimeoutDiagnosticsOp, VCExprGen.Integer(Microsoft.Basetypes.BigNum.FromInt(i))); + if (split.Contains(i)) { + lit = VCExprGen.Not(lit); + } + expr = VCExprGen.AndSimp(expr, lit); + } + SendThisVC("(assert " + VCExpr2String(expr, 1) + ")"); + if (options.Solver == SolverKind.Z3) + { + SendThisVC("(apply (then (using-params propagate-values :max_rounds 1) simplify) :print false)"); + } + FlushLogFile(); + SendThisVC("(check-sat)"); + queries++; + return GetResponse(); + } + + public override string[] CalculatePath(int controlFlowConstant) { + SendThisVC("(get-value ((ControlFlow " + controlFlowConstant + " 0)))"); + var path = new List<string>(); + while (true) { + var resp = Process.GetProverResponse(); + if (resp == null) break; + if (!(resp.Name == "" && resp.ArgCount == 1)) break; + resp = resp.Arguments[0]; + if (!(resp.Name == "" && resp.ArgCount == 2)) break; + resp = resp.Arguments[1]; + var v = resp.Name; + if (v == "-" && resp.ArgCount == 1) { + v = resp.Arguments[0].Name; + path.Add(v); + break; + } + else if (resp.ArgCount != 0) + break; + path.Add(v); + SendThisVC("(get-value ((ControlFlow " + controlFlowConstant + " " + v + ")))"); + } + return path.ToArray(); + } + + + private class SMTErrorModelConverter { + private struct SMTDataType { + public string Constructor; + public List<SExpr> Types; + } + + private List<SExpr> ErrorModelTodo; + private SMTLibProcessTheoremProver Parent; + private StringBuilder ErrorModel = new StringBuilder(); + private HashSet<SExpr> TopLevelProcessed = new HashSet<SExpr>(); + private int NumNewArrays = 0; + private Dictionary<string, int> SortSet = new Dictionary<string, int>(); + private Dictionary<string, SMTDataType> DataTypes = new Dictionary<string, SMTDataType>(); + private Dictionary<string, SExpr> Functions = new Dictionary<string, SExpr>(); + + public SMTErrorModelConverter(SExpr _ErrorModel, SMTLibProcessTheoremProver _Parent) { + ErrorModelTodo = _ErrorModel.Arguments.ToList();; + Parent = _Parent; + } + + public string Convert() { + ConvertErrorModel(ErrorModel); + return ErrorModel.ToString(); + } + + bool isConstArray(SExpr element, SExpr type) { + if (type.Name != "Array") + return false; + + if (element.Name == "__array_store_all__") // CVC4 1.4 + return true; + else if (element.Name == "" && element[0].Name == "as" && + element[0][0].Name == "const") // CVC4 > 1.4 + return true; + + return false; + } + + SExpr getConstArrayElement(SExpr element) { + if (element.Name == "__array_store_all__") // CVC4 1.4 + return element[1]; + else if (element.Name == "" && element[0].Name == "as" && + element[0][0].Name == "const") // CVC4 > 1.4 + return element[1]; + + Parent.HandleProverError("Unexpected value: " + element); + throw new BadExprFromProver (); + } + + void ConstructComplexValue(SExpr element, SExpr type, StringBuilder m) { + if (type.Name == "Array") { + if (element.Name == "store" || isConstArray(element, type)) { + NumNewArrays++; + m.Append("as-array[k!" + NumNewArrays + ']'); + SExpr[] args = {new SExpr("k!" + NumNewArrays), new SExpr(""), type, element}; + var newElement = new SExpr("define-fun", args); + TopLevelProcessed.Add(newElement); + ErrorModelTodo.Add(newElement); + return; + } + } + + ConstructSimpleValue(element, type, m); + } + + void ConstructSimpleValue(SExpr element, SExpr type, StringBuilder m) { + if (type.Name == "Bool" && element.ArgCount == 0) { + m.Append(element.ToString()); + return; + } + + if (type.Name == "Int") { + if (element.ArgCount == 0) { + m.Append(element.ToString()); + return; + } else if (element.Name == "-" && element.ArgCount == 1) { + m.Append(element.ToString()); + return; + } + } + + if (type.Name == "_" && type.ArgCount == 2 && type[0].Name == "BitVec") { + if (element.Name == "_" && element.ArgCount == 2 && + element[0].Name.StartsWith("bv") && element[0].ArgCount == 0 && + element[1].Name == type.Arguments[1].Name && element[1].ArgCount == 0) { + m.Append(element[0].Name + '[' + element[1].Name + ']'); + return; + } + } + + if (type.Name == "Array") { + while (element.Name == "store") { + ConstructComplexValue(element[1], type[0], m); + m.Append(" -> "); + ConstructComplexValue(element[2], type[1], m); + m.Append("\n "); + if (element[0].Name != "store") { + m.Append("else -> "); + } + element = element[0]; + } + + if (isConstArray(element, type)) { + ConstructComplexValue(getConstArrayElement(element), type[1], m); + return; + } else if (element.Name == "_" && element.ArgCount == 2 && + element[0].Name == "as-array") { + m.Append("as-array[" + element[1].Name + ']'); + return; + } + } + + if (SortSet.ContainsKey(type.Name) && SortSet[type.Name] == 0) { + var prefix = "@uc_T_" + type.Name.Substring(2) + "_"; + if (element.Name.StartsWith(prefix)) { + m.Append(type.Name + "!val!" + element.Name.Substring(prefix.Length)); + return; + } + } + + if (Functions.ContainsKey(element.Name) && + type.Name == Functions[element.Name].Name) { + m.Append(element.Name); + return; + } + + if (DataTypes.ContainsKey(type.Name) && + DataTypes[type.Name].Constructor == element.Name && + element.ArgCount == DataTypes[type.Name].Types.Count) { + m.Append("(" + element.Name); + for (int i = 0; i < element.ArgCount; ++i) { + m.Append(" "); + ConstructComplexValue(element[i], DataTypes[type.Name].Types[i], m); + } + m.Append(")"); + return; + } + + Parent.HandleProverError("Unexpected value: " + element); + throw new BadExprFromProver (); + } + + void ConstructFunctionArguments(SExpr arguments, List<SExpr> argTypes, StringBuilder[] argValues) { + if (arguments.Name == "and") { + ConstructFunctionArguments(arguments[0], argTypes, argValues); + ConstructFunctionArguments(arguments[1], argTypes, argValues); + } else if (arguments.Name == "=" && + (arguments[0].Name.StartsWith("_ufmt_") || arguments[0].Name.StartsWith("x!"))) { + int argNum; + if (arguments[0].Name.StartsWith("_ufmt_")) + argNum = System.Convert.ToInt32(arguments[0].Name.Substring("_uftm_".Length)) - 1; + else /* if (arguments[0].Name.StartsWith("x!")) */ + argNum = System.Convert.ToInt32(arguments[0].Name.Substring("x!".Length)) - 1; + if (argNum < 0 || argNum >= argTypes.Count) { + Parent.HandleProverError("Unexpected function argument: " + arguments[0]); + throw new BadExprFromProver (); + } + if (argValues[argNum] != null) { + Parent.HandleProverError("Function argument defined multiple times: " + arguments[0]); + throw new BadExprFromProver (); + } + argValues[argNum] = new StringBuilder(); + ConstructComplexValue(arguments[1], argTypes[argNum], argValues[argNum]); + } else { + Parent.HandleProverError("Unexpected function argument: " + arguments); + throw new BadExprFromProver (); + } + } + + void ConstructFunctionElements(SExpr element, List<SExpr> argTypes, SExpr outType, StringBuilder m) { + while (element.Name == "ite") { + StringBuilder[] argValues = new StringBuilder[argTypes.Count]; + ConstructFunctionArguments(element[0], argTypes, argValues); + foreach (var s in argValues) + m.Append(s + " "); + m.Append("-> "); + ConstructComplexValue(element[1], outType, m); + m.Append("\n "); + if (element[2].Name != "ite") + m.Append("else -> "); + element = element[2]; + } + + ConstructComplexValue(element, outType, m); + } + + void ConstructFunction(SExpr element, SExpr inType, SExpr outType, StringBuilder m) { + List<SExpr> argTypes = new List<SExpr>(); + + for (int i = 0; i < inType.ArgCount; ++i) { + if (inType[i].Name != "_ufmt_" + (i + 1) && inType[i].Name != "x!" + (i + 1) && + !inType[i].Name.StartsWith("BOUND_VARIABLE_")) { + Parent.HandleProverError("Unexpected function argument: " + inType[i].Name); + throw new BadExprFromProver (); + } + argTypes.Add(inType[i][0]); + } + + ConstructFunctionElements(element, argTypes, outType, m); + } + + void ConstructDefine(SExpr element, StringBuilder m) { + Debug.Assert(element.Name == "define-fun"); + + if (element[1].ArgCount != 0) + TopLevelProcessed.Add(element); + + m.Append(element[0] + " -> "); + if (TopLevelProcessed.Contains(element)) + m.Append("{\n "); + + if (element[1].ArgCount == 0 && element[2].Name == "Array" && !TopLevelProcessed.Contains(element)) { + ConstructComplexValue(element[3], element[2], m); + } else if (element[1].ArgCount == 0) { + ConstructSimpleValue(element[3], element[2], m); + } else { + ConstructFunction(element[3], element[1], element[2], m); + } + + if (TopLevelProcessed.Contains(element)) + m.Append("\n}"); + m.Append("\n"); + } + + void ExtractDataType(SExpr datatypes) { + Debug.Assert(datatypes.Name == "declare-datatypes"); + + if (datatypes[0].Name != "" || datatypes[1].Name != "" || datatypes[1].ArgCount != 1) { + Parent.HandleProverError("Unexpected datatype: " + datatypes); + throw new BadExprFromProver (); + } + + SMTDataType dt = new SMTDataType(); + SExpr typeDef = datatypes[1][0]; + + if (typeDef.ArgCount != 1) { + Parent.HandleProverError("Unexpected datatype: " + datatypes); + throw new BadExprFromProver (); + } + + dt.Constructor = typeDef[0].Name; + dt.Types = new List<SExpr>(); + + for (int i = 0; i < typeDef[0].ArgCount; ++i) { + if (typeDef[0][i].ArgCount != 1) { + Parent.HandleProverError("Unexpected datatype constructor: " + typeDef[0]); + throw new BadExprFromProver (); + } + dt.Types.Add(typeDef[0][i][0]); + } + + DataTypes[typeDef.Name] = dt; + } + + private void ConvertErrorModel(StringBuilder m) { + if (Parent.options.Solver == SolverKind.Z3) { + // Datatype declarations are not returned by Z3, so parse common + // instead. This is not very efficient, but currently not an issue, + // as this not the normal way of interfacing with Z3. + var ms = new MemoryStream(Encoding.ASCII.GetBytes(Parent.common.ToString())); + var sr = new StreamReader(ms); + SExpr.Parser p = new MyFileParser(sr, null); + var sexprs = p.ParseSExprs(false); + foreach (var e in sexprs) { + switch (e.Name) { + case "declare-datatypes": + ExtractDataType(e); + break; + } + } + } + + while (ErrorModelTodo.Count > 0) { + var e = ErrorModelTodo[0]; + ErrorModelTodo.RemoveAt(0); + + switch (e.Name) { + case "define-fun": + ConstructDefine(e, m); + break; + case "declare-sort": + SortSet[e[0].Name] = System.Convert.ToInt32(e[1].Name); + break; + case "declare-datatypes": + ExtractDataType(e); + break; + case "declare-fun": + if (e[1].Name != "" || e[1].ArgCount > 0 || e[2].ArgCount > 0 || + e[2].Name == "Bool" || e[2].Name == "Int") { + Parent.HandleProverError("Unexpected top level model element: " + e.Name); + throw new BadExprFromProver (); + } + Functions[e[0].Name] = e[2]; + break; + case "forall": + // ignore + break; + default: + Parent.HandleProverError("Unexpected top level model element: " + e.Name); + throw new BadExprFromProver (); + } + } + } + } + + private Model GetErrorModel() { + if (!options.ExpectingModel()) + return null; + SendThisVC("(get-model)"); + Process.Ping(); + Model theModel = null; + while (true) { + var resp = Process.GetProverResponse(); + if (resp == null || Process.IsPong(resp)) + break; + if (theModel != null) + HandleProverError("Expecting only one model but got many"); + + string modelStr = null; + if (resp.Name == "model" && resp.ArgCount >= 1) { + var converter = new SMTErrorModelConverter(resp, this); + modelStr = converter.Convert(); + } + else if (resp.ArgCount == 0 && resp.Name.Contains("->")) { + modelStr = resp.Name; + } + else { + HandleProverError("Unexpected prover response getting model: " + resp.ToString()); + } + + List<Model> models = null; + try { + switch (options.Solver) { + case SolverKind.Z3: + case SolverKind.CVC4: + models = Model.ParseModels(new StringReader("Error model: \n" + modelStr)); + break; + default: + Debug.Assert(false); + return null; + } + } + catch (ArgumentException exn) { + HandleProverError("Model parsing error: " + exn.Message); + } + if (models == null) + HandleProverError("Could not parse any models"); + else if (models.Count == 0) + HandleProverError("Could not parse any models"); + else if (models.Count > 1) + HandleProverError("Expecting only one model but got many"); + else + theModel = models[0]; + } + return theModel; + } + + private string[] GetLabelsInfo() + { + SendThisVC("(labels)"); + Process.Ping(); + + string[] res = null; + while (true) { + var resp = Process.GetProverResponse(); + if (resp == null || Process.IsPong(resp)) + break; + if (res != null) + HandleProverError("Expecting only one sequence of labels but got many"); + if (resp.Name == "labels" && resp.ArgCount >= 1) { + res = resp.Arguments.Select(a => a.Name.Replace("|", "")).ToArray(); + } + else { + HandleProverError("Unexpected prover response getting labels: " + resp.ToString()); + } + } + return res; + } + + private Outcome GetResponse() + { + var result = Outcome.Undetermined; + var wasUnknown = false; + + Process.Ping(); + + while (true) { + var resp = Process.GetProverResponse(); + if (resp == null || Process.IsPong(resp)) + break; + + switch (resp.Name) { + case "unsat": + result = Outcome.Valid; + break; + case "sat": + result = Outcome.Invalid; + break; + case "unknown": + result = Outcome.Invalid; + wasUnknown = true; + break; + default: + HandleProverError("Unexpected prover response: " + resp.ToString()); + break; + } + } + + if (wasUnknown) { + SendThisVC("(get-info :reason-unknown)"); + Process.Ping(); + while (true) { + var resp = Process.GetProverResponse(); + if (resp == null || Process.IsPong(resp)) + break; + + if (resp.ArgCount == 1 && resp.Name == ":reason-unknown") { + switch (resp[0].Name) { + case "memout": + currentErrorHandler.OnResourceExceeded("memory"); + result = Outcome.OutOfMemory; + Process.NeedsRestart = true; + break; + case "timeout": case "canceled": + currentErrorHandler.OnResourceExceeded("timeout"); + result = Outcome.TimeOut; + break; + default: + break; + } + } else { + HandleProverError("Unexpected prover response (getting info about 'unknown' response): " + resp.ToString()); + } + } + + } + + return result; + } + + protected string VCExpr2String(VCExpr expr, int polarity) + { + Contract.Requires(expr != null); + Contract.Ensures(Contract.Result<string>() != null); + + lock (gen) + { + DateTime start = DateTime.UtcNow; + //if (CommandLineOptions.Clo.Trace) + // Console.Write("Linearising ... "); + + // handle the types in the VCExpr + TypeEraser eraser; + switch (CommandLineOptions.Clo.TypeEncodingMethod) + { + case CommandLineOptions.TypeEncoding.Arguments: + eraser = new TypeEraserArguments((TypeAxiomBuilderArguments)AxBuilder, gen); + break; + case CommandLineOptions.TypeEncoding.Monomorphic: + eraser = null; + break; + default: + eraser = new TypeEraserPremisses((TypeAxiomBuilderPremisses)AxBuilder, gen); + break; + } + VCExpr exprWithoutTypes = eraser == null ? expr : eraser.Erase(expr, polarity); + Contract.Assert(exprWithoutTypes != null); + + LetBindingSorter letSorter = new LetBindingSorter(gen); + Contract.Assert(letSorter != null); + VCExpr sortedExpr = letSorter.Mutate(exprWithoutTypes, true); + Contract.Assert(sortedExpr != null); + VCExpr sortedAxioms = letSorter.Mutate(AxBuilder.GetNewAxioms(), true); + Contract.Assert(sortedAxioms != null); + + DeclCollector.Collect(sortedAxioms); + DeclCollector.Collect(sortedExpr); + FeedTypeDeclsToProver(); + + + + AddAxiom(SMTLibExprLineariser.ToString(sortedAxioms, Namer, options)); + string res = SMTLibExprLineariser.ToString(sortedExpr, Namer, options); + Contract.Assert(res != null); + + if (CommandLineOptions.Clo.Trace) + { + DateTime end = DateTime.UtcNow; + TimeSpan elapsed = end - start; + if (elapsed.TotalSeconds > 0.5) + Console.WriteLine("Linearising [{0} s]", elapsed.TotalSeconds); + } + return res; + } + } + + // the list of all known axioms, where have to be included in each + // verification condition + private readonly List<string/*!>!*/> Axioms = new List<string/*!*/>(); + private bool AxiomsAreSetup = false; + + + + + // similarly, a list of function/predicate declarations + private readonly List<string/*!>!*/> TypeDecls = new List<string/*!*/>(); + + protected void AddAxiom(string axiom) + { + Contract.Requires(axiom != null); + Axioms.Add(axiom); + // if (thmProver != null) { + // LogActivity(":assume " + axiom); + // thmProver.AddAxioms(axiom); + // } + } + + protected void AddTypeDecl(string decl) + { + Contract.Requires(decl != null); + TypeDecls.Add(decl); + // if (thmProver != null) { + // LogActivity(decl); + // thmProver.Feed(decl, 0); + // } + } + + //////////////////////////////////////////////////////////////////////////// + + private static string _backgroundPredicates; + + static void InitializeGlobalInformation() + { + Contract.Ensures(_backgroundPredicates != null); + //throws ProverException, System.IO.FileNotFoundException; + if (_backgroundPredicates == null) { + if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.Monomorphic) + { + _backgroundPredicates = ""; + } + else + { + _backgroundPredicates = @" +(set-info :category ""industrial"") +(declare-sort |T@U| 0) +(declare-sort |T@T| 0) +(declare-fun real_pow (Real Real) Real) +(declare-fun UOrdering2 (|T@U| |T@U|) Bool) +(declare-fun UOrdering3 (|T@T| |T@U| |T@U|) Bool)"; + } + } + } + + public override VCExpressionGenerator VCExprGen + { + get { return this.gen; } + } + + //// Push/pop interface + + //List<string> pushedAssertions = new List<string>(); + //int numRealPushes; + public override string VCExpressionToString(VCExpr vc) + { + return VCExpr2String(vc, 1); + } + + public override void PushVCExpression(VCExpr vc) + { + throw new NotImplementedException(); + + } + + public override void Pop() + { + SendThisVC("(pop 1)"); + DeclCollector.Pop(); + } + + public override int NumAxiomsPushed() + { + throw new NotImplementedException(); + //return numRealPushes + pushedAssertions.Count; + } + + private void FlushPushedAssertions() + { + throw new NotImplementedException(); + } + + public override void Assert(VCExpr vc, bool polarity) + { + string a = ""; + if (polarity) + { + a = "(assert " + VCExpr2String(vc, 1) + ")"; + } + else + { + a = "(assert (not\n" + VCExpr2String(vc, 1) + "\n))"; + } + AssertAxioms(); + SendThisVC(a); + } + + public override void DefineMacro(Macro f, VCExpr vc) { + DeclCollector.AddFunction(f); + string printedName = Namer.GetQuotedName(f, f.Name); + var argTypes = f.InParams.Cast<Variable>().MapConcat(p => DeclCollector.TypeToStringReg(p.TypedIdent.Type), " "); + string decl = "(define-fun " + printedName + " (" + argTypes + ") " + DeclCollector.TypeToStringReg(f.OutParams[0].TypedIdent.Type) + " " + VCExpr2String(vc, 1) + ")"; + AssertAxioms(); + SendThisVC(decl); + } + + public override void AssertAxioms() + { + FlushAxioms(); + } + + public override void Check() + { + PrepareCommon(); + SendThisVC("(check-sat)"); + FlushLogFile(); + } + + public override void SetTimeOut(int ms) + { + if (options.Solver == SolverKind.Z3) { + var name = Z3.SetTimeoutOption(); + var value = ms.ToString(); + options.TimeLimit = ms; + options.SmtOptions.RemoveAll(ov => ov.Option == name); + options.AddSmtOption(name, value); + SendThisVC(string.Format("(set-option :{0} {1})", name, value)); + } + } + + public override object Evaluate(VCExpr expr) + { + string vcString = VCExpr2String(expr, 1); + SendThisVC("(get-value (" + vcString + "))"); + var resp = Process.GetProverResponse(); + if (resp == null) throw new VCExprEvaluationException(); + if (!(resp.Name == "" && resp.ArgCount == 1)) throw new VCExprEvaluationException(); + resp = resp.Arguments[0]; + if (resp.Name == "") + { + // evaluating an expression + if (resp.ArgCount == 2) + resp = resp.Arguments[1]; + else + throw new VCExprEvaluationException(); + } + else + { + // evaluating a variable + if (resp.ArgCount == 1) + resp = resp.Arguments[0]; + else + throw new VCExprEvaluationException(); + } + if (resp.Name == "-" && resp.ArgCount == 1) // negative int + return Microsoft.Basetypes.BigNum.FromString("-" + resp.Arguments[0].Name); + if (resp.Name == "_" && resp.ArgCount == 2 && resp.Arguments[0].Name.StartsWith("bv")) // bitvector + return new BvConst(Microsoft.Basetypes.BigNum.FromString(resp.Arguments[0].Name.Substring("bv".Length)), + int.Parse(resp.Arguments[1].Name)); + if (resp.ArgCount != 0) + throw new VCExprEvaluationException(); + if (expr.Type.Equals(Boogie.Type.Bool)) + return bool.Parse(resp.Name); + else if (expr.Type.Equals(Boogie.Type.Int)) + return Microsoft.Basetypes.BigNum.FromString(resp.Name); + else + return resp.Name; + } + + /// <summary> + /// Extra state for ApiChecker (used by stratifiedInlining) + /// </summary> + static int nameCounter = 0; + + public override Outcome CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore, ErrorHandler handler) + { + unsatCore = new List<int>(); + + Push(); + // Name the assumptions + var nameToAssumption = new Dictionary<string, int>(); + int i = 0; + foreach (var vc in assumptions) + { + var name = "a" + nameCounter.ToString(); + nameCounter++; + nameToAssumption.Add(name, i); + + string vcString = VCExpr2String(vc, 1); + AssertAxioms(); + SendThisVC(string.Format("(assert (! {0} :named {1}))", vcString, name)); + i++; + } + Check(); + + var outcome = CheckOutcomeCore(handler); + + if (outcome != Outcome.Valid) { + Pop(); + return outcome; + } + + Contract.Assert(usingUnsatCore, "SMTLib prover not setup for computing unsat cores"); + SendThisVC("(get-unsat-core)"); + var resp = Process.GetProverResponse(); + unsatCore = new List<int>(); + if (resp.Name != "") unsatCore.Add(nameToAssumption[resp.Name]); + foreach (var s in resp.Arguments) unsatCore.Add(nameToAssumption[s.Name]); + + FlushLogFile(); + Pop(); + return outcome; + } + + public override void Push() + { + SendThisVC("(push 1)"); + DeclCollector.Push(); + } + + public override Outcome CheckAssumptions(List<VCExpr> hardAssumptions, List<VCExpr> softAssumptions, out List<int> unsatisfiedSoftAssumptions, ErrorHandler handler) { + unsatisfiedSoftAssumptions = new List<int>(); + + // First, convert both hard and soft assumptions to SMTLIB strings + List<string> hardAssumptionStrings = new List<string>(); + foreach (var a in hardAssumptions) { + hardAssumptionStrings.Add(VCExpr2String(a, 1)); + } + List<string> currAssumptionStrings = new List<string>(); + foreach (var a in softAssumptions) { + currAssumptionStrings.Add(VCExpr2String(a, 1)); + } + + Push(); + AssertAxioms(); + foreach (var a in hardAssumptionStrings) { + SendThisVC("(assert " + a + ")"); + } + Check(); + Outcome outcome = GetResponse(); + if (outcome != Outcome.Invalid) { + Pop(); + return outcome; + } + + int k = 0; + List<string> relaxVars = new List<string>(); + while (true) { + Push(); + foreach (var a in currAssumptionStrings) { + SendThisVC("(assert " + a + ")"); + } + Check(); + outcome = CheckOutcomeCore(handler); + if (outcome != Outcome.Valid) + break; + Pop(); + string relaxVar = "relax_" + k; + relaxVars.Add(relaxVar); + SendThisVC("(declare-fun " + relaxVar + " () Int)"); + List<string> nextAssumptionStrings = new List<string>(); + for (int i = 0; i < currAssumptionStrings.Count; i++) { + string constraint = "(= " + relaxVar + " " + i + ")"; + nextAssumptionStrings.Add("(or " + currAssumptionStrings[i] + " " + constraint + ")"); + } + currAssumptionStrings = nextAssumptionStrings; + k++; + } + + if (outcome == Outcome.Invalid) { + foreach (var relaxVar in relaxVars) { + SendThisVC("(get-value (" + relaxVar + "))"); + FlushLogFile(); + var resp = Process.GetProverResponse(); + if (resp == null) break; + if (!(resp.Name == "" && resp.ArgCount == 1)) break; + resp = resp.Arguments[0]; + if (!(resp.Name != "" && resp.ArgCount == 1)) break; + resp = resp.Arguments[0]; + if (resp.ArgCount != 0) + break; + int v; + if (int.TryParse(resp.Name, out v)) + unsatisfiedSoftAssumptions.Add(v); + else + break; + } + Pop(); + } + + Pop(); + return outcome; + } + } + + public class SMTLibInterpolatingProcessTheoremProver : SMTLibProcessTheoremProver + { + public SMTLibInterpolatingProcessTheoremProver(ProverOptions options, VCExpressionGenerator gen, + SMTLibProverContext ctx) + : base(AddInterpOption(options), gen, ctx) + { + + } + + private static ProverOptions AddInterpOption(ProverOptions options) + { + var opts = (SMTLibProverOptions)options; + opts.AddSmtOption("produce-interpolants", "true"); + if (CommandLineOptions.Clo.PrintFixedPoint == null) + CommandLineOptions.Clo.PrintFixedPoint = "itp.fixedpoint.bpl"; + return opts; + } + + public override void AssertNamed(VCExpr vc, bool polarity, string name) + { + string vcString; + if (polarity) + { + vcString = VCExpr2String(vc, 1); + } + else + { + vcString = "(not " + VCExpr2String(vc, 1) + ")"; + } + AssertAxioms(); + SendThisVC(string.Format("(assert (! {0} :named {1}))", vcString, name)); + } + + public override VCExpr ComputeInterpolant(VCExpr A, VCExpr B) + { + string A_str = VCExpr2String(A, 1); + string B_str = VCExpr2String(B, 1); + + AssertAxioms(); + SendThisVC("(compute-interpolant " + A_str + " " + B_str + ")"); + + SExpr interpolant; + Outcome result = GetInterpolantResponse(out interpolant); + + if (result != Outcome.Valid) + return null; + + VCExpr interpolantVC = SExprToVCExpr(interpolant, new Dictionary<string, VCExpr>()); + return interpolantVC; + } + + private Outcome GetInterpolantResponse(out SExpr interpolant) + { + var result = Outcome.Undetermined; + var wasUnknown = false; + interpolant = null; + + Process.Ping(); + bool onlyOnce = false; + + while (true) + { + var resp = Process.GetProverResponse(); + if (resp == null || Process.IsPong(resp)) + break; + + switch (resp.Name) + { + case "unsat": + result = Outcome.Valid; + break; + case "sat": + result = Outcome.Invalid; + break; + case "unknown": + result = Outcome.Invalid; + wasUnknown = true; + break; + default: + if (result == Outcome.Valid) + { + interpolant = resp as SExpr; + + Contract.Assert(onlyOnce == false); + onlyOnce = true; + continue; + } + HandleProverError("Unexpected prover response: " + resp.ToString()); + break; + } + } + + if (wasUnknown) + { + SendThisVC("(get-info :reason-unknown)"); + Process.Ping(); + + while (true) + { + var resp = Process.GetProverResponse(); + if (resp == null || Process.IsPong(resp)) + break; + + if (resp.ArgCount == 1 && resp.Name == ":reason-unknown") + { + switch (resp[0].Name) + { + case "memout": + currentErrorHandler.OnResourceExceeded("memory"); + result = Outcome.OutOfMemory; + Process.NeedsRestart = true; + break; + case "timeout": + case "canceled": + currentErrorHandler.OnResourceExceeded("timeout"); + result = Outcome.TimeOut; + break; + default: + break; + } + } + else + { + HandleProverError("Unexpected prover response (getting info about 'unknown' response): " + resp.ToString()); + } + } + } + + return result; + } + + public override List<VCExpr> GetTreeInterpolant(List<string> root, List<string> leaves) + { + List<VCExpr> result = new List<VCExpr>(); + + string vcStr = "true"; + foreach (string str in root) + vcStr = vcStr + " " + str; + foreach (string str in leaves) + vcStr = vcStr + "\r\n (interp " + str + ")"; + + vcStr = "(get-interpolant (and\r\n" + vcStr + "\r\n))"; + SendThisVC(vcStr); + if(currentLogFile != null) currentLogFile.Flush(); + + List<SExpr> interpolantList; + GetTreeInterpolantResponse(out interpolantList); + + Dictionary<string, VCExpr> bound = new Dictionary<string, VCExpr>(); + foreach (SExpr sexpr in interpolantList) + { + VCExpr interpolantVC = SExprToVCExpr(sexpr, bound); + result.Add(interpolantVC); + } + + return result; + } + + private void GetTreeInterpolantResponse(out List<SExpr> interpolantList) + { + interpolantList = new List<SExpr>(); + + Process.Ping(); + + while (true) + { + var resp = Process.GetProverResponse(); + if (resp == null || Process.IsPong(resp)) + break; + + SExpr interpolant = resp as SExpr; + if(interpolant == null) + HandleProverError("Unexpected prover response: got null for interpolant!"); + interpolantList.Add(interpolant); + } + } + } + + public class SMTLibProverContext : DeclFreeProverContext + { + internal SMTLibProcessTheoremProver parent; + + public readonly Dictionary<CtorType, List<Function>> KnownDatatypeConstructors = new Dictionary<CtorType, List<Function>>(); + + public SMTLibProverContext(VCExpressionGenerator gen, + VCGenerationOptions genOptions) + : base(gen, genOptions) + { + } + + protected SMTLibProverContext(SMTLibProverContext par) + : base(par) + { + } + + public override object Clone() + { + return new SMTLibProverContext(this); + } + + public override string Lookup(VCExprVar var) + { + VCExprVar v = parent.AxBuilder.TryTyped2Untyped(var); + if (v != null) { + var = v; + } + return parent.Namer.Lookup(var); + } + + public override void DeclareFunction(Function f, string attributes) { + if (f is DatatypeConstructor) { + CtorType datatype = (CtorType) f.OutParams[0].TypedIdent.Type; + if (!KnownDatatypeConstructors.ContainsKey(datatype)) + KnownDatatypeConstructors[datatype] = new List<Function>(); + KnownDatatypeConstructors[datatype].Add(f); + } + base.DeclareFunction(f, attributes); + } + } + + public class Factory : ProverFactory + { + // Set programmatically + public static bool UseInterpolation = false; + + public override object SpawnProver(ProverOptions options, object ctxt) + { + //Contract.Requires(ctxt != null); + //Contract.Requires(options != null); + Contract.Ensures(Contract.Result<object>() != null); + + return this.SpawnProver(options, + cce.NonNull((SMTLibProverContext)ctxt).ExprGen, + cce.NonNull((SMTLibProverContext)ctxt)); + } + + public override object NewProverContext(ProverOptions options) + { + //Contract.Requires(options != null); + Contract.Ensures(Contract.Result<object>() != null); + + VCExpressionGenerator gen = new VCExpressionGenerator(); + List<string>/*!>!*/ proverCommands = new List<string/*!*/>(); + proverCommands.Add("smtlib"); + var opts = (SMTLibProverOptions)options ; + if (opts.Solver == SolverKind.Z3) + proverCommands.Add("z3"); + else + proverCommands.Add("external"); + VCGenerationOptions genOptions = new VCGenerationOptions(proverCommands); + return new SMTLibProverContext(gen, genOptions); + } + + public override ProverOptions BlankProverOptions() + { + return new SMTLibProverOptions(); + } + + protected virtual SMTLibProcessTheoremProver SpawnProver(ProverOptions options, + VCExpressionGenerator gen, + SMTLibProverContext ctx) + { + Contract.Requires(options != null); + Contract.Requires(gen != null); + Contract.Requires(ctx != null); + Contract.Ensures(Contract.Result<SMTLibProcessTheoremProver>() != null); + + if (UseInterpolation) + return new SMTLibInterpolatingProcessTheoremProver(options, gen, ctx); + + return new SMTLibProcessTheoremProver(options, gen, ctx); + } + + public override bool SupportsLabels(ProverOptions options) + { + return ((SMTLibProverOptions)options).SupportsLabels; + } + } +} diff --git a/Source/Provers/SMTLib/SExpr.cs b/Source/Provers/SMTLib/SExpr.cs index ac681b8a..3e9687e1 100644 --- a/Source/Provers/SMTLib/SExpr.cs +++ b/Source/Provers/SMTLib/SExpr.cs @@ -1,263 +1,263 @@ -//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
-using System;
-using System.Linq;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Text;
-using System.Diagnostics.Contracts;
-using System.Globalization;
-
-namespace Microsoft.Boogie
-{
- public class SExpr
- {
- static readonly SExpr[] EmptyArgs = new SExpr[0];
- public readonly string Name;
- public SExpr[] Arguments
- {
- get
- {
- Contract.Ensures(Contract.Result<SExpr[]>() != null);
- Contract.Ensures(Contract.ForAll(Contract.Result<SExpr[]>(), expr => expr != null));
-
- return this.arguments;
- }
- }
-
- public SExpr this[int idx]
- {
- get
- {
- return Arguments[idx];
- }
- }
-
- public int ArgCount
- {
- get { return arguments.Length; }
- }
-
- public bool IsId
- {
- get { return Arguments.Length == 0; }
- }
-
- private readonly SExpr[] arguments;
-
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(this.Name != null);
- Contract.Invariant(this.arguments != null);
- Contract.Invariant(Contract.ForAll(this.arguments, arg => arg != null));
- }
-
- public SExpr(string name, params SExpr[] args)
- : this(name, (IEnumerable<SExpr>)args)
- {
- Contract.Requires(name != null);
- Contract.Requires(args != null);
- Contract.Requires(Contract.ForAll(args, x => x != null));
- }
-
- public SExpr(string name, IEnumerable<SExpr> args)
- {
- Contract.Requires(name != null);
- Contract.Requires(args != null);
- // We don't want to evaluate args twice!
- // Contract.Requires(Contract.ForAll(args, x => x != null));
- Name = name;
- arguments = args.ToArray();
- }
-
- public SExpr(string name)
- : this(name, EmptyArgs)
- {
- Contract.Requires(name != null);
- }
-
- #region pretty-printing
- void WriteTo(StringBuilder sb)
- {
- Contract.Requires(sb != null);
-
- if (Arguments.Length > 0) sb.Append('(');
- if (Name.Any(Char.IsWhiteSpace))
- sb.Append("\"").Append(Name).Append("\"");
- else if (Name.Length == 0)
- sb.Append("()");
- else
- sb.Append(Name);
- foreach (var a in Arguments) {
- sb.Append(' ');
- a.WriteTo(sb);
- }
- if (Arguments.Length > 0) sb.Append(')');
- }
-
- public override string ToString()
- {
- var sb = new StringBuilder();
- this.WriteTo(sb);
- return sb.ToString();
- }
- #endregion
-
- #region parsing
-
- public abstract class Parser
- {
- System.IO.StreamReader sr;
- int linePos = 0;
- string currLine = null;
-
- public Parser(System.IO.StreamReader _sr)
- {
- sr = _sr;
- }
- string Read()
- {
- return sr.ReadLine();
- }
- char SkipWs()
- {
- while (true)
- {
- if (currLine == null)
- {
- currLine = Read();
- if (currLine == null)
- return '\0';
- }
-
- while (linePos < currLine.Length && char.IsWhiteSpace(currLine[linePos]))
- linePos++;
-
- if (linePos < currLine.Length)
- return currLine[linePos];
- else
- {
- currLine = null;
- linePos = 0;
- }
- }
- }
-
- void Shift()
- {
- linePos++;
- }
-
- string ParseId()
- {
- var sb = new StringBuilder();
-
- var beg = SkipWs();
-
- var quoted = beg == '"' || beg == '|';
- if (quoted)
- Shift();
- while (true)
- {
- if (linePos >= currLine.Length)
- {
- if (quoted)
- {
- sb.Append("\n");
- currLine = Read();
- linePos = 0;
- if (currLine == null)
- break;
- }
- else break;
- }
-
- var c = currLine[linePos++];
- if (quoted && c == beg)
- break;
- if (!quoted && (char.IsWhiteSpace(c) || c == '(' || c == ')'))
- {
- linePos--;
- break;
- }
- if (quoted && c == '\\' && linePos < currLine.Length && currLine[linePos] == '"')
- {
- sb.Append('"');
- linePos++;
- continue;
- }
- sb.Append(c);
- }
-
- return sb.ToString();
- }
-
- public abstract void ParseError(string msg);
-
- public IEnumerable<SExpr> ParseSExprs(bool top)
- {
- while (true)
- {
- var c = SkipWs();
- if (c == '\0')
- break;
-
- if (c == ')')
- {
- if (top)
- ParseError("stray ')'");
- break;
- }
-
- string id;
-
- if (c == '(')
- {
- Shift();
- c = SkipWs();
- if (c == '\0')
- {
- ParseError("expecting something after '('");
- break;
- }
- else if (c == '(')
- {
- id = "";
- }
- else
- {
- id = ParseId();
- }
-
- var args = ParseSExprs(false).ToArray();
-
- c = SkipWs();
- if (c == ')')
- {
- Shift();
- }
- else
- {
- ParseError("unclosed '(" + id + "'");
- }
- yield return new SExpr(id, args);
- }
- else
- {
- id = ParseId();
- yield return new SExpr(id);
- }
-
- if (top) break;
- }
- }
- }
- #endregion
- }
-}
-
+//----------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- + +using System; +using System.Linq; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Text; +using System.Diagnostics.Contracts; +using System.Globalization; + +namespace Microsoft.Boogie +{ + public class SExpr + { + static readonly SExpr[] EmptyArgs = new SExpr[0]; + public readonly string Name; + public SExpr[] Arguments + { + get + { + Contract.Ensures(Contract.Result<SExpr[]>() != null); + Contract.Ensures(Contract.ForAll(Contract.Result<SExpr[]>(), expr => expr != null)); + + return this.arguments; + } + } + + public SExpr this[int idx] + { + get + { + return Arguments[idx]; + } + } + + public int ArgCount + { + get { return arguments.Length; } + } + + public bool IsId + { + get { return Arguments.Length == 0; } + } + + private readonly SExpr[] arguments; + + [ContractInvariantMethod] + void ObjectInvariant() + { + Contract.Invariant(this.Name != null); + Contract.Invariant(this.arguments != null); + Contract.Invariant(Contract.ForAll(this.arguments, arg => arg != null)); + } + + public SExpr(string name, params SExpr[] args) + : this(name, (IEnumerable<SExpr>)args) + { + Contract.Requires(name != null); + Contract.Requires(args != null); + Contract.Requires(Contract.ForAll(args, x => x != null)); + } + + public SExpr(string name, IEnumerable<SExpr> args) + { + Contract.Requires(name != null); + Contract.Requires(args != null); + // We don't want to evaluate args twice! + // Contract.Requires(Contract.ForAll(args, x => x != null)); + Name = name; + arguments = args.ToArray(); + } + + public SExpr(string name) + : this(name, EmptyArgs) + { + Contract.Requires(name != null); + } + + #region pretty-printing + void WriteTo(StringBuilder sb) + { + Contract.Requires(sb != null); + + if (Arguments.Length > 0) sb.Append('('); + if (Name.Any(Char.IsWhiteSpace)) + sb.Append("\"").Append(Name).Append("\""); + else if (Name.Length == 0) + sb.Append("()"); + else + sb.Append(Name); + foreach (var a in Arguments) { + sb.Append(' '); + a.WriteTo(sb); + } + if (Arguments.Length > 0) sb.Append(')'); + } + + public override string ToString() + { + var sb = new StringBuilder(); + this.WriteTo(sb); + return sb.ToString(); + } + #endregion + + #region parsing + + public abstract class Parser + { + System.IO.StreamReader sr; + int linePos = 0; + string currLine = null; + + public Parser(System.IO.StreamReader _sr) + { + sr = _sr; + } + string Read() + { + return sr.ReadLine(); + } + char SkipWs() + { + while (true) + { + if (currLine == null) + { + currLine = Read(); + if (currLine == null) + return '\0'; + } + + while (linePos < currLine.Length && char.IsWhiteSpace(currLine[linePos])) + linePos++; + + if (linePos < currLine.Length) + return currLine[linePos]; + else + { + currLine = null; + linePos = 0; + } + } + } + + void Shift() + { + linePos++; + } + + string ParseId() + { + var sb = new StringBuilder(); + + var beg = SkipWs(); + + var quoted = beg == '"' || beg == '|'; + if (quoted) + Shift(); + while (true) + { + if (linePos >= currLine.Length) + { + if (quoted) + { + sb.Append("\n"); + currLine = Read(); + linePos = 0; + if (currLine == null) + break; + } + else break; + } + + var c = currLine[linePos++]; + if (quoted && c == beg) + break; + if (!quoted && (char.IsWhiteSpace(c) || c == '(' || c == ')')) + { + linePos--; + break; + } + if (quoted && c == '\\' && linePos < currLine.Length && currLine[linePos] == '"') + { + sb.Append('"'); + linePos++; + continue; + } + sb.Append(c); + } + + return sb.ToString(); + } + + public abstract void ParseError(string msg); + + public IEnumerable<SExpr> ParseSExprs(bool top) + { + while (true) + { + var c = SkipWs(); + if (c == '\0') + break; + + if (c == ')') + { + if (top) + ParseError("stray ')'"); + break; + } + + string id; + + if (c == '(') + { + Shift(); + c = SkipWs(); + if (c == '\0') + { + ParseError("expecting something after '('"); + break; + } + else if (c == '(') + { + id = ""; + } + else + { + id = ParseId(); + } + + var args = ParseSExprs(false).ToArray(); + + c = SkipWs(); + if (c == ')') + { + Shift(); + } + else + { + ParseError("unclosed '(" + id + "'"); + } + yield return new SExpr(id, args); + } + else + { + id = ParseId(); + yield return new SExpr(id); + } + + if (top) break; + } + } + } + #endregion + } +} + diff --git a/Source/Provers/SMTLib/SMTLib.csproj b/Source/Provers/SMTLib/SMTLib.csproj index 5e80f4c1..00febc0a 100644 --- a/Source/Provers/SMTLib/SMTLib.csproj +++ b/Source/Provers/SMTLib/SMTLib.csproj @@ -1,237 +1,237 @@ -<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Microsoft.Boogie.SMTLib</RootNamespace>
- <AssemblyName>Provers.SMTLib</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly>
- </CodeContractsCustomRewriterAssembly>
- <CodeContractsCustomRewriterClass>
- </CodeContractsCustomRewriterClass>
- <CodeContractsLibPaths>
- </CodeContractsLibPaths>
- <CodeContractsExtraRewriteOptions>
- </CodeContractsExtraRewriteOptions>
- <CodeContractsExtraAnalysisOptions>
- </CodeContractsExtraAnalysisOptions>
- <CodeContractsBaseLineFile>
- </CodeContractsBaseLineFile>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for SMTLib.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\Provers.SMTLib.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core">
- <RequiredTargetFramework>3.5</RequiredTargetFramework>
- </Reference>
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="Inspector.cs" />
- <Compile Include="SMTLibProverOptions.cs" />
- <Compile Include="ProverInterface.cs" />
- <Compile Include="SExpr.cs" />
- <Compile Include="SMTLibLineariser.cs" />
- <Compile Include="SMTLibNamer.cs" />
- <Compile Include="SMTLibProcess.cs" />
- <Compile Include="TypeDeclCollector.cs" />
- <Compile Include="..\..\version.cs" />
- <Compile Include="Z3.cs" />
- <Compile Include="CVC4.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Graph\Graph.csproj">
- <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
- <Name>Graph</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\Model\Model.csproj">
- <Project>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</Project>
- <Name>Model</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\VCExpr\VCExpr.csproj">
- <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
- <Name>VCExpr</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\VCGeneration\VCGeneration.csproj">
- <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
- <Name>VCGeneration</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project>
+<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.21022</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Microsoft.Boogie.SMTLib</RootNamespace> + <AssemblyName>Provers.SMTLib</AssemblyName> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode> + <SignAssembly>true</SignAssembly> + <AssemblyOriginatorKeyFile>..\..\InterimKey.snk</AssemblyOriginatorKeyFile> + <FileUpgradeFlags> + </FileUpgradeFlags> + <OldToolsVersion>3.5</OldToolsVersion> + <UpgradeBackupLocation /> + <PublishUrl>publish\</PublishUrl> + <Install>true</Install> + <InstallFrom>Disk</InstallFrom> + <UpdateEnabled>false</UpdateEnabled> + <UpdateMode>Foreground</UpdateMode> + <UpdateInterval>7</UpdateInterval> + <UpdateIntervalUnits>Days</UpdateIntervalUnits> + <UpdatePeriodically>false</UpdatePeriodically> + <UpdateRequired>false</UpdateRequired> + <MapFileExtensions>true</MapFileExtensions> + <ApplicationRevision>0</ApplicationRevision> + <ApplicationVersion>1.0.0.%2a</ApplicationVersion> + <IsWebBootstrapper>false</IsWebBootstrapper> + <UseApplicationTrust>false</UseApplicationTrust> + <BootstrapperEnabled>true</BootstrapperEnabled> + <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking> + <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface> + <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure> + <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires> + <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis> + <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations> + <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations> + <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations> + <CodeContractsPointerObligations>False</CodeContractsPointerObligations> + <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis> + <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions> + <CodeContractsRunInBackground>True</CodeContractsRunInBackground> + <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies> + <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine> + <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs> + <CodeContractsCustomRewriterAssembly> + </CodeContractsCustomRewriterAssembly> + <CodeContractsCustomRewriterClass> + </CodeContractsCustomRewriterClass> + <CodeContractsLibPaths> + </CodeContractsLibPaths> + <CodeContractsExtraRewriteOptions> + </CodeContractsExtraRewriteOptions> + <CodeContractsExtraAnalysisOptions> + </CodeContractsExtraAnalysisOptions> + <CodeContractsBaseLineFile> + </CodeContractsBaseLineFile> + <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel> + <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <OutputPath>bin\z3apidebug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DebugType>full</DebugType> + <PlatformTarget>AnyCPU</PlatformTarget> + <CodeAnalysisRuleAssemblies> + </CodeAnalysisRuleAssemblies> + <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> + <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>Migrated rules for SMTLib.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules> + <WarningLevel>4</WarningLevel> + <Optimize>false</Optimize> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'"> + <DebugSymbols>true</DebugSymbols> + <OutputPath>bin\Checked\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DebugType>full</DebugType> + <PlatformTarget>AnyCPU</PlatformTarget> + <CodeAnalysisLogFile>bin\Debug\Provers.SMTLib.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile> + <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> + <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories> + <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories> + <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking> + <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface> + <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure> + <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires> + <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers> + <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis> + <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations> + <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations> + <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations> + <CodeContractsEnumObligations>False</CodeContractsEnumObligations> + <CodeContractsPointerObligations>False</CodeContractsPointerObligations> + <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions> + <CodeContractsRunInBackground>True</CodeContractsRunInBackground> + <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies> + <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine> + <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs> + <CodeContractsCustomRewriterAssembly /> + <CodeContractsCustomRewriterClass /> + <CodeContractsLibPaths /> + <CodeContractsExtraRewriteOptions /> + <CodeContractsExtraAnalysisOptions /> + <CodeContractsBaseLineFile /> + <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults> + <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel> + <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly> + <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel> + <WarningLevel>4</WarningLevel> + <Optimize>false</Optimize> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'"> + <DebugSymbols>true</DebugSymbols> + <OutputPath>bin\QED\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DebugType>full</DebugType> + <PlatformTarget>AnyCPU</PlatformTarget> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Inspector.cs" /> + <Compile Include="SMTLibProverOptions.cs" /> + <Compile Include="ProverInterface.cs" /> + <Compile Include="SExpr.cs" /> + <Compile Include="SMTLibLineariser.cs" /> + <Compile Include="SMTLibNamer.cs" /> + <Compile Include="SMTLibProcess.cs" /> + <Compile Include="TypeDeclCollector.cs" /> + <Compile Include="..\..\version.cs" /> + <Compile Include="Z3.cs" /> + <Compile Include="CVC4.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\Basetypes\Basetypes.csproj"> + <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project> + <Name>Basetypes</Name> + </ProjectReference> + <ProjectReference Include="..\..\CodeContractsExtender\CodeContractsExtender.csproj"> + <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project> + <Name>CodeContractsExtender</Name> + </ProjectReference> + <ProjectReference Include="..\..\Core\Core.csproj"> + <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project> + <Name>Core</Name> + </ProjectReference> + <ProjectReference Include="..\..\Graph\Graph.csproj"> + <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project> + <Name>Graph</Name> + </ProjectReference> + <ProjectReference Include="..\..\Model\Model.csproj"> + <Project>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</Project> + <Name>Model</Name> + </ProjectReference> + <ProjectReference Include="..\..\ParserHelper\ParserHelper.csproj"> + <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project> + <Name>ParserHelper</Name> + </ProjectReference> + <ProjectReference Include="..\..\VCExpr\VCExpr.csproj"> + <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project> + <Name>VCExpr</Name> + </ProjectReference> + <ProjectReference Include="..\..\VCGeneration\VCGeneration.csproj"> + <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project> + <Name>VCGeneration</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <Folder Include="Properties\" /> + </ItemGroup> + <ItemGroup> + <BootstrapperPackage Include="Microsoft.Net.Client.3.5"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1</ProductName> + <Install>true</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1"> + <Visible>False</Visible> + <ProductName>Windows Installer 3.1</ProductName> + <Install>true</Install> + </BootstrapperPackage> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project> diff --git a/Source/Provers/SMTLib/SMTLibLineariser.cs b/Source/Provers/SMTLib/SMTLibLineariser.cs index f431c3d5..dcf95bd2 100644 --- a/Source/Provers/SMTLib/SMTLibLineariser.cs +++ b/Source/Provers/SMTLib/SMTLibLineariser.cs @@ -1,851 +1,851 @@ -//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Linq;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-// Method to turn VCExprs into strings that can be fed into SMT
-// solvers. This is currently quite similar to the
-// SimplifyLikeLineariser (but the code is independent)
-
-namespace Microsoft.Boogie.SMTLib
-{
-
- // Options for the linearisation
- public class LineariserOptions
- {
- public static LineariserOptions Default = new LineariserOptions();
- public bool LabelsBelowQuantifiers = false;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////////////
-
- // Lineariser for expressions. The result (bool) is currently not used for anything
- public class SMTLibExprLineariser : IVCExprVisitor<bool, LineariserOptions/*!*/>
- {
-
- public static string ToString(VCExpr e, UniqueNamer namer, SMTLibProverOptions opts)
- {
- Contract.Requires(e != null);
- Contract.Requires(namer != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- StringWriter sw = new StringWriter();
- SMTLibExprLineariser lin = new SMTLibExprLineariser(sw, namer, opts);
- Contract.Assert(lin != null);
- lin.Linearise(e, LineariserOptions.Default);
- return cce.NonNull(sw.ToString());
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////
-
- private readonly TextWriter wr;
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(wr != null);
- Contract.Invariant(Namer != null);
- }
-
- private SMTLibOpLineariser OpLinObject = null;
- private IVCExprOpVisitor<bool, LineariserOptions>/*!>!*/ OpLineariser
- {
- get
- {
- Contract.Ensures(Contract.Result<IVCExprOpVisitor<bool, LineariserOptions>>() != null);
-
- if (OpLinObject == null)
- OpLinObject = new SMTLibOpLineariser(this, wr);
- return OpLinObject;
- }
- }
-
- internal readonly UniqueNamer Namer;
- internal int UnderQuantifier = 0;
- internal readonly SMTLibProverOptions ProverOptions;
-
- public SMTLibExprLineariser(TextWriter wr, UniqueNamer namer, SMTLibProverOptions opts)
- {
- Contract.Requires(wr != null); Contract.Requires(namer != null);
- this.wr = wr;
- this.Namer = namer;
- this.ProverOptions = opts;
- }
-
- public void Linearise(VCExpr expr, LineariserOptions options)
- {
- Contract.Requires(expr != null);
- Contract.Requires(options != null);
- expr.Accept<bool, LineariserOptions>(this, options);
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- private static void TypeToStringHelper(Type t, StringBuilder sb)
- {
- Contract.Requires(t != null);
-
- TypeSynonymAnnotation syn = t as TypeSynonymAnnotation;
- if (syn != null) {
- TypeToStringHelper(syn.ExpandedType, sb);
- } else {
- if (t.IsMap && CommandLineOptions.Clo.UseArrayTheory) {
- MapType m = t.AsMap;
- // Contract.Assert(m.MapArity == 1);
- sb.Append("(Array ");
- foreach (Type tp in m.Arguments)
- sb.Append(TypeToString(tp)).Append(" ");
- sb.Append(TypeToString(m.Result)).Append(")");
- } else if (t.IsMap) {
- MapType m = t.AsMap;
- sb.Append('[');
- for (int i = 0; i < m.MapArity; ++i) {
- if (i != 0)
- sb.Append(',');
- TypeToStringHelper(m.Arguments[i], sb);
- }
- sb.Append(']');
- TypeToStringHelper(m.Result, sb);
- } else if (t.IsBool || t.IsInt || t.IsReal || t.IsBv) {
- sb.Append(TypeToString(t));
- } else {
- System.IO.StringWriter buffer = new System.IO.StringWriter();
- using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/false, /*pretty=*/false)) {
- t.Emit(stream);
- }
- sb.Append(buffer.ToString());
- }
- }
-
- }
-
- public static string TypeToString(Type t)
- {
- Contract.Requires(t != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- if (t.IsBool)
- return "Bool";
- else if (t.IsInt)
- return "Int";
- else if (t.IsReal)
- return "Real";
- else if (t.IsBv) {
- return "(_ BitVec " + t.BvBits + ")";
- } else {
- StringBuilder sb = new StringBuilder();
- TypeToStringHelper(t, sb);
- var s = sb.ToString();
- if (s[0] == '(')
- return s;
- else
- return SMTLibNamer.QuoteId("T@" + s);
- }
- }
-
- public static string ExtractBuiltin(Function f)
- {
- Contract.Requires(f != null);
- string retVal = null;
- retVal = f.FindStringAttribute("bvbuiltin");
-
- // It used to be "sign_extend 12" in Simplify, and is "(_ sign_extend 12)" with SMT
- if (retVal != null && (retVal.StartsWith("sign_extend ") || retVal.StartsWith("zero_extend ")))
- return "(_ " + retVal + ")";
-
- if (retVal == null) {
- retVal = f.FindStringAttribute("builtin");
- }
-
- if (retVal != null && !CommandLineOptions.Clo.UseArrayTheory && SMTLibOpLineariser.ArrayOps.Contains(retVal))
- {
- retVal = null;
- }
-
- return retVal;
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprLiteral node, LineariserOptions options)
- {
- if (node == VCExpressionGenerator.True)
- wr.Write("true");
- else if (node == VCExpressionGenerator.False)
- wr.Write("false");
- else if (node is VCExprIntLit) {
- BigNum lit = ((VCExprIntLit)node).Val;
- if (lit.IsNegative)
- // In SMT2 "-42" is an identifier (SMT2, Sect. 3.2 "Symbols")
- wr.Write("(- 0 {0})", lit.Abs);
- else
- wr.Write(lit);
- }
- else if (node is VCExprRealLit) {
- BigDec lit = ((VCExprRealLit)node).Val;
- if (lit.IsNegative)
- // In SMT2 "-42" is an identifier (SMT2, Sect. 3.2 "Symbols")
- wr.Write("(- 0.0 {0})", lit.Abs.ToDecimalString());
- else
- wr.Write(lit.ToDecimalString());
- }
- else {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- return true;
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprNAry node, LineariserOptions options)
- {
- VCExprOp op = node.Op;
- Contract.Assert(op != null);
-
- var booleanOps = new HashSet<VCExprOp>();
- booleanOps.Add(VCExpressionGenerator.NotOp);
- booleanOps.Add(VCExpressionGenerator.ImpliesOp);
- booleanOps.Add(VCExpressionGenerator.AndOp);
- booleanOps.Add(VCExpressionGenerator.OrOp);
- if (booleanOps.Contains(op))
- {
- Stack<VCExpr> exprs = new Stack<VCExpr>();
- exprs.Push(node);
- while (exprs.Count > 0)
- {
- VCExpr expr = exprs.Pop();
- if (expr == null)
- {
- wr.Write(")");
- continue;
- }
- wr.Write(" ");
- VCExprNAry naryExpr = expr as VCExprNAry;
- if (naryExpr == null || !booleanOps.Contains(naryExpr.Op))
- {
- Linearise(expr, options);
- continue;
- }
- else if (naryExpr.Op.Equals(VCExpressionGenerator.NotOp))
- {
- wr.Write("(not");
- }
- else if (naryExpr.Op.Equals(VCExpressionGenerator.ImpliesOp))
- {
- wr.Write("(=>");
- }
- else if (naryExpr.Op.Equals(VCExpressionGenerator.AndOp))
- {
- wr.Write("(and");
- }
- else
- {
- System.Diagnostics.Debug.Assert(naryExpr.Op.Equals(VCExpressionGenerator.OrOp));
- wr.Write("(or");
- }
- exprs.Push(null);
- for (int i = naryExpr.Arity - 1; i >= 0; i--)
- {
- exprs.Push(naryExpr[i]);
- }
- }
- return true;
- }
- return node.Accept<bool, LineariserOptions/*!*/>(OpLineariser, options);
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprVar node, LineariserOptions options)
- {
- wr.Write(Namer.GetQuotedName(node, node.Name));
- return true;
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprQuantifier node, LineariserOptions options)
- {
- Contract.Assert(node.TypeParameters.Count == 0);
-
- UnderQuantifier++;
- Namer.PushScope(); try {
-
- string kind = node.Quan == Quantifier.ALL ? "forall" : "exists";
- wr.Write("({0} (", kind);
-
- for (int i = 0; i < node.BoundVars.Count; i++) {
- VCExprVar var = node.BoundVars[i];
- Contract.Assert(var != null);
- string printedName = Namer.GetQuotedLocalName(var, var.Name);
- Contract.Assert(printedName != null);
- wr.Write("({0} {1}) ", printedName, TypeToString(var.Type));
- }
-
- wr.Write(") ");
-
- VCQuantifierInfos infos = node.Infos;
- var weight = QKeyValue.FindIntAttribute(infos.attributes, "weight", 1);
- if (!ProverOptions.UseWeights)
- weight = 1;
- var hasAttrs = node.Triggers.Count > 0 || infos.qid != null || weight != 1 || infos.uniqueId != -1;
-
- if (hasAttrs)
- wr.Write("(! ");
-
- Linearise(node.Body, options);
-
- if (hasAttrs) {
- wr.Write("\n");
- if (infos.qid != null)
- wr.Write(" :qid {0}\n", SMTLibNamer.QuoteId(infos.qid));
- if (weight != 1)
- wr.Write(" :weight {0}\n", weight);
- if (infos.uniqueId != -1)
- wr.Write(" :skolemid |{0}|\n", infos.uniqueId);
- WriteTriggers(node.Triggers, options);
-
- wr.Write(")");
- }
-
- wr.Write(")");
-
- return true;
-
- } finally {
- UnderQuantifier--;
- Namer.PopScope();
- }
- }
-
- private void WriteTriggers(List<VCTrigger/*!>!*/> triggers, LineariserOptions options)
- {
- Contract.Requires(options != null);
- Contract.Requires(triggers != null);
- // first, count how many neg/pos triggers there are
- int negTriggers = 0;
- int posTriggers = 0;
- foreach (VCTrigger vcTrig in triggers) {
- Contract.Assert(vcTrig != null);
- if (vcTrig.Pos) {
- posTriggers++;
- } else {
- negTriggers++;
- }
- }
-
- if (posTriggers > 0) {
- foreach (VCTrigger vcTrig in triggers) {
- Contract.Assert(vcTrig != null);
- if (vcTrig.Pos) {
- wr.Write(" :pattern (");
- foreach (VCExpr e in vcTrig.Exprs) {
- Contract.Assert(e != null);
- wr.Write(" ");
- var subPat = e;
- var nary = e as VCExprNAry;
- if (nary != null && (nary.Op == VCExpressionGenerator.NeqOp || nary.Op == VCExpressionGenerator.EqOp)) {
- if (nary[0] is VCExprLiteral)
- subPat = nary[1];
- else if (nary[1] is VCExprLiteral)
- subPat = nary[0];
- }
- Linearise(subPat, options);
- }
- wr.Write(")\n");
- }
- }
- } else if (negTriggers > 0) {
- // if also positive triggers are given, the SMT solver (at least Z3)
- // will ignore the negative patterns and output a warning. Therefore
- // we never specify both negative and positive triggers
- foreach (VCTrigger vcTrig in triggers) {
- Contract.Assert(vcTrig != null);
- if (!vcTrig.Pos) {
- wr.Write(" :no-pattern ");
- Contract.Assert(vcTrig.Exprs.Count == 1);
- Linearise(vcTrig.Exprs[0], options);
- wr.Write("\n");
- }
- }
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprLet node, LineariserOptions options)
- {
- Namer.PushScope();
- try {
-
- foreach (VCExprLetBinding b in node) {
- wr.Write("(let (");
- Contract.Assert(b != null);
- wr.Write("({0} ", Namer.GetQuotedName(b.V, b.V.Name));
- Linearise(b.E, options);
- wr.Write("))\n");
- }
- Linearise(node.Body, options);
- foreach (VCExprLetBinding b in node)
- wr.Write(")");
- return true;
- } finally {
- Namer.PopScope();
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- // Lineariser for operator terms. The result (bool) is currently not used for anything
- internal class SMTLibOpLineariser : IVCExprOpVisitor<bool, LineariserOptions/*!*/>
- {
- private readonly SMTLibExprLineariser ExprLineariser;
- private readonly TextWriter wr;
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(wr != null);
- Contract.Invariant(ExprLineariser != null);
- }
-
-
- public SMTLibOpLineariser(SMTLibExprLineariser ExprLineariser, TextWriter wr)
- {
- Contract.Requires(ExprLineariser != null);
- Contract.Requires(wr != null);
- this.ExprLineariser = ExprLineariser;
- this.wr = wr;
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
- private void WriteApplication(string opName, IEnumerable<VCExpr>/*!>!*/ args, LineariserOptions options)
- {
- Contract.Requires(cce.NonNullElements(args));
- Contract.Requires(options != null);
- Contract.Assert(opName != null);
-
- bool hasArgs = false;
- foreach (VCExpr e in args) {
- Contract.Assert(e != null);
- if (!hasArgs)
- wr.Write("({0}", opName);
- wr.Write(" ");
- ExprLineariser.Linearise(e, options);
- hasArgs = true;
- }
-
- if (hasArgs)
- wr.Write(")");
- else
- wr.Write("{0}", opName);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public bool VisitNotOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("not", node, options); // arguments can be both terms and formulas
- return true;
- }
-
- private bool PrintEq(VCExprNAry node, LineariserOptions options)
- {
- Contract.Requires(node != null);
- Contract.Requires(options != null);
-
- WriteApplication("=", node, options);
-
- return true;
- }
-
- public bool VisitEqOp(VCExprNAry node, LineariserOptions options)
- {
- return PrintEq(node, options);
- }
-
- public bool VisitNeqOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
- wr.Write("(not ");
- PrintEq(node, options);
- wr.Write(")");
- return true;
- }
-
- public bool VisitAndOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("and", node, options);
- return true;
- }
-
- public bool VisitOrOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("or", node, options);
- return true;
- }
-
- public bool VisitImpliesOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("=>", node, options);
- return true;
- }
-
- public bool VisitIfThenElseOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("ite", node, options);
- return true;
- }
-
- public bool VisitCustomOp(VCExprNAry node, LineariserOptions options)
- {
- VCExprCustomOp op = (VCExprCustomOp)node.Op;
- if (!ExprLineariser.ProverOptions.UseTickleBool && op.Name == "tickleBool")
- ExprLineariser.Linearise(VCExpressionGenerator.True, options);
- else
- WriteApplication(op.Name, node, options);
- return true;
- }
-
- public bool VisitDistinctOp(VCExprNAry node, LineariserOptions options)
- {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
-
- if (node.Length < 2) {
- ExprLineariser.Linearise(VCExpressionGenerator.True, options);
- } else {
- var groupings = node.GroupBy(e => e.Type).Where(g => g.Count() > 1).ToArray();
- if (groupings.Length == 0) {
- ExprLineariser.Linearise(VCExpressionGenerator.True, options);
- } else {
- if (groupings.Length > 1)
- wr.Write("(and ");
-
- foreach (var g in groupings) {
- wr.Write("(distinct");
- foreach (VCExpr e in g) {
- Contract.Assert(e != null);
- wr.Write(" ");
- ExprLineariser.Linearise(e, options);
- }
- wr.Write(")");
- }
-
- if (groupings.Length > 1)
- wr.Write(")");
-
- wr.Write("\n");
- }
- }
-
- return true;
- }
-
- public bool VisitLabelOp(VCExprNAry node, LineariserOptions options)
- {
- if (ExprLineariser.UnderQuantifier > 0 && !options.LabelsBelowQuantifiers) {
- ExprLineariser.Linearise(node[0], options);
- return true;
- }
-
- var op = (VCExprLabelOp)node.Op;
-
- if (CommandLineOptions.Clo.UseLabels)
- {
- // Z3 extension
- //wr.Write("({0} {1} ", op.pos ? "lblpos" : "lblneg", SMTLibNamer.QuoteId(op.label));
- wr.Write("(! ");
- }
-
- if(!options.LabelsBelowQuantifiers)
- wr.Write("({0} {1} ", op.pos ? "and" : "or", SMTLibNamer.QuoteId(SMTLibNamer.LabelVar(op.label)));
-
- ExprLineariser.Linearise(node[0], options);
-
-
- if (!options.LabelsBelowQuantifiers)
- wr.Write(")");
-
- if (CommandLineOptions.Clo.UseLabels)
- wr.Write(" :{0} {1})", op.pos ? "lblpos" : "lblneg", SMTLibNamer.QuoteId(op.label));
-
- return true;
- }
-
- public bool VisitSelectOp(VCExprNAry node, LineariserOptions options)
- {
- var name = SimplifyLikeExprLineariser.SelectOpName(node);
- name = ExprLineariser.Namer.GetQuotedName(name, name);
- if (CommandLineOptions.Clo.UseArrayTheory)
- name = "select";
- WriteApplication(name, node, options);
- return true;
- }
-
- public bool VisitStoreOp(VCExprNAry node, LineariserOptions options)
- {
- var name = SimplifyLikeExprLineariser.StoreOpName(node);
- name = ExprLineariser.Namer.GetQuotedName(name, name);
- if (CommandLineOptions.Clo.UseArrayTheory)
- name = "store";
- WriteApplication(name, node, options);
- return true;
- }
-
- static char[] hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
- public bool VisitBvOp(VCExprNAry node, LineariserOptions options)
- {
- var lit = (VCExprIntLit)node[0];
- var bytes = lit.Val.ToByteArray();
- if (node.Type.BvBits % 8 == 0) {
- wr.Write("#x");
- for (var pos = node.Type.BvBits / 8 - 1; pos >= 0; pos--) {
- var k = pos < bytes.Length ? bytes[pos] : (byte)0;
- wr.Write(hex[k >> 4]);
- wr.Write(hex[k & 0xf]);
- }
- } else {
- wr.Write("#b");
- for (var pos = node.Type.BvBits - 1; pos >= 0; pos--) {
- var i = pos >> 3;
- var k = i < bytes.Length ? bytes[i] : (byte)0;
- wr.Write((k & (1 << (pos & 7))) == 0 ? '0' : '1');
- }
- }
- return true;
- }
-
- public bool VisitBvExtractOp(VCExprNAry node, LineariserOptions options)
- {
- var op = (VCExprBvExtractOp)node.Op;
- wr.Write("((_ extract {0} {1}) ", op.End - 1, op.Start);
- ExprLineariser.Linearise(node[0], options);
- wr.Write(")");
- return true;
- }
-
- public bool VisitBvConcatOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("concat", node, options);
- return true;
- }
-
- public bool VisitAddOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("+", node, options);
- return true;
- }
-
- public bool VisitSubOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("-", node, options);
- return true;
- }
-
- public bool VisitMulOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("*", node, options);
- return true;
- }
-
- public bool VisitDivOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("div", node, options);
- return true;
- }
-
- public bool VisitModOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("mod", node, options);
- return true;
- }
-
- public bool VisitRealDivOp(VCExprNAry node, LineariserOptions options) {
- WriteApplication("/", node, options);
- return true;
- }
-
- public bool VisitPowOp(VCExprNAry node, LineariserOptions options) {
- WriteApplication("real_pow", node, options);
- return true;
- }
-
- public bool VisitLtOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("<", node, options);
- return true;
- }
-
- public bool VisitLeOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("<=", node, options);
- return true;
- }
-
- public bool VisitGtOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication(">", node, options);
- return true;
- }
-
- public bool VisitGeOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication(">=", node, options);
- return true;
- }
-
- public bool VisitSubtypeOp(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("UOrdering2", node, options);
- return true;
- }
-
- public bool VisitSubtype3Op(VCExprNAry node, LineariserOptions options)
- {
- WriteApplication("UOrdering3", node, options);
- return true;
- }
-
- public bool VisitToIntOp(VCExprNAry node, LineariserOptions options) {
- WriteApplication("to_int", node, options);
- return true;
- }
-
- public bool VisitToRealOp(VCExprNAry node, LineariserOptions options) {
- WriteApplication("to_real", node, options);
- return true;
- }
-
- private string ExtractDatatype(Function func) {
- if (func is DatatypeSelector) {
- DatatypeSelector selector = (DatatypeSelector) func;
- Variable v = selector.constructor.InParams[selector.index];
- return ExprLineariser.Namer.GetQuotedName(v, v.Name + "#" + selector.constructor.Name);
- }
- else if (func is DatatypeMembership) {
- DatatypeMembership membership = (DatatypeMembership)func;
- return ExprLineariser.Namer.GetQuotedName(membership, "is-" + membership.constructor.Name);
- }
- else {
- return null;
- }
- }
-
- public bool VisitBoogieFunctionOp(VCExprNAry node, LineariserOptions options) {
- VCExprBoogieFunctionOp op = (VCExprBoogieFunctionOp)node.Op;
- Contract.Assert(op != null);
- string printedName;
-
- var builtin = ExtractBuiltin(op.Func);
- var datatype = ExtractDatatype(op.Func);
- if (builtin != null)
- {
- printedName = CheckMapApply(builtin, node);
- }
- else if (datatype != null)
- {
- printedName = datatype;
- }
- else
- {
- printedName = ExprLineariser.Namer.GetQuotedName(op.Func, op.Func.Name);
- }
- Contract.Assert(printedName != null);
-
- WriteApplication(printedName, node, options);
-
- return true;
- }
-
- private static Type ResultType(Type type) {
- MapType mapType = type as MapType;
- if (mapType != null) {
- return ResultType(mapType.Result);
- }
- else {
- return type;
- }
- }
-
- public static HashSet<string> ArrayOps = new HashSet<string>(new string[] {
- "MapConst", "MapAdd", "MapSub", "MapMul", "MapDiv", "MapMod", "MapEq", "MapIff", "MapGt", "MapGe", "MapLt", "MapLe", "MapOr", "MapAnd", "MapNot", "MapImp", "MapIte" });
-
- private static string CheckMapApply(string name, VCExprNAry node) {
- if (name == "MapConst") {
- Type type = node.Type;
- string s = TypeToString(type);
- return "(as const " + s + ")";
- }
- else if (name == "MapAdd") {
- return "(_ map (+ (Int Int) Int))";
- }
- else if (name == "MapSub") {
- return "(_ map (- (Int Int) Int))";
- }
- else if (name == "MapMul") {
- return "(_ map (* (Int Int) Int))";
- }
- else if (name == "MapDiv") {
- return "(_ map (div (Int Int) Int))";
- }
- else if (name == "MapMod") {
- return "(_ map (mod (Int Int) Int))";
- }
- else if (name == "MapEq") {
- Type type = ResultType(node[0].Type);
- string s = TypeToString(type);
- return "(_ map (= (" + s + " " + s + ") Bool))";
- }
- else if (name == "MapIff") {
- return "(_ map (= (Bool Bool) Bool))";
- }
- else if (name == "MapGt") {
- return "(_ map (> (Int Int) Int))";
- }
- else if (name == "MapGe") {
- return "(_ map (>= (Int Int) Int))";
- }
- else if (name == "MapLt") {
- return "(_ map (< (Int Int) Int))";
- }
- else if (name == "MapLe") {
- return "(_ map (<= (Int Int) Int))";
- }
- else if (name == "MapOr") {
- return "(_ map or)";
- }
- else if (name == "MapAnd") {
- return "(_ map and)";
- }
- else if (name == "MapNot") {
- return "(_ map not)";
- }
- else if (name == "MapImp") {
- return "(_ map =>)";
- }
- else if (name == "MapIte") {
- Type type = ResultType(node.Type);
- string s = TypeToString(type);
- return "(_ map (ite (Bool " + s + " " + s + ") " + s + "))";
- }
- else {
- return name;
- }
- }
- }
- }
-
-}
+//----------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- +using System; +using System.Text; +using System.IO; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Linq; +using Microsoft.Basetypes; +using Microsoft.Boogie.VCExprAST; + +// Method to turn VCExprs into strings that can be fed into SMT +// solvers. This is currently quite similar to the +// SimplifyLikeLineariser (but the code is independent) + +namespace Microsoft.Boogie.SMTLib +{ + + // Options for the linearisation + public class LineariserOptions + { + public static LineariserOptions Default = new LineariserOptions(); + public bool LabelsBelowQuantifiers = false; + } + + + //////////////////////////////////////////////////////////////////////////////////////// + + // Lineariser for expressions. The result (bool) is currently not used for anything + public class SMTLibExprLineariser : IVCExprVisitor<bool, LineariserOptions/*!*/> + { + + public static string ToString(VCExpr e, UniqueNamer namer, SMTLibProverOptions opts) + { + Contract.Requires(e != null); + Contract.Requires(namer != null); + Contract.Ensures(Contract.Result<string>() != null); + + StringWriter sw = new StringWriter(); + SMTLibExprLineariser lin = new SMTLibExprLineariser(sw, namer, opts); + Contract.Assert(lin != null); + lin.Linearise(e, LineariserOptions.Default); + return cce.NonNull(sw.ToString()); + } + + //////////////////////////////////////////////////////////////////////////////////////// + + private readonly TextWriter wr; + [ContractInvariantMethod] + void ObjectInvariant() + { + Contract.Invariant(wr != null); + Contract.Invariant(Namer != null); + } + + private SMTLibOpLineariser OpLinObject = null; + private IVCExprOpVisitor<bool, LineariserOptions>/*!>!*/ OpLineariser + { + get + { + Contract.Ensures(Contract.Result<IVCExprOpVisitor<bool, LineariserOptions>>() != null); + + if (OpLinObject == null) + OpLinObject = new SMTLibOpLineariser(this, wr); + return OpLinObject; + } + } + + internal readonly UniqueNamer Namer; + internal int UnderQuantifier = 0; + internal readonly SMTLibProverOptions ProverOptions; + + public SMTLibExprLineariser(TextWriter wr, UniqueNamer namer, SMTLibProverOptions opts) + { + Contract.Requires(wr != null); Contract.Requires(namer != null); + this.wr = wr; + this.Namer = namer; + this.ProverOptions = opts; + } + + public void Linearise(VCExpr expr, LineariserOptions options) + { + Contract.Requires(expr != null); + Contract.Requires(options != null); + expr.Accept<bool, LineariserOptions>(this, options); + } + + ///////////////////////////////////////////////////////////////////////////////////// + + private static void TypeToStringHelper(Type t, StringBuilder sb) + { + Contract.Requires(t != null); + + TypeSynonymAnnotation syn = t as TypeSynonymAnnotation; + if (syn != null) { + TypeToStringHelper(syn.ExpandedType, sb); + } else { + if (t.IsMap && CommandLineOptions.Clo.UseArrayTheory) { + MapType m = t.AsMap; + // Contract.Assert(m.MapArity == 1); + sb.Append("(Array "); + foreach (Type tp in m.Arguments) + sb.Append(TypeToString(tp)).Append(" "); + sb.Append(TypeToString(m.Result)).Append(")"); + } else if (t.IsMap) { + MapType m = t.AsMap; + sb.Append('['); + for (int i = 0; i < m.MapArity; ++i) { + if (i != 0) + sb.Append(','); + TypeToStringHelper(m.Arguments[i], sb); + } + sb.Append(']'); + TypeToStringHelper(m.Result, sb); + } else if (t.IsBool || t.IsInt || t.IsReal || t.IsBv) { + sb.Append(TypeToString(t)); + } else { + System.IO.StringWriter buffer = new System.IO.StringWriter(); + using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/false, /*pretty=*/false)) { + t.Emit(stream); + } + sb.Append(buffer.ToString()); + } + } + + } + + public static string TypeToString(Type t) + { + Contract.Requires(t != null); + Contract.Ensures(Contract.Result<string>() != null); + + if (t.IsBool) + return "Bool"; + else if (t.IsInt) + return "Int"; + else if (t.IsReal) + return "Real"; + else if (t.IsBv) { + return "(_ BitVec " + t.BvBits + ")"; + } else { + StringBuilder sb = new StringBuilder(); + TypeToStringHelper(t, sb); + var s = sb.ToString(); + if (s[0] == '(') + return s; + else + return SMTLibNamer.QuoteId("T@" + s); + } + } + + public static string ExtractBuiltin(Function f) + { + Contract.Requires(f != null); + string retVal = null; + retVal = f.FindStringAttribute("bvbuiltin"); + + // It used to be "sign_extend 12" in Simplify, and is "(_ sign_extend 12)" with SMT + if (retVal != null && (retVal.StartsWith("sign_extend ") || retVal.StartsWith("zero_extend "))) + return "(_ " + retVal + ")"; + + if (retVal == null) { + retVal = f.FindStringAttribute("builtin"); + } + + if (retVal != null && !CommandLineOptions.Clo.UseArrayTheory && SMTLibOpLineariser.ArrayOps.Contains(retVal)) + { + retVal = null; + } + + return retVal; + } + + ///////////////////////////////////////////////////////////////////////////////////// + + public bool Visit(VCExprLiteral node, LineariserOptions options) + { + if (node == VCExpressionGenerator.True) + wr.Write("true"); + else if (node == VCExpressionGenerator.False) + wr.Write("false"); + else if (node is VCExprIntLit) { + BigNum lit = ((VCExprIntLit)node).Val; + if (lit.IsNegative) + // In SMT2 "-42" is an identifier (SMT2, Sect. 3.2 "Symbols") + wr.Write("(- 0 {0})", lit.Abs); + else + wr.Write(lit); + } + else if (node is VCExprRealLit) { + BigDec lit = ((VCExprRealLit)node).Val; + if (lit.IsNegative) + // In SMT2 "-42" is an identifier (SMT2, Sect. 3.2 "Symbols") + wr.Write("(- 0.0 {0})", lit.Abs.ToDecimalString()); + else + wr.Write(lit.ToDecimalString()); + } + else { + Contract.Assert(false); + throw new cce.UnreachableException(); + } + + return true; + } + + ///////////////////////////////////////////////////////////////////////////////////// + + public bool Visit(VCExprNAry node, LineariserOptions options) + { + VCExprOp op = node.Op; + Contract.Assert(op != null); + + var booleanOps = new HashSet<VCExprOp>(); + booleanOps.Add(VCExpressionGenerator.NotOp); + booleanOps.Add(VCExpressionGenerator.ImpliesOp); + booleanOps.Add(VCExpressionGenerator.AndOp); + booleanOps.Add(VCExpressionGenerator.OrOp); + if (booleanOps.Contains(op)) + { + Stack<VCExpr> exprs = new Stack<VCExpr>(); + exprs.Push(node); + while (exprs.Count > 0) + { + VCExpr expr = exprs.Pop(); + if (expr == null) + { + wr.Write(")"); + continue; + } + wr.Write(" "); + VCExprNAry naryExpr = expr as VCExprNAry; + if (naryExpr == null || !booleanOps.Contains(naryExpr.Op)) + { + Linearise(expr, options); + continue; + } + else if (naryExpr.Op.Equals(VCExpressionGenerator.NotOp)) + { + wr.Write("(not"); + } + else if (naryExpr.Op.Equals(VCExpressionGenerator.ImpliesOp)) + { + wr.Write("(=>"); + } + else if (naryExpr.Op.Equals(VCExpressionGenerator.AndOp)) + { + wr.Write("(and"); + } + else + { + System.Diagnostics.Debug.Assert(naryExpr.Op.Equals(VCExpressionGenerator.OrOp)); + wr.Write("(or"); + } + exprs.Push(null); + for (int i = naryExpr.Arity - 1; i >= 0; i--) + { + exprs.Push(naryExpr[i]); + } + } + return true; + } + return node.Accept<bool, LineariserOptions/*!*/>(OpLineariser, options); + } + + ///////////////////////////////////////////////////////////////////////////////////// + + public bool Visit(VCExprVar node, LineariserOptions options) + { + wr.Write(Namer.GetQuotedName(node, node.Name)); + return true; + } + + ///////////////////////////////////////////////////////////////////////////////////// + + public bool Visit(VCExprQuantifier node, LineariserOptions options) + { + Contract.Assert(node.TypeParameters.Count == 0); + + UnderQuantifier++; + Namer.PushScope(); try { + + string kind = node.Quan == Quantifier.ALL ? "forall" : "exists"; + wr.Write("({0} (", kind); + + for (int i = 0; i < node.BoundVars.Count; i++) { + VCExprVar var = node.BoundVars[i]; + Contract.Assert(var != null); + string printedName = Namer.GetQuotedLocalName(var, var.Name); + Contract.Assert(printedName != null); + wr.Write("({0} {1}) ", printedName, TypeToString(var.Type)); + } + + wr.Write(") "); + + VCQuantifierInfos infos = node.Infos; + var weight = QKeyValue.FindIntAttribute(infos.attributes, "weight", 1); + if (!ProverOptions.UseWeights) + weight = 1; + var hasAttrs = node.Triggers.Count > 0 || infos.qid != null || weight != 1 || infos.uniqueId != -1; + + if (hasAttrs) + wr.Write("(! "); + + Linearise(node.Body, options); + + if (hasAttrs) { + wr.Write("\n"); + if (infos.qid != null) + wr.Write(" :qid {0}\n", SMTLibNamer.QuoteId(infos.qid)); + if (weight != 1) + wr.Write(" :weight {0}\n", weight); + if (infos.uniqueId != -1) + wr.Write(" :skolemid |{0}|\n", infos.uniqueId); + WriteTriggers(node.Triggers, options); + + wr.Write(")"); + } + + wr.Write(")"); + + return true; + + } finally { + UnderQuantifier--; + Namer.PopScope(); + } + } + + private void WriteTriggers(List<VCTrigger/*!>!*/> triggers, LineariserOptions options) + { + Contract.Requires(options != null); + Contract.Requires(triggers != null); + // first, count how many neg/pos triggers there are + int negTriggers = 0; + int posTriggers = 0; + foreach (VCTrigger vcTrig in triggers) { + Contract.Assert(vcTrig != null); + if (vcTrig.Pos) { + posTriggers++; + } else { + negTriggers++; + } + } + + if (posTriggers > 0) { + foreach (VCTrigger vcTrig in triggers) { + Contract.Assert(vcTrig != null); + if (vcTrig.Pos) { + wr.Write(" :pattern ("); + foreach (VCExpr e in vcTrig.Exprs) { + Contract.Assert(e != null); + wr.Write(" "); + var subPat = e; + var nary = e as VCExprNAry; + if (nary != null && (nary.Op == VCExpressionGenerator.NeqOp || nary.Op == VCExpressionGenerator.EqOp)) { + if (nary[0] is VCExprLiteral) + subPat = nary[1]; + else if (nary[1] is VCExprLiteral) + subPat = nary[0]; + } + Linearise(subPat, options); + } + wr.Write(")\n"); + } + } + } else if (negTriggers > 0) { + // if also positive triggers are given, the SMT solver (at least Z3) + // will ignore the negative patterns and output a warning. Therefore + // we never specify both negative and positive triggers + foreach (VCTrigger vcTrig in triggers) { + Contract.Assert(vcTrig != null); + if (!vcTrig.Pos) { + wr.Write(" :no-pattern "); + Contract.Assert(vcTrig.Exprs.Count == 1); + Linearise(vcTrig.Exprs[0], options); + wr.Write("\n"); + } + } + } + } + + ///////////////////////////////////////////////////////////////////////////////////// + + public bool Visit(VCExprLet node, LineariserOptions options) + { + Namer.PushScope(); + try { + + foreach (VCExprLetBinding b in node) { + wr.Write("(let ("); + Contract.Assert(b != null); + wr.Write("({0} ", Namer.GetQuotedName(b.V, b.V.Name)); + Linearise(b.E, options); + wr.Write("))\n"); + } + Linearise(node.Body, options); + foreach (VCExprLetBinding b in node) + wr.Write(")"); + return true; + } finally { + Namer.PopScope(); + } + } + + ///////////////////////////////////////////////////////////////////////////////////// + + // Lineariser for operator terms. The result (bool) is currently not used for anything + internal class SMTLibOpLineariser : IVCExprOpVisitor<bool, LineariserOptions/*!*/> + { + private readonly SMTLibExprLineariser ExprLineariser; + private readonly TextWriter wr; + [ContractInvariantMethod] + void ObjectInvariant() + { + Contract.Invariant(wr != null); + Contract.Invariant(ExprLineariser != null); + } + + + public SMTLibOpLineariser(SMTLibExprLineariser ExprLineariser, TextWriter wr) + { + Contract.Requires(ExprLineariser != null); + Contract.Requires(wr != null); + this.ExprLineariser = ExprLineariser; + this.wr = wr; + } + + /////////////////////////////////////////////////////////////////////////////////// + private void WriteApplication(string opName, IEnumerable<VCExpr>/*!>!*/ args, LineariserOptions options) + { + Contract.Requires(cce.NonNullElements(args)); + Contract.Requires(options != null); + Contract.Assert(opName != null); + + bool hasArgs = false; + foreach (VCExpr e in args) { + Contract.Assert(e != null); + if (!hasArgs) + wr.Write("({0}", opName); + wr.Write(" "); + ExprLineariser.Linearise(e, options); + hasArgs = true; + } + + if (hasArgs) + wr.Write(")"); + else + wr.Write("{0}", opName); + } + + /////////////////////////////////////////////////////////////////////////////////// + + public bool VisitNotOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("not", node, options); // arguments can be both terms and formulas + return true; + } + + private bool PrintEq(VCExprNAry node, LineariserOptions options) + { + Contract.Requires(node != null); + Contract.Requires(options != null); + + WriteApplication("=", node, options); + + return true; + } + + public bool VisitEqOp(VCExprNAry node, LineariserOptions options) + { + return PrintEq(node, options); + } + + public bool VisitNeqOp(VCExprNAry node, LineariserOptions options) + { + //Contract.Requires(node != null); + //Contract.Requires(options != null); + wr.Write("(not "); + PrintEq(node, options); + wr.Write(")"); + return true; + } + + public bool VisitAndOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("and", node, options); + return true; + } + + public bool VisitOrOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("or", node, options); + return true; + } + + public bool VisitImpliesOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("=>", node, options); + return true; + } + + public bool VisitIfThenElseOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("ite", node, options); + return true; + } + + public bool VisitCustomOp(VCExprNAry node, LineariserOptions options) + { + VCExprCustomOp op = (VCExprCustomOp)node.Op; + if (!ExprLineariser.ProverOptions.UseTickleBool && op.Name == "tickleBool") + ExprLineariser.Linearise(VCExpressionGenerator.True, options); + else + WriteApplication(op.Name, node, options); + return true; + } + + public bool VisitDistinctOp(VCExprNAry node, LineariserOptions options) + { + //Contract.Requires(node != null); + //Contract.Requires(options != null); + + if (node.Length < 2) { + ExprLineariser.Linearise(VCExpressionGenerator.True, options); + } else { + var groupings = node.GroupBy(e => e.Type).Where(g => g.Count() > 1).ToArray(); + if (groupings.Length == 0) { + ExprLineariser.Linearise(VCExpressionGenerator.True, options); + } else { + if (groupings.Length > 1) + wr.Write("(and "); + + foreach (var g in groupings) { + wr.Write("(distinct"); + foreach (VCExpr e in g) { + Contract.Assert(e != null); + wr.Write(" "); + ExprLineariser.Linearise(e, options); + } + wr.Write(")"); + } + + if (groupings.Length > 1) + wr.Write(")"); + + wr.Write("\n"); + } + } + + return true; + } + + public bool VisitLabelOp(VCExprNAry node, LineariserOptions options) + { + if (ExprLineariser.UnderQuantifier > 0 && !options.LabelsBelowQuantifiers) { + ExprLineariser.Linearise(node[0], options); + return true; + } + + var op = (VCExprLabelOp)node.Op; + + if (CommandLineOptions.Clo.UseLabels) + { + // Z3 extension + //wr.Write("({0} {1} ", op.pos ? "lblpos" : "lblneg", SMTLibNamer.QuoteId(op.label)); + wr.Write("(! "); + } + + if(!options.LabelsBelowQuantifiers) + wr.Write("({0} {1} ", op.pos ? "and" : "or", SMTLibNamer.QuoteId(SMTLibNamer.LabelVar(op.label))); + + ExprLineariser.Linearise(node[0], options); + + + if (!options.LabelsBelowQuantifiers) + wr.Write(")"); + + if (CommandLineOptions.Clo.UseLabels) + wr.Write(" :{0} {1})", op.pos ? "lblpos" : "lblneg", SMTLibNamer.QuoteId(op.label)); + + return true; + } + + public bool VisitSelectOp(VCExprNAry node, LineariserOptions options) + { + var name = SimplifyLikeExprLineariser.SelectOpName(node); + name = ExprLineariser.Namer.GetQuotedName(name, name); + if (CommandLineOptions.Clo.UseArrayTheory) + name = "select"; + WriteApplication(name, node, options); + return true; + } + + public bool VisitStoreOp(VCExprNAry node, LineariserOptions options) + { + var name = SimplifyLikeExprLineariser.StoreOpName(node); + name = ExprLineariser.Namer.GetQuotedName(name, name); + if (CommandLineOptions.Clo.UseArrayTheory) + name = "store"; + WriteApplication(name, node, options); + return true; + } + + static char[] hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + public bool VisitBvOp(VCExprNAry node, LineariserOptions options) + { + var lit = (VCExprIntLit)node[0]; + var bytes = lit.Val.ToByteArray(); + if (node.Type.BvBits % 8 == 0) { + wr.Write("#x"); + for (var pos = node.Type.BvBits / 8 - 1; pos >= 0; pos--) { + var k = pos < bytes.Length ? bytes[pos] : (byte)0; + wr.Write(hex[k >> 4]); + wr.Write(hex[k & 0xf]); + } + } else { + wr.Write("#b"); + for (var pos = node.Type.BvBits - 1; pos >= 0; pos--) { + var i = pos >> 3; + var k = i < bytes.Length ? bytes[i] : (byte)0; + wr.Write((k & (1 << (pos & 7))) == 0 ? '0' : '1'); + } + } + return true; + } + + public bool VisitBvExtractOp(VCExprNAry node, LineariserOptions options) + { + var op = (VCExprBvExtractOp)node.Op; + wr.Write("((_ extract {0} {1}) ", op.End - 1, op.Start); + ExprLineariser.Linearise(node[0], options); + wr.Write(")"); + return true; + } + + public bool VisitBvConcatOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("concat", node, options); + return true; + } + + public bool VisitAddOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("+", node, options); + return true; + } + + public bool VisitSubOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("-", node, options); + return true; + } + + public bool VisitMulOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("*", node, options); + return true; + } + + public bool VisitDivOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("div", node, options); + return true; + } + + public bool VisitModOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("mod", node, options); + return true; + } + + public bool VisitRealDivOp(VCExprNAry node, LineariserOptions options) { + WriteApplication("/", node, options); + return true; + } + + public bool VisitPowOp(VCExprNAry node, LineariserOptions options) { + WriteApplication("real_pow", node, options); + return true; + } + + public bool VisitLtOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("<", node, options); + return true; + } + + public bool VisitLeOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("<=", node, options); + return true; + } + + public bool VisitGtOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication(">", node, options); + return true; + } + + public bool VisitGeOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication(">=", node, options); + return true; + } + + public bool VisitSubtypeOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("UOrdering2", node, options); + return true; + } + + public bool VisitSubtype3Op(VCExprNAry node, LineariserOptions options) + { + WriteApplication("UOrdering3", node, options); + return true; + } + + public bool VisitToIntOp(VCExprNAry node, LineariserOptions options) { + WriteApplication("to_int", node, options); + return true; + } + + public bool VisitToRealOp(VCExprNAry node, LineariserOptions options) { + WriteApplication("to_real", node, options); + return true; + } + + private string ExtractDatatype(Function func) { + if (func is DatatypeSelector) { + DatatypeSelector selector = (DatatypeSelector) func; + Variable v = selector.constructor.InParams[selector.index]; + return ExprLineariser.Namer.GetQuotedName(v, v.Name + "#" + selector.constructor.Name); + } + else if (func is DatatypeMembership) { + DatatypeMembership membership = (DatatypeMembership)func; + return ExprLineariser.Namer.GetQuotedName(membership, "is-" + membership.constructor.Name); + } + else { + return null; + } + } + + public bool VisitBoogieFunctionOp(VCExprNAry node, LineariserOptions options) { + VCExprBoogieFunctionOp op = (VCExprBoogieFunctionOp)node.Op; + Contract.Assert(op != null); + string printedName; + + var builtin = ExtractBuiltin(op.Func); + var datatype = ExtractDatatype(op.Func); + if (builtin != null) + { + printedName = CheckMapApply(builtin, node); + } + else if (datatype != null) + { + printedName = datatype; + } + else + { + printedName = ExprLineariser.Namer.GetQuotedName(op.Func, op.Func.Name); + } + Contract.Assert(printedName != null); + + WriteApplication(printedName, node, options); + + return true; + } + + private static Type ResultType(Type type) { + MapType mapType = type as MapType; + if (mapType != null) { + return ResultType(mapType.Result); + } + else { + return type; + } + } + + public static HashSet<string> ArrayOps = new HashSet<string>(new string[] { + "MapConst", "MapAdd", "MapSub", "MapMul", "MapDiv", "MapMod", "MapEq", "MapIff", "MapGt", "MapGe", "MapLt", "MapLe", "MapOr", "MapAnd", "MapNot", "MapImp", "MapIte" }); + + private static string CheckMapApply(string name, VCExprNAry node) { + if (name == "MapConst") { + Type type = node.Type; + string s = TypeToString(type); + return "(as const " + s + ")"; + } + else if (name == "MapAdd") { + return "(_ map (+ (Int Int) Int))"; + } + else if (name == "MapSub") { + return "(_ map (- (Int Int) Int))"; + } + else if (name == "MapMul") { + return "(_ map (* (Int Int) Int))"; + } + else if (name == "MapDiv") { + return "(_ map (div (Int Int) Int))"; + } + else if (name == "MapMod") { + return "(_ map (mod (Int Int) Int))"; + } + else if (name == "MapEq") { + Type type = ResultType(node[0].Type); + string s = TypeToString(type); + return "(_ map (= (" + s + " " + s + ") Bool))"; + } + else if (name == "MapIff") { + return "(_ map (= (Bool Bool) Bool))"; + } + else if (name == "MapGt") { + return "(_ map (> (Int Int) Int))"; + } + else if (name == "MapGe") { + return "(_ map (>= (Int Int) Int))"; + } + else if (name == "MapLt") { + return "(_ map (< (Int Int) Int))"; + } + else if (name == "MapLe") { + return "(_ map (<= (Int Int) Int))"; + } + else if (name == "MapOr") { + return "(_ map or)"; + } + else if (name == "MapAnd") { + return "(_ map and)"; + } + else if (name == "MapNot") { + return "(_ map not)"; + } + else if (name == "MapImp") { + return "(_ map =>)"; + } + else if (name == "MapIte") { + Type type = ResultType(node.Type); + string s = TypeToString(type); + return "(_ map (ite (Bool " + s + " " + s + ") " + s + "))"; + } + else { + return name; + } + } + } + } + +} diff --git a/Source/Provers/SMTLib/SMTLibNamer.cs b/Source/Provers/SMTLib/SMTLibNamer.cs index 40007ab9..900bdbcc 100644 --- a/Source/Provers/SMTLib/SMTLibNamer.cs +++ b/Source/Provers/SMTLib/SMTLibNamer.cs @@ -1,147 +1,147 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie.VCExprAST;
-
-namespace Microsoft.Boogie.SMTLib
-{
- public class SMTLibNamer : UniqueNamer
- {
- // The following Boogie ID characters are not SMT ID characters: `'\#
- const string idCharacters = "~!@$%^&*_-+=<>.?/";
-
-
- static string[] reservedSmtWordsList =
- { // Basic symbols:
- "", "!", "_", "as", "DECIMAL", "exists", "forall", "let", "NUMERAL", "par", "STRING",
- // Commands:
- "assert", "check-sat", "declare-sort", "declare-fun", "define-sort,", "define-fun", "exit",
- "get-assertions", "get-assignment", "get-info", "get-option,", "get-proof", "get-unsat-core",
- "get-value", "pop", "push", "set-logic", "set-info", "set-option",
- // Core theory:
- "and", "or", "not", "iff", "true", "false", "xor", "distinct", "ite", "=", "Bool",
- "=>", // implies (sic!)
- // Integers and reals
- "Int", "Real", "*", "/", "-", "~", "+", "<", "<=", ">", ">=", "div", "mod", "rem",
- "^", "sin", "cos", "tan", "asin", "acos", "atan", "sinh", "cosh", "tanh", "asinh", "acosh", "atanh", "pi", "euler",
- "to_real", "to_int", "is_int",
- // Bitvectors
- "extract", "concat",
- "bvnot", "bvneg", "bvand", "bvor", "bvadd", "bvmul", "bvudiv", "bvurem", "bvshl", "bvlshr", "bvult",
- // arrays
- "store", "select", "const", "default", "map", "union", "intersect", "difference", "complement",
- "subset", "array-ext", "as-array", "Array",
- // Z3 (and not only?) extensions to bitvectors
- "bit1", "bit0", "bvsub", "bvsdiv", "bvsrem", "bvsmod", "bvsdiv0", "bvudiv0", "bvsrem0", "bvurem0",
- "bvsmod0", "bvsdiv_i", "bvudiv_i", "bvsrem_i", "bvurem_i", "bvumod_i", "bvule", "bvsle", "bvuge",
- "bvsge", "bvslt", "bvugt", "bvsgt", "bvxor", "bvnand", "bvnor", "bvxnor", "sign_extend", "zero_extend",
- "repeat", "bvredor", "bvredand", "bvcomp", "bvumul_noovfl", "bvsmul_noovfl", "bvsmul_noudfl", "bvashr",
- "rotate_left", "rotate_right", "ext_rotate_left", "ext_rotate_right", "int2bv", "bv2int", "mkbv",
- // floating point (FIXME: Legacy, remove this)
- "plusInfinity", "minusInfinity",
- "+", "-", "/", "*", "==", "<", ">", "<=", ">=",
- "abs", "remainder", "fusedMA", "squareRoot", "roundToIntegral",
- "isZero", "isNZero", "isPZero", "isSignMinus", "min", "max", "asFloat",
- // SMT v1 stuff (FIXME: Legacy, remove this)
- "flet", "implies", "!=", "if_then_else",
- // Z3 extensions
- "lblneg", "lblpos", "lbl-lit",
- "if", "&&", "||", "equals", "equiv", "bool",
- // Boogie-defined
- "real_pow", "UOrdering2", "UOrdering3",
- // Floating point (final draft SMTLIB-v2.5)
- "NaN",
- "roundNearestTiesToEven", "roundNearestTiesToAway", "roundTowardPositive", "roundTowardNegative", "roundTowardZero",
- "RNE", "RNA", "RTP", "RTN", "RTZ",
- "fp.abs", "fp.neg", "fp.add", "fp.sub", "fp.mul", "fp.div", "fp.fma", "fp.sqrt", "fp.rem", "fp.roundToIntegral",
- "fp.min", "fp.max", "fp.leq", "fp.lt", "fp.geq", "fp.gt", "fp.eq",
- "fp.isNormal", "fp.isSubnormal", "fp.isZero", "fp.isInfinite", "fp.isNaN", "fp.isNegative", "fp.isPositive",
- "fp", "fp.to_ubv", "fp.to_sbv", "to_fp",
- };
-
- static HashSet<string> reservedSmtWords;
- static bool[] validIdChar;
- static bool symbolListsInitilized;
-
- static void InitSymbolLists()
- {
- lock (reservedSmtWordsList) {
- // don't move out, c.f. http://en.wikipedia.org/wiki/Double-checked_locking
- if (symbolListsInitilized)
- return;
- reservedSmtWords = new HashSet<string>();
- foreach (var w in reservedSmtWordsList)
- reservedSmtWords.Add(w);
- validIdChar = new bool[255];
- for (int i = 0; i < validIdChar.Length; ++i)
- validIdChar[i] = char.IsLetterOrDigit((char)i) || idCharacters.IndexOf((char)i) >= 0;
- symbolListsInitilized = true;
- }
- }
-
- static string AddQuotes(string s)
- {
- var allGood = true;
-
- foreach (char ch in s) {
- var c = (int)ch;
- if (c >= validIdChar.Length || !validIdChar[c]) {
- allGood = false;
- break;
- }
- }
-
- if (allGood)
- return s;
-
- return "|" + s + "|";
- }
-
- static string FilterReserved(string s)
- {
- // Note symbols starting with ``.`` and ``@`` are reserved for internal
- // solver use in SMT-LIBv2 however if we check for the first character
- // being ``@`` then Boogie's tests fail spectacularly because they are
- // used for labels so we don't check for it here. It hopefully won't matter
- // in practice because ``@`` cannot be legally used in Boogie identifiers.
- if (reservedSmtWords.Contains(s) || char.IsDigit(s[0]) || s[0] == '.')
- s = "q@" + s;
-
- // | and \ are illegal even in quoted identifiers
- if (s.IndexOf('|') >= 0)
- s = s.Replace("|", "_");
-
- if (s.IndexOf('\\') >= 0)
- s = s.Replace("\\", "_");
-
- return s;
- }
-
- public static string LabelVar(string s)
- {
- return "%lbl%" + s;
- }
-
- public static string QuoteId(string s)
- {
- return AddQuotes(FilterReserved(s));
- }
-
- public override string GetQuotedLocalName(object thingie, string inherentName)
- {
- return AddQuotes(base.GetLocalName(thingie, FilterReserved(inherentName)));
- }
-
- public override string GetQuotedName(object thingie, string inherentName)
- {
- return AddQuotes(base.GetName(thingie, FilterReserved(inherentName)));
- }
-
- public SMTLibNamer()
- {
- this.Spacer = "@@";
- InitSymbolLists();
- }
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Boogie.VCExprAST; + +namespace Microsoft.Boogie.SMTLib +{ + public class SMTLibNamer : UniqueNamer + { + // The following Boogie ID characters are not SMT ID characters: `'\# + const string idCharacters = "~!@$%^&*_-+=<>.?/"; + + + static string[] reservedSmtWordsList = + { // Basic symbols: + "", "!", "_", "as", "DECIMAL", "exists", "forall", "let", "NUMERAL", "par", "STRING", + // Commands: + "assert", "check-sat", "declare-sort", "declare-fun", "define-sort,", "define-fun", "exit", + "get-assertions", "get-assignment", "get-info", "get-option,", "get-proof", "get-unsat-core", + "get-value", "pop", "push", "set-logic", "set-info", "set-option", + // Core theory: + "and", "or", "not", "iff", "true", "false", "xor", "distinct", "ite", "=", "Bool", + "=>", // implies (sic!) + // Integers and reals + "Int", "Real", "*", "/", "-", "~", "+", "<", "<=", ">", ">=", "div", "mod", "rem", + "^", "sin", "cos", "tan", "asin", "acos", "atan", "sinh", "cosh", "tanh", "asinh", "acosh", "atanh", "pi", "euler", + "to_real", "to_int", "is_int", + // Bitvectors + "extract", "concat", + "bvnot", "bvneg", "bvand", "bvor", "bvadd", "bvmul", "bvudiv", "bvurem", "bvshl", "bvlshr", "bvult", + // arrays + "store", "select", "const", "default", "map", "union", "intersect", "difference", "complement", + "subset", "array-ext", "as-array", "Array", + // Z3 (and not only?) extensions to bitvectors + "bit1", "bit0", "bvsub", "bvsdiv", "bvsrem", "bvsmod", "bvsdiv0", "bvudiv0", "bvsrem0", "bvurem0", + "bvsmod0", "bvsdiv_i", "bvudiv_i", "bvsrem_i", "bvurem_i", "bvumod_i", "bvule", "bvsle", "bvuge", + "bvsge", "bvslt", "bvugt", "bvsgt", "bvxor", "bvnand", "bvnor", "bvxnor", "sign_extend", "zero_extend", + "repeat", "bvredor", "bvredand", "bvcomp", "bvumul_noovfl", "bvsmul_noovfl", "bvsmul_noudfl", "bvashr", + "rotate_left", "rotate_right", "ext_rotate_left", "ext_rotate_right", "int2bv", "bv2int", "mkbv", + // floating point (FIXME: Legacy, remove this) + "plusInfinity", "minusInfinity", + "+", "-", "/", "*", "==", "<", ">", "<=", ">=", + "abs", "remainder", "fusedMA", "squareRoot", "roundToIntegral", + "isZero", "isNZero", "isPZero", "isSignMinus", "min", "max", "asFloat", + // SMT v1 stuff (FIXME: Legacy, remove this) + "flet", "implies", "!=", "if_then_else", + // Z3 extensions + "lblneg", "lblpos", "lbl-lit", + "if", "&&", "||", "equals", "equiv", "bool", + // Boogie-defined + "real_pow", "UOrdering2", "UOrdering3", + // Floating point (final draft SMTLIB-v2.5) + "NaN", + "roundNearestTiesToEven", "roundNearestTiesToAway", "roundTowardPositive", "roundTowardNegative", "roundTowardZero", + "RNE", "RNA", "RTP", "RTN", "RTZ", + "fp.abs", "fp.neg", "fp.add", "fp.sub", "fp.mul", "fp.div", "fp.fma", "fp.sqrt", "fp.rem", "fp.roundToIntegral", + "fp.min", "fp.max", "fp.leq", "fp.lt", "fp.geq", "fp.gt", "fp.eq", + "fp.isNormal", "fp.isSubnormal", "fp.isZero", "fp.isInfinite", "fp.isNaN", "fp.isNegative", "fp.isPositive", + "fp", "fp.to_ubv", "fp.to_sbv", "to_fp", + }; + + static HashSet<string> reservedSmtWords; + static bool[] validIdChar; + static bool symbolListsInitilized; + + static void InitSymbolLists() + { + lock (reservedSmtWordsList) { + // don't move out, c.f. http://en.wikipedia.org/wiki/Double-checked_locking + if (symbolListsInitilized) + return; + reservedSmtWords = new HashSet<string>(); + foreach (var w in reservedSmtWordsList) + reservedSmtWords.Add(w); + validIdChar = new bool[255]; + for (int i = 0; i < validIdChar.Length; ++i) + validIdChar[i] = char.IsLetterOrDigit((char)i) || idCharacters.IndexOf((char)i) >= 0; + symbolListsInitilized = true; + } + } + + static string AddQuotes(string s) + { + var allGood = true; + + foreach (char ch in s) { + var c = (int)ch; + if (c >= validIdChar.Length || !validIdChar[c]) { + allGood = false; + break; + } + } + + if (allGood) + return s; + + return "|" + s + "|"; + } + + static string FilterReserved(string s) + { + // Note symbols starting with ``.`` and ``@`` are reserved for internal + // solver use in SMT-LIBv2 however if we check for the first character + // being ``@`` then Boogie's tests fail spectacularly because they are + // used for labels so we don't check for it here. It hopefully won't matter + // in practice because ``@`` cannot be legally used in Boogie identifiers. + if (reservedSmtWords.Contains(s) || char.IsDigit(s[0]) || s[0] == '.') + s = "q@" + s; + + // | and \ are illegal even in quoted identifiers + if (s.IndexOf('|') >= 0) + s = s.Replace("|", "_"); + + if (s.IndexOf('\\') >= 0) + s = s.Replace("\\", "_"); + + return s; + } + + public static string LabelVar(string s) + { + return "%lbl%" + s; + } + + public static string QuoteId(string s) + { + return AddQuotes(FilterReserved(s)); + } + + public override string GetQuotedLocalName(object thingie, string inherentName) + { + return AddQuotes(base.GetLocalName(thingie, FilterReserved(inherentName))); + } + + public override string GetQuotedName(object thingie, string inherentName) + { + return AddQuotes(base.GetName(thingie, FilterReserved(inherentName))); + } + + public SMTLibNamer() + { + this.Spacer = "@@"; + InitSymbolLists(); + } + } +} diff --git a/Source/Provers/SMTLib/SMTLibProverOptions.cs b/Source/Provers/SMTLib/SMTLibProverOptions.cs index 0cfa65d8..5c3bed3e 100644 --- a/Source/Provers/SMTLib/SMTLibProverOptions.cs +++ b/Source/Provers/SMTLib/SMTLibProverOptions.cs @@ -1,158 +1,158 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics.Contracts;
-
-namespace Microsoft.Boogie.SMTLib
-{
-
- public class OptionValue
- {
- public readonly string Option;
- public readonly string Value;
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(Option != null);
- Contract.Invariant(Value != null);
- }
-
- public OptionValue(string option, string value)
- {
- Contract.Requires(option != null);
- Contract.Requires(value != null);
- Option = option;
- Value = value;
- }
- }
-
- public enum SolverKind { Z3, CVC4 };
-
- public class SMTLibProverOptions : ProverOptions
- {
- public bool UseWeights = true;
- public bool SupportsLabels { get { return Solver == SolverKind.Z3; } }
- public bool UseTickleBool { get { return Solver == SolverKind.Z3; } }
- public SolverKind Solver = SolverKind.Z3;
- public List<OptionValue> SmtOptions = new List<OptionValue>();
- public List<string> SolverArguments = new List<string>();
- public bool MultiTraces = false;
- public string Logic = "";
-
- // Z3 specific (at the moment; some of them make sense also for other provers)
- public string Inspector = null;
- public bool OptimizeForBv = false;
- public bool SMTLib2Model = false;
-
- public bool ProduceModel() {
- return !CommandLineOptions.Clo.UseLabels || CommandLineOptions.Clo.ExplainHoudini || CommandLineOptions.Clo.UseProverEvaluate ||
- ExpectingModel();
- }
-
- public bool ExpectingModel()
- {
- return CommandLineOptions.Clo.PrintErrorModel >= 1 ||
- CommandLineOptions.Clo.EnhancedErrorMessages == 1 ||
- CommandLineOptions.Clo.ModelViewFile != null ||
- (CommandLineOptions.Clo.StratifiedInlining > 0 && !CommandLineOptions.Clo.StratifiedInliningWithoutModels);
- }
-
- public void AddSolverArgument(string s)
- {
- SolverArguments.Add(s);
- }
-
- public void AddSmtOption(string name, string val)
- {
- SmtOptions.Add(new OptionValue(name, val));
- }
-
- public void AddWeakSmtOption(string name, string val)
- {
- if (!SmtOptions.Any(o => o.Option == name))
- SmtOptions.Add(new OptionValue(name, val));
- }
-
- public void AddSmtOption(string opt)
- {
- var idx = opt.IndexOf('=');
- if (idx <= 0 || idx == opt.Length - 1)
- ReportError("Options to be passed to the prover should have the format: O:<name>=<value>, got '" + opt + "'");
- AddSmtOption(opt.Substring(0, idx), opt.Substring(idx + 1));
- }
-
- protected override bool Parse(string opt)
- {
- string SolverStr = null;
- if (ParseString(opt, "SOLVER", ref SolverStr)) {
- switch (SolverStr) {
- case "Z3":
- case "z3":
- Solver = SolverKind.Z3;
- break;
- case "CVC4":
- case "cvc4":
- Solver = SolverKind.CVC4;
- if (Logic.Equals("")) Logic = "ALL_SUPPORTED";
- break;
- default:
- ReportError("Invalid SOLVER value; must be 'Z3' or 'CVC4'");
- return false;
- }
- return true;
- }
-
- if (opt.StartsWith("O:")) {
- AddSmtOption(opt.Substring(2));
- return true;
- }
-
- if (opt.StartsWith("C:")) {
- AddSolverArgument(opt.Substring(2));
- return true;
- }
-
- return
- ParseBool(opt, "MULTI_TRACES", ref MultiTraces) ||
- ParseBool(opt, "USE_WEIGHTS", ref UseWeights) ||
- ParseString(opt, "INSPECTOR", ref Inspector) ||
- ParseBool(opt, "OPTIMIZE_FOR_BV", ref OptimizeForBv) ||
- ParseBool(opt, "SMTLIB2_MODEL", ref SMTLib2Model) ||
- ParseString(opt, "LOGIC", ref Logic) ||
- base.Parse(opt);
- }
-
- public override void PostParse()
- {
- base.PostParse();
- if (Solver == SolverKind.Z3)
- Z3.SetupOptions(this);
- }
-
- public override string Help
- {
- get
- {
- return
-@"
-SMT-specific options:
-~~~~~~~~~~~~~~~~~~~~~
-SOLVER=<string> Use the given SMT solver (z3 or cvc4; default: z3)
-USE_WEIGHTS=<bool> Pass :weight annotations on quantified formulas (default: true)
-VERBOSITY=<int> 1 - print prover output (default: 0)
-O:<name>=<value> Pass (set-option :<name> <value>) to the SMT solver.
-C:<string> Pass <string> to the SMT on the command line.
-LOGIC=<string> Pass (set-logic <string>) to the prover (default: empty, 'ALL_SUPPORTED' for CVC4)
-
-Z3-specific options:
-~~~~~~~~~~~~~~~~~~~~
-MULTI_TRACES=<bool> Report errors with multiple paths leading to the same assertion.
-INSPECTOR=<string> Use the specified Z3Inspector binary.
-OPTIMIZE_FOR_BV=<bool> Optimize Z3 options for bitvector reasoning, and not quantifier instantiation. Defaults to false.
-SMTLIB2_MODEL=<bool> Use the SMTLIB2 output model. Defaults to false.
-" + base.Help;
- }
- }
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics.Contracts; + +namespace Microsoft.Boogie.SMTLib +{ + + public class OptionValue + { + public readonly string Option; + public readonly string Value; + [ContractInvariantMethod] + void ObjectInvariant() + { + Contract.Invariant(Option != null); + Contract.Invariant(Value != null); + } + + public OptionValue(string option, string value) + { + Contract.Requires(option != null); + Contract.Requires(value != null); + Option = option; + Value = value; + } + } + + public enum SolverKind { Z3, CVC4 }; + + public class SMTLibProverOptions : ProverOptions + { + public bool UseWeights = true; + public bool SupportsLabels { get { return Solver == SolverKind.Z3; } } + public bool UseTickleBool { get { return Solver == SolverKind.Z3; } } + public SolverKind Solver = SolverKind.Z3; + public List<OptionValue> SmtOptions = new List<OptionValue>(); + public List<string> SolverArguments = new List<string>(); + public bool MultiTraces = false; + public string Logic = ""; + + // Z3 specific (at the moment; some of them make sense also for other provers) + public string Inspector = null; + public bool OptimizeForBv = false; + public bool SMTLib2Model = false; + + public bool ProduceModel() { + return !CommandLineOptions.Clo.UseLabels || CommandLineOptions.Clo.ExplainHoudini || CommandLineOptions.Clo.UseProverEvaluate || + ExpectingModel(); + } + + public bool ExpectingModel() + { + return CommandLineOptions.Clo.PrintErrorModel >= 1 || + CommandLineOptions.Clo.EnhancedErrorMessages == 1 || + CommandLineOptions.Clo.ModelViewFile != null || + (CommandLineOptions.Clo.StratifiedInlining > 0 && !CommandLineOptions.Clo.StratifiedInliningWithoutModels); + } + + public void AddSolverArgument(string s) + { + SolverArguments.Add(s); + } + + public void AddSmtOption(string name, string val) + { + SmtOptions.Add(new OptionValue(name, val)); + } + + public void AddWeakSmtOption(string name, string val) + { + if (!SmtOptions.Any(o => o.Option == name)) + SmtOptions.Add(new OptionValue(name, val)); + } + + public void AddSmtOption(string opt) + { + var idx = opt.IndexOf('='); + if (idx <= 0 || idx == opt.Length - 1) + ReportError("Options to be passed to the prover should have the format: O:<name>=<value>, got '" + opt + "'"); + AddSmtOption(opt.Substring(0, idx), opt.Substring(idx + 1)); + } + + protected override bool Parse(string opt) + { + string SolverStr = null; + if (ParseString(opt, "SOLVER", ref SolverStr)) { + switch (SolverStr) { + case "Z3": + case "z3": + Solver = SolverKind.Z3; + break; + case "CVC4": + case "cvc4": + Solver = SolverKind.CVC4; + if (Logic.Equals("")) Logic = "ALL_SUPPORTED"; + break; + default: + ReportError("Invalid SOLVER value; must be 'Z3' or 'CVC4'"); + return false; + } + return true; + } + + if (opt.StartsWith("O:")) { + AddSmtOption(opt.Substring(2)); + return true; + } + + if (opt.StartsWith("C:")) { + AddSolverArgument(opt.Substring(2)); + return true; + } + + return + ParseBool(opt, "MULTI_TRACES", ref MultiTraces) || + ParseBool(opt, "USE_WEIGHTS", ref UseWeights) || + ParseString(opt, "INSPECTOR", ref Inspector) || + ParseBool(opt, "OPTIMIZE_FOR_BV", ref OptimizeForBv) || + ParseBool(opt, "SMTLIB2_MODEL", ref SMTLib2Model) || + ParseString(opt, "LOGIC", ref Logic) || + base.Parse(opt); + } + + public override void PostParse() + { + base.PostParse(); + if (Solver == SolverKind.Z3) + Z3.SetupOptions(this); + } + + public override string Help + { + get + { + return +@" +SMT-specific options: +~~~~~~~~~~~~~~~~~~~~~ +SOLVER=<string> Use the given SMT solver (z3 or cvc4; default: z3) +USE_WEIGHTS=<bool> Pass :weight annotations on quantified formulas (default: true) +VERBOSITY=<int> 1 - print prover output (default: 0) +O:<name>=<value> Pass (set-option :<name> <value>) to the SMT solver. +C:<string> Pass <string> to the SMT on the command line. +LOGIC=<string> Pass (set-logic <string>) to the prover (default: empty, 'ALL_SUPPORTED' for CVC4) + +Z3-specific options: +~~~~~~~~~~~~~~~~~~~~ +MULTI_TRACES=<bool> Report errors with multiple paths leading to the same assertion. +INSPECTOR=<string> Use the specified Z3Inspector binary. +OPTIMIZE_FOR_BV=<bool> Optimize Z3 options for bitvector reasoning, and not quantifier instantiation. Defaults to false. +SMTLIB2_MODEL=<bool> Use the SMTLIB2 output model. Defaults to false. +" + base.Help; + } + } + } +} diff --git a/Source/Provers/SMTLib/TypeDeclCollector.cs b/Source/Provers/SMTLib/TypeDeclCollector.cs index 9205d54c..32e28560 100644 --- a/Source/Provers/SMTLib/TypeDeclCollector.cs +++ b/Source/Provers/SMTLib/TypeDeclCollector.cs @@ -1,396 +1,396 @@ -//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie.VCExprAST;
-
-namespace Microsoft.Boogie.SMTLib
-{
- // Visitor for collecting the occurring function symbols in a VCExpr,
- // and for creating the corresponding declarations
-
- public class TypeDeclCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
-
- private readonly UniqueNamer Namer;
- private readonly SMTLibProverOptions Options;
- private HashSet<Function/*!*/>/*!*/ RegisteredRelations = new HashSet<Function>();
-
- [ContractInvariantMethod]
-void ObjectInvariant()
-{
- Contract.Invariant(Namer!=null);
- Contract.Invariant(AllDecls != null);
- Contract.Invariant(IncDecls != null);
- Contract.Invariant(KnownFunctions != null);
- Contract.Invariant(KnownVariables != null);
-}
-
-
- public TypeDeclCollector(SMTLibProverOptions opts, UniqueNamer namer) {
- Contract.Requires(namer != null);
- this.Namer = namer;
- this.Options = opts;
- InitializeKnownDecls();
- }
-
- // not used
- protected override bool StandardResult(VCExpr node, bool arg) {
- //Contract.Requires(node != null);
- return true;
- }
-
- private readonly List<string/*!>!*/> AllDecls = new List<string/*!*/> ();
- private readonly List<string/*!>!*/> IncDecls = new List<string/*!*/> ();
-
- // In order to support push/pop interface of the theorem prover, the "known" declarations
- // must be kept in a stack
-
- private HashSet<Function/*!*/>/*!*/ KnownFunctions
- {
- get { return _KnownFunctions.Peek(); }
- }
-
- private HashSet<VCExprVar/*!*/>/*!*/ KnownVariables
- {
- get { return _KnownVariables.Peek(); }
- }
-
- private HashSet<Type/*!*/>/*!*/ KnownTypes
- {
- get { return _KnownTypes.Peek(); }
- }
-
- private HashSet<string/*!*/>/*!*/ KnownStoreFunctions
- {
- get { return _KnownStoreFunctions.Peek(); }
- }
-
- private HashSet<string/*!*/>/*!*/ KnownSelectFunctions
- {
- get { return _KnownSelectFunctions.Peek(); }
- }
-
- private HashSet<string> KnownLBL
- {
- get { return _KnownLBL.Peek(); }
- }
-
- // ------
- private readonly Stack<HashSet<Function/*!*/>/*!*/> _KnownFunctions = new Stack<HashSet<Function/*!*/>>();
- private readonly Stack<HashSet<VCExprVar/*!*/>/*!*/> _KnownVariables = new Stack<HashSet<VCExprVar/*!*/>>();
-
- private readonly Stack<HashSet<Type/*!*/>/*!*/> _KnownTypes = new Stack<HashSet<Type>>();
- private readonly Stack<HashSet<string/*!*/>/*!*/> _KnownStoreFunctions = new Stack<HashSet<string>>();
- private readonly Stack<HashSet<string/*!*/>/*!*/> _KnownSelectFunctions = new Stack<HashSet<string>>();
- private readonly Stack<HashSet<string>> _KnownLBL = new Stack<HashSet<string>>();
-
- // lets RPFP checker capture decls
- public abstract class DeclHandler {
- public abstract void VarDecl(VCExprVar v);
- public abstract void FuncDecl(Function f);
- }
-
- private DeclHandler declHandler = null;
-
- public void SetDeclHandler(DeclHandler _d){
- declHandler = _d;
- }
-
- private void InitializeKnownDecls()
- {
- _KnownFunctions.Push(new HashSet<Function>());
- _KnownVariables.Push(new HashSet<VCExprVar>());
- _KnownTypes.Push(new HashSet<Type>());
- _KnownStoreFunctions.Push(new HashSet<string>());
- _KnownSelectFunctions.Push(new HashSet<string>());
- _KnownLBL.Push(new HashSet<string>());
- }
-
- public void Reset()
- {
- _KnownFunctions.Clear();
- _KnownVariables.Clear();
- _KnownTypes.Clear();
- _KnownStoreFunctions.Clear();
- _KnownSelectFunctions.Clear();
- _KnownLBL.Clear();
- AllDecls.Clear();
- IncDecls.Clear();
- InitializeKnownDecls();
- }
-
- public void Push()
- {
- Contract.Assert(_KnownFunctions.Count > 0);
- _KnownFunctions.Push(new HashSet<Function>(_KnownFunctions.Peek()));
- _KnownVariables.Push(new HashSet<VCExprVar>(_KnownVariables.Peek()));
- _KnownTypes.Push(new HashSet<Type>(_KnownTypes.Peek()));
- _KnownStoreFunctions.Push(new HashSet<string>(_KnownStoreFunctions.Peek()));
- _KnownSelectFunctions.Push(new HashSet<string>(_KnownSelectFunctions.Peek()));
- _KnownLBL.Push(new HashSet<string>(_KnownLBL.Peek()));
- }
-
- public void Pop()
- {
- Contract.Assert(_KnownFunctions.Count > 1);
- _KnownFunctions.Pop();
- _KnownVariables.Pop();
- _KnownTypes.Pop();
- _KnownStoreFunctions.Pop();
- _KnownSelectFunctions.Pop();
- _KnownLBL.Pop();
- }
-
- public List<string/*!>!*/> AllDeclarations { get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<string>>() ));
-
- List<string>/*!>!*/ res = new List<string/*!*/> ();
- res.AddRange(AllDecls);
- return res;
- } }
-
- public List<string/*!>!*/> GetNewDeclarations() {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<string>>() ));
- List<string>/*!>!*/ res = new List<string/*!*/>();
- res.AddRange(IncDecls);
- IncDecls.Clear();
- return res;
- }
-
- private void AddDeclaration(string decl) {
- Contract.Requires(decl != null);
- AllDecls.Add(decl);
- IncDecls.Add(decl);
- }
-
- public void Collect(VCExpr expr) {
- Contract.Requires(expr != null);
- Traverse(expr, true);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- private static string TypeToString(Type t) {
- Contract.Requires(t != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- return SMTLibExprLineariser.TypeToString(t);
- }
-
- public string TypeToStringReg(Type t)
- {
- RegisterType(t);
- return TypeToString(t);
- }
-
- public void AddFunction(Function func) {
- if (KnownFunctions.Contains(func))
- return;
- KnownFunctions.Add(func);
- if(declHandler != null)
- declHandler.FuncDecl(func);
- }
-
- public void RegisterRelation(Function func)
- {
- if (RegisteredRelations.Contains(func))
- return;
- RegisteredRelations.Add(func);
- }
-
- public override bool Visit(VCExprNAry node, bool arg) {
- Contract.Requires(node != null);
-
- if (node.Op is VCExprStoreOp) RegisterStore(node);
- else if (node.Op is VCExprSelectOp) RegisterSelect(node);
- else {
- VCExprBoogieFunctionOp op = node.Op as VCExprBoogieFunctionOp;
- if (op != null &&
- !(op.Func is DatatypeConstructor) && !(op.Func is DatatypeMembership) && !(op.Func is DatatypeSelector) &&
- !KnownFunctions.Contains(op.Func)) {
- Function f = op.Func;
- Contract.Assert(f != null);
-
- var builtin = SMTLibExprLineariser.ExtractBuiltin(f);
- if (builtin == null) {
- string printedName = Namer.GetQuotedName(f, f.Name);
- Contract.Assert(printedName != null);
-
- Contract.Assert(f.OutParams.Count == 1);
- var argTypes = f.InParams.Cast<Variable>().MapConcat(p => TypeToStringReg(p.TypedIdent.Type), " ");
- string decl;
- if(RegisteredRelations.Contains(op.Func))
- decl = "(declare-rel " + printedName + " (" + argTypes + ") " + ")";
- else
- decl = "(declare-fun " + printedName + " (" + argTypes + ") " + TypeToStringReg(f.OutParams[0].TypedIdent.Type) + ")";
- AddDeclaration(decl);
- if (declHandler != null) declHandler.FuncDecl(f);
- }
- KnownFunctions.Add(f);
- } else {
- var lab = node.Op as VCExprLabelOp;
- if (lab != null && !KnownLBL.Contains(lab.label)) {
- KnownLBL.Add(lab.label);
- var name = SMTLibNamer.QuoteId(SMTLibNamer.LabelVar(lab.label));
- AddDeclaration("(declare-fun " + name + " () Bool)");
- }
- }
- }
-
- return base.Visit(node, arg);
- }
-
- public override bool Visit(VCExprVar node, bool arg) {
- Contract.Requires(node != null);
- if (!BoundTermVars.Contains(node) && !KnownVariables.Contains(node)) {
- string printedName = Namer.GetQuotedName(node, node.Name);
- Contract.Assert(printedName!=null);
- RegisterType(node.Type);
- string decl =
- "(declare-fun " + printedName + " () " + TypeToString(node.Type) + ")";
- AddDeclaration(decl);
- KnownVariables.Add(node);
- if(declHandler != null)
- declHandler.VarDecl(node);
- }
-
- return base.Visit(node, arg);
- }
-
- public override bool Visit(VCExprQuantifier node, bool arg)
- {
- Contract.Requires(node != null);
- foreach (VCExprVar v in node.BoundVars) {
- Contract.Assert(v != null);
- RegisterType(v.Type);
- }
-
- return base.Visit(node, arg);
- }
-
- private void RegisterType(Type type)
- {
- Contract.Requires(type != null);
- if (KnownTypes.Contains(type)) return;
-
- if (type.IsMap && CommandLineOptions.Clo.MonomorphicArrays) {
- KnownTypes.Add(type);
- MapType mapType = type.AsMap;
- Contract.Assert(mapType != null);
-
- foreach (Type t in mapType.Arguments) {
- Contract.Assert(t != null);
- RegisterType(t);
- }
- RegisterType(mapType.Result);
-
- if (!CommandLineOptions.Clo.UseArrayTheory)
- AddDeclaration("(declare-sort " + TypeToString(type) + " 0)");
-
- return;
- }
-
- if (type.IsBool || type.IsInt || type.IsReal || type.IsBv)
- return;
-
- CtorType ctorType = type as CtorType;
- if (ctorType != null && ctorType.IsDatatype())
- return;
-
- if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.Monomorphic) {
- AddDeclaration("(declare-sort " + TypeToString(type) + " 0)");
- KnownTypes.Add(type);
- return;
- }
- }
-
- private void RegisterSelect(VCExprNAry node)
- {
- RegisterType(node[0].Type);
-
- if (CommandLineOptions.Clo.UseArrayTheory)
- return;
-
- string name = SimplifyLikeExprLineariser.SelectOpName(node);
- name = Namer.GetQuotedName(name, name);
-
- if (!KnownSelectFunctions.Contains(name)) {
- string decl = "(declare-fun " + name + " (" + node.MapConcat(n => TypeToString(n.Type), " ") + ") " + TypeToString(node.Type) + ")";
- AddDeclaration(decl);
- KnownSelectFunctions.Add(name);
- }
- }
-
- private void RegisterStore(VCExprNAry node)
- {
- RegisterType(node.Type); // this is the map type, registering it should register also the index and value types
-
- if (CommandLineOptions.Clo.UseArrayTheory)
- return;
-
- string name = SimplifyLikeExprLineariser.StoreOpName(node);
- name = Namer.GetQuotedName(name, name);
-
- if (!KnownStoreFunctions.Contains(name)) {
- string decl = "(declare-fun " + name + " (" + node.MapConcat(n => TypeToString(n.Type), " ") + ") " + TypeToString(node.Type) + ")";
- AddDeclaration(decl);
-
- if (CommandLineOptions.Clo.MonomorphicArrays) {
- var sel = SimplifyLikeExprLineariser.SelectOpName(node);
- sel = Namer.GetQuotedName(sel, sel);
-
- if (!KnownSelectFunctions.Contains(sel)) {
- // need to declare it before reference
- var args = node.SkipEnd(1);
- var ret = node.Last();
- string seldecl = "(declare-fun " + sel + " (" + args.MapConcat(n => TypeToString(n.Type), " ") + ") " + TypeToString(ret.Type) + ")";
- AddDeclaration(seldecl);
- KnownSelectFunctions.Add(sel);
- }
-
- string ax1 = "(assert (forall (";
- string ax2 = "(assert (forall (";
-
- string argX = "", argY = "";
- string dist = "";
- for (int i = 0; i < node.Arity; i++) {
- var t = " " + TypeToString(node[i].Type);
- var x = " ?x" + i;
- var y = " ?y" + i;
- ax1 += " (" + x + t + ")";
- ax2 += " (" + x + t + ")";
- if (i != 0 && i != node.Arity - 1) {
- argX += x;
- argY += y;
- ax2 += " (" + y + t + ")";
- dist += " (not (=" + x + y + "))";
- }
- }
- string v = " ?x" + (node.Arity - 1);
- ax1 += ") (= (" + sel + " (" + name + " ?x0" + argX + v + ")" + argX + ") " + v + ")";
- ax1 += "))";
-
- if (node.Arity > 3)
- dist = "(or " + dist + ")";
- ax2 += ") (=> " + dist + " (= (" + sel + " (" + name + " ?x0" + argX + v + ")" + argY + ") (" + sel + " ?x0" + argY + ")))";
- ax2 += "))";
-
- AddDeclaration(ax1);
- AddDeclaration(ax2);
- }
-
- KnownStoreFunctions.Add(name);
- }
- //
- }
-
- }
-
+//----------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Diagnostics; +using System.Diagnostics.Contracts; +using Microsoft.Boogie.VCExprAST; + +namespace Microsoft.Boogie.SMTLib +{ + // Visitor for collecting the occurring function symbols in a VCExpr, + // and for creating the corresponding declarations + + public class TypeDeclCollector : BoundVarTraversingVCExprVisitor<bool, bool> { + + private readonly UniqueNamer Namer; + private readonly SMTLibProverOptions Options; + private HashSet<Function/*!*/>/*!*/ RegisteredRelations = new HashSet<Function>(); + + [ContractInvariantMethod] +void ObjectInvariant() +{ + Contract.Invariant(Namer!=null); + Contract.Invariant(AllDecls != null); + Contract.Invariant(IncDecls != null); + Contract.Invariant(KnownFunctions != null); + Contract.Invariant(KnownVariables != null); +} + + + public TypeDeclCollector(SMTLibProverOptions opts, UniqueNamer namer) { + Contract.Requires(namer != null); + this.Namer = namer; + this.Options = opts; + InitializeKnownDecls(); + } + + // not used + protected override bool StandardResult(VCExpr node, bool arg) { + //Contract.Requires(node != null); + return true; + } + + private readonly List<string/*!>!*/> AllDecls = new List<string/*!*/> (); + private readonly List<string/*!>!*/> IncDecls = new List<string/*!*/> (); + + // In order to support push/pop interface of the theorem prover, the "known" declarations + // must be kept in a stack + + private HashSet<Function/*!*/>/*!*/ KnownFunctions + { + get { return _KnownFunctions.Peek(); } + } + + private HashSet<VCExprVar/*!*/>/*!*/ KnownVariables + { + get { return _KnownVariables.Peek(); } + } + + private HashSet<Type/*!*/>/*!*/ KnownTypes + { + get { return _KnownTypes.Peek(); } + } + + private HashSet<string/*!*/>/*!*/ KnownStoreFunctions + { + get { return _KnownStoreFunctions.Peek(); } + } + + private HashSet<string/*!*/>/*!*/ KnownSelectFunctions + { + get { return _KnownSelectFunctions.Peek(); } + } + + private HashSet<string> KnownLBL + { + get { return _KnownLBL.Peek(); } + } + + // ------ + private readonly Stack<HashSet<Function/*!*/>/*!*/> _KnownFunctions = new Stack<HashSet<Function/*!*/>>(); + private readonly Stack<HashSet<VCExprVar/*!*/>/*!*/> _KnownVariables = new Stack<HashSet<VCExprVar/*!*/>>(); + + private readonly Stack<HashSet<Type/*!*/>/*!*/> _KnownTypes = new Stack<HashSet<Type>>(); + private readonly Stack<HashSet<string/*!*/>/*!*/> _KnownStoreFunctions = new Stack<HashSet<string>>(); + private readonly Stack<HashSet<string/*!*/>/*!*/> _KnownSelectFunctions = new Stack<HashSet<string>>(); + private readonly Stack<HashSet<string>> _KnownLBL = new Stack<HashSet<string>>(); + + // lets RPFP checker capture decls + public abstract class DeclHandler { + public abstract void VarDecl(VCExprVar v); + public abstract void FuncDecl(Function f); + } + + private DeclHandler declHandler = null; + + public void SetDeclHandler(DeclHandler _d){ + declHandler = _d; + } + + private void InitializeKnownDecls() + { + _KnownFunctions.Push(new HashSet<Function>()); + _KnownVariables.Push(new HashSet<VCExprVar>()); + _KnownTypes.Push(new HashSet<Type>()); + _KnownStoreFunctions.Push(new HashSet<string>()); + _KnownSelectFunctions.Push(new HashSet<string>()); + _KnownLBL.Push(new HashSet<string>()); + } + + public void Reset() + { + _KnownFunctions.Clear(); + _KnownVariables.Clear(); + _KnownTypes.Clear(); + _KnownStoreFunctions.Clear(); + _KnownSelectFunctions.Clear(); + _KnownLBL.Clear(); + AllDecls.Clear(); + IncDecls.Clear(); + InitializeKnownDecls(); + } + + public void Push() + { + Contract.Assert(_KnownFunctions.Count > 0); + _KnownFunctions.Push(new HashSet<Function>(_KnownFunctions.Peek())); + _KnownVariables.Push(new HashSet<VCExprVar>(_KnownVariables.Peek())); + _KnownTypes.Push(new HashSet<Type>(_KnownTypes.Peek())); + _KnownStoreFunctions.Push(new HashSet<string>(_KnownStoreFunctions.Peek())); + _KnownSelectFunctions.Push(new HashSet<string>(_KnownSelectFunctions.Peek())); + _KnownLBL.Push(new HashSet<string>(_KnownLBL.Peek())); + } + + public void Pop() + { + Contract.Assert(_KnownFunctions.Count > 1); + _KnownFunctions.Pop(); + _KnownVariables.Pop(); + _KnownTypes.Pop(); + _KnownStoreFunctions.Pop(); + _KnownSelectFunctions.Pop(); + _KnownLBL.Pop(); + } + + public List<string/*!>!*/> AllDeclarations { get { + Contract.Ensures(cce.NonNullElements(Contract.Result<List<string>>() )); + + List<string>/*!>!*/ res = new List<string/*!*/> (); + res.AddRange(AllDecls); + return res; + } } + + public List<string/*!>!*/> GetNewDeclarations() { + Contract.Ensures(cce.NonNullElements(Contract.Result<List<string>>() )); + List<string>/*!>!*/ res = new List<string/*!*/>(); + res.AddRange(IncDecls); + IncDecls.Clear(); + return res; + } + + private void AddDeclaration(string decl) { + Contract.Requires(decl != null); + AllDecls.Add(decl); + IncDecls.Add(decl); + } + + public void Collect(VCExpr expr) { + Contract.Requires(expr != null); + Traverse(expr, true); + } + + /////////////////////////////////////////////////////////////////////////// + + private static string TypeToString(Type t) { + Contract.Requires(t != null); + Contract.Ensures(Contract.Result<string>() != null); + + return SMTLibExprLineariser.TypeToString(t); + } + + public string TypeToStringReg(Type t) + { + RegisterType(t); + return TypeToString(t); + } + + public void AddFunction(Function func) { + if (KnownFunctions.Contains(func)) + return; + KnownFunctions.Add(func); + if(declHandler != null) + declHandler.FuncDecl(func); + } + + public void RegisterRelation(Function func) + { + if (RegisteredRelations.Contains(func)) + return; + RegisteredRelations.Add(func); + } + + public override bool Visit(VCExprNAry node, bool arg) { + Contract.Requires(node != null); + + if (node.Op is VCExprStoreOp) RegisterStore(node); + else if (node.Op is VCExprSelectOp) RegisterSelect(node); + else { + VCExprBoogieFunctionOp op = node.Op as VCExprBoogieFunctionOp; + if (op != null && + !(op.Func is DatatypeConstructor) && !(op.Func is DatatypeMembership) && !(op.Func is DatatypeSelector) && + !KnownFunctions.Contains(op.Func)) { + Function f = op.Func; + Contract.Assert(f != null); + + var builtin = SMTLibExprLineariser.ExtractBuiltin(f); + if (builtin == null) { + string printedName = Namer.GetQuotedName(f, f.Name); + Contract.Assert(printedName != null); + + Contract.Assert(f.OutParams.Count == 1); + var argTypes = f.InParams.Cast<Variable>().MapConcat(p => TypeToStringReg(p.TypedIdent.Type), " "); + string decl; + if(RegisteredRelations.Contains(op.Func)) + decl = "(declare-rel " + printedName + " (" + argTypes + ") " + ")"; + else + decl = "(declare-fun " + printedName + " (" + argTypes + ") " + TypeToStringReg(f.OutParams[0].TypedIdent.Type) + ")"; + AddDeclaration(decl); + if (declHandler != null) declHandler.FuncDecl(f); + } + KnownFunctions.Add(f); + } else { + var lab = node.Op as VCExprLabelOp; + if (lab != null && !KnownLBL.Contains(lab.label)) { + KnownLBL.Add(lab.label); + var name = SMTLibNamer.QuoteId(SMTLibNamer.LabelVar(lab.label)); + AddDeclaration("(declare-fun " + name + " () Bool)"); + } + } + } + + return base.Visit(node, arg); + } + + public override bool Visit(VCExprVar node, bool arg) { + Contract.Requires(node != null); + if (!BoundTermVars.Contains(node) && !KnownVariables.Contains(node)) { + string printedName = Namer.GetQuotedName(node, node.Name); + Contract.Assert(printedName!=null); + RegisterType(node.Type); + string decl = + "(declare-fun " + printedName + " () " + TypeToString(node.Type) + ")"; + AddDeclaration(decl); + KnownVariables.Add(node); + if(declHandler != null) + declHandler.VarDecl(node); + } + + return base.Visit(node, arg); + } + + public override bool Visit(VCExprQuantifier node, bool arg) + { + Contract.Requires(node != null); + foreach (VCExprVar v in node.BoundVars) { + Contract.Assert(v != null); + RegisterType(v.Type); + } + + return base.Visit(node, arg); + } + + private void RegisterType(Type type) + { + Contract.Requires(type != null); + if (KnownTypes.Contains(type)) return; + + if (type.IsMap && CommandLineOptions.Clo.MonomorphicArrays) { + KnownTypes.Add(type); + MapType mapType = type.AsMap; + Contract.Assert(mapType != null); + + foreach (Type t in mapType.Arguments) { + Contract.Assert(t != null); + RegisterType(t); + } + RegisterType(mapType.Result); + + if (!CommandLineOptions.Clo.UseArrayTheory) + AddDeclaration("(declare-sort " + TypeToString(type) + " 0)"); + + return; + } + + if (type.IsBool || type.IsInt || type.IsReal || type.IsBv) + return; + + CtorType ctorType = type as CtorType; + if (ctorType != null && ctorType.IsDatatype()) + return; + + if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.Monomorphic) { + AddDeclaration("(declare-sort " + TypeToString(type) + " 0)"); + KnownTypes.Add(type); + return; + } + } + + private void RegisterSelect(VCExprNAry node) + { + RegisterType(node[0].Type); + + if (CommandLineOptions.Clo.UseArrayTheory) + return; + + string name = SimplifyLikeExprLineariser.SelectOpName(node); + name = Namer.GetQuotedName(name, name); + + if (!KnownSelectFunctions.Contains(name)) { + string decl = "(declare-fun " + name + " (" + node.MapConcat(n => TypeToString(n.Type), " ") + ") " + TypeToString(node.Type) + ")"; + AddDeclaration(decl); + KnownSelectFunctions.Add(name); + } + } + + private void RegisterStore(VCExprNAry node) + { + RegisterType(node.Type); // this is the map type, registering it should register also the index and value types + + if (CommandLineOptions.Clo.UseArrayTheory) + return; + + string name = SimplifyLikeExprLineariser.StoreOpName(node); + name = Namer.GetQuotedName(name, name); + + if (!KnownStoreFunctions.Contains(name)) { + string decl = "(declare-fun " + name + " (" + node.MapConcat(n => TypeToString(n.Type), " ") + ") " + TypeToString(node.Type) + ")"; + AddDeclaration(decl); + + if (CommandLineOptions.Clo.MonomorphicArrays) { + var sel = SimplifyLikeExprLineariser.SelectOpName(node); + sel = Namer.GetQuotedName(sel, sel); + + if (!KnownSelectFunctions.Contains(sel)) { + // need to declare it before reference + var args = node.SkipEnd(1); + var ret = node.Last(); + string seldecl = "(declare-fun " + sel + " (" + args.MapConcat(n => TypeToString(n.Type), " ") + ") " + TypeToString(ret.Type) + ")"; + AddDeclaration(seldecl); + KnownSelectFunctions.Add(sel); + } + + string ax1 = "(assert (forall ("; + string ax2 = "(assert (forall ("; + + string argX = "", argY = ""; + string dist = ""; + for (int i = 0; i < node.Arity; i++) { + var t = " " + TypeToString(node[i].Type); + var x = " ?x" + i; + var y = " ?y" + i; + ax1 += " (" + x + t + ")"; + ax2 += " (" + x + t + ")"; + if (i != 0 && i != node.Arity - 1) { + argX += x; + argY += y; + ax2 += " (" + y + t + ")"; + dist += " (not (=" + x + y + "))"; + } + } + string v = " ?x" + (node.Arity - 1); + ax1 += ") (= (" + sel + " (" + name + " ?x0" + argX + v + ")" + argX + ") " + v + ")"; + ax1 += "))"; + + if (node.Arity > 3) + dist = "(or " + dist + ")"; + ax2 += ") (=> " + dist + " (= (" + sel + " (" + name + " ?x0" + argX + v + ")" + argY + ") (" + sel + " ?x0" + argY + ")))"; + ax2 += "))"; + + AddDeclaration(ax1); + AddDeclaration(ax2); + } + + KnownStoreFunctions.Add(name); + } + // + } + + } + }
\ No newline at end of file diff --git a/Source/Provers/SMTLib/Z3.cs b/Source/Provers/SMTLib/Z3.cs index bbc23917..f4bbbd6d 100644 --- a/Source/Provers/SMTLib/Z3.cs +++ b/Source/Provers/SMTLib/Z3.cs @@ -1,387 +1,387 @@ -//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics.Contracts;
-using System.IO;
-using System.Text.RegularExpressions;
-
-namespace Microsoft.Boogie.SMTLib
-{
- class Z3
- {
- static string _proverPath;
-
- static string CodebaseString()
- {
- Contract.Ensures(Contract.Result<string>() != null);
- return Path.GetDirectoryName(cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location));
- }
-
- public static string ExecutablePath()
- {
- if (_proverPath == null)
- FindExecutable();
- return _proverPath;
- }
-
- static void FindExecutable()
- // throws ProverException, System.IO.FileNotFoundException;
- {
- Contract.Ensures(_proverPath != null);
-
- // Command line option 'z3exe' always has priority if set
- if (CommandLineOptions.Clo.Z3ExecutablePath != null)
- {
- _proverPath = CommandLineOptions.Clo.Z3ExecutablePath;
- if (!File.Exists(_proverPath))
- {
- throw new ProverException("Cannot find prover specified with z3exe: " + _proverPath);
- }
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("[TRACE] Using prover: " + _proverPath);
- }
- return;
- }
-
- var proverExe = CommandLineOptions.Clo.Z3ExecutableName;
- proverExe = proverExe == null ? "z3.exe" : proverExe;
-
- if (_proverPath == null)
- {
- // Initialize '_proverPath'
- _proverPath = Path.Combine(CodebaseString(), proverExe);
- string firstTry = _proverPath;
-
- if (File.Exists(firstTry))
- {
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("[TRACE] Using prover: " + _proverPath);
- }
- return;
- }
-
- List<string> z3Dirs = new List<string>();
- var msrDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Microsoft Research\");
- if (Directory.Exists(msrDir))
- {
- z3Dirs.AddRange(Directory.GetDirectories(msrDir, "Z3-*"));
- }
- var msrDirX86 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Microsoft Research\");
- if (Directory.Exists(msrDirX86))
- {
- z3Dirs.AddRange(Directory.GetDirectories(msrDirX86, "Z3-*"));
- }
-
- int minMajor = 3, minMinor = 2;
-
- // Look for the most recent version of Z3.
- int minor = 0, major = 0;
- string winner = null;
- Regex r = new Regex(@"^Z3-(\d+)\.(\d+)$");
- foreach (string d in z3Dirs)
- {
- string name = new DirectoryInfo(d).Name;
- foreach (Match m in r.Matches(name))
- {
- int ma, mi;
- ma = int.Parse(m.Groups[1].ToString());
- mi = int.Parse(m.Groups[2].ToString());
- if (major < ma || (major == ma && minor < mi))
- {
- major = ma;
- minor = mi;
- winner = d;
- }
- }
- }
-
- if (major == 0 && minor == 0)
- {
- throw new ProverException("Cannot find executable: " + firstTry);
- }
-
- Contract.Assert(winner != null);
-
- _proverPath = Path.Combine(Path.Combine(winner, "bin"), proverExe);
- if (!File.Exists(_proverPath))
- {
- throw new ProverException("Cannot find prover: " + _proverPath);
- }
-
- if (CommandLineOptions.Clo.Trace)
- {
- Console.WriteLine("[TRACE] Using prover: " + _proverPath);
- }
-
- if (major < minMajor || (major == minMajor && minor < minMinor))
- {
- throw new ProverException(string.Format("Found version {0}.{1} of Z3. Please install version {2}.{3} or later. " +
- "(More conservative users might opt to supply -prover:Z3 option instead to get the historic Simplify back-end)",
- major, minor, minMajor, minMinor));
- }
- }
- }
-
-
- static int Z3MajorVersion = 0;
- static int Z3MinorVersion = 0;
- static bool Z3VersionObtained = false;
-
- public static void GetVersion(out int major, out int minor)
- {
- if (!Z3VersionObtained)
- {
- var proc = new System.Diagnostics.Process();
- proc.StartInfo.FileName = _proverPath;
- proc.StartInfo.Arguments = "--version";
- proc.StartInfo.RedirectStandardOutput = true;
- proc.StartInfo.RedirectStandardError = true;
- proc.StartInfo.UseShellExecute = false;
- proc.StartInfo.CreateNoWindow = true;
- proc.Start();
- string answer = proc.StandardOutput.ReadToEnd();
- proc.WaitForExit();
- if (proc.ExitCode == 0)
- {
- var firstdot = answer.IndexOf('.');
- if (firstdot >= 0)
- {
- var seconddot = answer.IndexOf('.', firstdot + 1);
- if (seconddot >= firstdot + 1)
- {
- var spacebeforefirstdot = answer.LastIndexOf(' ', firstdot);
- if (spacebeforefirstdot >= 0)
- {
- var majorstr = answer.Substring(spacebeforefirstdot, firstdot - spacebeforefirstdot);
- var minorstr = answer.Substring(firstdot + 1, seconddot - firstdot - 1);
- Z3MajorVersion = Convert.ToInt32(majorstr);
- Z3MinorVersion = Convert.ToInt32(minorstr);
- }
- }
- }
- }
- Z3VersionObtained = true;
- }
- major = Z3MajorVersion;
- minor = Z3MinorVersion;
- }
-
- public static string SetTimeoutOption()
- {
- int major, minor;
- GetVersion(out major, out minor);
- if (major > 4 || major == 4 && minor >= 3)
- return "TIMEOUT";
- else
- return "SOFT_TIMEOUT";
- }
-
- // options that work only on the command line
- static string[] commandLineOnly = { "TRACE", "PROOF_MODE" };
-
-
- public static void SetupOptions(SMTLibProverOptions options)
- {
- FindExecutable();
- int major, minor;
- GetVersion(out major, out minor);
- if (major > 4 || major == 4 && minor >= 3)
- {
-
- bool fp = false; // CommandLineOptions.Clo.FixedPointEngine != null;
-
- // don't bother with auto-config - it would disable explicit settings for eager threshold and so on
- if(!fp) options.AddWeakSmtOption("AUTO_CONFIG", "false");
-
- //options.AddWeakSmtOption("MODEL_PARTIAL", "true");
- //options.WeakAddSmtOption("MODEL_VALUE_COMPLETION", "false");
-
- // options.AddWeakSmtOption("MODEL_HIDE_UNUSED_PARTITIONS", "false"); TODO: what does this do?
-
- // Make sure we get something that is parsable as a bitvector
- options.AddWeakSmtOption("pp.bv_literals", "false");
- if (!CommandLineOptions.Clo.UseSmtOutputFormat)
- {
- options.AddWeakSmtOption("MODEL.V2", "true");
- }
- //options.AddWeakSmtOption("ASYNC_COMMANDS", "false"); TODO: is this needed?
-
- if (!options.OptimizeForBv)
- {
- // Phase selection means to always try the negative literal polarity first, seems to be good for Boogie.
- // The restart parameters change the restart behavior to match Z3 v1, which also seems to be good.
- options.AddWeakSmtOption("smt.PHASE_SELECTION", "0");
- options.AddWeakSmtOption("smt.RESTART_STRATEGY", "0");
- options.AddWeakSmtOption("smt.RESTART_FACTOR", "|1.5|");
-
- // Make the integer model more diverse by default, speeds up some benchmarks a lot.
- options.AddWeakSmtOption("smt.ARITH.RANDOM_INITIAL_VALUE", "true");
-
- // The left-to-right structural case-splitting strategy.
- //options.AddWeakSmtOption("SORT_AND_OR", "false"); // always false now
-
- if (!fp) options.AddWeakSmtOption("smt.CASE_SPLIT", "3");
-
- // In addition delay adding unit conflicts.
- options.AddWeakSmtOption("smt.DELAY_UNITS", "true");
- //options.AddWeakSmtOption("DELAY_UNITS_THRESHOLD", "16"); TODO: what?
- }
-
- // This is used by VCC, but could be also useful for others, if sk_hack(foo(x)) is included as trigger,
- // the foo(x0) will be activated for e-matching when x is skolemized to x0.
- options.AddWeakSmtOption("NNF.SK_HACK", "true");
-
- // don't use model-based quantifier instantiation; it never finishes on non-trivial Boogie problems
- options.AddWeakSmtOption("smt.MBQI", "false");
-
- // More or less like MAM=0.
- options.AddWeakSmtOption("smt.QI.EAGER_THRESHOLD", "100");
- // Complex proof attempts in VCC (and likely elsewhere) require matching depth of 20 or more.
-
- // the following will make the :weight option more usable
- // KLM: this QI cost function is the default
- // if (!fp) options.AddWeakSmtOption("smt.QI.COST", "|(+ weight generation)|"); // TODO: this doesn't seem to work
-
- //if (options.Inspector != null)
- // options.WeakAddSmtOption("PROGRESS_SAMPLING_FREQ", "100");
-
- options.AddWeakSmtOption("TYPE_CHECK", "true");
- options.AddWeakSmtOption("smt.BV.REFLECT", "true");
-
- if (options.TimeLimit > 0)
- {
- options.AddWeakSmtOption("TIMEOUT", options.TimeLimit.ToString());
- options.AddWeakSmtOption("fixedpoint.TIMEOUT", options.TimeLimit.ToString());
- // This kills the Z3 *instance* after the specified time, not a particular query, so we cannot use it.
- // options.AddSolverArgument("/T:" + (options.TimeLimit + 1000) / 1000);
- }
-
- if (options.Inspector != null)
- options.AddWeakSmtOption("PROGRESS_SAMPLING_FREQ", "200");
-
- if (CommandLineOptions.Clo.WeakArrayTheory)
- {
- options.AddWeakSmtOption("smt.array.weak", "true");
- options.AddWeakSmtOption("smt.array.extensional", "false");
- }
-
- if (CommandLineOptions.Clo.PrintConjectures != null)
- {
- options.AddWeakSmtOption("fixedpoint.conjecture_file", CommandLineOptions.Clo.PrintConjectures + ".tmp");
- }
- }
- else
- {
- // don't bother with auto-config - it would disable explicit settings for eager threshold and so on
- options.AddWeakSmtOption("AUTO_CONFIG", "false");
-
- //options.AddWeakSmtOption("MODEL_PARTIAL", "true");
- //options.WeakAddSmtOption("MODEL_VALUE_COMPLETION", "false");
- options.AddWeakSmtOption("MODEL_HIDE_UNUSED_PARTITIONS", "false");
- options.AddWeakSmtOption("ASYNC_COMMANDS", "false");
-
- if (CommandLineOptions.Clo.UseSmtOutputFormat)
- {
- options.AddWeakSmtOption("pp-bv-literals", "false"); ;
- }
- else
- {
- options.AddWeakSmtOption("MODEL_V2", "true");
- }
-
- if (!options.OptimizeForBv)
- {
- // Phase selection means to always try the negative literal polarity first, seems to be good for Boogie.
- // The restart parameters change the restart behavior to match Z3 v1, which also seems to be good.
- options.AddWeakSmtOption("PHASE_SELECTION", "0");
- options.AddWeakSmtOption("RESTART_STRATEGY", "0");
- options.AddWeakSmtOption("RESTART_FACTOR", "|1.5|");
-
- // Make the integer model more diverse by default, speeds up some benchmarks a lot.
- options.AddWeakSmtOption("ARITH_RANDOM_INITIAL_VALUE", "true");
-
- // The left-to-right structural case-splitting strategy.
- //options.AddWeakSmtOption("SORT_AND_OR", "false"); // always false now
- options.AddWeakSmtOption("CASE_SPLIT", "3");
-
- // In addition delay adding unit conflicts.
- options.AddWeakSmtOption("DELAY_UNITS", "true");
- options.AddWeakSmtOption("DELAY_UNITS_THRESHOLD", "16");
- }
-
- // This is used by VCC, but could be also useful for others, if sk_hack(foo(x)) is included as trigger,
- // the foo(x0) will be activated for e-matching when x is skolemized to x0.
- options.AddWeakSmtOption("NNF_SK_HACK", "true");
-
- // don't use model-based quantifier instantiation; it never finishes on non-trivial Boogie problems
- options.AddWeakSmtOption("MBQI", "false");
-
- // More or less like MAM=0.
- options.AddWeakSmtOption("QI_EAGER_THRESHOLD", "100");
- // Complex proof attempts in VCC (and likely elsewhere) require matching depth of 20 or more.
-
- // the following will make the :weight option more usable
- options.AddWeakSmtOption("QI_COST", "|\"(+ weight generation)\"|");
-
- //if (options.Inspector != null)
- // options.WeakAddSmtOption("PROGRESS_SAMPLING_FREQ", "100");
-
- options.AddWeakSmtOption("TYPE_CHECK", "true");
- options.AddWeakSmtOption("BV_REFLECT", "true");
-
- if (options.TimeLimit > 0)
- {
- options.AddWeakSmtOption("SOFT_TIMEOUT", options.TimeLimit.ToString());
- // This kills the Z3 *instance* after the specified time, not a particular query, so we cannot use it.
- // options.AddSolverArgument("/T:" + (options.TimeLimit + 1000) / 1000);
- }
-
- if (options.Inspector != null)
- options.AddWeakSmtOption("PROGRESS_SAMPLING_FREQ", "200");
-
- if (CommandLineOptions.Clo.WeakArrayTheory)
- {
- options.AddWeakSmtOption("ARRAY_WEAK", "true");
- options.AddWeakSmtOption("ARRAY_EXTENSIONAL", "false");
- }
-
- options.AddWeakSmtOption("MODEL_ON_TIMEOUT", "true");
-
- }
-
- // KLM: don't add Z3 options here. The options are different in different Z3 versions.
- // Add options in the above condition for the appropriate version.
-
- // legacy option handling
- if (!CommandLineOptions.Clo.z3AtFlag)
- options.MultiTraces = true;
-
-
- foreach (string opt in CommandLineOptions.Clo.Z3Options)
- {
- Contract.Assert(opt != null);
- int eq = opt.IndexOf("=");
- if (eq > 0 && 'A' <= opt[0] && opt[0] <= 'Z' && !commandLineOnly.Contains(opt.Substring(0, eq)))
- {
- options.AddSmtOption(opt.Substring(0, eq), opt.Substring(eq + 1));
- }
- else
- {
- options.AddSolverArgument(opt);
- }
- }
- }
-
-
- }
-}
+//----------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- + + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics.Contracts; +using System.IO; +using System.Text.RegularExpressions; + +namespace Microsoft.Boogie.SMTLib +{ + class Z3 + { + static string _proverPath; + + static string CodebaseString() + { + Contract.Ensures(Contract.Result<string>() != null); + return Path.GetDirectoryName(cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location)); + } + + public static string ExecutablePath() + { + if (_proverPath == null) + FindExecutable(); + return _proverPath; + } + + static void FindExecutable() + // throws ProverException, System.IO.FileNotFoundException; + { + Contract.Ensures(_proverPath != null); + + // Command line option 'z3exe' always has priority if set + if (CommandLineOptions.Clo.Z3ExecutablePath != null) + { + _proverPath = CommandLineOptions.Clo.Z3ExecutablePath; + if (!File.Exists(_proverPath)) + { + throw new ProverException("Cannot find prover specified with z3exe: " + _proverPath); + } + if (CommandLineOptions.Clo.Trace) + { + Console.WriteLine("[TRACE] Using prover: " + _proverPath); + } + return; + } + + var proverExe = CommandLineOptions.Clo.Z3ExecutableName; + proverExe = proverExe == null ? "z3.exe" : proverExe; + + if (_proverPath == null) + { + // Initialize '_proverPath' + _proverPath = Path.Combine(CodebaseString(), proverExe); + string firstTry = _proverPath; + + if (File.Exists(firstTry)) + { + if (CommandLineOptions.Clo.Trace) + { + Console.WriteLine("[TRACE] Using prover: " + _proverPath); + } + return; + } + + List<string> z3Dirs = new List<string>(); + var msrDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Microsoft Research\"); + if (Directory.Exists(msrDir)) + { + z3Dirs.AddRange(Directory.GetDirectories(msrDir, "Z3-*")); + } + var msrDirX86 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Microsoft Research\"); + if (Directory.Exists(msrDirX86)) + { + z3Dirs.AddRange(Directory.GetDirectories(msrDirX86, "Z3-*")); + } + + int minMajor = 3, minMinor = 2; + + // Look for the most recent version of Z3. + int minor = 0, major = 0; + string winner = null; + Regex r = new Regex(@"^Z3-(\d+)\.(\d+)$"); + foreach (string d in z3Dirs) + { + string name = new DirectoryInfo(d).Name; + foreach (Match m in r.Matches(name)) + { + int ma, mi; + ma = int.Parse(m.Groups[1].ToString()); + mi = int.Parse(m.Groups[2].ToString()); + if (major < ma || (major == ma && minor < mi)) + { + major = ma; + minor = mi; + winner = d; + } + } + } + + if (major == 0 && minor == 0) + { + throw new ProverException("Cannot find executable: " + firstTry); + } + + Contract.Assert(winner != null); + + _proverPath = Path.Combine(Path.Combine(winner, "bin"), proverExe); + if (!File.Exists(_proverPath)) + { + throw new ProverException("Cannot find prover: " + _proverPath); + } + + if (CommandLineOptions.Clo.Trace) + { + Console.WriteLine("[TRACE] Using prover: " + _proverPath); + } + + if (major < minMajor || (major == minMajor && minor < minMinor)) + { + throw new ProverException(string.Format("Found version {0}.{1} of Z3. Please install version {2}.{3} or later. " + + "(More conservative users might opt to supply -prover:Z3 option instead to get the historic Simplify back-end)", + major, minor, minMajor, minMinor)); + } + } + } + + + static int Z3MajorVersion = 0; + static int Z3MinorVersion = 0; + static bool Z3VersionObtained = false; + + public static void GetVersion(out int major, out int minor) + { + if (!Z3VersionObtained) + { + var proc = new System.Diagnostics.Process(); + proc.StartInfo.FileName = _proverPath; + proc.StartInfo.Arguments = "--version"; + proc.StartInfo.RedirectStandardOutput = true; + proc.StartInfo.RedirectStandardError = true; + proc.StartInfo.UseShellExecute = false; + proc.StartInfo.CreateNoWindow = true; + proc.Start(); + string answer = proc.StandardOutput.ReadToEnd(); + proc.WaitForExit(); + if (proc.ExitCode == 0) + { + var firstdot = answer.IndexOf('.'); + if (firstdot >= 0) + { + var seconddot = answer.IndexOf('.', firstdot + 1); + if (seconddot >= firstdot + 1) + { + var spacebeforefirstdot = answer.LastIndexOf(' ', firstdot); + if (spacebeforefirstdot >= 0) + { + var majorstr = answer.Substring(spacebeforefirstdot, firstdot - spacebeforefirstdot); + var minorstr = answer.Substring(firstdot + 1, seconddot - firstdot - 1); + Z3MajorVersion = Convert.ToInt32(majorstr); + Z3MinorVersion = Convert.ToInt32(minorstr); + } + } + } + } + Z3VersionObtained = true; + } + major = Z3MajorVersion; + minor = Z3MinorVersion; + } + + public static string SetTimeoutOption() + { + int major, minor; + GetVersion(out major, out minor); + if (major > 4 || major == 4 && minor >= 3) + return "TIMEOUT"; + else + return "SOFT_TIMEOUT"; + } + + // options that work only on the command line + static string[] commandLineOnly = { "TRACE", "PROOF_MODE" }; + + + public static void SetupOptions(SMTLibProverOptions options) + { + FindExecutable(); + int major, minor; + GetVersion(out major, out minor); + if (major > 4 || major == 4 && minor >= 3) + { + + bool fp = false; // CommandLineOptions.Clo.FixedPointEngine != null; + + // don't bother with auto-config - it would disable explicit settings for eager threshold and so on + if(!fp) options.AddWeakSmtOption("AUTO_CONFIG", "false"); + + //options.AddWeakSmtOption("MODEL_PARTIAL", "true"); + //options.WeakAddSmtOption("MODEL_VALUE_COMPLETION", "false"); + + // options.AddWeakSmtOption("MODEL_HIDE_UNUSED_PARTITIONS", "false"); TODO: what does this do? + + // Make sure we get something that is parsable as a bitvector + options.AddWeakSmtOption("pp.bv_literals", "false"); + if (!CommandLineOptions.Clo.UseSmtOutputFormat) + { + options.AddWeakSmtOption("MODEL.V2", "true"); + } + //options.AddWeakSmtOption("ASYNC_COMMANDS", "false"); TODO: is this needed? + + if (!options.OptimizeForBv) + { + // Phase selection means to always try the negative literal polarity first, seems to be good for Boogie. + // The restart parameters change the restart behavior to match Z3 v1, which also seems to be good. + options.AddWeakSmtOption("smt.PHASE_SELECTION", "0"); + options.AddWeakSmtOption("smt.RESTART_STRATEGY", "0"); + options.AddWeakSmtOption("smt.RESTART_FACTOR", "|1.5|"); + + // Make the integer model more diverse by default, speeds up some benchmarks a lot. + options.AddWeakSmtOption("smt.ARITH.RANDOM_INITIAL_VALUE", "true"); + + // The left-to-right structural case-splitting strategy. + //options.AddWeakSmtOption("SORT_AND_OR", "false"); // always false now + + if (!fp) options.AddWeakSmtOption("smt.CASE_SPLIT", "3"); + + // In addition delay adding unit conflicts. + options.AddWeakSmtOption("smt.DELAY_UNITS", "true"); + //options.AddWeakSmtOption("DELAY_UNITS_THRESHOLD", "16"); TODO: what? + } + + // This is used by VCC, but could be also useful for others, if sk_hack(foo(x)) is included as trigger, + // the foo(x0) will be activated for e-matching when x is skolemized to x0. + options.AddWeakSmtOption("NNF.SK_HACK", "true"); + + // don't use model-based quantifier instantiation; it never finishes on non-trivial Boogie problems + options.AddWeakSmtOption("smt.MBQI", "false"); + + // More or less like MAM=0. + options.AddWeakSmtOption("smt.QI.EAGER_THRESHOLD", "100"); + // Complex proof attempts in VCC (and likely elsewhere) require matching depth of 20 or more. + + // the following will make the :weight option more usable + // KLM: this QI cost function is the default + // if (!fp) options.AddWeakSmtOption("smt.QI.COST", "|(+ weight generation)|"); // TODO: this doesn't seem to work + + //if (options.Inspector != null) + // options.WeakAddSmtOption("PROGRESS_SAMPLING_FREQ", "100"); + + options.AddWeakSmtOption("TYPE_CHECK", "true"); + options.AddWeakSmtOption("smt.BV.REFLECT", "true"); + + if (options.TimeLimit > 0) + { + options.AddWeakSmtOption("TIMEOUT", options.TimeLimit.ToString()); + options.AddWeakSmtOption("fixedpoint.TIMEOUT", options.TimeLimit.ToString()); + // This kills the Z3 *instance* after the specified time, not a particular query, so we cannot use it. + // options.AddSolverArgument("/T:" + (options.TimeLimit + 1000) / 1000); + } + + if (options.Inspector != null) + options.AddWeakSmtOption("PROGRESS_SAMPLING_FREQ", "200"); + + if (CommandLineOptions.Clo.WeakArrayTheory) + { + options.AddWeakSmtOption("smt.array.weak", "true"); + options.AddWeakSmtOption("smt.array.extensional", "false"); + } + + if (CommandLineOptions.Clo.PrintConjectures != null) + { + options.AddWeakSmtOption("fixedpoint.conjecture_file", CommandLineOptions.Clo.PrintConjectures + ".tmp"); + } + } + else + { + // don't bother with auto-config - it would disable explicit settings for eager threshold and so on + options.AddWeakSmtOption("AUTO_CONFIG", "false"); + + //options.AddWeakSmtOption("MODEL_PARTIAL", "true"); + //options.WeakAddSmtOption("MODEL_VALUE_COMPLETION", "false"); + options.AddWeakSmtOption("MODEL_HIDE_UNUSED_PARTITIONS", "false"); + options.AddWeakSmtOption("ASYNC_COMMANDS", "false"); + + if (CommandLineOptions.Clo.UseSmtOutputFormat) + { + options.AddWeakSmtOption("pp-bv-literals", "false"); ; + } + else + { + options.AddWeakSmtOption("MODEL_V2", "true"); + } + + if (!options.OptimizeForBv) + { + // Phase selection means to always try the negative literal polarity first, seems to be good for Boogie. + // The restart parameters change the restart behavior to match Z3 v1, which also seems to be good. + options.AddWeakSmtOption("PHASE_SELECTION", "0"); + options.AddWeakSmtOption("RESTART_STRATEGY", "0"); + options.AddWeakSmtOption("RESTART_FACTOR", "|1.5|"); + + // Make the integer model more diverse by default, speeds up some benchmarks a lot. + options.AddWeakSmtOption("ARITH_RANDOM_INITIAL_VALUE", "true"); + + // The left-to-right structural case-splitting strategy. + //options.AddWeakSmtOption("SORT_AND_OR", "false"); // always false now + options.AddWeakSmtOption("CASE_SPLIT", "3"); + + // In addition delay adding unit conflicts. + options.AddWeakSmtOption("DELAY_UNITS", "true"); + options.AddWeakSmtOption("DELAY_UNITS_THRESHOLD", "16"); + } + + // This is used by VCC, but could be also useful for others, if sk_hack(foo(x)) is included as trigger, + // the foo(x0) will be activated for e-matching when x is skolemized to x0. + options.AddWeakSmtOption("NNF_SK_HACK", "true"); + + // don't use model-based quantifier instantiation; it never finishes on non-trivial Boogie problems + options.AddWeakSmtOption("MBQI", "false"); + + // More or less like MAM=0. + options.AddWeakSmtOption("QI_EAGER_THRESHOLD", "100"); + // Complex proof attempts in VCC (and likely elsewhere) require matching depth of 20 or more. + + // the following will make the :weight option more usable + options.AddWeakSmtOption("QI_COST", "|\"(+ weight generation)\"|"); + + //if (options.Inspector != null) + // options.WeakAddSmtOption("PROGRESS_SAMPLING_FREQ", "100"); + + options.AddWeakSmtOption("TYPE_CHECK", "true"); + options.AddWeakSmtOption("BV_REFLECT", "true"); + + if (options.TimeLimit > 0) + { + options.AddWeakSmtOption("SOFT_TIMEOUT", options.TimeLimit.ToString()); + // This kills the Z3 *instance* after the specified time, not a particular query, so we cannot use it. + // options.AddSolverArgument("/T:" + (options.TimeLimit + 1000) / 1000); + } + + if (options.Inspector != null) + options.AddWeakSmtOption("PROGRESS_SAMPLING_FREQ", "200"); + + if (CommandLineOptions.Clo.WeakArrayTheory) + { + options.AddWeakSmtOption("ARRAY_WEAK", "true"); + options.AddWeakSmtOption("ARRAY_EXTENSIONAL", "false"); + } + + options.AddWeakSmtOption("MODEL_ON_TIMEOUT", "true"); + + } + + // KLM: don't add Z3 options here. The options are different in different Z3 versions. + // Add options in the above condition for the appropriate version. + + // legacy option handling + if (!CommandLineOptions.Clo.z3AtFlag) + options.MultiTraces = true; + + + foreach (string opt in CommandLineOptions.Clo.Z3Options) + { + Contract.Assert(opt != null); + int eq = opt.IndexOf("="); + if (eq > 0 && 'A' <= opt[0] && opt[0] <= 'Z' && !commandLineOnly.Contains(opt.Substring(0, eq))) + { + options.AddSmtOption(opt.Substring(0, eq), opt.Substring(eq + 1)); + } + else + { + options.AddSolverArgument(opt); + } + } + } + + + } +} diff --git a/Source/Provers/SMTLib/cce.cs b/Source/Provers/SMTLib/cce.cs index ef594484..1e0b12a5 100644 --- a/Source/Provers/SMTLib/cce.cs +++ b/Source/Provers/SMTLib/cce.cs @@ -1,193 +1,193 @@ -using System;
-using SA=System.Attribute;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-//using Microsoft.Boogie;
-
-/// <summary>
-/// A class containing static methods to extend the functionality of Code Contracts
-/// </summary>
-
-public static class cce {
- //[Pure]
- //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
- // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
- //}
- [Pure]
- public static T NonNull<T>(T t) {
- Contract.Assert(t != null);
- return t;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection) {
- return collection != null && Contract.ForAll(collection, c => c != null);
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
- return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
- }
- //[Pure]
- //public static bool NonNullElements(VariableSeq collection) {
- // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
- //}
- /// <summary>
- /// For possibly-null lists of non-null elements
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="collection"></param>
- /// <param name="nullability">If true, the collection is treated as an IEnumerable<T!>?, rather than an IEnumerable<T!>!</param>
- /// <returns></returns>
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
- return (nullability && collection == null) || cce.NonNullElements(collection);
- //Should be the same as:
- /*if(nullability&&collection==null)
- * return true;
- * return cce.NonNullElements(collection)
- */
-
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
- return kvp.Key != null && kvp.Value != null;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
- return iEnumerator != null;
- }
- //[Pure]
- //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
- // return cce.NonNullElements(graph.TopologicalSort());
- //}
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
- [Pure]
- public static bool IsPeerConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposable(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposed(object o) {
- return true;
- }
- [Pure]
- public static bool IsNew(object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- [Pure]
- public static void AssignSame(object o, object p) {
- }
- [Pure]
- public static object ElementProxy(object o) {
- return o;
- }
- [Pure]
- public static bool None(object o) {
- return true;
- }
- [Pure]
- public static bool Different(object o, object p) {
- return true;
- }
- [Pure]
- public static bool New(object o) {
- return true;
- }
- }
- [Pure]
- public static void LoopInvariant(bool p) {
- Contract.Assert(p);
- }
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
- //[Pure]
- //public static bool IsValid(Microsoft.Dafny.Expression expression) {
- // return true;
- //}
- //public static List<T> toList<T>(PureCollections.Sequence s) {
- // List<T> toRet = new List<T>();
- // foreach (T t in s.elems)
- // if(t!=null)
- // toRet.Add(t);
- // return toRet;
- //}
-
- //internal static bool NonNullElements(Set set) {
- // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
- //}
-}
-
-public class PeerAttribute : SA {
-}
-public class RepAttribute : SA {
-}
-public class CapturedAttribute : SA {
-}
-public class NotDelayedAttribute : SA {
-}
-public class NoDefaultContractAttribute : SA {
-}
-public class VerifyAttribute : SA {
- public VerifyAttribute(bool b) {
-
- }
-}
-public class StrictReadonlyAttribute : SA {
-}
-public class AdditiveAttribute : SA {
-}
-public class ReadsAttribute : SA {
- public enum Reads {
- Nothing,
- Everything,
- };
- public ReadsAttribute(object o) {
- }
-}
-public class GlobalAccessAttribute : SA {
- public GlobalAccessAttribute(bool b) {
- }
-}
-public class EscapesAttribute : SA {
- public EscapesAttribute(bool b, bool b_2) {
- }
-}
-public class NeedsContractsAttribute : SA {
- public NeedsContractsAttribute() {
- }
- public NeedsContractsAttribute(bool ret, bool parameters) {
- }
- public NeedsContractsAttribute(bool ret, int[] parameters) {
- }
-}
-public class ImmutableAttribute : SA {
-}
-public class InsideAttribute : SA {
-}
-public class SpecPublicAttribute : SA {
-}
-public class ElementsPeerAttribute : SA {
-}
-public class ResultNotNewlyAllocatedAttribute : SA {
-}
-public class OnceAttribute : SA {
+using System; +using SA=System.Attribute; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Text; +//using Microsoft.Boogie; + +/// <summary> +/// A class containing static methods to extend the functionality of Code Contracts +/// </summary> + +public static class cce { + //[Pure] + //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) { + // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents()); + //} + [Pure] + public static T NonNull<T>(T t) { + Contract.Assert(t != null); + return t; + } + [Pure] + public static bool NonNullElements<T>(IEnumerable<T> collection) { + return collection != null && Contract.ForAll(collection, c => c != null); + } + [Pure] + public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) { + return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair)); + } + //[Pure] + //public static bool NonNullElements(VariableSeq collection) { + // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null); + //} + /// <summary> + /// For possibly-null lists of non-null elements + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="collection"></param> + /// <param name="nullability">If true, the collection is treated as an IEnumerable<T!>?, rather than an IEnumerable<T!>!</param> + /// <returns></returns> + [Pure] + public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) { + return (nullability && collection == null) || cce.NonNullElements(collection); + //Should be the same as: + /*if(nullability&&collection==null) + * return true; + * return cce.NonNullElements(collection) + */ + + } + [Pure] + public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) { + return kvp.Key != null && kvp.Value != null; + } + [Pure] + public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) { + return iEnumerator != null; + } + //[Pure] + //public static bool NonNullElements<T>(Graphing.Graph<T> graph) { + // return cce.NonNullElements(graph.TopologicalSort()); + //} + [Pure] + public static void BeginExpose(object o) { + } + [Pure] + public static void EndExpose() { + } + [Pure] + public static bool IsPeerConsistent(object o) { + return true; + } + [Pure] + public static bool IsConsistent(object o) { + return true; + } + [Pure] + public static bool IsExposable(object o) { + return true; + } + [Pure] + public static bool IsExposed(object o) { + return true; + } + [Pure] + public static bool IsNew(object o) { + return true; + } + public static class Owner { + [Pure] + public static bool Same(object o, object p) { + return true; + } + [Pure] + public static void AssignSame(object o, object p) { + } + [Pure] + public static object ElementProxy(object o) { + return o; + } + [Pure] + public static bool None(object o) { + return true; + } + [Pure] + public static bool Different(object o, object p) { + return true; + } + [Pure] + public static bool New(object o) { + return true; + } + } + [Pure] + public static void LoopInvariant(bool p) { + Contract.Assert(p); + } + public class UnreachableException : Exception { + public UnreachableException() { + } + } + //[Pure] + //public static bool IsValid(Microsoft.Dafny.Expression expression) { + // return true; + //} + //public static List<T> toList<T>(PureCollections.Sequence s) { + // List<T> toRet = new List<T>(); + // foreach (T t in s.elems) + // if(t!=null) + // toRet.Add(t); + // return toRet; + //} + + //internal static bool NonNullElements(Set set) { + // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null); + //} +} + +public class PeerAttribute : SA { +} +public class RepAttribute : SA { +} +public class CapturedAttribute : SA { +} +public class NotDelayedAttribute : SA { +} +public class NoDefaultContractAttribute : SA { +} +public class VerifyAttribute : SA { + public VerifyAttribute(bool b) { + + } +} +public class StrictReadonlyAttribute : SA { +} +public class AdditiveAttribute : SA { +} +public class ReadsAttribute : SA { + public enum Reads { + Nothing, + Everything, + }; + public ReadsAttribute(object o) { + } +} +public class GlobalAccessAttribute : SA { + public GlobalAccessAttribute(bool b) { + } +} +public class EscapesAttribute : SA { + public EscapesAttribute(bool b, bool b_2) { + } +} +public class NeedsContractsAttribute : SA { + public NeedsContractsAttribute() { + } + public NeedsContractsAttribute(bool ret, bool parameters) { + } + public NeedsContractsAttribute(bool ret, int[] parameters) { + } +} +public class ImmutableAttribute : SA { +} +public class InsideAttribute : SA { +} +public class SpecPublicAttribute : SA { +} +public class ElementsPeerAttribute : SA { +} +public class ResultNotNewlyAllocatedAttribute : SA { +} +public class OnceAttribute : SA { }
\ No newline at end of file |