//----------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.IO; using System.Text; using Microsoft.Contracts; using Microsoft.Boogie.VCExprAST; namespace Microsoft.Boogie { /// /// The methods of this class are called in the following order: /// DeclareType* /// (DeclareConstant DeclareFunction)* /// AddAxiom* /// DeclareGlobalVariable* /// At this time, all "attributes" are passed in as null. /// public abstract class ProverContext : ICloneable { protected virtual void ProcessDeclaration(Declaration! decl) {} public virtual void DeclareType(TypeCtorDecl! t, string attributes) { ProcessDeclaration(t); } public virtual void DeclareConstant(Constant! c, bool uniq, string attributes) { ProcessDeclaration(c); } public virtual void DeclareFunction(Function! f, string attributes) { ProcessDeclaration(f); } public virtual void AddAxiom(Axiom! a, string attributes) { ProcessDeclaration(a); } public abstract void AddAxiom(VCExpr! vc); public virtual void DeclareGlobalVariable(GlobalVariable! v, string attributes) { ProcessDeclaration(v); } public abstract VCExpressionGenerator! ExprGen { get; } public abstract Boogie2VCExprTranslator! BoogieExprTranslator { get; } public abstract VCGenerationOptions! VCGenOptions { get; } public abstract object! Clone(); } // ----------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------- /// /// This ProverContext subclass is intended for use with untyped provers that do not require names /// to be declared before use. It constructs its context from unique constants and given axioms. /// public class DeclFreeProverContext : ProverContext { protected VCExpressionGenerator! gen; protected VCGenerationOptions! genOptions; protected Boogie2VCExprTranslator! translator; protected OrderingAxiomBuilder! orderingAxiomBuilder; StringBuilder! proverCommands; StringBuilder! incrementalProverCommands; protected List! distincts; protected List! axiomConjuncts; public VCExprTranslator exprTranslator; public DeclFreeProverContext(VCExpressionGenerator! gen, VCGenerationOptions! genOptions) { this.gen = gen; this.genOptions = genOptions; Boogie2VCExprTranslator! t = new Boogie2VCExprTranslator (gen, genOptions); this.translator = t; OrderingAxiomBuilder! oab = new OrderingAxiomBuilder(gen, t); oab.Setup(); this.orderingAxiomBuilder = oab; proverCommands = new StringBuilder(); incrementalProverCommands = new StringBuilder(); distincts = new List(); axiomConjuncts = new List(); exprTranslator = null; } private DeclFreeProverContext(DeclFreeProverContext! ctxt) { this.gen = ctxt.gen; this.genOptions = ctxt.genOptions; Boogie2VCExprTranslator! t = (Boogie2VCExprTranslator)ctxt.translator.Clone(); this.translator = t; this.orderingAxiomBuilder = new OrderingAxiomBuilder(ctxt.gen, t, ctxt.orderingAxiomBuilder); StringBuilder! cmds = new StringBuilder (); cmds.Append(ctxt.proverCommands); proverCommands = cmds; StringBuilder! incCmds = new StringBuilder (); incCmds.Append(ctxt.incrementalProverCommands); incrementalProverCommands = incCmds; distincts = new List(ctxt.distincts); axiomConjuncts = new List(ctxt.axiomConjuncts); if (ctxt.exprTranslator == null) exprTranslator = null; else exprTranslator = (VCExprTranslator!)ctxt.exprTranslator.Clone(); } public override object! Clone() { return new DeclFreeProverContext(this); } internal protected void SayToProver(string! msg) { msg = msg + "\r\n"; proverCommands.Append(msg); incrementalProverCommands.Append(msg); } protected override void ProcessDeclaration(Declaration! decl) { for (QKeyValue a = decl.Attributes; a != null; a = a.Next) { if (a.Key == "prover" && a.Params.Count == 1) { string cmd = a.Params[0] as string; if (cmd != null) { int pos = cmd.IndexOf(':'); if (pos <= 0) throw new ProverException("Invalid syntax of :prover string: `" + cmd + "'"); string kind = cmd.Substring(0, pos); if (genOptions.IsAnyProverCommandSupported(kind)) SayToProver(cmd.Substring(pos + 1)); } } } } public override void DeclareFunction(Function! f, string attributes) { base.ProcessDeclaration(f); } public override void DeclareConstant(Constant! c, bool uniq, string attributes) { base.DeclareConstant(c, uniq, attributes); orderingAxiomBuilder.AddConstant(c); // TODO: make separate distinct lists for names coming from different types // e.g., one for strings, one for ints, one for program types. if (uniq){ distincts.Add(c); } } public override void AddAxiom(Axiom! ax, string attributes) { base.AddAxiom(ax, attributes); string ignore = ax.FindStringAttribute("ignore"); if (ignore != null && genOptions.IsAnyProverCommandSupported(ignore)) { return; } axiomConjuncts.Add(translator.Translate(ax.Expr)); } public override void AddAxiom(VCExpr! vc) { axiomConjuncts.Add(vc); } public VCExpr! Axioms { get { VCExpr axioms = gen.NAry(VCExpressionGenerator.AndOp, axiomConjuncts); List! distinctVars = new List (); foreach (Variable! v in distincts) distinctVars.Add(translator.LookupVariable(v)); axioms = gen.AndSimp(gen.Distinct(distinctVars), axioms); if (CommandLineOptions.Clo.TypeEncodingMethod != CommandLineOptions.TypeEncoding.Monomorphic) axioms = gen.AndSimp(orderingAxiomBuilder.Axioms, axioms); return axioms; } } public string! GetProverCommands(bool full) { string! res = (full ? proverCommands : incrementalProverCommands).ToString(); incrementalProverCommands.Length = 0; return res; } public override VCExpressionGenerator! ExprGen { get { return gen; } } public override Boogie2VCExprTranslator! BoogieExprTranslator { get { return translator; } } public override VCGenerationOptions! VCGenOptions { get { return genOptions; } } } // Translator from VCExpressions to strings, which are implemented // by the various provers public abstract class VCExprTranslator : ICloneable { public abstract string! translate(VCExpr! expr, int polarity); public abstract string! Lookup(VCExprVar! var); public abstract Object! Clone(); } }