diff options
Diffstat (limited to 'Source/VCExpr/Boogie2VCExpr.cs')
-rw-r--r-- | Source/VCExpr/Boogie2VCExpr.cs | 2478 |
1 files changed, 1239 insertions, 1239 deletions
diff --git a/Source/VCExpr/Boogie2VCExpr.cs b/Source/VCExpr/Boogie2VCExpr.cs index ad319c0e..a3364ad8 100644 --- a/Source/VCExpr/Boogie2VCExpr.cs +++ b/Source/VCExpr/Boogie2VCExpr.cs @@ -1,1239 +1,1239 @@ -//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Linq;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-
-// A translator from the Boogie AST to the VCExpr AST.
-// This was previously realised in the methods AbsyExpr.VCView
-
-namespace Microsoft.Boogie.VCExprAST {
- using Microsoft.Boogie;
-
- // TODO: in future we might use that for defining symbols for Boogie's conditional compilation
- public class VCGenerationOptions {
- private readonly List<string/*!*/>/*!*/ SupportedProverCommands;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(SupportedProverCommands));
- }
-
-
- public bool IsProverCommandSupported(string kind) {
- Contract.Requires(kind != null);
- return SupportedProverCommands.Contains(kind);
- }
-
- public bool IsAnyProverCommandSupported(string kinds) {
- Contract.Requires(kinds != null);
- if (kinds.IndexOf(',') < 0) {
- return IsProverCommandSupported(kinds);
- } else {
- return kinds.Split(',', ' ').Any(k => IsProverCommandSupported(k));
- }
- }
-
- public VCGenerationOptions(List<string/*!*/>/*!*/ supportedProverCommands) {
- Contract.Requires(cce.NonNullElements(supportedProverCommands));
- this.SupportedProverCommands = supportedProverCommands;
- }
- }
-
- public delegate VCExpr/*!*/ CodeExprConverter(CodeExpr/*!*/ codeExpr, Hashtable/*<Block, VCExprVar!>*//*!*/ blockVariables, List<VCExprLetBinding> bindings, bool isPositiveContext);
-
- public class Boogie2VCExprTranslator : ReadOnlyVisitor, ICloneable {
- // Stack on which the various Visit-methods put the result of the translation
- private readonly Stack<VCExpr/*!*/>/*!*/ SubExpressions = new Stack<VCExpr>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(SubExpressions));
- Contract.Invariant(Gen != null);
- }
-
-
- private void Push(VCExpr expr) {
- Contract.Requires(expr != null);
- SubExpressions.Push(expr);
- }
-
- private VCExpr Pop() {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return SubExpressions.Pop();
- }
-
- public VCExpr Translate(Expr expr) {
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- this.Visit(expr);
- return Pop();
- }
-
- public List<VCExpr/*!*/>/*!*/ Translate(IList<Expr> exprs) {
- Contract.Requires(exprs != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
- List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>();
- foreach (Expr e in exprs)
- res.Add(Translate(cce.NonNull(e)));
- return res;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
- internal readonly VCExpressionGenerator/*!*/ Gen;
-
- public Boogie2VCExprTranslator(VCExpressionGenerator gen,
- VCGenerationOptions genOptions) {
- Contract.Requires(gen != null);
- Contract.Requires(genOptions != null);
- this.Gen = gen;
- this.GenerationOptions = genOptions;
- UnboundVariables = new VariableMapping<Variable>();
- BoundVariables = new VariableMapping<BoundVariable>();
- Formals = new VariableMapping<Formal>();
- }
-
- private Boogie2VCExprTranslator(Boogie2VCExprTranslator tl) {
- Contract.Requires(tl != null);
- this.Gen = tl.Gen;
- this.GenerationOptions = tl.GenerationOptions;
- UnboundVariables =
- (VariableMapping<Variable>)tl.UnboundVariables.Clone();
- BoundVariables = new VariableMapping<BoundVariable>();
- Formals = new VariableMapping<Formal>();
- }
-
- public object Clone() {
- Contract.Ensures(Contract.Result<object>() != null);
- return new Boogie2VCExprTranslator(this);
- }
-
- private IAppliableTranslator IAppTranslatorAttr = null;
- private IAppliableTranslator IAppTranslator {
- get {
- Contract.Ensures(Contract.Result<IAppliableTranslator>() != null);
-
- if (IAppTranslatorAttr == null)
- IAppTranslatorAttr = new IAppliableTranslator(this);
- return IAppTranslatorAttr;
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Class for handling occurring variables
-
- private class VariableMapping<VarKind> : ICloneable {
- private readonly List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>/*!*/ Mapping;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Mapping != null && Contract.ForAll(Mapping, i => cce.NonNullDictionaryAndValues(i)));
- }
-
-
- public VariableMapping() {
- List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>/*!*/ mapping =
- new List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>();
- mapping.Add(new Dictionary<VarKind/*!*/, VCExprVar/*!*/>());
- this.Mapping = mapping;
- }
-
- private VariableMapping(VariableMapping<VarKind> vm) {
- Contract.Requires(vm != null);
- List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>/*!*/ mapping =
- new List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>();
- foreach (Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/ d in vm.Mapping) {
- Contract.Assert(cce.NonNullDictionaryAndValues(d));
- mapping.Add(new Dictionary<VarKind/*!*/, VCExprVar/*!*/>(d));
- }
- this.Mapping = mapping;
- }
-
- public object Clone() {
- Contract.Ensures(Contract.Result<object>() != null);
- return new VariableMapping<VarKind>(this);
- }
-
- public void PushScope() {
- Mapping.Add(new Dictionary<VarKind/*!*/, VCExprVar/*!*/>());
- }
-
- public void PopScope() {
- Contract.Assume(Mapping.Count > 0);
- Mapping.RemoveAt(Mapping.Count - 1);
- }
-
- public void Bind(VarKind boogieVar, VCExprVar/*!*/ vcExprVar) {
- Contract.Requires(vcExprVar != null);
- Contract.Requires(boogieVar != null);
- Contract.Requires(!Contains(boogieVar));
- Mapping[Mapping.Count - 1].Add(boogieVar, vcExprVar);
- }
-
- public VCExprVar Lookup(VarKind boogieVar) {
- Contract.Requires(boogieVar != null);
- Contract.Ensures(Contract.Result<VCExprVar>() != null);
- VCExprVar res = LookupHelp(boogieVar);
- Contract.Assume(res != null);
- return res;
- }
-
- [Pure]
- public bool Contains(VarKind boogieVar) {
- Contract.Requires(boogieVar != null);
- return LookupHelp(boogieVar) != null;
- }
-
- public bool TryGetValue(VarKind boogieVar, out VCExprVar res) {
- Contract.Requires(boogieVar != null);
- res = LookupHelp(boogieVar);
- return res != null;
- }
-
- [Pure]
- private VCExprVar LookupHelp(VarKind boogieVar) {
- Contract.Requires(boogieVar != null);
- VCExprVar res;
- foreach (Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/ d in Mapping) {
- //Contract.Assert(cce.NonNullElements(d));
- if (d.TryGetValue(boogieVar, out res)) {
- Contract.Assert(res != null);
- return res;
- }
- }
- return null;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////////
-
- private readonly VariableMapping<Variable>/*!*/ UnboundVariables;
- private readonly VariableMapping<BoundVariable>/*!*/ BoundVariables;
- // used when translating the bodies of function expansions
- private readonly VariableMapping<Formal>/*!*/ Formals;
- [ContractInvariantMethod]
- void ObjectInvairant() {
- Contract.Invariant(UnboundVariables != null);
- Contract.Invariant(BoundVariables != null);
- Contract.Invariant(Formals != null);
- }
-
-
- internal void PushBoundVariableScope() {
- BoundVariables.PushScope();
- }
- internal void PopBoundVariableScope() {
- BoundVariables.PopScope();
- }
-
- internal void PushFormalsScope() {
- Formals.PushScope();
- }
- internal void PopFormalsScope() {
- Formals.PopScope();
- }
-
- public VCExprVar BindVariable(Variable boogieVar) {
- Contract.Requires(boogieVar != null);
- Contract.Ensures(Contract.Result<VCExprVar>() != null);
- if (boogieVar is BoundVariable) {
- VCExprVar/*!*/ newVar = Gen.Variable(boogieVar.Name, boogieVar.TypedIdent.Type);
- BoundVariables.Bind((BoundVariable)boogieVar, newVar);
- return newVar;
- } else if (boogieVar is Formal) {
- VCExprVar/*!*/ newVar = Gen.Variable(boogieVar.Name, boogieVar.TypedIdent.Type);
- Formals.Bind((Formal)boogieVar, newVar);
- return newVar;
- } else {
- // only bound variables and formals are declared explicitly
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
-
- public VCExprVar LookupVariable(Variable boogieVar) {
- Contract.Requires(boogieVar != null);
- Contract.Ensures(Contract.Result<VCExprVar>() != null);
-
- BoundVariable bv = boogieVar as BoundVariable;
- if (bv != null) {
- return BoundVariables.Lookup(bv);
- }
- VCExprVar res;
- Formal fml = boogieVar as Formal;
- if (fml != null && Formals.TryGetValue(fml, out res))
- return cce.NonNull(res);
-
- // global variables, local variables, incarnations, etc. are
- // bound the first time they occur
- if (!UnboundVariables.TryGetValue(boogieVar, out res)) {
- if (boogieVar is Constant)
- res = new VCExprConstant(boogieVar.Name, boogieVar.TypedIdent.Type);
- else
- res = new VCExprVar(boogieVar.Name, boogieVar.TypedIdent.Type);
- UnboundVariables.Bind(boogieVar, res);
- }
- return cce.NonNull(res);
- }
-
- /// <summary>
- /// Unlike LookupVariable, this method does not create a new variable mapping if none is
- /// found. Instead, this method returns null in such cases. Also, this method does not
- /// look for bound variables.
- /// </summary>
- /// <param name="boogieVar"></param>
- /// <returns></returns>
- public VCExprVar TryLookupVariable(Variable boogieVar) {
- Contract.Requires(boogieVar != null);
-
- VCExprVar res;
- Formal fml = boogieVar as Formal;
- if (fml != null && Formals.TryGetValue(fml, out res))
- return cce.NonNull(res);
-
- if (UnboundVariables.TryGetValue(boogieVar, out res)) {
- return cce.NonNull(res);
- }
-
- return null; // not present
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- internal readonly VCGenerationOptions/*!*/ GenerationOptions;
- [ContractInvariantMethod]
- void ObjectInvarian() {
- Contract.Invariant(GenerationOptions != null);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public override Expr VisitLiteralExpr(LiteralExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Push(TranslateLiteralExpr(node));
- return node;
- }
- private VCExpr TranslateLiteralExpr(LiteralExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (node.Val is bool) {
- bool b = (bool)node.Val;
- if (b) {
- return VCExpressionGenerator.True;
- } else {
- return VCExpressionGenerator.False;
- }
- } else if (node.Val is BigNum) {
- return Gen.Integer(node.asBigNum);
- } else if (node.Val is BigDec) {
- return Gen.Real(node.asBigDec);
- } else if (node.Val is BigFloat) {
- return Gen.Float(node.asBigFloat);
- }
- else if (node.Val is BvConst) {
- return Gen.Bitvector((BvConst)node.Val);
- } else {
- System.Diagnostics.Debug.Assert(false, "unknown kind of literal " + node.tok.ToString());
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public override Expr VisitIdentifierExpr(IdentifierExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Contract.Assume(node.Decl != null); // the expression has to be resolved
- Push(LookupVariable(node.Decl));
- return node;
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- // Because of our scheme for numbering incarnations of variables, the pre-state
- // value of a variable x is always just "x". (The first update to it in a method
- // causes it to become "x0". So we just remove old expressions with a visitor
- // before transforming it into a VCExpr.
- public override Expr VisitOldExpr(OldExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public override Expr VisitNAryExpr(NAryExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Push(TranslateNAryExpr(node));
- return node;
- }
-
- public bool isPositiveContext = true;
- private VCExpr TranslateNAryExpr(NAryExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- bool flipContextForArg0 = false;
- if (node.Fun is UnaryOperator)
- {
- UnaryOperator oper = (UnaryOperator)node.Fun;
- if (oper.Op == UnaryOperator.Opcode.Not)
- flipContextForArg0 = true;
- }
- else if (node.Fun is BinaryOperator)
- {
- BinaryOperator oper = (BinaryOperator)node.Fun;
- if (oper.Op == BinaryOperator.Opcode.Imp)
- flipContextForArg0 = true;
- else if (oper.Op == BinaryOperator.Opcode.Iff) {
- Expr one = new NAryExpr(node.tok, new BinaryOperator(node.tok, BinaryOperator.Opcode.Imp), new List<Expr> { node.Args[0], node.Args[1] });
- Expr two = new NAryExpr(node.tok, new BinaryOperator(node.tok, BinaryOperator.Opcode.Imp), new List<Expr> { node.Args[1], node.Args[0] });
- NAryExpr cmpd = new NAryExpr(node.tok, new BinaryOperator(node.tok, BinaryOperator.Opcode.And), new List<Expr> { one, two });
- TypecheckingContext tc = new TypecheckingContext(null);
- cmpd.Typecheck(tc);
- return TranslateNAryExpr(cmpd);
- }
- }
-
- int n = node.Args.Count;
- List<VCExpr/*!*/>/*!*/ vcs = new List<VCExpr/*!*/>(n);
-
- for (int i = 0; i < n; i++) {
- if (i == 0 && flipContextForArg0)
- isPositiveContext = !isPositiveContext;
- vcs.Add(Translate(cce.NonNull(node.Args)[i]));
- if (i == 0 && flipContextForArg0)
- isPositiveContext = !isPositiveContext;
- }
-
- if (node.Type == null) {
- System.Console.WriteLine("*** type is null for {0}", node);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- return IAppTranslator.Translate(node.Fun, node.Type, vcs,
- ToList(cce.NonNull(node.TypeParameters)));
- }
-
-
- private static List<Type/*!*/>/*!*/ EMPTY_TYPE_LIST = new List<Type/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvirant() {
- Contract.Invariant(EMPTY_TYPE_LIST != null);
- }
-
-
- private List<Type/*!*/>/*!*/ ToList(TypeParamInstantiation insts) {
- Contract.Requires(insts != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
- if (insts.FormalTypeParams.Count == 0)
- return EMPTY_TYPE_LIST;
-
- List<Type/*!*/>/*!*/ typeArgs = new List<Type/*!*/>();
- foreach (TypeVariable/*!*/ var in insts.FormalTypeParams) {
- Contract.Assert(var != null);
- typeArgs.Add(insts[var]);
- }
- return typeArgs;
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<QuantifierExpr>() != null);
- Push(TranslateQuantifierExpr(node));
- return node;
- }
-
- public override Expr VisitExistsExpr(ExistsExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- node = (ExistsExpr)this.VisitQuantifierExpr(node);
- return node;
- }
-
- public override Expr VisitForallExpr(ForallExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- node = (ForallExpr)this.VisitQuantifierExpr(node);
- return node;
- }
-
- private VCExpr TranslateQuantifierExpr(QuantifierExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<TypeVariable/*!*/>/*!*/ typeParams = new List<TypeVariable/*!*/>();
- foreach (TypeVariable/*!*/ v in node.TypeParameters) {
- Contract.Assert(v != null);
- typeParams.Add(v);
- }
-
- PushBoundVariableScope();
-
- List<VCExprVar/*!*/>/*!*/ boundVars = new List<VCExprVar/*!*/>();
- foreach (Variable/*!*/ v in node.Dummies)
- boundVars.Add(BindVariable(v));
-
- try {
- List<VCTrigger/*!*/>/*!*/ triggers = TranslateTriggers(node.Triggers);
- VCExpr/*!*/ body = Translate(node.Body);
- VCQuantifierInfos/*!*/ infos = GenerateQuantifierInfos(node);
-
- Quantifier quan;
- if (node is ForallExpr)
- quan = Quantifier.ALL;
- else if (node is ExistsExpr)
- quan = Quantifier.EX;
- else {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- return Gen.Quantify(quan, typeParams, boundVars, triggers, infos, body);
- } finally {
- PopBoundVariableScope();
- }
- }
-
- private List<VCTrigger/*!*/>/*!*/ TranslateTriggers(Trigger node) {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCTrigger>>()));
- List<VCTrigger/*!*/>/*!*/ res = new List<VCTrigger/*!*/>();
- Trigger curTrigger = node;
- while (curTrigger != null) {
- res.Add(Gen.Trigger(curTrigger.Pos, Translate(curTrigger.Tr)));
- curTrigger = curTrigger.Next;
- }
- return res;
- }
-
- private VCQuantifierInfos GenerateQuantifierInfos(QuantifierExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCQuantifierInfos>() != null);
- string qid = getQidNameFromQKeyValue(node.Dummies, node.Attributes);
- return new VCQuantifierInfos(qid, node.SkolemId, false, node.Attributes);
- }
-
- private string getQidNameFromQKeyValue(List<Variable> vars, QKeyValue attributes) {
- Contract.Requires(vars != null);
- // Check for a 'qid, name' pair in keyvalues
- string qid = QKeyValue.FindStringAttribute(attributes, "qid");
- if (qid == null && vars.Count != 0) {
- // generate default name (line:column position in .bpl file)
- Variable v = vars[0];
- Contract.Assert(v != null); // Rustan's claim!
- // Include the first 8 characters of the filename in QID (helpful in case we use /concat)
- // We limit it to 8, so the SX file doesn't grow too big, and who on earth would need
- // more than 8 characters in a filename anyways.
- int max = 8;
- StringBuilder buf = new StringBuilder(max + 20);
- string filename = v.tok.filename;
- if (filename == null)
- filename = "unknown";
- for (int i = 0; i < filename.Length; ++i) {
- if (filename[i] == '/' || filename[i] == '\\')
- buf.Length = 0;
- if (buf.Length < max && char.IsLetterOrDigit(filename[i])) {
- if (buf.Length == 0 && char.IsDigit(filename[i])) {
- // Z3 does not like QID's to start with a digit, so we prepend another character
- buf.Append('_');
- }
- buf.Append(filename[i]);
- }
- }
- buf.Append('.').Append(v.Line).Append(':').Append(v.Col);
- qid = buf.ToString();
- }
- return qid;
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public override Expr VisitBvExtractExpr(BvExtractExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Push(TranslateBvExtractExpr(node));
- return node;
- }
-
- private VCExpr TranslateBvExtractExpr(BvExtractExpr node) {
- Contract.Requires(node != null);
- Contract.Requires((node.Start <= node.End));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr/*!*/ bv = Translate(node.Bitvector);
- return Gen.BvExtract(bv, cce.NonNull(node.Bitvector.Type).BvBits, node.Start, node.End);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public override Expr VisitBvConcatExpr(BvConcatExpr node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Push(TranslateBvConcatExpr(node));
- return node;
- }
-
- private VCExpr TranslateBvConcatExpr(BvConcatExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr/*!*/ bv0 = Translate(node.E0);
- VCExpr/*!*/ bv1 = Translate(node.E1);
- return Gen.BvConcat(bv0, bv1);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
- // all the other cases should never happen
-
- public override Cmd VisitAssertCmd(AssertCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitAssignCmd(AssignCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitAssumeCmd(AssumeCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override AtomicRE VisitAtomicRE(AtomicRE node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<AtomicRE>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Axiom VisitAxiom(Axiom node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Axiom>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Type VisitBasicType(BasicType node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Type VisitBvType(BvType node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Block VisitBlock(Block node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Block>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public CodeExprConverter codeExprConverter = null;
- public void SetCodeExprConverter(CodeExprConverter f) {
- this.codeExprConverter = f;
- }
- public override Expr/*!*/ VisitCodeExpr(CodeExpr/*!*/ codeExpr) {
- //Contract.Requires(codeExpr != null);
- Contract.Ensures(Contract.Result<Expr>() != null);
- Contract.Assume(codeExprConverter != null);
-
- Hashtable/*<Block, LetVariable!>*/ blockVariables = new Hashtable/*<Block, LetVariable!!>*/();
- List<VCExprLetBinding/*!*/> bindings = new List<VCExprLetBinding/*!*/>();
- VCExpr e = codeExprConverter(codeExpr, blockVariables, bindings, isPositiveContext);
- Push(e);
- return codeExpr;
- }
- public override List<Block> VisitBlockSeq(List<Block> blockSeq) {
- //Contract.Requires(blockSeq != null);
- Contract.Ensures(Contract.Result<List<Block>>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override List<Block/*!*/>/*!*/ VisitBlockList(List<Block/*!*/>/*!*/ blocks) {
- //Contract.Requires(cce.NonNullElements(blocks));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override BoundVariable VisitBoundVariable(BoundVariable node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<BoundVariable>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitCallCmd(CallCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitParCallCmd(ParCallCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override List<Cmd> VisitCmdSeq(List<Cmd> cmdSeq) {
- //Contract.Requires(cmdSeq != null);
- Contract.Ensures(Contract.Result<List<Cmd>>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Choice VisitChoice(Choice node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Choice>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitCommentCmd(CommentCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Constant VisitConstant(Constant node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Constant>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override CtorType VisitCtorType(CtorType node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<CtorType>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Declaration VisitDeclaration(Declaration node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Declaration>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override List<Declaration/*!*/>/*!*/ VisitDeclarationList(List<Declaration/*!*/>/*!*/ declarationList) {
- //Contract.Requires(cce.NonNullElements(declarationList));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Declaration>>()));
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override DeclWithFormals VisitDeclWithFormals(DeclWithFormals node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<DeclWithFormals>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Requires VisitRequires(Requires @requires) {
- //Contract.Requires(@requires != null);
- Contract.Ensures(Contract.Result<Requires>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override List<Requires> VisitRequiresSeq(List<Requires> requiresSeq) {
- //Contract.Requires(requiresSeq != null);
- Contract.Ensures(Contract.Result<List<Requires>>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Ensures VisitEnsures(Ensures @ensures) {
- //Contract.Requires(@ensures != null);
- Contract.Ensures(Contract.Result<Ensures>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override List<Ensures> VisitEnsuresSeq(List<Ensures> ensuresSeq) {
- //Contract.Requires(ensuresSeq != null);
- Contract.Ensures(Contract.Result<List<Ensures>>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Formal VisitFormal(Formal node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Formal>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Function VisitFunction(Function node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override GlobalVariable VisitGlobalVariable(GlobalVariable node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<GlobalVariable>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override GotoCmd VisitGotoCmd(GotoCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<GotoCmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitHavocCmd(HavocCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Implementation VisitImplementation(Implementation node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Implementation>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override LocalVariable VisitLocalVariable(LocalVariable node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<LocalVariable>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override AssignLhs VisitMapAssignLhs(MapAssignLhs node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<AssignLhs>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override MapType VisitMapType(MapType node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<MapType>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Procedure VisitProcedure(Procedure node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Procedure>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Program VisitProgram(Program node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Program>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitRE(RE node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override List<RE> VisitRESeq(List<RE> reSeq) {
- //Contract.Requires(reSeq != null);
- Contract.Ensures(Contract.Result<List<RE>>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override ReturnCmd VisitReturnCmd(ReturnCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<ReturnCmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override ReturnExprCmd VisitReturnExprCmd(ReturnExprCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<ReturnExprCmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Sequential VisitSequential(Sequential node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Sequential>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<AssignLhs>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitStateCmd(StateCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override TransferCmd VisitTransferCmd(TransferCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<TransferCmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Trigger VisitTrigger(Trigger node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Trigger>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Type VisitType(Type node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override TypedIdent VisitTypedIdent(TypedIdent node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<TypedIdent>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Type VisitTypeSynonymAnnotation(TypeSynonymAnnotation node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Type VisitTypeVariable(TypeVariable node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Variable VisitVariable(Variable node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Variable>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override List<Variable> VisitVariableSeq(List<Variable> variableSeq) {
- //Contract.Requires(variableSeq != null);
- Contract.Ensures(Contract.Result<List<Variable>>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitAssertEnsuresCmd(AssertEnsuresCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public override Cmd VisitAssertRequiresCmd(AssertRequiresCmd node) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Cmd>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- }
-
-
- /////////////////////////////////////////////////////////////////////////////////
-
- public class IAppliableTranslator : IAppliableVisitor<VCExpr/*!*/> {
-
- private readonly Boogie2VCExprTranslator/*!*/ BaseTranslator;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(BaseTranslator != null);
- }
-
-
- private VCExpressionGenerator/*!*/ Gen {
- get {
- Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null);
-
- return BaseTranslator.Gen;
- }
- }
- private VCGenerationOptions GenerationOptions {
- get {
- Contract.Ensures(Contract.Result<VCGenerationOptions>() != null);
-
- return BaseTranslator.GenerationOptions;
- }
- }
-
- public IAppliableTranslator(Boogie2VCExprTranslator baseTranslator) {
- Contract.Requires(baseTranslator != null);
- this.BaseTranslator = baseTranslator;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
- private List<VCExpr/*!*/>/*!*/ args = new List<VCExpr/*!*/>();
- private List<Type/*!*/>/*!*/ typeArgs = new List<Type/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvarianet() {
- Contract.Invariant(args != null);
- Contract.Invariant(typeArgs != null);
- }
-
-
- public VCExpr Translate(IAppliable app, Type ty, List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs) {
- Contract.Requires(ty != null);
- Contract.Requires(app != null);
- Contract.Requires(cce.NonNullElements(typeArgs));
- Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- List<VCExpr/*!*/>/*!*/ oldArgs = this.args;
- List<Type/*!*/>/*!*/ oldTypeArgs = this.typeArgs;
- this.args = args;
- this.typeArgs = typeArgs;
- VCExpr/*!*/ result = app.Dispatch<VCExpr/*!*/>(this);
- this.args = oldArgs;
- this.typeArgs = oldTypeArgs;
- return result;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
-
-
- public VCExpr Visit(UnaryOperator unaryOperator) {
- //Contract.Requires(unaryOperator != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- Contract.Assert(unaryOperator.Op == UnaryOperator.Opcode.Neg || unaryOperator.Op == UnaryOperator.Opcode.Not);
- Contract.Assert(this.args.Count == 1);
- if (unaryOperator.Op == UnaryOperator.Opcode.Neg) {
- VCExpr e = cce.NonNull(this.args[0]);
- if (cce.NonNull(e.Type).IsInt) {
- return Gen.Function(VCExpressionGenerator.SubIOp, Gen.Integer(BigNum.ZERO), e);
- }
- else {// if (cce.NonNull(e.Type).IsReal) {
- return Gen.Function(VCExpressionGenerator.SubROp, Gen.Real(BigDec.ZERO), e);
- }
- //else {//is float
- //return Gen.Function(VCExpressionGenerator.SubFOp, Gen.Float(BigFloat.ZERO(8, 23)), e);
- //}
- }
- else {
- return Gen.Not(this.args);
- }
- }
-
- public VCExpr Visit(BinaryOperator binaryOperator) {
- //Contract.Requires(binaryOperator != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return TranslateBinaryOperator(binaryOperator, this.args);
- }
-
- public VCExpr Visit(FunctionCall functionCall) {
- //Contract.Requires(functionCall != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return TranslateFunctionCall(functionCall, this.args, this.typeArgs);
- }
-
- public VCExpr Visit(MapSelect mapSelect) {
- //Contract.Requires(mapSelect != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Gen.Select(this.args, this.typeArgs);
- }
-
- public VCExpr Visit(MapStore mapStore) {
- //Contract.Requires(mapStore != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Gen.Store(this.args, this.typeArgs);
- }
-
- public VCExpr Visit(TypeCoercion typeCoercion) {
- //Contract.Requires(typeCoercion != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- Contract.Assert(this.args.Count == 1);
- return this.args[0];
- }
-
- public VCExpr Visit(ArithmeticCoercion arithCoercion) {
- //Contract.Requires(arithCoercion != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- Contract.Assert(this.args.Count == 1);
- switch (arithCoercion.Coercion) {
- case ArithmeticCoercion.CoercionType.ToInt:
- return Gen.Function(VCExpressionGenerator.ToIntOp, this.args);
- case ArithmeticCoercion.CoercionType.ToReal:
- return Gen.Function(VCExpressionGenerator.ToRealOp, this.args);
- default:
- Contract.Assert(false);
- return null;
- }
- }
-
- public VCExpr Visit(IfThenElse ite) {
- //Contract.Requires(ite != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Gen.Function(VCExpressionGenerator.IfThenElseOp, this.args);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
- private VCExpr TranslateBinaryOperator(BinaryOperator app, List<VCExpr/*!*/>/*!*/ args) {
- Contract.Requires(app != null);
- Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- Contract.Assert(args.Count == 2);
- Type t = cce.NonNull(cce.NonNull(args[0]).Type);
-
- switch (app.Op) {
- case BinaryOperator.Opcode.Add:
- if (t.IsInt) {
- return Gen.Function(VCExpressionGenerator.AddIOp, args);
- }
- else if (t.IsReal) {
- return Gen.Function(VCExpressionGenerator.AddROp, args);
- }
- else { //t is float
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "+"), args);
- }
- case BinaryOperator.Opcode.Sub:
- if (t.IsInt) {
- return Gen.Function(VCExpressionGenerator.SubIOp, args);
- }
- else if (t.IsReal) {
- return Gen.Function(VCExpressionGenerator.SubROp, args);
- }
- else { //t is float
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "-"), args);
- }
- case BinaryOperator.Opcode.Mul:
- if (t.IsInt) {
- return Gen.Function(VCExpressionGenerator.MulIOp, args);
- }
- else if (t.IsReal) {
- return Gen.Function(VCExpressionGenerator.MulROp, args);
- }
- else
- { //t is float
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "*"), args);
- }
- case BinaryOperator.Opcode.Div:
- return Gen.Function(VCExpressionGenerator.DivIOp, args);
- case BinaryOperator.Opcode.Mod:
- return Gen.Function(VCExpressionGenerator.ModOp, args);
- case BinaryOperator.Opcode.RealDiv:
- if (t.IsFloat) {
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "/"), args);
- }
- VCExpr arg0 = cce.NonNull(args[0]);
- VCExpr arg1 = cce.NonNull(args[1]);
- if (cce.NonNull(arg0.Type).IsInt) {
- arg0 = Gen.Function(VCExpressionGenerator.ToRealOp, arg0);
- }
- if (cce.NonNull(arg1.Type).IsInt) {
- arg1 = Gen.Function(VCExpressionGenerator.ToRealOp, arg1);
- }
- return Gen.Function(VCExpressionGenerator.DivROp, arg0, arg1);
- case BinaryOperator.Opcode.Pow:
- return Gen.Function(VCExpressionGenerator.PowOp, args);
- case BinaryOperator.Opcode.Eq:
- case BinaryOperator.Opcode.Iff:
- // we don't distinguish between equality and equivalence at this point
- if (t.IsFloat)
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "=="), args);
- return Gen.Function(VCExpressionGenerator.EqOp, args);
- case BinaryOperator.Opcode.Neq:
- return Gen.Function(VCExpressionGenerator.NeqOp, args);
- case BinaryOperator.Opcode.Lt:
- if (t.IsFloat)
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "<"), args);
- return Gen.Function(VCExpressionGenerator.LtOp, args);
- case BinaryOperator.Opcode.Le:
- if (t.IsFloat)
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "<="), args);
- return Gen.Function(VCExpressionGenerator.LeOp, args);
- case BinaryOperator.Opcode.Ge:
- if (t.IsFloat)
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, ">="), args);
- return Gen.Function(VCExpressionGenerator.GeOp, args);
- case BinaryOperator.Opcode.Gt:
- if (t.IsFloat)
- return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, ">"), args);
- return Gen.Function(VCExpressionGenerator.GtOp, args);
- case BinaryOperator.Opcode.Imp:
- return Gen.Function(VCExpressionGenerator.ImpliesOp, args);
- case BinaryOperator.Opcode.And:
- return Gen.Function(VCExpressionGenerator.AndOp, args);
- case BinaryOperator.Opcode.Or:
- return Gen.Function(VCExpressionGenerator.OrOp, args);
- case BinaryOperator.Opcode.Subtype:
- return Gen.Function(VCExpressionGenerator.SubtypeOp, args);
- default:
- Contract.Assert(false);
- throw new cce.UnreachableException(); // unexpected binary operator
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
- private VCExpr/*!*/ TranslateFunctionCall(FunctionCall app, List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs) {
- Contract.Requires(cce.NonNullElements(args));
- Contract.Requires(cce.NonNullElements(typeArgs));
- Contract.Requires(app != null);
- Contract.Requires((app.Func != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null); // resolution must have happened
-
- VCExpr res = ApplyExpansion(app, args, typeArgs);
- if (res != null)
- return res;
-
- VCExprOp/*!*/ functionOp = Gen.BoogieFunctionOp(app.Func);
- return Gen.Function(functionOp, args, typeArgs);
- }
-
- private VCExpr ApplyExpansion(FunctionCall app, List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs) {
- Contract.Requires(app != null);
- Contract.Requires(cce.NonNullElements(args));
- Contract.Requires(cce.NonNullElements(typeArgs));
- Contract.Assert(app.Func != null); // resolution must have happened
-
- lock (app.Func)
- {
- if (app.Func.doingExpansion)
- {
- System.Console.WriteLine("*** detected expansion loop on {0}", app.Func);
- return null;
- }
-
- var exp = app.Func.Body;
- if (exp == null)
- return null;
-
- VCExpr/*!*/ translatedBody;
- VCExprSubstitution/*!*/ subst = new VCExprSubstitution();
- try
- {
- BaseTranslator.PushFormalsScope();
- BaseTranslator.PushBoundVariableScope();
- app.Func.doingExpansion = true;
-
- // first bind the formals to VCExpr variables, which are later
- // substituted with the actual parameters
- var inParams = app.Func.InParams;
- for (int i = 0; i < inParams.Count; ++i)
- subst[BaseTranslator.BindVariable(inParams[i])] = args[i];
-
- // recursively translate the body of the expansion
- translatedBody = BaseTranslator.Translate(exp);
- }
- finally
- {
- BaseTranslator.PopFormalsScope();
- BaseTranslator.PopBoundVariableScope();
- app.Func.doingExpansion = false;
- }
-
- // substitute the formals with the actual parameters in the body
- var tparms = app.Func.TypeParameters;
- Contract.Assert(typeArgs.Count == tparms.Count);
- for (int i = 0; i < typeArgs.Count; ++i)
- subst[tparms[i]] = typeArgs[i];
- SubstitutingVCExprVisitor/*!*/ substituter = new SubstitutingVCExprVisitor(Gen);
- return substituter.Mutate(translatedBody, subst);
- }
- }
- }
-}
+//----------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- +using System; +using System.Text; +using System.IO; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using Microsoft.Basetypes; + +// A translator from the Boogie AST to the VCExpr AST. +// This was previously realised in the methods AbsyExpr.VCView + +namespace Microsoft.Boogie.VCExprAST { + using Microsoft.Boogie; + + // TODO: in future we might use that for defining symbols for Boogie's conditional compilation + public class VCGenerationOptions { + private readonly List<string/*!*/>/*!*/ SupportedProverCommands; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(cce.NonNullElements(SupportedProverCommands)); + } + + + public bool IsProverCommandSupported(string kind) { + Contract.Requires(kind != null); + return SupportedProverCommands.Contains(kind); + } + + public bool IsAnyProverCommandSupported(string kinds) { + Contract.Requires(kinds != null); + if (kinds.IndexOf(',') < 0) { + return IsProverCommandSupported(kinds); + } else { + return kinds.Split(',', ' ').Any(k => IsProverCommandSupported(k)); + } + } + + public VCGenerationOptions(List<string/*!*/>/*!*/ supportedProverCommands) { + Contract.Requires(cce.NonNullElements(supportedProverCommands)); + this.SupportedProverCommands = supportedProverCommands; + } + } + + public delegate VCExpr/*!*/ CodeExprConverter(CodeExpr/*!*/ codeExpr, Hashtable/*<Block, VCExprVar!>*//*!*/ blockVariables, List<VCExprLetBinding> bindings, bool isPositiveContext); + + public class Boogie2VCExprTranslator : ReadOnlyVisitor, ICloneable { + // Stack on which the various Visit-methods put the result of the translation + private readonly Stack<VCExpr/*!*/>/*!*/ SubExpressions = new Stack<VCExpr>(); + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(cce.NonNullElements(SubExpressions)); + Contract.Invariant(Gen != null); + } + + + private void Push(VCExpr expr) { + Contract.Requires(expr != null); + SubExpressions.Push(expr); + } + + private VCExpr Pop() { + Contract.Ensures(Contract.Result<VCExpr>() != null); + return SubExpressions.Pop(); + } + + public VCExpr Translate(Expr expr) { + Contract.Requires(expr != null); + Contract.Ensures(Contract.Result<VCExpr>() != null); + this.Visit(expr); + return Pop(); + } + + public List<VCExpr/*!*/>/*!*/ Translate(IList<Expr> exprs) { + Contract.Requires(exprs != null); + Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>())); + List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>(); + foreach (Expr e in exprs) + res.Add(Translate(cce.NonNull(e))); + return res; + } + + /////////////////////////////////////////////////////////////////////////////// + + internal readonly VCExpressionGenerator/*!*/ Gen; + + public Boogie2VCExprTranslator(VCExpressionGenerator gen, + VCGenerationOptions genOptions) { + Contract.Requires(gen != null); + Contract.Requires(genOptions != null); + this.Gen = gen; + this.GenerationOptions = genOptions; + UnboundVariables = new VariableMapping<Variable>(); + BoundVariables = new VariableMapping<BoundVariable>(); + Formals = new VariableMapping<Formal>(); + } + + private Boogie2VCExprTranslator(Boogie2VCExprTranslator tl) { + Contract.Requires(tl != null); + this.Gen = tl.Gen; + this.GenerationOptions = tl.GenerationOptions; + UnboundVariables = + (VariableMapping<Variable>)tl.UnboundVariables.Clone(); + BoundVariables = new VariableMapping<BoundVariable>(); + Formals = new VariableMapping<Formal>(); + } + + public object Clone() { + Contract.Ensures(Contract.Result<object>() != null); + return new Boogie2VCExprTranslator(this); + } + + private IAppliableTranslator IAppTranslatorAttr = null; + private IAppliableTranslator IAppTranslator { + get { + Contract.Ensures(Contract.Result<IAppliableTranslator>() != null); + + if (IAppTranslatorAttr == null) + IAppTranslatorAttr = new IAppliableTranslator(this); + return IAppTranslatorAttr; + } + } + + /////////////////////////////////////////////////////////////////////////////// + // Class for handling occurring variables + + private class VariableMapping<VarKind> : ICloneable { + private readonly List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>/*!*/ Mapping; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(Mapping != null && Contract.ForAll(Mapping, i => cce.NonNullDictionaryAndValues(i))); + } + + + public VariableMapping() { + List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>/*!*/ mapping = + new List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>(); + mapping.Add(new Dictionary<VarKind/*!*/, VCExprVar/*!*/>()); + this.Mapping = mapping; + } + + private VariableMapping(VariableMapping<VarKind> vm) { + Contract.Requires(vm != null); + List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>/*!*/ mapping = + new List<Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/>(); + foreach (Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/ d in vm.Mapping) { + Contract.Assert(cce.NonNullDictionaryAndValues(d)); + mapping.Add(new Dictionary<VarKind/*!*/, VCExprVar/*!*/>(d)); + } + this.Mapping = mapping; + } + + public object Clone() { + Contract.Ensures(Contract.Result<object>() != null); + return new VariableMapping<VarKind>(this); + } + + public void PushScope() { + Mapping.Add(new Dictionary<VarKind/*!*/, VCExprVar/*!*/>()); + } + + public void PopScope() { + Contract.Assume(Mapping.Count > 0); + Mapping.RemoveAt(Mapping.Count - 1); + } + + public void Bind(VarKind boogieVar, VCExprVar/*!*/ vcExprVar) { + Contract.Requires(vcExprVar != null); + Contract.Requires(boogieVar != null); + Contract.Requires(!Contains(boogieVar)); + Mapping[Mapping.Count - 1].Add(boogieVar, vcExprVar); + } + + public VCExprVar Lookup(VarKind boogieVar) { + Contract.Requires(boogieVar != null); + Contract.Ensures(Contract.Result<VCExprVar>() != null); + VCExprVar res = LookupHelp(boogieVar); + Contract.Assume(res != null); + return res; + } + + [Pure] + public bool Contains(VarKind boogieVar) { + Contract.Requires(boogieVar != null); + return LookupHelp(boogieVar) != null; + } + + public bool TryGetValue(VarKind boogieVar, out VCExprVar res) { + Contract.Requires(boogieVar != null); + res = LookupHelp(boogieVar); + return res != null; + } + + [Pure] + private VCExprVar LookupHelp(VarKind boogieVar) { + Contract.Requires(boogieVar != null); + VCExprVar res; + foreach (Dictionary<VarKind/*!*/, VCExprVar/*!*/>/*!*/ d in Mapping) { + //Contract.Assert(cce.NonNullElements(d)); + if (d.TryGetValue(boogieVar, out res)) { + Contract.Assert(res != null); + return res; + } + } + return null; + } + } + + ////////////////////////////////////////////////////////////////////////////////// + + private readonly VariableMapping<Variable>/*!*/ UnboundVariables; + private readonly VariableMapping<BoundVariable>/*!*/ BoundVariables; + // used when translating the bodies of function expansions + private readonly VariableMapping<Formal>/*!*/ Formals; + [ContractInvariantMethod] + void ObjectInvairant() { + Contract.Invariant(UnboundVariables != null); + Contract.Invariant(BoundVariables != null); + Contract.Invariant(Formals != null); + } + + + internal void PushBoundVariableScope() { + BoundVariables.PushScope(); + } + internal void PopBoundVariableScope() { + BoundVariables.PopScope(); + } + + internal void PushFormalsScope() { + Formals.PushScope(); + } + internal void PopFormalsScope() { + Formals.PopScope(); + } + + public VCExprVar BindVariable(Variable boogieVar) { + Contract.Requires(boogieVar != null); + Contract.Ensures(Contract.Result<VCExprVar>() != null); + if (boogieVar is BoundVariable) { + VCExprVar/*!*/ newVar = Gen.Variable(boogieVar.Name, boogieVar.TypedIdent.Type); + BoundVariables.Bind((BoundVariable)boogieVar, newVar); + return newVar; + } else if (boogieVar is Formal) { + VCExprVar/*!*/ newVar = Gen.Variable(boogieVar.Name, boogieVar.TypedIdent.Type); + Formals.Bind((Formal)boogieVar, newVar); + return newVar; + } else { + // only bound variables and formals are declared explicitly + Contract.Assert(false); + throw new cce.UnreachableException(); + } + } + + public VCExprVar LookupVariable(Variable boogieVar) { + Contract.Requires(boogieVar != null); + Contract.Ensures(Contract.Result<VCExprVar>() != null); + + BoundVariable bv = boogieVar as BoundVariable; + if (bv != null) { + return BoundVariables.Lookup(bv); + } + VCExprVar res; + Formal fml = boogieVar as Formal; + if (fml != null && Formals.TryGetValue(fml, out res)) + return cce.NonNull(res); + + // global variables, local variables, incarnations, etc. are + // bound the first time they occur + if (!UnboundVariables.TryGetValue(boogieVar, out res)) { + if (boogieVar is Constant) + res = new VCExprConstant(boogieVar.Name, boogieVar.TypedIdent.Type); + else + res = new VCExprVar(boogieVar.Name, boogieVar.TypedIdent.Type); + UnboundVariables.Bind(boogieVar, res); + } + return cce.NonNull(res); + } + + /// <summary> + /// Unlike LookupVariable, this method does not create a new variable mapping if none is + /// found. Instead, this method returns null in such cases. Also, this method does not + /// look for bound variables. + /// </summary> + /// <param name="boogieVar"></param> + /// <returns></returns> + public VCExprVar TryLookupVariable(Variable boogieVar) { + Contract.Requires(boogieVar != null); + + VCExprVar res; + Formal fml = boogieVar as Formal; + if (fml != null && Formals.TryGetValue(fml, out res)) + return cce.NonNull(res); + + if (UnboundVariables.TryGetValue(boogieVar, out res)) { + return cce.NonNull(res); + } + + return null; // not present + } + + /////////////////////////////////////////////////////////////////////////////////// + + internal readonly VCGenerationOptions/*!*/ GenerationOptions; + [ContractInvariantMethod] + void ObjectInvarian() { + Contract.Invariant(GenerationOptions != null); + } + + /////////////////////////////////////////////////////////////////////////////////// + + public override Expr VisitLiteralExpr(LiteralExpr node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Expr>() != null); + Push(TranslateLiteralExpr(node)); + return node; + } + private VCExpr TranslateLiteralExpr(LiteralExpr node) { + Contract.Requires(node != null); + Contract.Ensures(Contract.Result<VCExpr>() != null); + if (node.Val is bool) { + bool b = (bool)node.Val; + if (b) { + return VCExpressionGenerator.True; + } else { + return VCExpressionGenerator.False; + } + } else if (node.Val is BigNum) { + return Gen.Integer(node.asBigNum); + } else if (node.Val is BigDec) { + return Gen.Real(node.asBigDec); + } else if (node.Val is BigFloat) { + return Gen.Float(node.asBigFloat); + } + else if (node.Val is BvConst) { + return Gen.Bitvector((BvConst)node.Val); + } else { + System.Diagnostics.Debug.Assert(false, "unknown kind of literal " + node.tok.ToString()); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + } + + /////////////////////////////////////////////////////////////////////////////////// + + public override Expr VisitIdentifierExpr(IdentifierExpr node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Expr>() != null); + Contract.Assume(node.Decl != null); // the expression has to be resolved + Push(LookupVariable(node.Decl)); + return node; + } + + /////////////////////////////////////////////////////////////////////////////////// + + // Because of our scheme for numbering incarnations of variables, the pre-state + // value of a variable x is always just "x". (The first update to it in a method + // causes it to become "x0". So we just remove old expressions with a visitor + // before transforming it into a VCExpr. + public override Expr VisitOldExpr(OldExpr node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Expr>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + + /////////////////////////////////////////////////////////////////////////////////// + + public override Expr VisitNAryExpr(NAryExpr node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Expr>() != null); + Push(TranslateNAryExpr(node)); + return node; + } + + public bool isPositiveContext = true; + private VCExpr TranslateNAryExpr(NAryExpr node) { + Contract.Requires(node != null); + Contract.Ensures(Contract.Result<VCExpr>() != null); + + bool flipContextForArg0 = false; + if (node.Fun is UnaryOperator) + { + UnaryOperator oper = (UnaryOperator)node.Fun; + if (oper.Op == UnaryOperator.Opcode.Not) + flipContextForArg0 = true; + } + else if (node.Fun is BinaryOperator) + { + BinaryOperator oper = (BinaryOperator)node.Fun; + if (oper.Op == BinaryOperator.Opcode.Imp) + flipContextForArg0 = true; + else if (oper.Op == BinaryOperator.Opcode.Iff) { + Expr one = new NAryExpr(node.tok, new BinaryOperator(node.tok, BinaryOperator.Opcode.Imp), new List<Expr> { node.Args[0], node.Args[1] }); + Expr two = new NAryExpr(node.tok, new BinaryOperator(node.tok, BinaryOperator.Opcode.Imp), new List<Expr> { node.Args[1], node.Args[0] }); + NAryExpr cmpd = new NAryExpr(node.tok, new BinaryOperator(node.tok, BinaryOperator.Opcode.And), new List<Expr> { one, two }); + TypecheckingContext tc = new TypecheckingContext(null); + cmpd.Typecheck(tc); + return TranslateNAryExpr(cmpd); + } + } + + int n = node.Args.Count; + List<VCExpr/*!*/>/*!*/ vcs = new List<VCExpr/*!*/>(n); + + for (int i = 0; i < n; i++) { + if (i == 0 && flipContextForArg0) + isPositiveContext = !isPositiveContext; + vcs.Add(Translate(cce.NonNull(node.Args)[i])); + if (i == 0 && flipContextForArg0) + isPositiveContext = !isPositiveContext; + } + + if (node.Type == null) { + System.Console.WriteLine("*** type is null for {0}", node); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + + return IAppTranslator.Translate(node.Fun, node.Type, vcs, + ToList(cce.NonNull(node.TypeParameters))); + } + + + private static List<Type/*!*/>/*!*/ EMPTY_TYPE_LIST = new List<Type/*!*/>(); + [ContractInvariantMethod] + void ObjectInvirant() { + Contract.Invariant(EMPTY_TYPE_LIST != null); + } + + + private List<Type/*!*/>/*!*/ ToList(TypeParamInstantiation insts) { + Contract.Requires(insts != null); + Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>())); + if (insts.FormalTypeParams.Count == 0) + return EMPTY_TYPE_LIST; + + List<Type/*!*/>/*!*/ typeArgs = new List<Type/*!*/>(); + foreach (TypeVariable/*!*/ var in insts.FormalTypeParams) { + Contract.Assert(var != null); + typeArgs.Add(insts[var]); + } + return typeArgs; + } + + /////////////////////////////////////////////////////////////////////////////////// + + public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<QuantifierExpr>() != null); + Push(TranslateQuantifierExpr(node)); + return node; + } + + public override Expr VisitExistsExpr(ExistsExpr node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Expr>() != null); + node = (ExistsExpr)this.VisitQuantifierExpr(node); + return node; + } + + public override Expr VisitForallExpr(ForallExpr node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Expr>() != null); + node = (ForallExpr)this.VisitQuantifierExpr(node); + return node; + } + + private VCExpr TranslateQuantifierExpr(QuantifierExpr node) { + Contract.Requires(node != null); + Contract.Ensures(Contract.Result<VCExpr>() != null); + List<TypeVariable/*!*/>/*!*/ typeParams = new List<TypeVariable/*!*/>(); + foreach (TypeVariable/*!*/ v in node.TypeParameters) { + Contract.Assert(v != null); + typeParams.Add(v); + } + + PushBoundVariableScope(); + + List<VCExprVar/*!*/>/*!*/ boundVars = new List<VCExprVar/*!*/>(); + foreach (Variable/*!*/ v in node.Dummies) + boundVars.Add(BindVariable(v)); + + try { + List<VCTrigger/*!*/>/*!*/ triggers = TranslateTriggers(node.Triggers); + VCExpr/*!*/ body = Translate(node.Body); + VCQuantifierInfos/*!*/ infos = GenerateQuantifierInfos(node); + + Quantifier quan; + if (node is ForallExpr) + quan = Quantifier.ALL; + else if (node is ExistsExpr) + quan = Quantifier.EX; + else { + Contract.Assert(false); + throw new cce.UnreachableException(); + } + + return Gen.Quantify(quan, typeParams, boundVars, triggers, infos, body); + } finally { + PopBoundVariableScope(); + } + } + + private List<VCTrigger/*!*/>/*!*/ TranslateTriggers(Trigger node) { + Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCTrigger>>())); + List<VCTrigger/*!*/>/*!*/ res = new List<VCTrigger/*!*/>(); + Trigger curTrigger = node; + while (curTrigger != null) { + res.Add(Gen.Trigger(curTrigger.Pos, Translate(curTrigger.Tr))); + curTrigger = curTrigger.Next; + } + return res; + } + + private VCQuantifierInfos GenerateQuantifierInfos(QuantifierExpr node) { + Contract.Requires(node != null); + Contract.Ensures(Contract.Result<VCQuantifierInfos>() != null); + string qid = getQidNameFromQKeyValue(node.Dummies, node.Attributes); + return new VCQuantifierInfos(qid, node.SkolemId, false, node.Attributes); + } + + private string getQidNameFromQKeyValue(List<Variable> vars, QKeyValue attributes) { + Contract.Requires(vars != null); + // Check for a 'qid, name' pair in keyvalues + string qid = QKeyValue.FindStringAttribute(attributes, "qid"); + if (qid == null && vars.Count != 0) { + // generate default name (line:column position in .bpl file) + Variable v = vars[0]; + Contract.Assert(v != null); // Rustan's claim! + // Include the first 8 characters of the filename in QID (helpful in case we use /concat) + // We limit it to 8, so the SX file doesn't grow too big, and who on earth would need + // more than 8 characters in a filename anyways. + int max = 8; + StringBuilder buf = new StringBuilder(max + 20); + string filename = v.tok.filename; + if (filename == null) + filename = "unknown"; + for (int i = 0; i < filename.Length; ++i) { + if (filename[i] == '/' || filename[i] == '\\') + buf.Length = 0; + if (buf.Length < max && char.IsLetterOrDigit(filename[i])) { + if (buf.Length == 0 && char.IsDigit(filename[i])) { + // Z3 does not like QID's to start with a digit, so we prepend another character + buf.Append('_'); + } + buf.Append(filename[i]); + } + } + buf.Append('.').Append(v.Line).Append(':').Append(v.Col); + qid = buf.ToString(); + } + return qid; + } + + /////////////////////////////////////////////////////////////////////////////////// + + public override Expr VisitBvExtractExpr(BvExtractExpr node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Expr>() != null); + Push(TranslateBvExtractExpr(node)); + return node; + } + + private VCExpr TranslateBvExtractExpr(BvExtractExpr node) { + Contract.Requires(node != null); + Contract.Requires((node.Start <= node.End)); + Contract.Ensures(Contract.Result<VCExpr>() != null); + VCExpr/*!*/ bv = Translate(node.Bitvector); + return Gen.BvExtract(bv, cce.NonNull(node.Bitvector.Type).BvBits, node.Start, node.End); + } + + /////////////////////////////////////////////////////////////////////////////////// + + public override Expr VisitBvConcatExpr(BvConcatExpr node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Expr>() != null); + Push(TranslateBvConcatExpr(node)); + return node; + } + + private VCExpr TranslateBvConcatExpr(BvConcatExpr node) { + Contract.Requires(node != null); + Contract.Ensures(Contract.Result<VCExpr>() != null); + VCExpr/*!*/ bv0 = Translate(node.E0); + VCExpr/*!*/ bv1 = Translate(node.E1); + return Gen.BvConcat(bv0, bv1); + } + + /////////////////////////////////////////////////////////////////////////////////// + // all the other cases should never happen + + public override Cmd VisitAssertCmd(AssertCmd node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Cmd>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Cmd VisitAssignCmd(AssignCmd node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Cmd>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Cmd VisitAssumeCmd(AssumeCmd node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Cmd>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override AtomicRE VisitAtomicRE(AtomicRE node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<AtomicRE>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Axiom VisitAxiom(Axiom node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Axiom>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Type VisitBasicType(BasicType node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Type>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Type VisitBvType(BvType node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Type>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Block VisitBlock(Block node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Block>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public CodeExprConverter codeExprConverter = null; + public void SetCodeExprConverter(CodeExprConverter f) { + this.codeExprConverter = f; + } + public override Expr/*!*/ VisitCodeExpr(CodeExpr/*!*/ codeExpr) { + //Contract.Requires(codeExpr != null); + Contract.Ensures(Contract.Result<Expr>() != null); + Contract.Assume(codeExprConverter != null); + + Hashtable/*<Block, LetVariable!>*/ blockVariables = new Hashtable/*<Block, LetVariable!!>*/(); + List<VCExprLetBinding/*!*/> bindings = new List<VCExprLetBinding/*!*/>(); + VCExpr e = codeExprConverter(codeExpr, blockVariables, bindings, isPositiveContext); + Push(e); + return codeExpr; + } + public override List<Block> VisitBlockSeq(List<Block> blockSeq) { + //Contract.Requires(blockSeq != null); + Contract.Ensures(Contract.Result<List<Block>>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override List<Block/*!*/>/*!*/ VisitBlockList(List<Block/*!*/>/*!*/ blocks) { + //Contract.Requires(cce.NonNullElements(blocks)); + Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>())); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override BoundVariable VisitBoundVariable(BoundVariable node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<BoundVariable>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Cmd VisitCallCmd(CallCmd node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Cmd>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Cmd VisitParCallCmd(ParCallCmd node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Cmd>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override List<Cmd> VisitCmdSeq(List<Cmd> cmdSeq) { + //Contract.Requires(cmdSeq != null); + Contract.Ensures(Contract.Result<List<Cmd>>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Choice VisitChoice(Choice node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Choice>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Cmd VisitCommentCmd(CommentCmd node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Cmd>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Constant VisitConstant(Constant node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Constant>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override CtorType VisitCtorType(CtorType node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<CtorType>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Declaration VisitDeclaration(Declaration node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Declaration>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override List<Declaration/*!*/>/*!*/ VisitDeclarationList(List<Declaration/*!*/>/*!*/ declarationList) { + //Contract.Requires(cce.NonNullElements(declarationList)); + Contract.Ensures(cce.NonNullElements(Contract.Result<List<Declaration>>())); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override DeclWithFormals VisitDeclWithFormals(DeclWithFormals node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<DeclWithFormals>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Requires VisitRequires(Requires @requires) { + //Contract.Requires(@requires != null); + Contract.Ensures(Contract.Result<Requires>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override List<Requires> VisitRequiresSeq(List<Requires> requiresSeq) { + //Contract.Requires(requiresSeq != null); + Contract.Ensures(Contract.Result<List<Requires>>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Ensures VisitEnsures(Ensures @ensures) { + //Contract.Requires(@ensures != null); + Contract.Ensures(Contract.Result<Ensures>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override List<Ensures> VisitEnsuresSeq(List<Ensures> ensuresSeq) { + //Contract.Requires(ensuresSeq != null); + Contract.Ensures(Contract.Result<List<Ensures>>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Formal VisitFormal(Formal node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Formal>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Function VisitFunction(Function node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Function>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override GlobalVariable VisitGlobalVariable(GlobalVariable node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<GlobalVariable>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override GotoCmd VisitGotoCmd(GotoCmd node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<GotoCmd>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Cmd VisitHavocCmd(HavocCmd node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Cmd>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Implementation VisitImplementation(Implementation node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Implementation>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override LocalVariable VisitLocalVariable(LocalVariable node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<LocalVariable>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override AssignLhs VisitMapAssignLhs(MapAssignLhs node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<AssignLhs>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override MapType VisitMapType(MapType node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<MapType>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Procedure VisitProcedure(Procedure node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Procedure>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Program VisitProgram(Program node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Program>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Cmd VisitRE(RE node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Cmd>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override List<RE> VisitRESeq(List<RE> reSeq) { + //Contract.Requires(reSeq != null); + Contract.Ensures(Contract.Result<List<RE>>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override ReturnCmd VisitReturnCmd(ReturnCmd node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<ReturnCmd>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override ReturnExprCmd VisitReturnExprCmd(ReturnExprCmd node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<ReturnExprCmd>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Sequential VisitSequential(Sequential node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Sequential>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<AssignLhs>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Cmd VisitStateCmd(StateCmd node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Cmd>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override TransferCmd VisitTransferCmd(TransferCmd node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<TransferCmd>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Trigger VisitTrigger(Trigger node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Trigger>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Type VisitType(Type node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Type>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override TypedIdent VisitTypedIdent(TypedIdent node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<TypedIdent>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Type VisitTypeSynonymAnnotation(TypeSynonymAnnotation node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Type>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Type VisitTypeVariable(TypeVariable node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Type>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Variable VisitVariable(Variable node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Variable>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override List<Variable> VisitVariableSeq(List<Variable> variableSeq) { + //Contract.Requires(variableSeq != null); + Contract.Ensures(Contract.Result<List<Variable>>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Cmd VisitAssertEnsuresCmd(AssertEnsuresCmd node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Cmd>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + public override Cmd VisitAssertRequiresCmd(AssertRequiresCmd node) { + //Contract.Requires(node != null); + Contract.Ensures(Contract.Result<Cmd>() != null); + Contract.Assert(false); + throw new cce.UnreachableException(); + } + + } + + + ///////////////////////////////////////////////////////////////////////////////// + + public class IAppliableTranslator : IAppliableVisitor<VCExpr/*!*/> { + + private readonly Boogie2VCExprTranslator/*!*/ BaseTranslator; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(BaseTranslator != null); + } + + + private VCExpressionGenerator/*!*/ Gen { + get { + Contract.Ensures(Contract.Result<VCExpressionGenerator>() != null); + + return BaseTranslator.Gen; + } + } + private VCGenerationOptions GenerationOptions { + get { + Contract.Ensures(Contract.Result<VCGenerationOptions>() != null); + + return BaseTranslator.GenerationOptions; + } + } + + public IAppliableTranslator(Boogie2VCExprTranslator baseTranslator) { + Contract.Requires(baseTranslator != null); + this.BaseTranslator = baseTranslator; + } + + /////////////////////////////////////////////////////////////////////////////// + + private List<VCExpr/*!*/>/*!*/ args = new List<VCExpr/*!*/>(); + private List<Type/*!*/>/*!*/ typeArgs = new List<Type/*!*/>(); + [ContractInvariantMethod] + void ObjectInvarianet() { + Contract.Invariant(args != null); + Contract.Invariant(typeArgs != null); + } + + + public VCExpr Translate(IAppliable app, Type ty, List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs) { + Contract.Requires(ty != null); + Contract.Requires(app != null); + Contract.Requires(cce.NonNullElements(typeArgs)); + Contract.Requires(cce.NonNullElements(args)); + Contract.Ensures(Contract.Result<VCExpr>() != null); + + List<VCExpr/*!*/>/*!*/ oldArgs = this.args; + List<Type/*!*/>/*!*/ oldTypeArgs = this.typeArgs; + this.args = args; + this.typeArgs = typeArgs; + VCExpr/*!*/ result = app.Dispatch<VCExpr/*!*/>(this); + this.args = oldArgs; + this.typeArgs = oldTypeArgs; + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + + + + public VCExpr Visit(UnaryOperator unaryOperator) { + //Contract.Requires(unaryOperator != null); + Contract.Ensures(Contract.Result<VCExpr>() != null); + Contract.Assert(unaryOperator.Op == UnaryOperator.Opcode.Neg || unaryOperator.Op == UnaryOperator.Opcode.Not); + Contract.Assert(this.args.Count == 1); + if (unaryOperator.Op == UnaryOperator.Opcode.Neg) { + VCExpr e = cce.NonNull(this.args[0]); + if (cce.NonNull(e.Type).IsInt) { + return Gen.Function(VCExpressionGenerator.SubIOp, Gen.Integer(BigNum.ZERO), e); + } + else {// if (cce.NonNull(e.Type).IsReal) { + return Gen.Function(VCExpressionGenerator.SubROp, Gen.Real(BigDec.ZERO), e); + } + //else {//is float + //return Gen.Function(VCExpressionGenerator.SubFOp, Gen.Float(BigFloat.ZERO(8, 23)), e); + //} + } + else { + return Gen.Not(this.args); + } + } + + public VCExpr Visit(BinaryOperator binaryOperator) { + //Contract.Requires(binaryOperator != null); + Contract.Ensures(Contract.Result<VCExpr>() != null); + return TranslateBinaryOperator(binaryOperator, this.args); + } + + public VCExpr Visit(FunctionCall functionCall) { + //Contract.Requires(functionCall != null); + Contract.Ensures(Contract.Result<VCExpr>() != null); + return TranslateFunctionCall(functionCall, this.args, this.typeArgs); + } + + public VCExpr Visit(MapSelect mapSelect) { + //Contract.Requires(mapSelect != null); + Contract.Ensures(Contract.Result<VCExpr>() != null); + return Gen.Select(this.args, this.typeArgs); + } + + public VCExpr Visit(MapStore mapStore) { + //Contract.Requires(mapStore != null); + Contract.Ensures(Contract.Result<VCExpr>() != null); + return Gen.Store(this.args, this.typeArgs); + } + + public VCExpr Visit(TypeCoercion typeCoercion) { + //Contract.Requires(typeCoercion != null); + Contract.Ensures(Contract.Result<VCExpr>() != null); + Contract.Assert(this.args.Count == 1); + return this.args[0]; + } + + public VCExpr Visit(ArithmeticCoercion arithCoercion) { + //Contract.Requires(arithCoercion != null); + Contract.Ensures(Contract.Result<VCExpr>() != null); + Contract.Assert(this.args.Count == 1); + switch (arithCoercion.Coercion) { + case ArithmeticCoercion.CoercionType.ToInt: + return Gen.Function(VCExpressionGenerator.ToIntOp, this.args); + case ArithmeticCoercion.CoercionType.ToReal: + return Gen.Function(VCExpressionGenerator.ToRealOp, this.args); + default: + Contract.Assert(false); + return null; + } + } + + public VCExpr Visit(IfThenElse ite) { + //Contract.Requires(ite != null); + Contract.Ensures(Contract.Result<VCExpr>() != null); + return Gen.Function(VCExpressionGenerator.IfThenElseOp, this.args); + } + + /////////////////////////////////////////////////////////////////////////////// + + private VCExpr TranslateBinaryOperator(BinaryOperator app, List<VCExpr/*!*/>/*!*/ args) { + Contract.Requires(app != null); + Contract.Requires(cce.NonNullElements(args)); + Contract.Ensures(Contract.Result<VCExpr>() != null); + Contract.Assert(args.Count == 2); + Type t = cce.NonNull(cce.NonNull(args[0]).Type); + + switch (app.Op) { + case BinaryOperator.Opcode.Add: + if (t.IsInt) { + return Gen.Function(VCExpressionGenerator.AddIOp, args); + } + else if (t.IsReal) { + return Gen.Function(VCExpressionGenerator.AddROp, args); + } + else { //t is float + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "+"), args); + } + case BinaryOperator.Opcode.Sub: + if (t.IsInt) { + return Gen.Function(VCExpressionGenerator.SubIOp, args); + } + else if (t.IsReal) { + return Gen.Function(VCExpressionGenerator.SubROp, args); + } + else { //t is float + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "-"), args); + } + case BinaryOperator.Opcode.Mul: + if (t.IsInt) { + return Gen.Function(VCExpressionGenerator.MulIOp, args); + } + else if (t.IsReal) { + return Gen.Function(VCExpressionGenerator.MulROp, args); + } + else + { //t is float + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "*"), args); + } + case BinaryOperator.Opcode.Div: + return Gen.Function(VCExpressionGenerator.DivIOp, args); + case BinaryOperator.Opcode.Mod: + return Gen.Function(VCExpressionGenerator.ModOp, args); + case BinaryOperator.Opcode.RealDiv: + if (t.IsFloat) { + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "/"), args); + } + VCExpr arg0 = cce.NonNull(args[0]); + VCExpr arg1 = cce.NonNull(args[1]); + if (cce.NonNull(arg0.Type).IsInt) { + arg0 = Gen.Function(VCExpressionGenerator.ToRealOp, arg0); + } + if (cce.NonNull(arg1.Type).IsInt) { + arg1 = Gen.Function(VCExpressionGenerator.ToRealOp, arg1); + } + return Gen.Function(VCExpressionGenerator.DivROp, arg0, arg1); + case BinaryOperator.Opcode.Pow: + return Gen.Function(VCExpressionGenerator.PowOp, args); + case BinaryOperator.Opcode.Eq: + case BinaryOperator.Opcode.Iff: + // we don't distinguish between equality and equivalence at this point + if (t.IsFloat) + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "=="), args); + return Gen.Function(VCExpressionGenerator.EqOp, args); + case BinaryOperator.Opcode.Neq: + return Gen.Function(VCExpressionGenerator.NeqOp, args); + case BinaryOperator.Opcode.Lt: + if (t.IsFloat) + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "<"), args); + return Gen.Function(VCExpressionGenerator.LtOp, args); + case BinaryOperator.Opcode.Le: + if (t.IsFloat) + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "<="), args); + return Gen.Function(VCExpressionGenerator.LeOp, args); + case BinaryOperator.Opcode.Ge: + if (t.IsFloat) + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, ">="), args); + return Gen.Function(VCExpressionGenerator.GeOp, args); + case BinaryOperator.Opcode.Gt: + if (t.IsFloat) + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, ">"), args); + return Gen.Function(VCExpressionGenerator.GtOp, args); + case BinaryOperator.Opcode.Imp: + return Gen.Function(VCExpressionGenerator.ImpliesOp, args); + case BinaryOperator.Opcode.And: + return Gen.Function(VCExpressionGenerator.AndOp, args); + case BinaryOperator.Opcode.Or: + return Gen.Function(VCExpressionGenerator.OrOp, args); + case BinaryOperator.Opcode.Subtype: + return Gen.Function(VCExpressionGenerator.SubtypeOp, args); + default: + Contract.Assert(false); + throw new cce.UnreachableException(); // unexpected binary operator + } + } + + /////////////////////////////////////////////////////////////////////////////// + + private VCExpr/*!*/ TranslateFunctionCall(FunctionCall app, List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs) { + Contract.Requires(cce.NonNullElements(args)); + Contract.Requires(cce.NonNullElements(typeArgs)); + Contract.Requires(app != null); + Contract.Requires((app.Func != null)); + Contract.Ensures(Contract.Result<VCExpr>() != null); // resolution must have happened + + VCExpr res = ApplyExpansion(app, args, typeArgs); + if (res != null) + return res; + + VCExprOp/*!*/ functionOp = Gen.BoogieFunctionOp(app.Func); + return Gen.Function(functionOp, args, typeArgs); + } + + private VCExpr ApplyExpansion(FunctionCall app, List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs) { + Contract.Requires(app != null); + Contract.Requires(cce.NonNullElements(args)); + Contract.Requires(cce.NonNullElements(typeArgs)); + Contract.Assert(app.Func != null); // resolution must have happened + + lock (app.Func) + { + if (app.Func.doingExpansion) + { + System.Console.WriteLine("*** detected expansion loop on {0}", app.Func); + return null; + } + + var exp = app.Func.Body; + if (exp == null) + return null; + + VCExpr/*!*/ translatedBody; + VCExprSubstitution/*!*/ subst = new VCExprSubstitution(); + try + { + BaseTranslator.PushFormalsScope(); + BaseTranslator.PushBoundVariableScope(); + app.Func.doingExpansion = true; + + // first bind the formals to VCExpr variables, which are later + // substituted with the actual parameters + var inParams = app.Func.InParams; + for (int i = 0; i < inParams.Count; ++i) + subst[BaseTranslator.BindVariable(inParams[i])] = args[i]; + + // recursively translate the body of the expansion + translatedBody = BaseTranslator.Translate(exp); + } + finally + { + BaseTranslator.PopFormalsScope(); + BaseTranslator.PopBoundVariableScope(); + app.Func.doingExpansion = false; + } + + // substitute the formals with the actual parameters in the body + var tparms = app.Func.TypeParameters; + Contract.Assert(typeArgs.Count == tparms.Count); + for (int i = 0; i < typeArgs.Count; ++i) + subst[tparms[i]] = typeArgs[i]; + SubstitutingVCExprVisitor/*!*/ substituter = new SubstitutingVCExprVisitor(Gen); + return substituter.Mutate(translatedBody, subst); + } + } + } +} |