using System; using System.Collections; using System.Collections.Generic; using System.Threading; using System.IO; using System.Diagnostics; using Microsoft.Contracts; using Microsoft.Boogie.AbstractInterpretation; using Microsoft.Boogie; using Microsoft.Boogie.Z3; using Microsoft.Z3; using Microsoft.Boogie.VCExprAST; using Microsoft.Boogie.Simplify; using TypeAst = System.IntPtr; using TermAst = System.IntPtr; using ConstDeclAst = System.IntPtr; using ConstAst = System.IntPtr; using Value = System.IntPtr; using PatternAst = System.IntPtr; namespace Microsoft.Boogie.Z3 { public class Z3apiProcessTheoremProver : ProverInterface { public Z3apiProcessTheoremProver(Z3InstanceOptions opts, DeclFreeProverContext ctxt) { this.options = opts; this.context = (Z3apiProverContext) ctxt; this.z3ContextIsUsed = false; } private Z3InstanceOptions options; private Z3apiProverContext context; public override ProverContext Context { get { return context; } } public override VCExpressionGenerator VCExprGen { get { return context.ExprGen; } } public override void Close() { base.Close(); ((Z3apiProverContext)context).cm.z3.Dispose(); ((Z3apiProverContext)context).cm.config.Config.Dispose(); } private bool z3ContextIsUsed; public void PushAxiom(VCExpr axiom) { Z3SafeContext cm = ((Z3apiProverContext)context).cm; cm.CreateBacktrackPoint(); LineariserOptions linOptions = new Z3LineariserOptions(false, (Z3InstanceOptions)this.options, new List()); cm.AddAxiom(axiom, linOptions); } private void PushConjecture(VCExpr conjecture) { Z3SafeContext cm = ((Z3apiProverContext)context).cm; cm.CreateBacktrackPoint(); LineariserOptions linOptions = new Z3LineariserOptions(false, (Z3InstanceOptions)this.options, new List()); cm.AddConjecture(conjecture, linOptions); } public void PrepareCheck(string descriptiveName, VCExpr vc) { PushAxiom(context.Axioms); PushConjecture(vc); } public void BeginPreparedCheck() { Z3SafeContext cm = ((Z3apiProverContext)context).cm; outcome = Outcome.Undetermined; outcome = cm.Check(out z3LabelModels); } public override void PushVCExpression(VCExpr vc) { PushAxiom(vc); } public override void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler) { LineariserOptions linOptions = new Z3LineariserOptions(false, (Z3InstanceOptions)this.options, new List()); Z3SafeContext cm = ((Z3apiProverContext)context).cm; if (z3ContextIsUsed) { cm.Backtrack(); } else { cm.AddAxiom(context.Axioms, linOptions); z3ContextIsUsed = true; } cm.CreateBacktrackPoint(); cm.AddConjecture(vc, linOptions); BeginPreparedCheck(); } private Outcome outcome; private List z3LabelModels = new List(); [NoDefaultContract] public override Outcome CheckOutcome(ErrorHandler handler) { if (outcome == Outcome.Invalid) { foreach (Z3ErrorModelAndLabels z3LabelModel in z3LabelModels) { List unprefixedLabels = RemovePrefixes(z3LabelModel.RelevantLabels); handler.OnModel(unprefixedLabels, z3LabelModel.ErrorModel); } } return outcome; } public void CreateBacktrackPoint() { Z3SafeContext cm = ((Z3apiProverContext)context).cm; cm.CreateBacktrackPoint(); } override public void Pop() { Z3SafeContext cm = ((Z3apiProverContext)context).cm; cm.Backtrack(); } private List RemovePrefixes(List labels) { List result = new List(); foreach (string label in labels) { if (label.StartsWith("+")) { result.Add(label.Substring(1)); } else if (label.StartsWith("|")) { result.Add(label.Substring(1)); } else if (label.StartsWith("@")) { result.Add(label.Substring(1)); } else throw new Exception("Unknown prefix in label " + label); } return result; } } public class Z3apiProverContext : DeclFreeProverContext { public Z3SafeContext cm; public Z3apiProverContext(Z3InstanceOptions opts, VCExpressionGenerator gen) : base(gen, new VCGenerationOptions(new List())) { Z3Config config = BuildConfig(opts.Timeout, true); this.cm = new Z3SafeContext(this, config, gen); } private static Z3Config BuildConfig(int timeout, bool nativeBv) { Z3Config config = new Z3Config(); config.SetModelCompletion(false); config.SetModel(true); if (0 <= CommandLineOptions.Clo.ProverCCLimit) { config.SetCounterExample(CommandLineOptions.Clo.ProverCCLimit); } if (0 <= timeout) { config.SetSoftTimeout(timeout.ToString()); } config.SetTypeCheck(true); return config; } public override void DeclareType(TypeCtorDecl t, string attributes) { base.DeclareType(t, attributes); cm.DeclareType(t.Name); } public override void DeclareConstant(Constant c, bool uniq, string attributes) { base.DeclareConstant(c, uniq, attributes); cm.DeclareConstant(c.Name, c.TypedIdent.Type); } public override void DeclareFunction(Function f, string attributes) { base.DeclareFunction(f, attributes); List domain = new List(); foreach (Variable v in f.InParams) { domain.Add(v.TypedIdent.Type); } if (f.OutParams.Length != 1) throw new Exception("Cannot handle functions with " + f.OutParams + " out parameters."); Type range = f.OutParams[0].TypedIdent.Type; cm.DeclareFunction(f.Name, domain, range); } public override void DeclareGlobalVariable(GlobalVariable v, string attributes) { base.DeclareGlobalVariable(v, attributes); cm.DeclareConstant(v.Name, v.TypedIdent.Type); } public override string Lookup(VCExprVar var) { return cm.Namer.Lookup(var); } } } namespace Microsoft.Boogie.Z3api { public class Factory : ProverFactory { public override object SpawnProver(ProverOptions options, object ctxt) { return new Z3apiProcessTheoremProver((Z3InstanceOptions) options, (Z3apiProverContext) ctxt); } public override object NewProverContext(ProverOptions opts) { if (CommandLineOptions.Clo.BracketIdsInVC < 0) { CommandLineOptions.Clo.BracketIdsInVC = 0; } VCExpressionGenerator gen = new VCExpressionGenerator(); return new Z3apiProverContext((Z3InstanceOptions)opts, gen); } public override ProverOptions BlankProverOptions() { return new Z3InstanceOptions(); } } }