summaryrefslogtreecommitdiff
path: root/Source/VCExpr
diff options
context:
space:
mode:
authorGravatar Dan Liew <daniel.liew@imperial.ac.uk>2015-06-28 01:44:30 +0100
committerGravatar Dan Liew <daniel.liew@imperial.ac.uk>2015-06-28 01:44:30 +0100
commit962f8d5252b3f5ec4d19e0cd2a430934bd55cc6d (patch)
tree27d5f9b0d130c6c1a6758bc0b7456b0aa51e34e0 /Source/VCExpr
parente11d65009d0b4ba1327f5f5dd6b26367330611f0 (diff)
Normalise line endings using a .gitattributes file. Unfortunately
this required that this commit globally modify most files. If you want to use git blame to see the real author of a line use the ``-w`` flag so that whitespace changes are ignored.
Diffstat (limited to 'Source/VCExpr')
-rw-r--r--Source/VCExpr/BigLiteralAbstracter.cs462
-rw-r--r--Source/VCExpr/Boogie2VCExpr.cs2418
-rw-r--r--Source/VCExpr/Clustering.cs1042
-rw-r--r--Source/VCExpr/LetBindingSorter.cs322
-rw-r--r--Source/VCExpr/NameClashResolver.cs392
-rw-r--r--Source/VCExpr/SimplifyLikeLineariser.cs2196
-rw-r--r--Source/VCExpr/TermFormulaFlattening.cs494
-rw-r--r--Source/VCExpr/TypeErasure.cs3238
-rw-r--r--Source/VCExpr/TypeErasureArguments.cs1506
-rw-r--r--Source/VCExpr/TypeErasurePremisses.cs2674
-rw-r--r--Source/VCExpr/VCExpr.csproj446
-rw-r--r--Source/VCExpr/VCExprAST.cs4260
-rw-r--r--Source/VCExpr/VCExprASTPrinter.cs720
-rw-r--r--Source/VCExpr/VCExprASTVisitors.cs3052
-rw-r--r--Source/VCExpr/cce.cs384
15 files changed, 11803 insertions, 11803 deletions
diff --git a/Source/VCExpr/BigLiteralAbstracter.cs b/Source/VCExpr/BigLiteralAbstracter.cs
index 879ab6d6..39064fb7 100644
--- a/Source/VCExpr/BigLiteralAbstracter.cs
+++ b/Source/VCExpr/BigLiteralAbstracter.cs
@@ -1,232 +1,232 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-
-// Code for replacing large integer literals in VCExpr with
-// constants. This is necessary for Simplify, which cannot deal with
-// literals larger than 32 bits
-
-namespace Microsoft.Boogie.VCExprAST {
-
- public class BigLiteralAbstracter : MutatingVCExprVisitor<bool>, ICloneable {
-
- public BigLiteralAbstracter(VCExpressionGenerator gen)
- : base(gen) {
- Contract.Requires(gen != null);
- DummyVar = gen.Variable("x", Type.Int);
- IncAxioms = new List<VCExpr>();
- Literals = new List<KeyValuePair<BigNum, VCExprVar>>();
- }
-
- private BigLiteralAbstracter(BigLiteralAbstracter abstracter)
- : base(abstracter.Gen) {
- Contract.Requires(abstracter != null);
- DummyVar = abstracter.DummyVar;
- IncAxioms = new List<VCExpr>(abstracter.IncAxioms);
- Literals = new List<KeyValuePair<BigNum, VCExprVar>>(abstracter.Literals);
- }
-
- public Object Clone() {
- Contract.Ensures(Contract.Result<Object>() != null);
-
- return new BigLiteralAbstracter(this);
- }
-
- private static readonly BigNum ConstantDistance = BigNum.FromLong(100000);
- private static readonly BigNum NegConstantDistance = BigNum.FromLong(-100000);
- // distance twice plus one
- private static readonly BigNum ConstantDistanceTPO = BigNum.FromLong(200001);
- private static readonly BigNum ConstantDistancePO = BigNum.FromLong(100001);
-
- public VCExpr Abstract(VCExpr expr) {
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return Mutate(expr, true);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // list in which axioms are incrementally collected
- private readonly List<VCExpr/*!*/>/*!*/ IncAxioms;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(IncAxioms));
- }
-
- private void AddAxiom(VCExpr/*!*/ axiom) {
- Contract.Requires(axiom != null);
- IncAxioms.Add(axiom);
- }
-
- // Return all axioms that were added since the last time NewAxioms
- // was called
- public VCExpr GetNewAxioms() {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr res = Gen.NAry(VCExpressionGenerator.AndOp, IncAxioms);
- IncAxioms.Clear();
- return res;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // All named integer literals known to the visitor, in ascending
- // order. Such literals are always positive, and the distance
- // between two literals is always more than ConstantDistance.
- private readonly List<KeyValuePair<BigNum, VCExprVar/*!*/>>/*!*/ Literals;
-
- [ContractInvariantMethod]
- void ObjectInvariat() {
- Contract.Invariant(Literals != null);
- Contract.Invariant(Contract.ForAll(Literals, i => i.Value != null));
- }
-
-
- private class EntryComparerC : IComparer<KeyValuePair<BigNum, VCExprVar/*!*/>> {
- public int Compare(KeyValuePair<BigNum, VCExprVar/*!*/> a,
- KeyValuePair<BigNum, VCExprVar/*!*/> b) {
- //Contract.Requires(a.Value!=null);
- //Contract.Requires(b.Value!=null);
- return a.Key.CompareTo(b.Key);
- }
- }
-
- private static readonly EntryComparerC EntryComparer = new EntryComparerC();
-
- // variable used when searching for entries in the literal list
- private readonly VCExprVar/*!*/ DummyVar;
- [ContractInvariantMethod]
- void ObjectInvarint() {
- Contract.Invariant(DummyVar != null);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////
-
- // Construct an expression to represent the given (large) integer
- // literal. Constants are defined and axiomatised if necessary
- private VCExpr Represent(BigNum lit) {
- Contract.Requires((NegConstantDistance > lit || lit > ConstantDistance));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- if (lit.IsNegative)
- return Gen.Function(VCExpressionGenerator.SubIOp,
- Gen.Integer(BigNum.ZERO), RepresentPos(lit.Neg));
- else
- return RepresentPos(lit);
- }
-
- private VCExpr RepresentPos(BigNum lit) {
- Contract.Requires((lit > ConstantDistance));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- int index = GetIndexFor(lit);
- if (index >= 0)
- // precise match
- return Literals[index].Value;
-
- // check whether a constant is defined that is at most
- // ConstantDistance away from lit
- index = ~index;
- VCExpr res = null;
- BigNum resDistance = ConstantDistancePO;
-
- if (index > 0) {
- BigNum dist = lit - Literals[index - 1].Key;
- if (dist < resDistance) {
- resDistance = dist;
- res = Gen.Function(VCExpressionGenerator.AddIOp,
- Literals[index - 1].Value, Gen.Integer(dist));
- }
- }
-
- if (index < Literals.Count) {
- BigNum dist = Literals[index].Key - lit;
- if (dist < resDistance) {
- resDistance = dist;
- res = Gen.Function(VCExpressionGenerator.SubIOp,
- Literals[index].Value, Gen.Integer(dist));
- }
- }
-
- if (res != null)
- return res;
-
- // otherwise, define a new constant to represent this literal
- return AddConstantFor(lit);
- }
-
- private VCExpr AddConstantFor(BigNum lit) {
- Contract.Requires((lit > ConstantDistance));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExprVar res = Gen.Variable("int#" + lit, Type.Int);
- int index = GetIndexFor(lit);
- Contract.Assert(index < 0);
- index = ~index;
-
- Literals.Insert(index, new KeyValuePair<BigNum, VCExprVar>(lit, res));
-
- // relate the new constant to the predecessor and successor
- if (index > 0)
- DefineRelationship(Literals[index - 1].Value, Literals[index - 1].Key,
- res, lit);
- else
- DefineRelationship(Gen.Integer(BigNum.ZERO), BigNum.ZERO, res, lit);
-
- if (index < Literals.Count - 1)
- DefineRelationship(res, lit,
- Literals[index + 1].Value, Literals[index + 1].Key);
-
- return res;
- }
-
- private void DefineRelationship(VCExpr/*!*/ aExpr, BigNum aValue,
- VCExpr/*!*/ bExpr, BigNum bValue) {
- Contract.Requires(aValue < bValue);
- Contract.Requires(aExpr != null);
- Contract.Requires(bExpr != null);
-
- BigNum dist = bValue - aValue;
- VCExpr distExpr = Gen.Function(VCExpressionGenerator.SubIOp, bExpr, aExpr);
- if (dist <= ConstantDistanceTPO)
- // constants that are sufficiently close to each other are put
- // into a precise relationship
- AddAxiom(Gen.Eq(distExpr, Gen.Integer(dist)));
- else
- AddAxiom(Gen.Function(VCExpressionGenerator.GtOp,
- distExpr, Gen.Integer(ConstantDistanceTPO)));
- }
-
- private int GetIndexFor(BigNum lit) {
- return Literals.BinarySearch(new KeyValuePair<BigNum, VCExprVar>
- (lit, DummyVar),
- EntryComparer);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override VCExpr Visit(VCExprLiteral node, bool arg) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExprIntLit intLit = node as VCExprIntLit;
- if (intLit != null) {
- if (NegConstantDistance > intLit.Val || intLit.Val > ConstantDistance)
- return Represent(intLit.Val);
- }
- return node;
- }
-
- }
-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+
+// Code for replacing large integer literals in VCExpr with
+// constants. This is necessary for Simplify, which cannot deal with
+// literals larger than 32 bits
+
+namespace Microsoft.Boogie.VCExprAST {
+
+ public class BigLiteralAbstracter : MutatingVCExprVisitor<bool>, ICloneable {
+
+ public BigLiteralAbstracter(VCExpressionGenerator gen)
+ : base(gen) {
+ Contract.Requires(gen != null);
+ DummyVar = gen.Variable("x", Type.Int);
+ IncAxioms = new List<VCExpr>();
+ Literals = new List<KeyValuePair<BigNum, VCExprVar>>();
+ }
+
+ private BigLiteralAbstracter(BigLiteralAbstracter abstracter)
+ : base(abstracter.Gen) {
+ Contract.Requires(abstracter != null);
+ DummyVar = abstracter.DummyVar;
+ IncAxioms = new List<VCExpr>(abstracter.IncAxioms);
+ Literals = new List<KeyValuePair<BigNum, VCExprVar>>(abstracter.Literals);
+ }
+
+ public Object Clone() {
+ Contract.Ensures(Contract.Result<Object>() != null);
+
+ return new BigLiteralAbstracter(this);
+ }
+
+ private static readonly BigNum ConstantDistance = BigNum.FromLong(100000);
+ private static readonly BigNum NegConstantDistance = BigNum.FromLong(-100000);
+ // distance twice plus one
+ private static readonly BigNum ConstantDistanceTPO = BigNum.FromLong(200001);
+ private static readonly BigNum ConstantDistancePO = BigNum.FromLong(100001);
+
+ public VCExpr Abstract(VCExpr expr) {
+ Contract.Requires(expr != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return Mutate(expr, true);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // list in which axioms are incrementally collected
+ private readonly List<VCExpr/*!*/>/*!*/ IncAxioms;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(IncAxioms));
+ }
+
+ private void AddAxiom(VCExpr/*!*/ axiom) {
+ Contract.Requires(axiom != null);
+ IncAxioms.Add(axiom);
+ }
+
+ // Return all axioms that were added since the last time NewAxioms
+ // was called
+ public VCExpr GetNewAxioms() {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr res = Gen.NAry(VCExpressionGenerator.AndOp, IncAxioms);
+ IncAxioms.Clear();
+ return res;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // All named integer literals known to the visitor, in ascending
+ // order. Such literals are always positive, and the distance
+ // between two literals is always more than ConstantDistance.
+ private readonly List<KeyValuePair<BigNum, VCExprVar/*!*/>>/*!*/ Literals;
+
+ [ContractInvariantMethod]
+ void ObjectInvariat() {
+ Contract.Invariant(Literals != null);
+ Contract.Invariant(Contract.ForAll(Literals, i => i.Value != null));
+ }
+
+
+ private class EntryComparerC : IComparer<KeyValuePair<BigNum, VCExprVar/*!*/>> {
+ public int Compare(KeyValuePair<BigNum, VCExprVar/*!*/> a,
+ KeyValuePair<BigNum, VCExprVar/*!*/> b) {
+ //Contract.Requires(a.Value!=null);
+ //Contract.Requires(b.Value!=null);
+ return a.Key.CompareTo(b.Key);
+ }
+ }
+
+ private static readonly EntryComparerC EntryComparer = new EntryComparerC();
+
+ // variable used when searching for entries in the literal list
+ private readonly VCExprVar/*!*/ DummyVar;
+ [ContractInvariantMethod]
+ void ObjectInvarint() {
+ Contract.Invariant(DummyVar != null);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Construct an expression to represent the given (large) integer
+ // literal. Constants are defined and axiomatised if necessary
+ private VCExpr Represent(BigNum lit) {
+ Contract.Requires((NegConstantDistance > lit || lit > ConstantDistance));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ if (lit.IsNegative)
+ return Gen.Function(VCExpressionGenerator.SubIOp,
+ Gen.Integer(BigNum.ZERO), RepresentPos(lit.Neg));
+ else
+ return RepresentPos(lit);
+ }
+
+ private VCExpr RepresentPos(BigNum lit) {
+ Contract.Requires((lit > ConstantDistance));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ int index = GetIndexFor(lit);
+ if (index >= 0)
+ // precise match
+ return Literals[index].Value;
+
+ // check whether a constant is defined that is at most
+ // ConstantDistance away from lit
+ index = ~index;
+ VCExpr res = null;
+ BigNum resDistance = ConstantDistancePO;
+
+ if (index > 0) {
+ BigNum dist = lit - Literals[index - 1].Key;
+ if (dist < resDistance) {
+ resDistance = dist;
+ res = Gen.Function(VCExpressionGenerator.AddIOp,
+ Literals[index - 1].Value, Gen.Integer(dist));
+ }
+ }
+
+ if (index < Literals.Count) {
+ BigNum dist = Literals[index].Key - lit;
+ if (dist < resDistance) {
+ resDistance = dist;
+ res = Gen.Function(VCExpressionGenerator.SubIOp,
+ Literals[index].Value, Gen.Integer(dist));
+ }
+ }
+
+ if (res != null)
+ return res;
+
+ // otherwise, define a new constant to represent this literal
+ return AddConstantFor(lit);
+ }
+
+ private VCExpr AddConstantFor(BigNum lit) {
+ Contract.Requires((lit > ConstantDistance));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExprVar res = Gen.Variable("int#" + lit, Type.Int);
+ int index = GetIndexFor(lit);
+ Contract.Assert(index < 0);
+ index = ~index;
+
+ Literals.Insert(index, new KeyValuePair<BigNum, VCExprVar>(lit, res));
+
+ // relate the new constant to the predecessor and successor
+ if (index > 0)
+ DefineRelationship(Literals[index - 1].Value, Literals[index - 1].Key,
+ res, lit);
+ else
+ DefineRelationship(Gen.Integer(BigNum.ZERO), BigNum.ZERO, res, lit);
+
+ if (index < Literals.Count - 1)
+ DefineRelationship(res, lit,
+ Literals[index + 1].Value, Literals[index + 1].Key);
+
+ return res;
+ }
+
+ private void DefineRelationship(VCExpr/*!*/ aExpr, BigNum aValue,
+ VCExpr/*!*/ bExpr, BigNum bValue) {
+ Contract.Requires(aValue < bValue);
+ Contract.Requires(aExpr != null);
+ Contract.Requires(bExpr != null);
+
+ BigNum dist = bValue - aValue;
+ VCExpr distExpr = Gen.Function(VCExpressionGenerator.SubIOp, bExpr, aExpr);
+ if (dist <= ConstantDistanceTPO)
+ // constants that are sufficiently close to each other are put
+ // into a precise relationship
+ AddAxiom(Gen.Eq(distExpr, Gen.Integer(dist)));
+ else
+ AddAxiom(Gen.Function(VCExpressionGenerator.GtOp,
+ distExpr, Gen.Integer(ConstantDistanceTPO)));
+ }
+
+ private int GetIndexFor(BigNum lit) {
+ return Literals.BinarySearch(new KeyValuePair<BigNum, VCExprVar>
+ (lit, DummyVar),
+ EntryComparer);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr Visit(VCExprLiteral node, bool arg) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExprIntLit intLit = node as VCExprIntLit;
+ if (intLit != null) {
+ if (NegConstantDistance > intLit.Val || intLit.Val > ConstantDistance)
+ return Represent(intLit.Val);
+ }
+ return node;
+ }
+
+ }
+
} \ No newline at end of file
diff --git a/Source/VCExpr/Boogie2VCExpr.cs b/Source/VCExpr/Boogie2VCExpr.cs
index 8674f8c0..0c817756 100644
--- a/Source/VCExpr/Boogie2VCExpr.cs
+++ b/Source/VCExpr/Boogie2VCExpr.cs
@@ -1,1209 +1,1209 @@
-//-----------------------------------------------------------------------------
-//
-// 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 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 {
- return Gen.Function(VCExpressionGenerator.SubROp, Gen.Real(BigDec.ZERO), 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);
-
- switch (app.Op) {
- case BinaryOperator.Opcode.Add:
- if (cce.NonNull(cce.NonNull(args[0]).Type).IsInt) {
- return Gen.Function(VCExpressionGenerator.AddIOp, args);
- }
- else {
- return Gen.Function(VCExpressionGenerator.AddROp, args);
- }
- case BinaryOperator.Opcode.Sub:
- if (cce.NonNull(cce.NonNull(args[0]).Type).IsInt) {
- return Gen.Function(VCExpressionGenerator.SubIOp, args);
- }
- else {
- return Gen.Function(VCExpressionGenerator.SubROp, args);
- }
- case BinaryOperator.Opcode.Mul:
- if (cce.NonNull(cce.NonNull(args[0]).Type).IsInt) {
- return Gen.Function(VCExpressionGenerator.MulIOp, args);
- }
- else {
- return Gen.Function(VCExpressionGenerator.MulROp, 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:
- 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
- return Gen.Function(VCExpressionGenerator.EqOp, args);
- case BinaryOperator.Opcode.Neq:
- return Gen.Function(VCExpressionGenerator.NeqOp, args);
- case BinaryOperator.Opcode.Lt:
- return Gen.Function(VCExpressionGenerator.LtOp, args);
- case BinaryOperator.Opcode.Le:
- return Gen.Function(VCExpressionGenerator.LeOp, args);
- case BinaryOperator.Opcode.Ge:
- return Gen.Function(VCExpressionGenerator.GeOp, args);
- case BinaryOperator.Opcode.Gt:
- 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 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 {
+ return Gen.Function(VCExpressionGenerator.SubROp, Gen.Real(BigDec.ZERO), 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);
+
+ switch (app.Op) {
+ case BinaryOperator.Opcode.Add:
+ if (cce.NonNull(cce.NonNull(args[0]).Type).IsInt) {
+ return Gen.Function(VCExpressionGenerator.AddIOp, args);
+ }
+ else {
+ return Gen.Function(VCExpressionGenerator.AddROp, args);
+ }
+ case BinaryOperator.Opcode.Sub:
+ if (cce.NonNull(cce.NonNull(args[0]).Type).IsInt) {
+ return Gen.Function(VCExpressionGenerator.SubIOp, args);
+ }
+ else {
+ return Gen.Function(VCExpressionGenerator.SubROp, args);
+ }
+ case BinaryOperator.Opcode.Mul:
+ if (cce.NonNull(cce.NonNull(args[0]).Type).IsInt) {
+ return Gen.Function(VCExpressionGenerator.MulIOp, args);
+ }
+ else {
+ return Gen.Function(VCExpressionGenerator.MulROp, 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:
+ 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
+ return Gen.Function(VCExpressionGenerator.EqOp, args);
+ case BinaryOperator.Opcode.Neq:
+ return Gen.Function(VCExpressionGenerator.NeqOp, args);
+ case BinaryOperator.Opcode.Lt:
+ return Gen.Function(VCExpressionGenerator.LtOp, args);
+ case BinaryOperator.Opcode.Le:
+ return Gen.Function(VCExpressionGenerator.LeOp, args);
+ case BinaryOperator.Opcode.Ge:
+ return Gen.Function(VCExpressionGenerator.GeOp, args);
+ case BinaryOperator.Opcode.Gt:
+ 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);
+ }
+ }
+ }
+}
diff --git a/Source/VCExpr/Clustering.cs b/Source/VCExpr/Clustering.cs
index 1ab10107..a799aaae 100644
--- a/Source/VCExpr/Clustering.cs
+++ b/Source/VCExpr/Clustering.cs
@@ -1,522 +1,522 @@
-//-----------------------------------------------------------------------------
-//
-// 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;
-using Microsoft.Boogie.VCExprAST;
-
-// Code for managing and clusterings sets of terms; this is used to
-// compress the input given to the theorem prover
-
-namespace Microsoft.Boogie.Clustering {
- using Microsoft.Boogie.VCExprAST;
-
-
- public class SubtermCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
-
- private readonly VCExpressionGenerator/*!*/ Gen;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Gen != null);
- Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalVariables));
- Contract.Invariant(cce.NonNullDictionaryAndValues(SubtermClusters));
- }
-
-
- public SubtermCollector(VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Gen = gen;
- }
-
- // variables that are global and treated like constants
- private readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/> GlobalVariables = new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>();
-
- private readonly IDictionary<VCExprOp/*!*/, TermClustersSameHead/*!*/> SubtermClusters =
- new Dictionary<VCExprOp/*!*/, TermClustersSameHead/*!*/>();
-
- public void UnifyClusters() {
- foreach (KeyValuePair<VCExprOp/*!*/, TermClustersSameHead/*!*/> pair
- in SubtermClusters) {
- Contract.Assert(cce.NonNullElements(pair));
- pair.Value.UnifyClusters();
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- protected override bool StandardResult(VCExpr node, bool arg) {
- //Contract.Requires(node != null);
- return false; // by default, do not collect terms containing node
- }
-
- public override bool Visit(VCExprLiteral node, bool arg) {
- Contract.Requires(node != null);
- return true;
- }
-
- public override bool Visit(VCExprNAry node, bool arg) {
- Contract.Requires(node != null);
- VCExprBoogieFunctionOp op = node.Op as VCExprBoogieFunctionOp;
- if (op == null) {
- base.Visit(node, arg);
- return false;
- }
-
- bool res = true;
- foreach (VCExpr subexpr in node) {
- Contract.Assert(subexpr != null);
- res &= this.Traverse(subexpr, arg);
- }
-
- if (res) {
- TermClustersSameHead clusters;
- if (!SubtermClusters.TryGetValue(op, out clusters)) {
- clusters = new TermClustersSameHead(op, GlobalVariables, Gen);
- SubtermClusters.Add(op, clusters);
- }
- cce.NonNull(clusters).AddExpr(node);
- }
-
- return res;
- }
-
- public override bool Visit(VCExprVar node, bool arg) {
- Contract.Requires(node != null);
- if (!BoundTermVars.Contains(node))
- GlobalVariables[node] = node;
- return true;
- }
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- string/*!*/ res = "";
- foreach (KeyValuePair<VCExprOp/*!*/, TermClustersSameHead/*!*/> pair
- in SubtermClusters) {
- Contract.Assert(cce.NonNullElements(pair));
- res = res + pair.Value + "\n";
- }
- return res;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- // Class for managing and clustering a set of terms that all start
- // with the same function symbol
- internal class TermClustersSameHead {
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Op != null);
- Contract.Invariant(Gen != null);
- Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalVariables));
- }
- // variables that are global and treated like constants
- private readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ GlobalVariables;
- public readonly VCExprOp/*!*/ Op;
- private readonly VCExpressionGenerator/*!*/ Gen;
-
- public TermClustersSameHead(VCExprOp op, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars, VCExpressionGenerator/*!*/ gen) {
- Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
- Contract.Requires(gen != null);
- Contract.Requires(op != null);
- Op = op;
- GlobalVariables = globalVars;
- Gen = gen;
- }
-
- private readonly List<Cluster>/*!*/ Clusters = new List<Cluster>();
-
- private struct Cluster {
- public readonly VCExprNAry/*!*/ Generator;
- public readonly int Size;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Generator != null);
- }
-
- public Cluster(VCExprNAry generator, int size) {
- Contract.Requires(generator != null);
- Generator = generator;
- Size = size;
- }
- }
-
- private int Distance(Cluster a, Cluster b) {
- AntiUnificationVisitor/*!*/ visitor = new AntiUnificationVisitor(Gen);
- visitor.AntiUnify(a.Generator, b.Generator);
-
- int reprSizeA, reprSizeB;
- visitor.RepresentationSize(GlobalVariables, out reprSizeA, out reprSizeB);
- return (a.Size - 1) * reprSizeA + (b.Size - 1) * reprSizeB;
- }
-
- private bool EqualUpToRenaming(Cluster a, Cluster b) {
- AntiUnificationVisitor/*!*/ visitor = new AntiUnificationVisitor(Gen);
- visitor.AntiUnify(a.Generator, b.Generator);
- return visitor.RepresentationIsRenaming(GlobalVariables);
- }
-
- private Cluster Merge(Cluster a, Cluster b) {
- AntiUnificationVisitor/*!*/ visitor = new AntiUnificationVisitor(Gen);
- VCExpr/*!*/ generator = visitor.AntiUnify(a.Generator, b.Generator);
- Contract.Assert(generator != null);
- VCExprNAry generatorNAry = generator as VCExprNAry;
- Contract.Assert(generatorNAry != null && Op.Equals(generatorNAry.Op));
- return new Cluster(generatorNAry, a.Size + b.Size);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public void AddExpr(VCExprNAry expr) {
- Contract.Requires(expr != null);
- Contract.Requires(Op.Equals(expr.Op));
-
- Cluster c = new Cluster(expr, 1);
- for (int i = 0; i < Clusters.Count; ++i) {
- Cluster d = Clusters[i];
- if (EqualUpToRenaming(c, d)) {
- Clusters[i] = new Cluster(d.Generator, d.Size + 1);
- return;
- }
- }
-
- Clusters.Add(c);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- private struct ClusteringMatrix {
-
- private readonly VCExpressionGenerator/*!*/ Gen;
- private readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ GlobalVariables;
-
- public readonly List<Cluster>/*!*/ Clusters;
- public readonly bool[]/*!*/ RemainingClusters;
-
- public readonly Distance[,]/*!*/ Distances;
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Gen != null);
- Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalVariables));
- Contract.Invariant(Clusters != null);
- Contract.Invariant(RemainingClusters != null);
- Contract.Invariant(Distances != null);
- }
-
-
- public struct Distance {
- public readonly int Dist;
- public readonly VCExprNAry/*!*/ Generator;
-
- public Distance(Cluster a, Cluster b, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars, VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
- AntiUnificationVisitor/*!*/ visitor = new AntiUnificationVisitor(gen);
- Generator = (VCExprNAry)visitor.AntiUnify(a.Generator, b.Generator);
-
- int reprSizeA, reprSizeB;
- visitor.RepresentationSize(globalVars, out reprSizeA, out reprSizeB);
- Dist = (a.Size - 1) * reprSizeA + (b.Size - 1) * reprSizeB;
- }
- }
-
- public ClusteringMatrix(List<Cluster> clusters, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars, VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Contract.Requires(clusters != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
- List<Cluster> c = new List<Cluster>();
- c.AddRange(clusters);
- Clusters = c;
-
- GlobalVariables = globalVars;
- Gen = gen;
-
- bool[] remaining = new bool[clusters.Count];
- RemainingClusters = remaining;
- for (int i = 0; i < remaining.Length; ++i)
- remaining[i] = true;
-
- Distance[,]/*!*/ distances = new Distance[clusters.Count, clusters.Count];
- Distances = distances;
- for (int i = 1; i < clusters.Count; ++i)
- for (int j = 0; j < i; ++j)
- distances[i, j] =
- new Distance(clusters[i], clusters[j], GlobalVariables, Gen);
- }
-
- public void UnifyClusters(int maxDist) {
- while (true) {
- int i, j;
- int minDist = FindMinDistance(out i, out j);
-
- if (minDist > maxDist)
- return;
-
- MergeClusters(i, j);
- }
- }
-
- public void ResultingClusters(List<Cluster> clusters) {
- Contract.Requires(clusters != null);
- clusters.Clear();
- for (int i = 0; i < Clusters.Count; ++i)
- if (RemainingClusters[i])
- clusters.Add(Clusters[i]);
- }
-
- //////////////////////////////////////////////////////////////////////////
-
- private void Update(int i) {
- for (int j = 0; j < i; ++j) {
- if (RemainingClusters[j])
- Distances[i, j] =
- new Distance(Clusters[i], Clusters[j], GlobalVariables, Gen);
- }
- for (int j = i + 1; j < Clusters.Count; ++j) {
- if (RemainingClusters[j])
- Distances[j, i] =
- new Distance(Clusters[j], Clusters[i], GlobalVariables, Gen);
- }
- }
-
- private int FindMinDistance(out int c0, out int c1) {
- int minDist = int.MaxValue;
- c0 = -1;
- c1 = -1;
-
- for (int i = 0; i < Clusters.Count; ++i)
- if (RemainingClusters[i]) {
- for (int j = 0; j < i; ++j)
- if (RemainingClusters[j]) {
- if (Distances[i, j].Dist < minDist) {
- minDist = Distances[i, j].Dist;
- c0 = i;
- c1 = j;
- }
- }
- }
-
- Contract.Assert(c0 == -1 && c1 == -1 || c0 > c1 && c1 >= 0);
- return minDist;
- }
-
- private void MergeClusters(int i, int j) {
- Contract.Requires(j >= 0 && i > j && RemainingClusters[i] && RemainingClusters[j]);
- Clusters[i] = new Cluster(Distances[i, j].Generator,
- Clusters[i].Size + Clusters[j].Size);
- RemainingClusters[j] = false;
- Update(i);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public void UnifyClusters() {
- ClusteringMatrix matrix =
- new ClusteringMatrix(Clusters, GlobalVariables, Gen);
- matrix.UnifyClusters(50);
- matrix.ResultingClusters(Clusters);
- }
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- string/*!*/ res = "";
- foreach (Cluster c in Clusters)
- res = res + c.Generator + "\t" + c.Size + "\n";
- return res;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- internal class AntiUnificationVisitor : TraversingVCExprVisitor<VCExpr/*!*/, VCExpr/*!*/> {
-
- private readonly VCExpressionGenerator/*!*/ Gen;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Gen != null);
- Contract.Invariant(cce.NonNullDictionaryAndValues(Representation));
- }
-
-
- public AntiUnificationVisitor(VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Gen = gen;
- }
-
- // Sub-expressions in the first and second expression to be
- // anti-unified that are replaced with variables
- private readonly IDictionary<ExprPair, VCExprVar/*!*/>/*!*/ Representation =
- new Dictionary<ExprPair, VCExprVar/*!*/>();
-
-
-
- private struct ExprPair {
- public readonly VCExpr/*!*/ Expr0, Expr1;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Expr0 != null);
- Contract.Invariant(Expr1 != null);
- }
-
- public ExprPair(VCExpr expr0, VCExpr expr1) {
- Contract.Requires(expr1 != null);
- Contract.Requires(expr0 != null);
- Expr0 = expr0;
- Expr1 = expr1;
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (that is ExprPair) {
- ExprPair thatPair = (ExprPair)that;
- return this.Expr0.Equals(thatPair.Expr0) &&
- this.Expr1.Equals(thatPair.Expr1);
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Expr0.GetHashCode() + Expr1.GetHashCode() * 13;
- }
- }
-
- public void Reset() {
- Representation.Clear();
- }
-
- public bool RepresentationIsRenaming(IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars) {
- Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
- if (!Representation.Any(pair => pair.Key.Expr0 is VCExprVar && pair.Key.Expr1 is VCExprVar && !globalVars.ContainsKey(cce.NonNull((VCExprVar)pair.Key.Expr0)) && !globalVars.ContainsKey(cce.NonNull((VCExprVar/*!*/)pair.Key.Expr1))))
- return false;
- // check that all substituted variables are distinct
- // TODO: optimise
- return
- Representation.All(pair1 => Representation.All(pair2 => pair1.Value.Equals(pair2.Value) || !pair1.Key.Expr0.Equals(pair2.Key.Expr0) && !pair1.Key.Expr1.Equals(pair2.Key.Expr1)));
- }
-
- public void RepresentationSize(IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars, out int expr0Size, out int expr1Size) {
- Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
- ReprSizeComputingVisitor/*!*/ size0Visitor = new ReprSizeComputingVisitor();
- ReprSizeComputingVisitor/*!*/ size1Visitor = new ReprSizeComputingVisitor();
-
- foreach (KeyValuePair<ExprPair, VCExprVar/*!*/> pair in Representation) {
- Contract.Assert(pair.Value != null);
- size0Visitor.ComputeSize(pair.Key.Expr0, globalVars);
- size1Visitor.ComputeSize(pair.Key.Expr1, globalVars);
- }
-
- expr0Size = size0Visitor.Size;
- expr1Size = size1Visitor.Size;
- }
-
- public VCExpr AntiUnify(VCExpr s, VCExpr t) {
- Contract.Requires(t != null);
- Contract.Requires(s != null);
- Contract.Requires((s.Type.Equals(t.Type)));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Traverse(s, t);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- private VCExprVar AbstractWithVariable(VCExpr s, VCExpr t) {
- Contract.Requires(t != null);
- Contract.Requires(s != null);
- Contract.Requires((s.Type.Equals(t.Type)));
-Contract.Ensures(Contract.Result<VCExprVar>() != null);
-
- ExprPair pair = new ExprPair(s, t);
- VCExprVar repr;
- if (!Representation.TryGetValue(pair, out repr)) {
- repr = Gen.Variable("abs" + Representation.Count, s.Type);
- Representation.Add(pair, repr);
- }
- return cce.NonNull(repr);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override VCExpr Visit(VCExprLiteral node, VCExpr that) {
- Contract.Requires(that != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (node.Equals(that))
- return node;
- return AbstractWithVariable(node, that);
- }
-
- public override VCExpr Visit(VCExprNAry node, VCExpr that) {
- Contract.Requires(that != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExprNAry thatNAry = that as VCExprNAry;
- if (thatNAry != null && node.Op.Equals(thatNAry.Op)) {
- // type parameters should already have been eliminated at this
- // stage
- Contract.Assert(node.TypeParamArity == 0 && thatNAry.TypeParamArity == 0 && node.Arity == thatNAry.Arity);
-
- List<VCExpr/*!*/>/*!*/ unifiedArgs = new List<VCExpr/*!*/>();
- for (int i = 0; i < node.Arity; ++i)
- unifiedArgs.Add(Traverse(node[i], thatNAry[i]));
-
- return Gen.Function(node.Op, unifiedArgs);
- }
- return AbstractWithVariable(node, that);
- }
-
- public override VCExpr Visit(VCExprVar node, VCExpr that) {
- Contract.Requires(that != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (node.Equals(that))
- return node;
- return AbstractWithVariable(node, that);
- }
-
- protected override VCExpr StandardResult(VCExpr node, VCExpr that) {
- //Contract.Requires(that != null);
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- Contract.Assert(false);
- throw new cce.UnreachableException(); // not handled here
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- internal class ReprSizeComputingVisitor
- : TraversingVCExprVisitor<bool,
- // variables considered as global constants
- IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/> {
-
- public int Size = 0;
-
- public void ComputeSize(VCExpr expr, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars) {
- Contract.Requires(expr != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
- Traverse(expr, globalVars);
- }
-
- protected override bool StandardResult(VCExpr node, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars) {
- //Contract.Requires(node != null);
- //Contract.Requires(cce.NonNullElements(globalVars));
- VCExprVar nodeAsVar = node as VCExprVar;
- if (nodeAsVar == null || globalVars.ContainsKey(nodeAsVar))
- Size = Size + 1;
- return true;
- }
- }
+//-----------------------------------------------------------------------------
+//
+// 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;
+using Microsoft.Boogie.VCExprAST;
+
+// Code for managing and clusterings sets of terms; this is used to
+// compress the input given to the theorem prover
+
+namespace Microsoft.Boogie.Clustering {
+ using Microsoft.Boogie.VCExprAST;
+
+
+ public class SubtermCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
+
+ private readonly VCExpressionGenerator/*!*/ Gen;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Gen != null);
+ Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalVariables));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(SubtermClusters));
+ }
+
+
+ public SubtermCollector(VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ Gen = gen;
+ }
+
+ // variables that are global and treated like constants
+ private readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/> GlobalVariables = new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>();
+
+ private readonly IDictionary<VCExprOp/*!*/, TermClustersSameHead/*!*/> SubtermClusters =
+ new Dictionary<VCExprOp/*!*/, TermClustersSameHead/*!*/>();
+
+ public void UnifyClusters() {
+ foreach (KeyValuePair<VCExprOp/*!*/, TermClustersSameHead/*!*/> pair
+ in SubtermClusters) {
+ Contract.Assert(cce.NonNullElements(pair));
+ pair.Value.UnifyClusters();
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected override bool StandardResult(VCExpr node, bool arg) {
+ //Contract.Requires(node != null);
+ return false; // by default, do not collect terms containing node
+ }
+
+ public override bool Visit(VCExprLiteral node, bool arg) {
+ Contract.Requires(node != null);
+ return true;
+ }
+
+ public override bool Visit(VCExprNAry node, bool arg) {
+ Contract.Requires(node != null);
+ VCExprBoogieFunctionOp op = node.Op as VCExprBoogieFunctionOp;
+ if (op == null) {
+ base.Visit(node, arg);
+ return false;
+ }
+
+ bool res = true;
+ foreach (VCExpr subexpr in node) {
+ Contract.Assert(subexpr != null);
+ res &= this.Traverse(subexpr, arg);
+ }
+
+ if (res) {
+ TermClustersSameHead clusters;
+ if (!SubtermClusters.TryGetValue(op, out clusters)) {
+ clusters = new TermClustersSameHead(op, GlobalVariables, Gen);
+ SubtermClusters.Add(op, clusters);
+ }
+ cce.NonNull(clusters).AddExpr(node);
+ }
+
+ return res;
+ }
+
+ public override bool Visit(VCExprVar node, bool arg) {
+ Contract.Requires(node != null);
+ if (!BoundTermVars.Contains(node))
+ GlobalVariables[node] = node;
+ return true;
+ }
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ string/*!*/ res = "";
+ foreach (KeyValuePair<VCExprOp/*!*/, TermClustersSameHead/*!*/> pair
+ in SubtermClusters) {
+ Contract.Assert(cce.NonNullElements(pair));
+ res = res + pair.Value + "\n";
+ }
+ return res;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ // Class for managing and clustering a set of terms that all start
+ // with the same function symbol
+ internal class TermClustersSameHead {
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Op != null);
+ Contract.Invariant(Gen != null);
+ Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalVariables));
+ }
+ // variables that are global and treated like constants
+ private readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ GlobalVariables;
+ public readonly VCExprOp/*!*/ Op;
+ private readonly VCExpressionGenerator/*!*/ Gen;
+
+ public TermClustersSameHead(VCExprOp op, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars, VCExpressionGenerator/*!*/ gen) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
+ Contract.Requires(gen != null);
+ Contract.Requires(op != null);
+ Op = op;
+ GlobalVariables = globalVars;
+ Gen = gen;
+ }
+
+ private readonly List<Cluster>/*!*/ Clusters = new List<Cluster>();
+
+ private struct Cluster {
+ public readonly VCExprNAry/*!*/ Generator;
+ public readonly int Size;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Generator != null);
+ }
+
+ public Cluster(VCExprNAry generator, int size) {
+ Contract.Requires(generator != null);
+ Generator = generator;
+ Size = size;
+ }
+ }
+
+ private int Distance(Cluster a, Cluster b) {
+ AntiUnificationVisitor/*!*/ visitor = new AntiUnificationVisitor(Gen);
+ visitor.AntiUnify(a.Generator, b.Generator);
+
+ int reprSizeA, reprSizeB;
+ visitor.RepresentationSize(GlobalVariables, out reprSizeA, out reprSizeB);
+ return (a.Size - 1) * reprSizeA + (b.Size - 1) * reprSizeB;
+ }
+
+ private bool EqualUpToRenaming(Cluster a, Cluster b) {
+ AntiUnificationVisitor/*!*/ visitor = new AntiUnificationVisitor(Gen);
+ visitor.AntiUnify(a.Generator, b.Generator);
+ return visitor.RepresentationIsRenaming(GlobalVariables);
+ }
+
+ private Cluster Merge(Cluster a, Cluster b) {
+ AntiUnificationVisitor/*!*/ visitor = new AntiUnificationVisitor(Gen);
+ VCExpr/*!*/ generator = visitor.AntiUnify(a.Generator, b.Generator);
+ Contract.Assert(generator != null);
+ VCExprNAry generatorNAry = generator as VCExprNAry;
+ Contract.Assert(generatorNAry != null && Op.Equals(generatorNAry.Op));
+ return new Cluster(generatorNAry, a.Size + b.Size);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public void AddExpr(VCExprNAry expr) {
+ Contract.Requires(expr != null);
+ Contract.Requires(Op.Equals(expr.Op));
+
+ Cluster c = new Cluster(expr, 1);
+ for (int i = 0; i < Clusters.Count; ++i) {
+ Cluster d = Clusters[i];
+ if (EqualUpToRenaming(c, d)) {
+ Clusters[i] = new Cluster(d.Generator, d.Size + 1);
+ return;
+ }
+ }
+
+ Clusters.Add(c);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private struct ClusteringMatrix {
+
+ private readonly VCExpressionGenerator/*!*/ Gen;
+ private readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ GlobalVariables;
+
+ public readonly List<Cluster>/*!*/ Clusters;
+ public readonly bool[]/*!*/ RemainingClusters;
+
+ public readonly Distance[,]/*!*/ Distances;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Gen != null);
+ Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalVariables));
+ Contract.Invariant(Clusters != null);
+ Contract.Invariant(RemainingClusters != null);
+ Contract.Invariant(Distances != null);
+ }
+
+
+ public struct Distance {
+ public readonly int Dist;
+ public readonly VCExprNAry/*!*/ Generator;
+
+ public Distance(Cluster a, Cluster b, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars, VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
+ AntiUnificationVisitor/*!*/ visitor = new AntiUnificationVisitor(gen);
+ Generator = (VCExprNAry)visitor.AntiUnify(a.Generator, b.Generator);
+
+ int reprSizeA, reprSizeB;
+ visitor.RepresentationSize(globalVars, out reprSizeA, out reprSizeB);
+ Dist = (a.Size - 1) * reprSizeA + (b.Size - 1) * reprSizeB;
+ }
+ }
+
+ public ClusteringMatrix(List<Cluster> clusters, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars, VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(clusters != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
+ List<Cluster> c = new List<Cluster>();
+ c.AddRange(clusters);
+ Clusters = c;
+
+ GlobalVariables = globalVars;
+ Gen = gen;
+
+ bool[] remaining = new bool[clusters.Count];
+ RemainingClusters = remaining;
+ for (int i = 0; i < remaining.Length; ++i)
+ remaining[i] = true;
+
+ Distance[,]/*!*/ distances = new Distance[clusters.Count, clusters.Count];
+ Distances = distances;
+ for (int i = 1; i < clusters.Count; ++i)
+ for (int j = 0; j < i; ++j)
+ distances[i, j] =
+ new Distance(clusters[i], clusters[j], GlobalVariables, Gen);
+ }
+
+ public void UnifyClusters(int maxDist) {
+ while (true) {
+ int i, j;
+ int minDist = FindMinDistance(out i, out j);
+
+ if (minDist > maxDist)
+ return;
+
+ MergeClusters(i, j);
+ }
+ }
+
+ public void ResultingClusters(List<Cluster> clusters) {
+ Contract.Requires(clusters != null);
+ clusters.Clear();
+ for (int i = 0; i < Clusters.Count; ++i)
+ if (RemainingClusters[i])
+ clusters.Add(Clusters[i]);
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+
+ private void Update(int i) {
+ for (int j = 0; j < i; ++j) {
+ if (RemainingClusters[j])
+ Distances[i, j] =
+ new Distance(Clusters[i], Clusters[j], GlobalVariables, Gen);
+ }
+ for (int j = i + 1; j < Clusters.Count; ++j) {
+ if (RemainingClusters[j])
+ Distances[j, i] =
+ new Distance(Clusters[j], Clusters[i], GlobalVariables, Gen);
+ }
+ }
+
+ private int FindMinDistance(out int c0, out int c1) {
+ int minDist = int.MaxValue;
+ c0 = -1;
+ c1 = -1;
+
+ for (int i = 0; i < Clusters.Count; ++i)
+ if (RemainingClusters[i]) {
+ for (int j = 0; j < i; ++j)
+ if (RemainingClusters[j]) {
+ if (Distances[i, j].Dist < minDist) {
+ minDist = Distances[i, j].Dist;
+ c0 = i;
+ c1 = j;
+ }
+ }
+ }
+
+ Contract.Assert(c0 == -1 && c1 == -1 || c0 > c1 && c1 >= 0);
+ return minDist;
+ }
+
+ private void MergeClusters(int i, int j) {
+ Contract.Requires(j >= 0 && i > j && RemainingClusters[i] && RemainingClusters[j]);
+ Clusters[i] = new Cluster(Distances[i, j].Generator,
+ Clusters[i].Size + Clusters[j].Size);
+ RemainingClusters[j] = false;
+ Update(i);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public void UnifyClusters() {
+ ClusteringMatrix matrix =
+ new ClusteringMatrix(Clusters, GlobalVariables, Gen);
+ matrix.UnifyClusters(50);
+ matrix.ResultingClusters(Clusters);
+ }
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ string/*!*/ res = "";
+ foreach (Cluster c in Clusters)
+ res = res + c.Generator + "\t" + c.Size + "\n";
+ return res;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ internal class AntiUnificationVisitor : TraversingVCExprVisitor<VCExpr/*!*/, VCExpr/*!*/> {
+
+ private readonly VCExpressionGenerator/*!*/ Gen;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Gen != null);
+ Contract.Invariant(cce.NonNullDictionaryAndValues(Representation));
+ }
+
+
+ public AntiUnificationVisitor(VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ Gen = gen;
+ }
+
+ // Sub-expressions in the first and second expression to be
+ // anti-unified that are replaced with variables
+ private readonly IDictionary<ExprPair, VCExprVar/*!*/>/*!*/ Representation =
+ new Dictionary<ExprPair, VCExprVar/*!*/>();
+
+
+
+ private struct ExprPair {
+ public readonly VCExpr/*!*/ Expr0, Expr1;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Expr0 != null);
+ Contract.Invariant(Expr1 != null);
+ }
+
+ public ExprPair(VCExpr expr0, VCExpr expr1) {
+ Contract.Requires(expr1 != null);
+ Contract.Requires(expr0 != null);
+ Expr0 = expr0;
+ Expr1 = expr1;
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (that is ExprPair) {
+ ExprPair thatPair = (ExprPair)that;
+ return this.Expr0.Equals(thatPair.Expr0) &&
+ this.Expr1.Equals(thatPair.Expr1);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Expr0.GetHashCode() + Expr1.GetHashCode() * 13;
+ }
+ }
+
+ public void Reset() {
+ Representation.Clear();
+ }
+
+ public bool RepresentationIsRenaming(IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
+ if (!Representation.Any(pair => pair.Key.Expr0 is VCExprVar && pair.Key.Expr1 is VCExprVar && !globalVars.ContainsKey(cce.NonNull((VCExprVar)pair.Key.Expr0)) && !globalVars.ContainsKey(cce.NonNull((VCExprVar/*!*/)pair.Key.Expr1))))
+ return false;
+ // check that all substituted variables are distinct
+ // TODO: optimise
+ return
+ Representation.All(pair1 => Representation.All(pair2 => pair1.Value.Equals(pair2.Value) || !pair1.Key.Expr0.Equals(pair2.Key.Expr0) && !pair1.Key.Expr1.Equals(pair2.Key.Expr1)));
+ }
+
+ public void RepresentationSize(IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars, out int expr0Size, out int expr1Size) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
+ ReprSizeComputingVisitor/*!*/ size0Visitor = new ReprSizeComputingVisitor();
+ ReprSizeComputingVisitor/*!*/ size1Visitor = new ReprSizeComputingVisitor();
+
+ foreach (KeyValuePair<ExprPair, VCExprVar/*!*/> pair in Representation) {
+ Contract.Assert(pair.Value != null);
+ size0Visitor.ComputeSize(pair.Key.Expr0, globalVars);
+ size1Visitor.ComputeSize(pair.Key.Expr1, globalVars);
+ }
+
+ expr0Size = size0Visitor.Size;
+ expr1Size = size1Visitor.Size;
+ }
+
+ public VCExpr AntiUnify(VCExpr s, VCExpr t) {
+ Contract.Requires(t != null);
+ Contract.Requires(s != null);
+ Contract.Requires((s.Type.Equals(t.Type)));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Traverse(s, t);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private VCExprVar AbstractWithVariable(VCExpr s, VCExpr t) {
+ Contract.Requires(t != null);
+ Contract.Requires(s != null);
+ Contract.Requires((s.Type.Equals(t.Type)));
+Contract.Ensures(Contract.Result<VCExprVar>() != null);
+
+ ExprPair pair = new ExprPair(s, t);
+ VCExprVar repr;
+ if (!Representation.TryGetValue(pair, out repr)) {
+ repr = Gen.Variable("abs" + Representation.Count, s.Type);
+ Representation.Add(pair, repr);
+ }
+ return cce.NonNull(repr);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr Visit(VCExprLiteral node, VCExpr that) {
+ Contract.Requires(that != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (node.Equals(that))
+ return node;
+ return AbstractWithVariable(node, that);
+ }
+
+ public override VCExpr Visit(VCExprNAry node, VCExpr that) {
+ Contract.Requires(that != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExprNAry thatNAry = that as VCExprNAry;
+ if (thatNAry != null && node.Op.Equals(thatNAry.Op)) {
+ // type parameters should already have been eliminated at this
+ // stage
+ Contract.Assert(node.TypeParamArity == 0 && thatNAry.TypeParamArity == 0 && node.Arity == thatNAry.Arity);
+
+ List<VCExpr/*!*/>/*!*/ unifiedArgs = new List<VCExpr/*!*/>();
+ for (int i = 0; i < node.Arity; ++i)
+ unifiedArgs.Add(Traverse(node[i], thatNAry[i]));
+
+ return Gen.Function(node.Op, unifiedArgs);
+ }
+ return AbstractWithVariable(node, that);
+ }
+
+ public override VCExpr Visit(VCExprVar node, VCExpr that) {
+ Contract.Requires(that != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (node.Equals(that))
+ return node;
+ return AbstractWithVariable(node, that);
+ }
+
+ protected override VCExpr StandardResult(VCExpr node, VCExpr that) {
+ //Contract.Requires(that != null);
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException(); // not handled here
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ internal class ReprSizeComputingVisitor
+ : TraversingVCExprVisitor<bool,
+ // variables considered as global constants
+ IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/> {
+
+ public int Size = 0;
+
+ public void ComputeSize(VCExpr expr, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars) {
+ Contract.Requires(expr != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(globalVars));
+ Traverse(expr, globalVars);
+ }
+
+ protected override bool StandardResult(VCExpr node, IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ globalVars) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(cce.NonNullElements(globalVars));
+ VCExprVar nodeAsVar = node as VCExprVar;
+ if (nodeAsVar == null || globalVars.ContainsKey(nodeAsVar))
+ Size = Size + 1;
+ return true;
+ }
+ }
} \ No newline at end of file
diff --git a/Source/VCExpr/LetBindingSorter.cs b/Source/VCExpr/LetBindingSorter.cs
index 474770d0..2bf28fbb 100644
--- a/Source/VCExpr/LetBindingSorter.cs
+++ b/Source/VCExpr/LetBindingSorter.cs
@@ -1,161 +1,161 @@
-//-----------------------------------------------------------------------------
-//
-// 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;
-
-// Sort the bindings in a let-expression so that terms bound earlier do
-// not contain variables bound later
-
-namespace Microsoft.Boogie.VCExprAST {
-
- // (argument is not used)
- public class LetBindingSorter : MutatingVCExprVisitor<bool> {
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(FreeVarCollector != null);
- }
-
- private readonly FreeVariableCollector/*!*/ FreeVarCollector =
- new FreeVariableCollector();
-
- private List<VCExprVar/*!*/>/*!*/ FreeVarsIn(VCExpr expr) {
- Contract.Requires(expr != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
- FreeVarCollector.Collect(expr);
- List<VCExprVar/*!*/>/*!*/ freeVars = new List<VCExprVar/*!*/>(FreeVarCollector.FreeTermVars.Keys);
- FreeVarCollector.Reset();
- return freeVars;
- }
-
- public LetBindingSorter(VCExpressionGenerator gen):base(gen) {
- Contract.Requires(gen != null);
-
- }
-
- public override VCExpr Visit(VCExprLet node, bool arg){
-Contract.Requires(node != null);
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- IDictionary<VCExprVar/*!*/, Binding/*!*/> boundVars =
- new Dictionary<VCExprVar/*!*/, Binding/*!*/> ();
-
- // recurse and collect the free variables in bound terms and formulae
- foreach (VCExprLetBinding/*!*/ binding in node) {Contract.Assert(binding != null);
- VCExpr/*!*/ newE = Mutate(binding.E, arg);
- Binding/*!*/ b = new Binding (binding.V, newE, FreeVarsIn(newE));
- boundVars.Add(b.V, b);
- }
-
- // generate the occurrence edges
- foreach (KeyValuePair<VCExprVar/*!*/, Binding/*!*/> pair in boundVars) {Contract.Assert(cce.NonNullElements(pair));
- Binding/*!*/ b = pair.Value;
- Contract.Assert(b != null);
- foreach (VCExprVar/*!*/ v in b.FreeVars) {Contract.Assert(v != null);
- Binding b2;
- if (boundVars.TryGetValue(v, out b2)) {
- cce.NonNull(b2).Occurrences.Add(b);
- b.InvOccurrencesNum = b.InvOccurrencesNum + 1;
- }
- }
- }
-
- // topological sort
- Stack<Binding/*!*/> rootBindings = new Stack<Binding/*!*/> ();
- foreach (KeyValuePair<VCExprVar/*!*/, Binding/*!*/> pair in boundVars)
- {Contract.Assert(cce.NonNullElements(pair));
- if (pair.Value.InvOccurrencesNum == 0)
- rootBindings.Push(pair.Value);}
-
- List<Binding/*!*/>/*!*/ sortedBindings = new List<Binding/*!*/> ();
- while (rootBindings.Count > 0) {
- Binding/*!*/ b = rootBindings.Pop();
- Contract.Assert(b != null);
- sortedBindings.Add(b);
- foreach (Binding/*!*/ b2 in b.Occurrences) {
- Contract.Assert(b2 != null);
- b2.InvOccurrencesNum = b2.InvOccurrencesNum - 1;
- if (b2.InvOccurrencesNum == 0)
- rootBindings.Push(b2);
- }
- }
-
- if (boundVars.Any(pair=> pair.Value.InvOccurrencesNum > 0))
- System.Diagnostics.Debug.Fail("Cyclic let-bindings");
-
- Contract.Assert(node.Length == sortedBindings.Count);
-
- // check which of the bindings can be dropped
- VCExpr newBody = Mutate(node.Body, arg);
- Contract.Assert(newBody != null);
-
- IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ usedVars =
- new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/> ();
- foreach (VCExprVar/*!*/ v in FreeVarsIn(newBody)){Contract.Assert(v != null);
- if (!usedVars.ContainsKey(v))
- usedVars.Add(v, v);}
-
- for (int i = sortedBindings.Count - 1; i >= 0; --i) {
- if (usedVars.ContainsKey(sortedBindings[i].V)) {
- foreach (VCExprVar/*!*/ v in sortedBindings[i].FreeVars){
- Contract.Assert(v != null);
- if (!usedVars.ContainsKey(v))
- usedVars.Add(v, v);}
- } else {
- sortedBindings.RemoveAt(i);
- }
- }
-
- // assemble the resulting let-expression
- List<VCExprLetBinding/*!*/>/*!*/ newBindings = new List<VCExprLetBinding/*!*/>();
- foreach (Binding b in sortedBindings)
- newBindings.Add(Gen.LetBinding(b.V, b.E));
-
- return Gen.Let(newBindings, newBody);
- }
-
- private class Binding {
- public readonly VCExprVar/*!*/ V;
- public readonly VCExpr/*!*/ E;
- public readonly List<VCExprVar/*!*/>/*!*/ FreeVars;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(V != null);
- Contract.Invariant(E != null);
- Contract.Invariant(cce.NonNullElements(FreeVars));
- Contract.Invariant(Occurrences != null);
- }
-
-
- // list of all bound expression in which the variable V occurs
- // (outgoing edges)
- public readonly List<Binding>/*!*/ Occurrences;
-
- // number of variables that are bound in this let-expression
- // and that occur in FreeVars
- // (incoming edges)
- public int InvOccurrencesNum;
-
- public Binding(VCExprVar v, VCExpr e, List<VCExprVar/*!*/>/*!*/ freeVars) {
- Contract.Requires(e != null);
- Contract.Requires(v != null);
- Contract.Requires(cce.NonNullElements(freeVars));
- this.V = v;
- this.E = e;
- this.FreeVars = freeVars;
- this.Occurrences = new List<Binding>();
- this.InvOccurrencesNum = 0;
- }
- }
-
- }
-
-}
+//-----------------------------------------------------------------------------
+//
+// 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;
+
+// Sort the bindings in a let-expression so that terms bound earlier do
+// not contain variables bound later
+
+namespace Microsoft.Boogie.VCExprAST {
+
+ // (argument is not used)
+ public class LetBindingSorter : MutatingVCExprVisitor<bool> {
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(FreeVarCollector != null);
+ }
+
+ private readonly FreeVariableCollector/*!*/ FreeVarCollector =
+ new FreeVariableCollector();
+
+ private List<VCExprVar/*!*/>/*!*/ FreeVarsIn(VCExpr expr) {
+ Contract.Requires(expr != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+ FreeVarCollector.Collect(expr);
+ List<VCExprVar/*!*/>/*!*/ freeVars = new List<VCExprVar/*!*/>(FreeVarCollector.FreeTermVars.Keys);
+ FreeVarCollector.Reset();
+ return freeVars;
+ }
+
+ public LetBindingSorter(VCExpressionGenerator gen):base(gen) {
+ Contract.Requires(gen != null);
+
+ }
+
+ public override VCExpr Visit(VCExprLet node, bool arg){
+Contract.Requires(node != null);
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ IDictionary<VCExprVar/*!*/, Binding/*!*/> boundVars =
+ new Dictionary<VCExprVar/*!*/, Binding/*!*/> ();
+
+ // recurse and collect the free variables in bound terms and formulae
+ foreach (VCExprLetBinding/*!*/ binding in node) {Contract.Assert(binding != null);
+ VCExpr/*!*/ newE = Mutate(binding.E, arg);
+ Binding/*!*/ b = new Binding (binding.V, newE, FreeVarsIn(newE));
+ boundVars.Add(b.V, b);
+ }
+
+ // generate the occurrence edges
+ foreach (KeyValuePair<VCExprVar/*!*/, Binding/*!*/> pair in boundVars) {Contract.Assert(cce.NonNullElements(pair));
+ Binding/*!*/ b = pair.Value;
+ Contract.Assert(b != null);
+ foreach (VCExprVar/*!*/ v in b.FreeVars) {Contract.Assert(v != null);
+ Binding b2;
+ if (boundVars.TryGetValue(v, out b2)) {
+ cce.NonNull(b2).Occurrences.Add(b);
+ b.InvOccurrencesNum = b.InvOccurrencesNum + 1;
+ }
+ }
+ }
+
+ // topological sort
+ Stack<Binding/*!*/> rootBindings = new Stack<Binding/*!*/> ();
+ foreach (KeyValuePair<VCExprVar/*!*/, Binding/*!*/> pair in boundVars)
+ {Contract.Assert(cce.NonNullElements(pair));
+ if (pair.Value.InvOccurrencesNum == 0)
+ rootBindings.Push(pair.Value);}
+
+ List<Binding/*!*/>/*!*/ sortedBindings = new List<Binding/*!*/> ();
+ while (rootBindings.Count > 0) {
+ Binding/*!*/ b = rootBindings.Pop();
+ Contract.Assert(b != null);
+ sortedBindings.Add(b);
+ foreach (Binding/*!*/ b2 in b.Occurrences) {
+ Contract.Assert(b2 != null);
+ b2.InvOccurrencesNum = b2.InvOccurrencesNum - 1;
+ if (b2.InvOccurrencesNum == 0)
+ rootBindings.Push(b2);
+ }
+ }
+
+ if (boundVars.Any(pair=> pair.Value.InvOccurrencesNum > 0))
+ System.Diagnostics.Debug.Fail("Cyclic let-bindings");
+
+ Contract.Assert(node.Length == sortedBindings.Count);
+
+ // check which of the bindings can be dropped
+ VCExpr newBody = Mutate(node.Body, arg);
+ Contract.Assert(newBody != null);
+
+ IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ usedVars =
+ new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/> ();
+ foreach (VCExprVar/*!*/ v in FreeVarsIn(newBody)){Contract.Assert(v != null);
+ if (!usedVars.ContainsKey(v))
+ usedVars.Add(v, v);}
+
+ for (int i = sortedBindings.Count - 1; i >= 0; --i) {
+ if (usedVars.ContainsKey(sortedBindings[i].V)) {
+ foreach (VCExprVar/*!*/ v in sortedBindings[i].FreeVars){
+ Contract.Assert(v != null);
+ if (!usedVars.ContainsKey(v))
+ usedVars.Add(v, v);}
+ } else {
+ sortedBindings.RemoveAt(i);
+ }
+ }
+
+ // assemble the resulting let-expression
+ List<VCExprLetBinding/*!*/>/*!*/ newBindings = new List<VCExprLetBinding/*!*/>();
+ foreach (Binding b in sortedBindings)
+ newBindings.Add(Gen.LetBinding(b.V, b.E));
+
+ return Gen.Let(newBindings, newBody);
+ }
+
+ private class Binding {
+ public readonly VCExprVar/*!*/ V;
+ public readonly VCExpr/*!*/ E;
+ public readonly List<VCExprVar/*!*/>/*!*/ FreeVars;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(V != null);
+ Contract.Invariant(E != null);
+ Contract.Invariant(cce.NonNullElements(FreeVars));
+ Contract.Invariant(Occurrences != null);
+ }
+
+
+ // list of all bound expression in which the variable V occurs
+ // (outgoing edges)
+ public readonly List<Binding>/*!*/ Occurrences;
+
+ // number of variables that are bound in this let-expression
+ // and that occur in FreeVars
+ // (incoming edges)
+ public int InvOccurrencesNum;
+
+ public Binding(VCExprVar v, VCExpr e, List<VCExprVar/*!*/>/*!*/ freeVars) {
+ Contract.Requires(e != null);
+ Contract.Requires(v != null);
+ Contract.Requires(cce.NonNullElements(freeVars));
+ this.V = v;
+ this.E = e;
+ this.FreeVars = freeVars;
+ this.Occurrences = new List<Binding>();
+ this.InvOccurrencesNum = 0;
+ }
+ }
+
+ }
+
+}
diff --git a/Source/VCExpr/NameClashResolver.cs b/Source/VCExpr/NameClashResolver.cs
index a46105f8..0effb386 100644
--- a/Source/VCExpr/NameClashResolver.cs
+++ b/Source/VCExpr/NameClashResolver.cs
@@ -1,196 +1,196 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-
-// Visitor that establishes unique variable (or constant) names in a VCExpr.
-// This is done by adding a counter as suffix if name clashes occur
-
-// TODO: also handle type variables here
-
-namespace Microsoft.Boogie.VCExprAST {
- using TEHelperFuns = Microsoft.Boogie.TypeErasure.HelperFuns;
-
- public class UniqueNamer : ICloneable {
- public string Spacer = "@@";
-
- public UniqueNamer() {
- GlobalNames = new Dictionary<Object, string>();
- LocalNames = TEHelperFuns.ToList(new Dictionary<Object/*!*/, string/*!*/>()
- as IDictionary<Object/*!*/, string/*!*/>);
- UsedNames = new HashSet<string>();
- CurrentCounters = new Dictionary<string, int>();
- GlobalPlusLocalNames = new Dictionary<Object, string>();
- }
-
- private UniqueNamer(UniqueNamer namer) {
- Contract.Requires(namer != null);
-
- Spacer = namer.Spacer;
- GlobalNames = new Dictionary<Object, string>(namer.GlobalNames);
- LocalNames = new List<IDictionary<Object, string>>();
-
- foreach (IDictionary<Object/*!*/, string/*!*/>/*!*/ d in namer.LocalNames)
- LocalNames.Add(new Dictionary<Object/*!*/, string/*!*/>(d));
-
- UsedNames = new HashSet<string>(namer.UsedNames);
- CurrentCounters = new Dictionary<string, int>(namer.CurrentCounters);
- GlobalPlusLocalNames = new Dictionary<Object, string>(namer.GlobalPlusLocalNames);
- }
-
- public Object Clone() {
- Contract.Ensures(Contract.Result<Object>() != null);
- return new UniqueNamer(this);
- }
-
- public void Reset()
- {
- GlobalNames.Clear();
- LocalNames.Clear();
- LocalNames.Add(new Dictionary<Object/*!*/, string/*!*/>());
- UsedNames.Clear();
- CurrentCounters.Clear();
- GlobalPlusLocalNames.Clear();
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- private readonly IDictionary<Object/*!*/, string/*!*/>/*!*/ GlobalNames;
- [ContractInvariantMethod]
- void GlobalNamesInvariantMethod() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalNames));
- }
- private readonly List<IDictionary<Object/*!*/, string/*!*/>/*!*/>/*!*/ LocalNames;
- [ContractInvariantMethod]
- void LocalNamesInvariantMethod() {
- Contract.Invariant(Contract.ForAll(LocalNames, i => i != null && cce.NonNullDictionaryAndValues(i)));
- }
-
- // dictionary of all names that have already been used
- // (locally or globally)
- private readonly HashSet<string/*!*/>/*!*/ UsedNames;
- [ContractInvariantMethod]
- void UsedNamesInvariantMethod() {
- Contract.Invariant(cce.NonNull(UsedNames));
- }
- private readonly IDictionary<string/*!*/, int/*!*/>/*!*/ CurrentCounters;
- [ContractInvariantMethod]
- void CurrentCountersInvariantMethod() {
- Contract.Invariant(CurrentCounters != null);
- }
- private readonly IDictionary<Object/*!*/, string/*!*/>/*!*/ GlobalPlusLocalNames;
- [ContractInvariantMethod]
- void GlobalPlusLocalNamesInvariantMethod() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalPlusLocalNames));
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public void PushScope() {
- LocalNames.Add(new Dictionary<Object/*!*/, string/*!*/>());
- }
-
- public void PopScope() {
- LocalNames.RemoveAt(LocalNames.Count - 1);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- private string NextFreeName(Object thingie, string baseName) {
- Contract.Requires(baseName != null);
- Contract.Requires(thingie != null);
- Contract.Ensures(Contract.Result<string>() != null);
- string/*!*/ candidate;
- int counter;
-
- if (CurrentCounters.TryGetValue(baseName, out counter)) {
- candidate = baseName + Spacer + counter;
- counter = counter + 1;
- } else {
- candidate = baseName;
- counter = 0;
- }
-
- while (UsedNames.Contains(candidate)) {
- candidate = baseName + Spacer + counter;
- counter = counter + 1;
- }
-
- UsedNames.Add(candidate);
- CurrentCounters[baseName] = counter;
- GlobalPlusLocalNames[thingie] = candidate;
- return candidate;
- }
-
- // retrieve the name of a thingie; if it does not have a name yet,
- // generate a unique name for it (as close as possible to its inherent
- // name) and register it globally
- public string GetName(Object thingie, string inherentName) {
- Contract.Requires(inherentName != null);
- Contract.Requires(thingie != null);
- Contract.Ensures(Contract.Result<string>() != null);
- string res = this[thingie];
-
- if (res != null)
- return res;
-
- // if the object is not yet registered, create a name for it
- res = NextFreeName(thingie, inherentName);
- GlobalNames.Add(thingie, res);
-
- return res;
- }
-
- [Pure]
- public string this[Object/*!*/ thingie] {
- get {
- Contract.Requires(thingie != null);
-
- string res;
- for (int i = LocalNames.Count - 1; i >= 0; --i) {
- if (LocalNames[i].TryGetValue(thingie, out res))
- return res;
- }
-
- GlobalNames.TryGetValue(thingie, out res);
- return res;
- }
- }
-
- public string GetLocalName(Object thingie, string inherentName) {
- Contract.Requires(inherentName != null);
- Contract.Requires(thingie != null);
- Contract.Ensures(Contract.Result<string>() != null);
- string res = NextFreeName(thingie, inherentName);
- LocalNames[LocalNames.Count - 1][thingie] = res;
- return res;
- }
-
- public virtual string GetQuotedName(Object thingie, string inherentName)
- {
- return GetName(thingie, inherentName);
- }
-
- public virtual string GetQuotedLocalName(Object thingie, string inherentName)
- {
- return GetLocalName(thingie, inherentName);
- }
-
- public string Lookup(Object thingie) {
- Contract.Requires(thingie != null);
- Contract.Ensures(Contract.Result<string>() != null);
- string name;
- if (GlobalPlusLocalNames.TryGetValue(thingie, out name))
- return name;
- return Spacer + "undefined" + Spacer + thingie.GetHashCode() + Spacer;
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+
+// Visitor that establishes unique variable (or constant) names in a VCExpr.
+// This is done by adding a counter as suffix if name clashes occur
+
+// TODO: also handle type variables here
+
+namespace Microsoft.Boogie.VCExprAST {
+ using TEHelperFuns = Microsoft.Boogie.TypeErasure.HelperFuns;
+
+ public class UniqueNamer : ICloneable {
+ public string Spacer = "@@";
+
+ public UniqueNamer() {
+ GlobalNames = new Dictionary<Object, string>();
+ LocalNames = TEHelperFuns.ToList(new Dictionary<Object/*!*/, string/*!*/>()
+ as IDictionary<Object/*!*/, string/*!*/>);
+ UsedNames = new HashSet<string>();
+ CurrentCounters = new Dictionary<string, int>();
+ GlobalPlusLocalNames = new Dictionary<Object, string>();
+ }
+
+ private UniqueNamer(UniqueNamer namer) {
+ Contract.Requires(namer != null);
+
+ Spacer = namer.Spacer;
+ GlobalNames = new Dictionary<Object, string>(namer.GlobalNames);
+ LocalNames = new List<IDictionary<Object, string>>();
+
+ foreach (IDictionary<Object/*!*/, string/*!*/>/*!*/ d in namer.LocalNames)
+ LocalNames.Add(new Dictionary<Object/*!*/, string/*!*/>(d));
+
+ UsedNames = new HashSet<string>(namer.UsedNames);
+ CurrentCounters = new Dictionary<string, int>(namer.CurrentCounters);
+ GlobalPlusLocalNames = new Dictionary<Object, string>(namer.GlobalPlusLocalNames);
+ }
+
+ public Object Clone() {
+ Contract.Ensures(Contract.Result<Object>() != null);
+ return new UniqueNamer(this);
+ }
+
+ public void Reset()
+ {
+ GlobalNames.Clear();
+ LocalNames.Clear();
+ LocalNames.Add(new Dictionary<Object/*!*/, string/*!*/>());
+ UsedNames.Clear();
+ CurrentCounters.Clear();
+ GlobalPlusLocalNames.Clear();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private readonly IDictionary<Object/*!*/, string/*!*/>/*!*/ GlobalNames;
+ [ContractInvariantMethod]
+ void GlobalNamesInvariantMethod() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalNames));
+ }
+ private readonly List<IDictionary<Object/*!*/, string/*!*/>/*!*/>/*!*/ LocalNames;
+ [ContractInvariantMethod]
+ void LocalNamesInvariantMethod() {
+ Contract.Invariant(Contract.ForAll(LocalNames, i => i != null && cce.NonNullDictionaryAndValues(i)));
+ }
+
+ // dictionary of all names that have already been used
+ // (locally or globally)
+ private readonly HashSet<string/*!*/>/*!*/ UsedNames;
+ [ContractInvariantMethod]
+ void UsedNamesInvariantMethod() {
+ Contract.Invariant(cce.NonNull(UsedNames));
+ }
+ private readonly IDictionary<string/*!*/, int/*!*/>/*!*/ CurrentCounters;
+ [ContractInvariantMethod]
+ void CurrentCountersInvariantMethod() {
+ Contract.Invariant(CurrentCounters != null);
+ }
+ private readonly IDictionary<Object/*!*/, string/*!*/>/*!*/ GlobalPlusLocalNames;
+ [ContractInvariantMethod]
+ void GlobalPlusLocalNamesInvariantMethod() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(GlobalPlusLocalNames));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public void PushScope() {
+ LocalNames.Add(new Dictionary<Object/*!*/, string/*!*/>());
+ }
+
+ public void PopScope() {
+ LocalNames.RemoveAt(LocalNames.Count - 1);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private string NextFreeName(Object thingie, string baseName) {
+ Contract.Requires(baseName != null);
+ Contract.Requires(thingie != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ string/*!*/ candidate;
+ int counter;
+
+ if (CurrentCounters.TryGetValue(baseName, out counter)) {
+ candidate = baseName + Spacer + counter;
+ counter = counter + 1;
+ } else {
+ candidate = baseName;
+ counter = 0;
+ }
+
+ while (UsedNames.Contains(candidate)) {
+ candidate = baseName + Spacer + counter;
+ counter = counter + 1;
+ }
+
+ UsedNames.Add(candidate);
+ CurrentCounters[baseName] = counter;
+ GlobalPlusLocalNames[thingie] = candidate;
+ return candidate;
+ }
+
+ // retrieve the name of a thingie; if it does not have a name yet,
+ // generate a unique name for it (as close as possible to its inherent
+ // name) and register it globally
+ public string GetName(Object thingie, string inherentName) {
+ Contract.Requires(inherentName != null);
+ Contract.Requires(thingie != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ string res = this[thingie];
+
+ if (res != null)
+ return res;
+
+ // if the object is not yet registered, create a name for it
+ res = NextFreeName(thingie, inherentName);
+ GlobalNames.Add(thingie, res);
+
+ return res;
+ }
+
+ [Pure]
+ public string this[Object/*!*/ thingie] {
+ get {
+ Contract.Requires(thingie != null);
+
+ string res;
+ for (int i = LocalNames.Count - 1; i >= 0; --i) {
+ if (LocalNames[i].TryGetValue(thingie, out res))
+ return res;
+ }
+
+ GlobalNames.TryGetValue(thingie, out res);
+ return res;
+ }
+ }
+
+ public string GetLocalName(Object thingie, string inherentName) {
+ Contract.Requires(inherentName != null);
+ Contract.Requires(thingie != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ string res = NextFreeName(thingie, inherentName);
+ LocalNames[LocalNames.Count - 1][thingie] = res;
+ return res;
+ }
+
+ public virtual string GetQuotedName(Object thingie, string inherentName)
+ {
+ return GetName(thingie, inherentName);
+ }
+
+ public virtual string GetQuotedLocalName(Object thingie, string inherentName)
+ {
+ return GetLocalName(thingie, inherentName);
+ }
+
+ public string Lookup(Object thingie) {
+ Contract.Requires(thingie != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ string name;
+ if (GlobalPlusLocalNames.TryGetValue(thingie, out name))
+ return name;
+ return Spacer + "undefined" + Spacer + thingie.GetHashCode() + Spacer;
+ }
+ }
+}
diff --git a/Source/VCExpr/SimplifyLikeLineariser.cs b/Source/VCExpr/SimplifyLikeLineariser.cs
index e0a4b4c6..b554c331 100644
--- a/Source/VCExpr/SimplifyLikeLineariser.cs
+++ b/Source/VCExpr/SimplifyLikeLineariser.cs
@@ -1,1098 +1,1098 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-// a naive method to turn VCExprs into strings that can be fed into Simplify
-
-namespace Microsoft.Boogie.VCExprAST {
- [ContractClassFor(typeof(LineariserOptions))]
- public abstract class LinOptContracts : LineariserOptions {
- public LinOptContracts()
- : base(true) {
- }
- public override LineariserOptions SetAsTerm(bool newVal) {
- Contract.Ensures(Contract.Result<LineariserOptions>() != null);
- throw new NotImplementedException();
- }
-
- }
-
- // Options for the linearisation. Here one can choose, for instance,
- // whether Simplify or Z3 output is to be produced
- [ContractClass(typeof(LinOptContracts))]
- public abstract class LineariserOptions {
-
- public readonly bool AsTerm;
- public abstract LineariserOptions/*!*/ SetAsTerm(bool newVal);
-
- public abstract bool QuantifierIds {
- get;
- }
-
- public virtual bool UseWeights {
- get {
- return false;
- }
- }
-
- public virtual bool InverseImplies {
- get {
- return false;
- }
- }
-
- // whether to include type specifications in quantifiers
- public abstract bool UseTypes {
- get;
- }
-
- // variables representing formulas in let-bindings have to be
- // printed in a different way than other variables
- public virtual List<VCExprVar/*!*/>/*!*/ LetVariables {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
- return EmptyList;
- }
- }
-
- public virtual LineariserOptions AddLetVariable(VCExprVar furtherVar) {
- Contract.Requires(furtherVar != null);
- Contract.Ensures(Contract.Result<LineariserOptions>() != null);
- return this;
- }
-
- public virtual LineariserOptions AddLetVariables(List<VCExprVar/*!*/>/*!*/ furtherVars) {
- Contract.Requires(cce.NonNullElements(furtherVars));
- Contract.Ensures(Contract.Result<LineariserOptions>() != null);
- return this;
- }
-
- private static readonly List<VCExprVar/*!*/>/*!*/ EmptyList = new List<VCExprVar/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvarinat() {
- Contract.Invariant(EmptyList != null);
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////
-
- protected LineariserOptions(bool asTerm) {
- this.AsTerm = asTerm;
- }
-
- public static readonly LineariserOptions SimplifyDefault = new SimplifyOptions(false);
- internal static readonly LineariserOptions SimplifyDefaultTerm = new SimplifyOptions(true);
-
- ////////////////////////////////////////////////////////////////////////////////////////
-
- private class SimplifyOptions : LineariserOptions {
- internal SimplifyOptions(bool asTerm)
- : base(asTerm) {
-
- }
- public override bool QuantifierIds {
- get {
- return false;
- }
- }
- public override bool UseTypes {
- get {
- return false;
- }
- }
- public override LineariserOptions SetAsTerm(bool newVal) {
- Contract.Ensures(Contract.Result<LineariserOptions>() != null);
- if (newVal)
- return SimplifyDefaultTerm;
- else
- return SimplifyDefault;
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////
-
- // Lineariser for expressions. The result (bool) is currently not used for anything
- public class SimplifyLikeExprLineariser : IVCExprVisitor<bool, LineariserOptions/*!*/> {
-
- public static string ToSimplifyString(VCExpr e, UniqueNamer namer) {
- Contract.Requires(namer != null);
- Contract.Requires(e != null);
- Contract.Ensures(Contract.Result<string>() != null);
- return ToString(e, LineariserOptions.SimplifyDefault, namer);
- }
-
- public static string ToString(VCExpr/*!*/ e, LineariserOptions/*!*/ options, UniqueNamer/*!*/ namer) {
- Contract.Requires(e != null);
- Contract.Requires(options != null);
- Contract.Requires(namer != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- StringWriter sw = new StringWriter();
- SimplifyLikeExprLineariser lin = new SimplifyLikeExprLineariser(sw, namer);
- lin.Linearise(e, options);
- return sw.ToString();
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////
-
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(wr != null);
- Contract.Invariant(Namer != null);
- }
-
- private readonly TextWriter/*!*/ wr;
- private SimplifyLikeOpLineariser OpLinObject = null;
- private IVCExprOpVisitor<bool, LineariserOptions/*!*/>/*!*/ OpLineariser {
- get {
- Contract.Ensures(Contract.Result<IVCExprOpVisitor<bool, LineariserOptions>>() != null);
- if (OpLinObject == null)
- OpLinObject = new SimplifyLikeOpLineariser(this, wr);
- return OpLinObject;
- }
- }
-
- internal readonly UniqueNamer Namer;
-
- public SimplifyLikeExprLineariser(TextWriter wr, UniqueNamer namer) {
- Contract.Requires(namer != null);
- Contract.Requires(wr != null);
- this.wr = wr;
- this.Namer = namer;
- }
-
- public void Linearise(VCExpr expr, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(expr != null);
- expr.Accept<bool, LineariserOptions>(this, options);
- }
-
- public void LineariseAsTerm(VCExpr expr, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(expr != null);
- Linearise(expr, options.SetAsTerm(true));
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public static string MakeIdPrintable(string s) {
- Contract.Requires(s != null);
- Contract.Requires(s != "");
- Contract.Ensures(Contract.Result<string>() != null);
- // make sure that no keywords are used as identifiers
- switch (s) {
- case andName:
- case orName:
- case notName:
- case impliesName:
- case iffName:
- case eqName:
- case neqName:
- case distinctName:
- case TRUEName:
- case FALSEName:
- s = "nonkeyword_" + s;
- break;
- }
-
- if (CommandLineOptions.Clo.BracketIdsInVC == 0) {
- // In this form, we go with any identifier, so we don't ever bother about brackets.
- // Except: @true and @false are always written with brackets
- return s;
- }
- bool looksLikeOperator = true;
- bool looksLikeSimpleId = true;
- bool useBrackets = false;
- foreach (char ch in s) {
- switch (ch) {
- case '=':
- case '<':
- case '>':
- case '+':
- case '-':
- case '*':
- case '/':
- case '%':
- case ':':
- // looks like operator, not simple id
- looksLikeSimpleId = false;
- break;
- default:
- if (Char.IsLetterOrDigit(ch)) {
- // looks like simple id, not operator
- looksLikeOperator = false;
- } else {
- // looks like neither operator nor simple id
- looksLikeOperator = false;
- looksLikeSimpleId = false;
- }
- break;
- }
- if (!looksLikeOperator && !looksLikeSimpleId) {
- useBrackets = true;
- break;
- }
- }
- if (useBrackets) {
- return "|" + s + "|";
- } else {
- return s;
- }
- }
-
- private static void TypeToStringHelper(Type t, StringBuilder sb) {
- Contract.Requires(t != null);
-
- TypeSynonymAnnotation syn = t as TypeSynonymAnnotation;
- if (syn != null) {
- TypeToStringHelper(syn.ExpandedType, sb);
- } else {
- if (t.IsMap) {
- MapType m = t.AsMap;
- sb.Append('[');
- for (int i = 0; i < m.MapArity; ++i) {
- if (i != 0)
- sb.Append(',');
- TypeToStringHelper(m.Arguments[i], sb);
- }
- sb.Append(']');
- TypeToStringHelper(m.Result, sb);
- } else if (t.IsBool || t.IsInt || t.IsBv) {
- sb.Append(TypeToString(t));
- } else {
- System.IO.StringWriter buffer = new System.IO.StringWriter();
- using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/ false, /*pretty=*/ false)) {
- t.Emit(stream);
- }
- sb.Append(buffer.ToString());
- }
- }
-
- }
-
-
- public static string TypeToString(Type t) {
- Contract.Requires(t != null);
- Contract.Ensures(Contract.Result<string>() != null);
-
- if (t.IsBool)
- return "$bool";
- else if (t.IsInt)
- return "$int";
- else if (t.IsBv)
- return "$bv" + t.BvBits;
- else {
- StringBuilder sb = new StringBuilder();
- TypeToStringHelper(t, sb);
- return sb.ToString();
- }
- }
-
- public static string BvConcatOpName(VCExprNAry node) {
- Contract.Requires(node != null);
- Contract.Requires((node.Op is VCExprBvConcatOp));
- Contract.Ensures(Contract.Result<string>() != null);
- int bits1 = node[0].Type.BvBits;
- int bits2 = node[1].Type.BvBits;
- return "$bv" + (bits1 + bits2) + "_concat[" + bits1 + "." + bits2 + "]";
- }
-
- public static string BvExtractOpName(VCExprNAry node) {
- Contract.Requires(node != null);
- Contract.Requires(node.Op is VCExprBvExtractOp);
- Contract.Ensures(Contract.Result<string>() != null);
- VCExprBvExtractOp op = (VCExprBvExtractOp)node.Op;
- return "$bv" + node.Type.BvBits + "_extract" + op.Total + "[" + op.Start + ":" + op.End + "]";
- }
-
- public static string StoreOpName(VCExprNAry node) {
- Contract.Requires(node != null);
- Contract.Requires((node.Op is VCExprSelectOp) || (node.Op is VCExprStoreOp));
- Contract.Ensures(Contract.Result<string>() != null);
- return "Store_" + TypeToString(node[0].Type);
- }
-
- public static string SelectOpName(VCExprNAry node) {
- Contract.Requires(node != null);
- Contract.Requires((node.Op is VCExprSelectOp) || (node.Op is VCExprStoreOp));
- Contract.Ensures(Contract.Result<string>() != null);
- return "Select_" + TypeToString(node[0].Type);
- }
-
- internal void WriteId(string s) {
- Contract.Requires(s != null);
- wr.Write(MakeIdPrintable(s));
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// The name for logical conjunction in Simplify
- /// </summary>
- internal const string andName = "AND"; // conjunction
- internal const string orName = "OR"; // disjunction
- internal const string notName = "NOT"; // negation
- internal const string impliesName = "IMPLIES"; // implication
- internal const string iffName = "IFF"; // logical equivalence
- internal const string eqName = "EQ"; // equality
- internal const string neqName = "NEQ"; // inequality
- internal const string lessName = "<";
- internal const string greaterName = ">";
- internal const string atmostName = "<=";
- internal const string atleastName = ">=";
- internal const string TRUEName = "TRUE"; // nullary predicate that is always true
- internal const string FALSEName = "FALSE"; // nullary predicate that is always false
- internal const string subtypeName = "<:";
- internal const string subtypeArgsName = "<::";
-
- internal const string distinctName = "DISTINCT";
- /// <summary>
- /// name of the main inclusion relation
- /// </summary>
- internal const string boolTrueName = "|@true|";
- internal const string boolFalseName = "|@false|";
- internal const string boolAndName = "boolAnd";
- internal const string boolOrName = "boolOr";
- internal const string boolNotName = "boolNot";
- internal const string termEqName = "anyEqual";
- internal const string termNeqName = "anyNeq";
- internal const string termLessName = "intLess";
- internal const string termGreaterName = "intGreater";
- internal const string termAtmostName = "intAtMost";
- internal const string termAtleastName = "intAtLeast";
- internal const string intAddName = "+";
- internal const string intAddNameReflect = "Reflect$Add";
- internal const string intSubName = "-";
- internal const string intMulName = "*";
- internal const string intDivName = "/";
- internal const string intModName = "%";
- internal const string realAddName = "realAdd";
- internal const string realSubName = "realSub";
- internal const string realMulName = "realMul";
- internal const string realDivName = "realDiv";
- internal const string realPowName = "realPow";
- internal const string toIntName = "toIntCoercion";
- internal const string toRealName = "toRealCoercion";
-
- internal void AssertAsTerm(string x, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(x != null);
- if (!options.AsTerm)
- System.Diagnostics.Debug.Fail("One should never write " + x + " as a formula!");
- }
-
- internal void AssertAsFormula(string x, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(x != null);
- if (options.AsTerm)
- System.Diagnostics.Debug.Fail("One should never write " + x + " as a term!");
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprLiteral node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- if (options.AsTerm) {
-
- if (node == VCExpressionGenerator.True)
- wr.Write(options.UseTypes ? TRUEName : boolTrueName);
- else if (node == VCExpressionGenerator.False)
- wr.Write(options.UseTypes ? FALSEName : boolFalseName);
- else if (node is VCExprIntLit) {
- wr.Write(((VCExprIntLit)node).Val);
- } else {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- } else {
-
- if (node == VCExpressionGenerator.True)
- wr.Write(TRUEName);
- else if (node == VCExpressionGenerator.False)
- wr.Write(FALSEName);
- else if (node is VCExprIntLit) {
- System.Diagnostics.Debug.Fail("One should never write IntLit as a predicate!");
- } else {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- }
-
- return true;
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- VCExprOp op = node.Op;
- Contract.Assert(op != null);
-
- if (!options.AsTerm &&
- (op.Equals(VCExpressionGenerator.AndOp) ||
- op.Equals(VCExpressionGenerator.OrOp))) {
- // handle these operators without recursion
-
- wr.Write("({0}",
- op.Equals(VCExpressionGenerator.AndOp) ? andName : orName);
- IEnumerator enumerator = new VCExprNAryUniformOpEnumerator(node);
- Contract.Assert(enumerator != null);
- while (enumerator.MoveNext()) {
- VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
- if (naryExpr == null || !naryExpr.Op.Equals(op)) {
- wr.Write(" ");
- Linearise(cce.NonNull((VCExpr)enumerator.Current), options);
- }
- }
-
- wr.Write(")");
-
- return true;
- }
-
- return node.Accept<bool, LineariserOptions>(OpLineariser, options);
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprVar node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- string printedName = Namer.GetName(node, node.Name);
- Contract.Assert(printedName != null);
-
- if (options.AsTerm ||
- // variables for formulas bound in a let-binding are never
- // written as an equation
- options.LetVariables.Contains(node) ||
- // if variables are properly typed, they cannot be written as
- // equation either
- options.UseTypes) {
- WriteId(printedName);
- } else {
- wr.Write("({0} ", eqName);
- WriteId(printedName);
- wr.Write(" {0})", boolTrueName);
- }
-
- return true;
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprQuantifier node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- AssertAsFormula(node.Quan.ToString(), options);
- Contract.Assert(node.TypeParameters.Count == 0);
-
- Namer.PushScope();
- try {
-
- string kind = node.Quan == Quantifier.ALL ? "FORALL" : "EXISTS";
- wr.Write("({0} (", kind);
-
- for (int i = 0; i < node.BoundVars.Count; i++) {
- VCExprVar var = node.BoundVars[i];
- Contract.Assert(var != null);
- string printedName = Namer.GetLocalName(var, var.Name);
- Contract.Assert(printedName != null);
- if (i != 0)
- wr.Write(" ");
- WriteId(printedName);
- if (options.UseTypes)
- wr.Write(" :TYPE {0}", TypeToString(var.Type));
- }
- wr.Write(") ");
-
- WriteTriggers(node.Triggers, options);
-
- if (options.QuantifierIds) {
- // only needed for Z3
- VCQuantifierInfos infos = node.Infos;
- Contract.Assert(infos != null);
- if (infos.qid != null) {
- wr.Write("(QID ");
- wr.Write(infos.qid);
- wr.Write(") ");
- }
- if (0 <= infos.uniqueId) {
- wr.Write("(SKOLEMID ");
- wr.Write(infos.uniqueId);
- wr.Write(") ");
- }
- }
-
- if (options.UseWeights) {
- int weight = QKeyValue.FindIntAttribute(node.Infos.attributes, "weight", 1);
- if (weight != 1) {
- wr.Write("(WEIGHT ");
- wr.Write(weight);
- wr.Write(") ");
- }
- }
-
- Linearise(node.Body, options);
- wr.Write(")");
-
- return true;
-
- } finally {
- Namer.PopScope();
- }
- }
-
- private void WriteTriggers(List<VCTrigger/*!*/>/*!*/ triggers, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(cce.NonNullElements(triggers));
- // first, count how many neg/pos triggers there are
- int negTriggers = 0;
- int posTriggers = 0;
- foreach (VCTrigger vcTrig in triggers) {
- Contract.Assert(vcTrig != null);
- if (vcTrig.Pos) {
- posTriggers++;
- } else {
- negTriggers++;
- }
- }
-
- if (posTriggers > 0) {
- wr.Write("(PATS");
- foreach (VCTrigger vcTrig in triggers) {
- Contract.Assert(vcTrig != null);
- if (vcTrig.Pos) {
- if (vcTrig.Exprs.Count > 1) {
- wr.Write(" (MPAT");
- }
- foreach (VCExpr e in vcTrig.Exprs) {
- Contract.Assert(e != null);
- wr.Write(" ");
- LineariseAsTerm(e, options);
- }
- if (vcTrig.Exprs.Count > 1) {
- wr.Write(")");
- }
- }
- }
- wr.Write(") ");
- } else if (negTriggers > 0) {
- // if also positive triggers are given, the SMT solver (at least Z3)
- // will ignore the negative patterns and output a warning. Therefore
- // we never specify both negative and positive triggers
- wr.Write("(NOPATS");
- foreach (VCTrigger vcTrig in triggers) {
- Contract.Assert(vcTrig != null);
- if (!vcTrig.Pos) {
- wr.Write(" ");
- Contract.Assert(vcTrig.Exprs.Count == 1);
- LineariseAsTerm(vcTrig.Exprs[0], options);
- }
- }
- wr.Write(") ");
- }
-
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- public bool Visit(VCExprLet node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- Namer.PushScope();
- try {
-
- wr.Write("(LET (");
-
- LineariserOptions optionsWithVars = options.AddLetVariables(node.BoundVars);
- Contract.Assert(optionsWithVars != null);
-
- string s = "(";
- foreach (VCExprLetBinding b in node) {
- Contract.Assert(b != null);
- wr.Write(s);
- string printedName = Namer.GetLocalName(b.V, b.V.Name);
-
- bool formula = b.V.Type.IsBool;
- if (formula)
- wr.Write("FORMULA ");
- else
- wr.Write("TERM ");
- WriteId(printedName);
- wr.Write(" ");
- Linearise(b.E, optionsWithVars.SetAsTerm(!formula));
- wr.Write(")");
- s = " (";
- }
- wr.Write(") ");
- Linearise(node.Body, optionsWithVars);
- wr.Write(")");
-
- return true;
-
- } finally {
- Namer.PopScope();
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////////
-
- // Lineariser for operator terms. The result (bool) is currently not used for anything
- internal class SimplifyLikeOpLineariser : IVCExprOpVisitor<bool, LineariserOptions/*!*/> {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(ExprLineariser != null);
- Contract.Invariant(wr != null);
- }
-
- private readonly SimplifyLikeExprLineariser/*!*/ ExprLineariser;
- private readonly TextWriter/*!*/ wr;
-
- public SimplifyLikeOpLineariser(SimplifyLikeExprLineariser ExprLineariser, TextWriter wr) {
- Contract.Requires(wr != null);
- Contract.Requires(ExprLineariser != null);
- this.ExprLineariser = ExprLineariser;
- this.wr = wr;
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- private void WriteApplication(string op, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options, bool argsAsTerms) {
- Contract.Requires(options != null);
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(args));
- WriteApplication(op, op, args, options, argsAsTerms);
- }
-
- private void WriteApplication(string op, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(args));
- WriteApplication(op, op, args, options, options.AsTerm);
- }
-
- private void WriteTermApplication(string op, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(args));
- ExprLineariser.AssertAsTerm(op, options);
- WriteApplication(op, op, args, options, options.AsTerm);
- }
-
- private void WriteApplication(string termOp, string predOp, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(predOp != null);
- Contract.Requires(termOp != null);
- Contract.Requires(cce.NonNullElements(args));
- WriteApplication(termOp, predOp, args, options, options.AsTerm);
- }
-
- private void WriteApplication(string termOp, string predOp, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options, bool argsAsTerms) {
- Contract.Requires(options != null);
- Contract.Requires(predOp != null);
- Contract.Requires(termOp != null);
- Contract.Requires(cce.NonNullElements(args));// change the AsTerm option for the arguments?
- wr.Write("({0}", options.AsTerm ? termOp : predOp);
-
- LineariserOptions newOptions = options.SetAsTerm(argsAsTerms);
-
- foreach (VCExpr e in args) {
- Contract.Assert(e != null);
- wr.Write(" ");
- ExprLineariser.Linearise(e, newOptions);
- }
-
- wr.Write(")");
- }
-
- // write an application that can only be a term.
- // if the expression is supposed to be printed as a formula,
- // it is turned into an equation (EQ (f args) |@true|)
- private void WriteApplicationTermOnly(string termOp, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options) {
- Contract.Requires(options != null);
- Contract.Requires(termOp != null);
- Contract.Requires(cce.NonNullElements(args));
- if (!options.AsTerm)
- // Write: (EQ (f args) |@true|)
- // where "args" are written as terms
- wr.Write("({0} ", eqName);
-
- WriteApplication(termOp, args, options, true);
-
- if (!options.AsTerm)
- wr.Write(" {0})", boolTrueName);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
-
- public bool VisitNotOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(boolNotName, notName, node, options); // arguments can be both terms and formulas
- return true;
- }
-
- public bool VisitEqOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- if (options.AsTerm) {
- // use equality on terms, also if the arguments have type bool
- WriteApplication(termEqName, node, options);
- } else {
- if (node[0].Type.IsBool) {
- Contract.Assert(node[1].Type.IsBool);
- // use equivalence
- WriteApplication(iffName, node, options);
- } else {
- Contract.Assert(!node[1].Type.IsBool);
- // use equality and write the arguments as terms
- WriteApplication(eqName, node, options, true);
- }
- }
-
- return true;
- }
-
- public bool VisitNeqOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- if (options.AsTerm) {
- // use equality on terms, also if the arguments have type bool
- WriteApplication(termNeqName, node, options);
- } else {
- if (node[0].Type.IsBool) {
- Contract.Assert(node[1].Type.IsBool);
- // use equivalence and negate the whole thing
- wr.Write("({0} ", notName);
- WriteApplication(iffName, node, options);
- wr.Write(")");
- } else {
- // use equality and write the arguments as terms
- WriteApplication(neqName, node, options, true);
- }
- }
-
- return true;
- }
-
- public bool VisitAndOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- Contract.Assert(options.AsTerm);
- WriteApplication(boolAndName, andName, node, options); // arguments can be both terms and formulas
- return true;
- }
-
- public bool VisitOrOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- Contract.Assert(options.AsTerm);
- WriteApplication(boolOrName, orName, node, options); // arguments can be both terms and formulas
- return true;
- }
-
- public bool VisitImpliesOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- if (options.AsTerm) {
- wr.Write("({0} ({1} ", boolOrName, boolNotName);
- ExprLineariser.Linearise(node[0], options);
- wr.Write(") ");
- ExprLineariser.Linearise(node[1], options);
- wr.Write(")");
- } else if (options.InverseImplies) {
- wr.Write("({0} ", orName);
- ExprLineariser.Linearise(node[1], options);
- wr.Write(" ({0} ", notName);
- ExprLineariser.Linearise(node[0], options);
- wr.Write("))");
- } else {
- WriteApplication(impliesName, node, options);
- }
- return true;
- }
-
- public bool VisitDistinctOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- ExprLineariser.AssertAsFormula(distinctName, options);
-
- if (node.Length < 2) {
- ExprLineariser.Linearise(VCExpressionGenerator.True, options);
- } else {
- wr.Write("({0}", distinctName);
- foreach (VCExpr e in node) {
- Contract.Assert(e != null);
- wr.Write(" ");
- ExprLineariser.LineariseAsTerm(e, options);
- }
- wr.Write(")");
- }
-
- return true;
- }
-
- public bool VisitLabelOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- VCExprLabelOp op = (VCExprLabelOp)node.Op;
- Contract.Assert(op != null);
- wr.Write(String.Format("({0} |{1}| ", op.pos ? "LBLPOS" : "LBLNEG", op.label));
- ExprLineariser.Linearise(node[0], options);
- wr.Write(")");
- return true;
- }
-
- public bool VisitSelectOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- wr.Write("(" + SelectOpName(node));
- foreach (VCExpr/*!*/ e in node) {
- Contract.Assert(e != null);
- wr.Write(" ");
- ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
- }
- wr.Write(")");
- return true;
- }
-
- public bool VisitStoreOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- wr.Write("(" + StoreOpName(node));
- foreach (VCExpr e in node) {
- Contract.Assert(e != null);
- wr.Write(" ");
- ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
- }
- wr.Write(")");
- return true;
- }
-
- public bool VisitBvOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication("$make_bv" + node.Type.BvBits, node, options);
- return true;
- }
-
- public bool VisitBvExtractOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(BvExtractOpName(node), node, options);
- return true;
- }
-
- public bool VisitBvConcatOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(BvConcatOpName(node), node, options);
- return true;
- }
-
- public bool VisitIfThenElseOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
-
- wr.Write("(ITE ");
- ExprLineariser.Linearise(node[0], options.SetAsTerm(false));
- wr.Write(" ");
- ExprLineariser.Linearise(node[1], options);
- wr.Write(" ");
- ExprLineariser.Linearise(node[2], options);
- wr.Write(")");
-
- return true;
- }
-
- public bool VisitCustomOp(VCExprNAry/*!*/ node, LineariserOptions/*!*/ options) {
- //Contract.Requires(node != null);
- //Contract.Requires(options != null);
- VCExprCustomOp op = (VCExprCustomOp)node.Op;
- wr.Write("({0}", op.Name);
- foreach (VCExpr arg in node) {
- wr.Write(" ");
- ExprLineariser.Linearise(arg, options);
- }
- wr.Write(")");
- return true;
- }
-
- public bool VisitAddOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- if (node.Type.IsInt) {
- if (CommandLineOptions.Clo.ReflectAdd) {
- WriteTermApplication(intAddNameReflect, node, options);
- }
- else {
- WriteTermApplication(intAddName, node, options);
- }
- }
- else {
- WriteTermApplication(realAddName, node, options);
- }
- return true;
- }
-
- public bool VisitSubOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- if (node.Type.IsInt) {
- WriteTermApplication(intSubName, node, options);
- }
- else {
- WriteTermApplication(realSubName, node, options);
- }
- return true;
- }
-
- public bool VisitMulOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- if (node.Type.IsInt) {
- WriteTermApplication(intMulName, node, options);
- }
- else {
- WriteTermApplication(realMulName, node, options);
- }
- return true;
- }
-
- public bool VisitDivOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(intDivName, node, options);
- return true;
- }
-
- public bool VisitModOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(intModName, node, options);
- return true;
- }
-
- public bool VisitRealDivOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(realDivName, node, options);
- return true;
- }
-
- public bool VisitPowOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteTermApplication(realPowName, node, options);
- return true;
- }
-
- public bool VisitLtOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(termLessName, lessName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitLeOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(termAtmostName, atmostName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitGtOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(termGreaterName, greaterName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitGeOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(termAtleastName, atleastName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitSubtypeOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(subtypeName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitSubtype3Op(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(subtypeArgsName, node, options, true); // arguments are always terms
- return true;
- }
-
- public bool VisitToIntOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(toIntName, node, options);
- return true;
- }
-
- public bool VisitToRealOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- WriteApplication(toRealName, node, options);
- return true;
- }
-
- public bool VisitBoogieFunctionOp(VCExprNAry node, LineariserOptions options) {
- //Contract.Requires(options != null);
- //Contract.Requires(node != null);
- VCExprBoogieFunctionOp op = (VCExprBoogieFunctionOp)node.Op;
- Contract.Assert(op != null);
- string funcName = op.Func.Name;
- Contract.Assert(funcName != null);
- string bvzName = op.Func.FindStringAttribute("external");
- string printedName = ExprLineariser.Namer.GetName(op.Func, funcName);
- Contract.Assert(printedName != null);
- if (bvzName != null)
- printedName = bvzName;
-
- if (options.UseTypes) {
- // we use term notation for arguments whose type is not bool, and
- // formula notation for boolean arguments
-
- wr.Write("(");
- ExprLineariser.WriteId(printedName);
-
- foreach (VCExpr e in node) {
- Contract.Assert(e != null);
- wr.Write(" ");
- ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
- }
-
- wr.Write(")");
- } else {
- // arguments are always terms
- WriteApplicationTermOnly(SimplifyLikeExprLineariser.MakeIdPrintable(printedName),
- node, options);
- }
- return true;
- }
-
- }
- }
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// a naive method to turn VCExprs into strings that can be fed into Simplify
+
+namespace Microsoft.Boogie.VCExprAST {
+ [ContractClassFor(typeof(LineariserOptions))]
+ public abstract class LinOptContracts : LineariserOptions {
+ public LinOptContracts()
+ : base(true) {
+ }
+ public override LineariserOptions SetAsTerm(bool newVal) {
+ Contract.Ensures(Contract.Result<LineariserOptions>() != null);
+ throw new NotImplementedException();
+ }
+
+ }
+
+ // Options for the linearisation. Here one can choose, for instance,
+ // whether Simplify or Z3 output is to be produced
+ [ContractClass(typeof(LinOptContracts))]
+ public abstract class LineariserOptions {
+
+ public readonly bool AsTerm;
+ public abstract LineariserOptions/*!*/ SetAsTerm(bool newVal);
+
+ public abstract bool QuantifierIds {
+ get;
+ }
+
+ public virtual bool UseWeights {
+ get {
+ return false;
+ }
+ }
+
+ public virtual bool InverseImplies {
+ get {
+ return false;
+ }
+ }
+
+ // whether to include type specifications in quantifiers
+ public abstract bool UseTypes {
+ get;
+ }
+
+ // variables representing formulas in let-bindings have to be
+ // printed in a different way than other variables
+ public virtual List<VCExprVar/*!*/>/*!*/ LetVariables {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+ return EmptyList;
+ }
+ }
+
+ public virtual LineariserOptions AddLetVariable(VCExprVar furtherVar) {
+ Contract.Requires(furtherVar != null);
+ Contract.Ensures(Contract.Result<LineariserOptions>() != null);
+ return this;
+ }
+
+ public virtual LineariserOptions AddLetVariables(List<VCExprVar/*!*/>/*!*/ furtherVars) {
+ Contract.Requires(cce.NonNullElements(furtherVars));
+ Contract.Ensures(Contract.Result<LineariserOptions>() != null);
+ return this;
+ }
+
+ private static readonly List<VCExprVar/*!*/>/*!*/ EmptyList = new List<VCExprVar/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvarinat() {
+ Contract.Invariant(EmptyList != null);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ protected LineariserOptions(bool asTerm) {
+ this.AsTerm = asTerm;
+ }
+
+ public static readonly LineariserOptions SimplifyDefault = new SimplifyOptions(false);
+ internal static readonly LineariserOptions SimplifyDefaultTerm = new SimplifyOptions(true);
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ private class SimplifyOptions : LineariserOptions {
+ internal SimplifyOptions(bool asTerm)
+ : base(asTerm) {
+
+ }
+ public override bool QuantifierIds {
+ get {
+ return false;
+ }
+ }
+ public override bool UseTypes {
+ get {
+ return false;
+ }
+ }
+ public override LineariserOptions SetAsTerm(bool newVal) {
+ Contract.Ensures(Contract.Result<LineariserOptions>() != null);
+ if (newVal)
+ return SimplifyDefaultTerm;
+ else
+ return SimplifyDefault;
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ // Lineariser for expressions. The result (bool) is currently not used for anything
+ public class SimplifyLikeExprLineariser : IVCExprVisitor<bool, LineariserOptions/*!*/> {
+
+ public static string ToSimplifyString(VCExpr e, UniqueNamer namer) {
+ Contract.Requires(namer != null);
+ Contract.Requires(e != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ return ToString(e, LineariserOptions.SimplifyDefault, namer);
+ }
+
+ public static string ToString(VCExpr/*!*/ e, LineariserOptions/*!*/ options, UniqueNamer/*!*/ namer) {
+ Contract.Requires(e != null);
+ Contract.Requires(options != null);
+ Contract.Requires(namer != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ StringWriter sw = new StringWriter();
+ SimplifyLikeExprLineariser lin = new SimplifyLikeExprLineariser(sw, namer);
+ lin.Linearise(e, options);
+ return sw.ToString();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(wr != null);
+ Contract.Invariant(Namer != null);
+ }
+
+ private readonly TextWriter/*!*/ wr;
+ private SimplifyLikeOpLineariser OpLinObject = null;
+ private IVCExprOpVisitor<bool, LineariserOptions/*!*/>/*!*/ OpLineariser {
+ get {
+ Contract.Ensures(Contract.Result<IVCExprOpVisitor<bool, LineariserOptions>>() != null);
+ if (OpLinObject == null)
+ OpLinObject = new SimplifyLikeOpLineariser(this, wr);
+ return OpLinObject;
+ }
+ }
+
+ internal readonly UniqueNamer Namer;
+
+ public SimplifyLikeExprLineariser(TextWriter wr, UniqueNamer namer) {
+ Contract.Requires(namer != null);
+ Contract.Requires(wr != null);
+ this.wr = wr;
+ this.Namer = namer;
+ }
+
+ public void Linearise(VCExpr expr, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(expr != null);
+ expr.Accept<bool, LineariserOptions>(this, options);
+ }
+
+ public void LineariseAsTerm(VCExpr expr, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(expr != null);
+ Linearise(expr, options.SetAsTerm(true));
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public static string MakeIdPrintable(string s) {
+ Contract.Requires(s != null);
+ Contract.Requires(s != "");
+ Contract.Ensures(Contract.Result<string>() != null);
+ // make sure that no keywords are used as identifiers
+ switch (s) {
+ case andName:
+ case orName:
+ case notName:
+ case impliesName:
+ case iffName:
+ case eqName:
+ case neqName:
+ case distinctName:
+ case TRUEName:
+ case FALSEName:
+ s = "nonkeyword_" + s;
+ break;
+ }
+
+ if (CommandLineOptions.Clo.BracketIdsInVC == 0) {
+ // In this form, we go with any identifier, so we don't ever bother about brackets.
+ // Except: @true and @false are always written with brackets
+ return s;
+ }
+ bool looksLikeOperator = true;
+ bool looksLikeSimpleId = true;
+ bool useBrackets = false;
+ foreach (char ch in s) {
+ switch (ch) {
+ case '=':
+ case '<':
+ case '>':
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case ':':
+ // looks like operator, not simple id
+ looksLikeSimpleId = false;
+ break;
+ default:
+ if (Char.IsLetterOrDigit(ch)) {
+ // looks like simple id, not operator
+ looksLikeOperator = false;
+ } else {
+ // looks like neither operator nor simple id
+ looksLikeOperator = false;
+ looksLikeSimpleId = false;
+ }
+ break;
+ }
+ if (!looksLikeOperator && !looksLikeSimpleId) {
+ useBrackets = true;
+ break;
+ }
+ }
+ if (useBrackets) {
+ return "|" + s + "|";
+ } else {
+ return s;
+ }
+ }
+
+ private static void TypeToStringHelper(Type t, StringBuilder sb) {
+ Contract.Requires(t != null);
+
+ TypeSynonymAnnotation syn = t as TypeSynonymAnnotation;
+ if (syn != null) {
+ TypeToStringHelper(syn.ExpandedType, sb);
+ } else {
+ if (t.IsMap) {
+ MapType m = t.AsMap;
+ sb.Append('[');
+ for (int i = 0; i < m.MapArity; ++i) {
+ if (i != 0)
+ sb.Append(',');
+ TypeToStringHelper(m.Arguments[i], sb);
+ }
+ sb.Append(']');
+ TypeToStringHelper(m.Result, sb);
+ } else if (t.IsBool || t.IsInt || t.IsBv) {
+ sb.Append(TypeToString(t));
+ } else {
+ System.IO.StringWriter buffer = new System.IO.StringWriter();
+ using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, /*setTokens=*/ false, /*pretty=*/ false)) {
+ t.Emit(stream);
+ }
+ sb.Append(buffer.ToString());
+ }
+ }
+
+ }
+
+
+ public static string TypeToString(Type t) {
+ Contract.Requires(t != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ if (t.IsBool)
+ return "$bool";
+ else if (t.IsInt)
+ return "$int";
+ else if (t.IsBv)
+ return "$bv" + t.BvBits;
+ else {
+ StringBuilder sb = new StringBuilder();
+ TypeToStringHelper(t, sb);
+ return sb.ToString();
+ }
+ }
+
+ public static string BvConcatOpName(VCExprNAry node) {
+ Contract.Requires(node != null);
+ Contract.Requires((node.Op is VCExprBvConcatOp));
+ Contract.Ensures(Contract.Result<string>() != null);
+ int bits1 = node[0].Type.BvBits;
+ int bits2 = node[1].Type.BvBits;
+ return "$bv" + (bits1 + bits2) + "_concat[" + bits1 + "." + bits2 + "]";
+ }
+
+ public static string BvExtractOpName(VCExprNAry node) {
+ Contract.Requires(node != null);
+ Contract.Requires(node.Op is VCExprBvExtractOp);
+ Contract.Ensures(Contract.Result<string>() != null);
+ VCExprBvExtractOp op = (VCExprBvExtractOp)node.Op;
+ return "$bv" + node.Type.BvBits + "_extract" + op.Total + "[" + op.Start + ":" + op.End + "]";
+ }
+
+ public static string StoreOpName(VCExprNAry node) {
+ Contract.Requires(node != null);
+ Contract.Requires((node.Op is VCExprSelectOp) || (node.Op is VCExprStoreOp));
+ Contract.Ensures(Contract.Result<string>() != null);
+ return "Store_" + TypeToString(node[0].Type);
+ }
+
+ public static string SelectOpName(VCExprNAry node) {
+ Contract.Requires(node != null);
+ Contract.Requires((node.Op is VCExprSelectOp) || (node.Op is VCExprStoreOp));
+ Contract.Ensures(Contract.Result<string>() != null);
+ return "Select_" + TypeToString(node[0].Type);
+ }
+
+ internal void WriteId(string s) {
+ Contract.Requires(s != null);
+ wr.Write(MakeIdPrintable(s));
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ /// <summary>
+ /// The name for logical conjunction in Simplify
+ /// </summary>
+ internal const string andName = "AND"; // conjunction
+ internal const string orName = "OR"; // disjunction
+ internal const string notName = "NOT"; // negation
+ internal const string impliesName = "IMPLIES"; // implication
+ internal const string iffName = "IFF"; // logical equivalence
+ internal const string eqName = "EQ"; // equality
+ internal const string neqName = "NEQ"; // inequality
+ internal const string lessName = "<";
+ internal const string greaterName = ">";
+ internal const string atmostName = "<=";
+ internal const string atleastName = ">=";
+ internal const string TRUEName = "TRUE"; // nullary predicate that is always true
+ internal const string FALSEName = "FALSE"; // nullary predicate that is always false
+ internal const string subtypeName = "<:";
+ internal const string subtypeArgsName = "<::";
+
+ internal const string distinctName = "DISTINCT";
+ /// <summary>
+ /// name of the main inclusion relation
+ /// </summary>
+ internal const string boolTrueName = "|@true|";
+ internal const string boolFalseName = "|@false|";
+ internal const string boolAndName = "boolAnd";
+ internal const string boolOrName = "boolOr";
+ internal const string boolNotName = "boolNot";
+ internal const string termEqName = "anyEqual";
+ internal const string termNeqName = "anyNeq";
+ internal const string termLessName = "intLess";
+ internal const string termGreaterName = "intGreater";
+ internal const string termAtmostName = "intAtMost";
+ internal const string termAtleastName = "intAtLeast";
+ internal const string intAddName = "+";
+ internal const string intAddNameReflect = "Reflect$Add";
+ internal const string intSubName = "-";
+ internal const string intMulName = "*";
+ internal const string intDivName = "/";
+ internal const string intModName = "%";
+ internal const string realAddName = "realAdd";
+ internal const string realSubName = "realSub";
+ internal const string realMulName = "realMul";
+ internal const string realDivName = "realDiv";
+ internal const string realPowName = "realPow";
+ internal const string toIntName = "toIntCoercion";
+ internal const string toRealName = "toRealCoercion";
+
+ internal void AssertAsTerm(string x, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(x != null);
+ if (!options.AsTerm)
+ System.Diagnostics.Debug.Fail("One should never write " + x + " as a formula!");
+ }
+
+ internal void AssertAsFormula(string x, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(x != null);
+ if (options.AsTerm)
+ System.Diagnostics.Debug.Fail("One should never write " + x + " as a term!");
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprLiteral node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ if (options.AsTerm) {
+
+ if (node == VCExpressionGenerator.True)
+ wr.Write(options.UseTypes ? TRUEName : boolTrueName);
+ else if (node == VCExpressionGenerator.False)
+ wr.Write(options.UseTypes ? FALSEName : boolFalseName);
+ else if (node is VCExprIntLit) {
+ wr.Write(((VCExprIntLit)node).Val);
+ } else {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+
+ } else {
+
+ if (node == VCExpressionGenerator.True)
+ wr.Write(TRUEName);
+ else if (node == VCExpressionGenerator.False)
+ wr.Write(FALSEName);
+ else if (node is VCExprIntLit) {
+ System.Diagnostics.Debug.Fail("One should never write IntLit as a predicate!");
+ } else {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+
+ }
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ VCExprOp op = node.Op;
+ Contract.Assert(op != null);
+
+ if (!options.AsTerm &&
+ (op.Equals(VCExpressionGenerator.AndOp) ||
+ op.Equals(VCExpressionGenerator.OrOp))) {
+ // handle these operators without recursion
+
+ wr.Write("({0}",
+ op.Equals(VCExpressionGenerator.AndOp) ? andName : orName);
+ IEnumerator enumerator = new VCExprNAryUniformOpEnumerator(node);
+ Contract.Assert(enumerator != null);
+ while (enumerator.MoveNext()) {
+ VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
+ if (naryExpr == null || !naryExpr.Op.Equals(op)) {
+ wr.Write(" ");
+ Linearise(cce.NonNull((VCExpr)enumerator.Current), options);
+ }
+ }
+
+ wr.Write(")");
+
+ return true;
+ }
+
+ return node.Accept<bool, LineariserOptions>(OpLineariser, options);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprVar node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ string printedName = Namer.GetName(node, node.Name);
+ Contract.Assert(printedName != null);
+
+ if (options.AsTerm ||
+ // variables for formulas bound in a let-binding are never
+ // written as an equation
+ options.LetVariables.Contains(node) ||
+ // if variables are properly typed, they cannot be written as
+ // equation either
+ options.UseTypes) {
+ WriteId(printedName);
+ } else {
+ wr.Write("({0} ", eqName);
+ WriteId(printedName);
+ wr.Write(" {0})", boolTrueName);
+ }
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprQuantifier node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ AssertAsFormula(node.Quan.ToString(), options);
+ Contract.Assert(node.TypeParameters.Count == 0);
+
+ Namer.PushScope();
+ try {
+
+ string kind = node.Quan == Quantifier.ALL ? "FORALL" : "EXISTS";
+ wr.Write("({0} (", kind);
+
+ for (int i = 0; i < node.BoundVars.Count; i++) {
+ VCExprVar var = node.BoundVars[i];
+ Contract.Assert(var != null);
+ string printedName = Namer.GetLocalName(var, var.Name);
+ Contract.Assert(printedName != null);
+ if (i != 0)
+ wr.Write(" ");
+ WriteId(printedName);
+ if (options.UseTypes)
+ wr.Write(" :TYPE {0}", TypeToString(var.Type));
+ }
+ wr.Write(") ");
+
+ WriteTriggers(node.Triggers, options);
+
+ if (options.QuantifierIds) {
+ // only needed for Z3
+ VCQuantifierInfos infos = node.Infos;
+ Contract.Assert(infos != null);
+ if (infos.qid != null) {
+ wr.Write("(QID ");
+ wr.Write(infos.qid);
+ wr.Write(") ");
+ }
+ if (0 <= infos.uniqueId) {
+ wr.Write("(SKOLEMID ");
+ wr.Write(infos.uniqueId);
+ wr.Write(") ");
+ }
+ }
+
+ if (options.UseWeights) {
+ int weight = QKeyValue.FindIntAttribute(node.Infos.attributes, "weight", 1);
+ if (weight != 1) {
+ wr.Write("(WEIGHT ");
+ wr.Write(weight);
+ wr.Write(") ");
+ }
+ }
+
+ Linearise(node.Body, options);
+ wr.Write(")");
+
+ return true;
+
+ } finally {
+ Namer.PopScope();
+ }
+ }
+
+ private void WriteTriggers(List<VCTrigger/*!*/>/*!*/ triggers, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(cce.NonNullElements(triggers));
+ // first, count how many neg/pos triggers there are
+ int negTriggers = 0;
+ int posTriggers = 0;
+ foreach (VCTrigger vcTrig in triggers) {
+ Contract.Assert(vcTrig != null);
+ if (vcTrig.Pos) {
+ posTriggers++;
+ } else {
+ negTriggers++;
+ }
+ }
+
+ if (posTriggers > 0) {
+ wr.Write("(PATS");
+ foreach (VCTrigger vcTrig in triggers) {
+ Contract.Assert(vcTrig != null);
+ if (vcTrig.Pos) {
+ if (vcTrig.Exprs.Count > 1) {
+ wr.Write(" (MPAT");
+ }
+ foreach (VCExpr e in vcTrig.Exprs) {
+ Contract.Assert(e != null);
+ wr.Write(" ");
+ LineariseAsTerm(e, options);
+ }
+ if (vcTrig.Exprs.Count > 1) {
+ wr.Write(")");
+ }
+ }
+ }
+ wr.Write(") ");
+ } else if (negTriggers > 0) {
+ // if also positive triggers are given, the SMT solver (at least Z3)
+ // will ignore the negative patterns and output a warning. Therefore
+ // we never specify both negative and positive triggers
+ wr.Write("(NOPATS");
+ foreach (VCTrigger vcTrig in triggers) {
+ Contract.Assert(vcTrig != null);
+ if (!vcTrig.Pos) {
+ wr.Write(" ");
+ Contract.Assert(vcTrig.Exprs.Count == 1);
+ LineariseAsTerm(vcTrig.Exprs[0], options);
+ }
+ }
+ wr.Write(") ");
+ }
+
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ public bool Visit(VCExprLet node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ Namer.PushScope();
+ try {
+
+ wr.Write("(LET (");
+
+ LineariserOptions optionsWithVars = options.AddLetVariables(node.BoundVars);
+ Contract.Assert(optionsWithVars != null);
+
+ string s = "(";
+ foreach (VCExprLetBinding b in node) {
+ Contract.Assert(b != null);
+ wr.Write(s);
+ string printedName = Namer.GetLocalName(b.V, b.V.Name);
+
+ bool formula = b.V.Type.IsBool;
+ if (formula)
+ wr.Write("FORMULA ");
+ else
+ wr.Write("TERM ");
+ WriteId(printedName);
+ wr.Write(" ");
+ Linearise(b.E, optionsWithVars.SetAsTerm(!formula));
+ wr.Write(")");
+ s = " (";
+ }
+ wr.Write(") ");
+ Linearise(node.Body, optionsWithVars);
+ wr.Write(")");
+
+ return true;
+
+ } finally {
+ Namer.PopScope();
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ // Lineariser for operator terms. The result (bool) is currently not used for anything
+ internal class SimplifyLikeOpLineariser : IVCExprOpVisitor<bool, LineariserOptions/*!*/> {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(ExprLineariser != null);
+ Contract.Invariant(wr != null);
+ }
+
+ private readonly SimplifyLikeExprLineariser/*!*/ ExprLineariser;
+ private readonly TextWriter/*!*/ wr;
+
+ public SimplifyLikeOpLineariser(SimplifyLikeExprLineariser ExprLineariser, TextWriter wr) {
+ Contract.Requires(wr != null);
+ Contract.Requires(ExprLineariser != null);
+ this.ExprLineariser = ExprLineariser;
+ this.wr = wr;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ private void WriteApplication(string op, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options, bool argsAsTerms) {
+ Contract.Requires(options != null);
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(args));
+ WriteApplication(op, op, args, options, argsAsTerms);
+ }
+
+ private void WriteApplication(string op, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(args));
+ WriteApplication(op, op, args, options, options.AsTerm);
+ }
+
+ private void WriteTermApplication(string op, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(args));
+ ExprLineariser.AssertAsTerm(op, options);
+ WriteApplication(op, op, args, options, options.AsTerm);
+ }
+
+ private void WriteApplication(string termOp, string predOp, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(predOp != null);
+ Contract.Requires(termOp != null);
+ Contract.Requires(cce.NonNullElements(args));
+ WriteApplication(termOp, predOp, args, options, options.AsTerm);
+ }
+
+ private void WriteApplication(string termOp, string predOp, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options, bool argsAsTerms) {
+ Contract.Requires(options != null);
+ Contract.Requires(predOp != null);
+ Contract.Requires(termOp != null);
+ Contract.Requires(cce.NonNullElements(args));// change the AsTerm option for the arguments?
+ wr.Write("({0}", options.AsTerm ? termOp : predOp);
+
+ LineariserOptions newOptions = options.SetAsTerm(argsAsTerms);
+
+ foreach (VCExpr e in args) {
+ Contract.Assert(e != null);
+ wr.Write(" ");
+ ExprLineariser.Linearise(e, newOptions);
+ }
+
+ wr.Write(")");
+ }
+
+ // write an application that can only be a term.
+ // if the expression is supposed to be printed as a formula,
+ // it is turned into an equation (EQ (f args) |@true|)
+ private void WriteApplicationTermOnly(string termOp, IEnumerable<VCExpr/*!*/>/*!*/ args, LineariserOptions options) {
+ Contract.Requires(options != null);
+ Contract.Requires(termOp != null);
+ Contract.Requires(cce.NonNullElements(args));
+ if (!options.AsTerm)
+ // Write: (EQ (f args) |@true|)
+ // where "args" are written as terms
+ wr.Write("({0} ", eqName);
+
+ WriteApplication(termOp, args, options, true);
+
+ if (!options.AsTerm)
+ wr.Write(" {0})", boolTrueName);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ public bool VisitNotOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(boolNotName, notName, node, options); // arguments can be both terms and formulas
+ return true;
+ }
+
+ public bool VisitEqOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ if (options.AsTerm) {
+ // use equality on terms, also if the arguments have type bool
+ WriteApplication(termEqName, node, options);
+ } else {
+ if (node[0].Type.IsBool) {
+ Contract.Assert(node[1].Type.IsBool);
+ // use equivalence
+ WriteApplication(iffName, node, options);
+ } else {
+ Contract.Assert(!node[1].Type.IsBool);
+ // use equality and write the arguments as terms
+ WriteApplication(eqName, node, options, true);
+ }
+ }
+
+ return true;
+ }
+
+ public bool VisitNeqOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ if (options.AsTerm) {
+ // use equality on terms, also if the arguments have type bool
+ WriteApplication(termNeqName, node, options);
+ } else {
+ if (node[0].Type.IsBool) {
+ Contract.Assert(node[1].Type.IsBool);
+ // use equivalence and negate the whole thing
+ wr.Write("({0} ", notName);
+ WriteApplication(iffName, node, options);
+ wr.Write(")");
+ } else {
+ // use equality and write the arguments as terms
+ WriteApplication(neqName, node, options, true);
+ }
+ }
+
+ return true;
+ }
+
+ public bool VisitAndOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ Contract.Assert(options.AsTerm);
+ WriteApplication(boolAndName, andName, node, options); // arguments can be both terms and formulas
+ return true;
+ }
+
+ public bool VisitOrOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ Contract.Assert(options.AsTerm);
+ WriteApplication(boolOrName, orName, node, options); // arguments can be both terms and formulas
+ return true;
+ }
+
+ public bool VisitImpliesOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ if (options.AsTerm) {
+ wr.Write("({0} ({1} ", boolOrName, boolNotName);
+ ExprLineariser.Linearise(node[0], options);
+ wr.Write(") ");
+ ExprLineariser.Linearise(node[1], options);
+ wr.Write(")");
+ } else if (options.InverseImplies) {
+ wr.Write("({0} ", orName);
+ ExprLineariser.Linearise(node[1], options);
+ wr.Write(" ({0} ", notName);
+ ExprLineariser.Linearise(node[0], options);
+ wr.Write("))");
+ } else {
+ WriteApplication(impliesName, node, options);
+ }
+ return true;
+ }
+
+ public bool VisitDistinctOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ ExprLineariser.AssertAsFormula(distinctName, options);
+
+ if (node.Length < 2) {
+ ExprLineariser.Linearise(VCExpressionGenerator.True, options);
+ } else {
+ wr.Write("({0}", distinctName);
+ foreach (VCExpr e in node) {
+ Contract.Assert(e != null);
+ wr.Write(" ");
+ ExprLineariser.LineariseAsTerm(e, options);
+ }
+ wr.Write(")");
+ }
+
+ return true;
+ }
+
+ public bool VisitLabelOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ VCExprLabelOp op = (VCExprLabelOp)node.Op;
+ Contract.Assert(op != null);
+ wr.Write(String.Format("({0} |{1}| ", op.pos ? "LBLPOS" : "LBLNEG", op.label));
+ ExprLineariser.Linearise(node[0], options);
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitSelectOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ wr.Write("(" + SelectOpName(node));
+ foreach (VCExpr/*!*/ e in node) {
+ Contract.Assert(e != null);
+ wr.Write(" ");
+ ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
+ }
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitStoreOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ wr.Write("(" + StoreOpName(node));
+ foreach (VCExpr e in node) {
+ Contract.Assert(e != null);
+ wr.Write(" ");
+ ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
+ }
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitBvOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication("$make_bv" + node.Type.BvBits, node, options);
+ return true;
+ }
+
+ public bool VisitBvExtractOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(BvExtractOpName(node), node, options);
+ return true;
+ }
+
+ public bool VisitBvConcatOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(BvConcatOpName(node), node, options);
+ return true;
+ }
+
+ public bool VisitIfThenElseOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+
+ wr.Write("(ITE ");
+ ExprLineariser.Linearise(node[0], options.SetAsTerm(false));
+ wr.Write(" ");
+ ExprLineariser.Linearise(node[1], options);
+ wr.Write(" ");
+ ExprLineariser.Linearise(node[2], options);
+ wr.Write(")");
+
+ return true;
+ }
+
+ public bool VisitCustomOp(VCExprNAry/*!*/ node, LineariserOptions/*!*/ options) {
+ //Contract.Requires(node != null);
+ //Contract.Requires(options != null);
+ VCExprCustomOp op = (VCExprCustomOp)node.Op;
+ wr.Write("({0}", op.Name);
+ foreach (VCExpr arg in node) {
+ wr.Write(" ");
+ ExprLineariser.Linearise(arg, options);
+ }
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitAddOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ if (node.Type.IsInt) {
+ if (CommandLineOptions.Clo.ReflectAdd) {
+ WriteTermApplication(intAddNameReflect, node, options);
+ }
+ else {
+ WriteTermApplication(intAddName, node, options);
+ }
+ }
+ else {
+ WriteTermApplication(realAddName, node, options);
+ }
+ return true;
+ }
+
+ public bool VisitSubOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ if (node.Type.IsInt) {
+ WriteTermApplication(intSubName, node, options);
+ }
+ else {
+ WriteTermApplication(realSubName, node, options);
+ }
+ return true;
+ }
+
+ public bool VisitMulOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ if (node.Type.IsInt) {
+ WriteTermApplication(intMulName, node, options);
+ }
+ else {
+ WriteTermApplication(realMulName, node, options);
+ }
+ return true;
+ }
+
+ public bool VisitDivOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(intDivName, node, options);
+ return true;
+ }
+
+ public bool VisitModOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(intModName, node, options);
+ return true;
+ }
+
+ public bool VisitRealDivOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(realDivName, node, options);
+ return true;
+ }
+
+ public bool VisitPowOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteTermApplication(realPowName, node, options);
+ return true;
+ }
+
+ public bool VisitLtOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(termLessName, lessName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitLeOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(termAtmostName, atmostName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitGtOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(termGreaterName, greaterName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitGeOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(termAtleastName, atleastName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitSubtypeOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(subtypeName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitSubtype3Op(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(subtypeArgsName, node, options, true); // arguments are always terms
+ return true;
+ }
+
+ public bool VisitToIntOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(toIntName, node, options);
+ return true;
+ }
+
+ public bool VisitToRealOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ WriteApplication(toRealName, node, options);
+ return true;
+ }
+
+ public bool VisitBoogieFunctionOp(VCExprNAry node, LineariserOptions options) {
+ //Contract.Requires(options != null);
+ //Contract.Requires(node != null);
+ VCExprBoogieFunctionOp op = (VCExprBoogieFunctionOp)node.Op;
+ Contract.Assert(op != null);
+ string funcName = op.Func.Name;
+ Contract.Assert(funcName != null);
+ string bvzName = op.Func.FindStringAttribute("external");
+ string printedName = ExprLineariser.Namer.GetName(op.Func, funcName);
+ Contract.Assert(printedName != null);
+ if (bvzName != null)
+ printedName = bvzName;
+
+ if (options.UseTypes) {
+ // we use term notation for arguments whose type is not bool, and
+ // formula notation for boolean arguments
+
+ wr.Write("(");
+ ExprLineariser.WriteId(printedName);
+
+ foreach (VCExpr e in node) {
+ Contract.Assert(e != null);
+ wr.Write(" ");
+ ExprLineariser.Linearise(e, options.SetAsTerm(!e.Type.IsBool));
+ }
+
+ wr.Write(")");
+ } else {
+ // arguments are always terms
+ WriteApplicationTermOnly(SimplifyLikeExprLineariser.MakeIdPrintable(printedName),
+ node, options);
+ }
+ return true;
+ }
+
+ }
+ }
+
+}
diff --git a/Source/VCExpr/TermFormulaFlattening.cs b/Source/VCExpr/TermFormulaFlattening.cs
index 7815413f..c4150024 100644
--- a/Source/VCExpr/TermFormulaFlattening.cs
+++ b/Source/VCExpr/TermFormulaFlattening.cs
@@ -1,248 +1,248 @@
-//-----------------------------------------------------------------------------
-//
-// 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;
-using Microsoft.Boogie.VCExprAST;
-
-// Ensure that no formulas (expressions of type boolean that are not
-// just a variable) occur with terms (expressions of some other
-// type). This is done by introducing let-binders for boolean
-// variables.
-
-namespace Microsoft.Boogie.VCExprAST
-{
-
- public struct FlattenerState {
- public readonly int Polarity;
- public readonly bool InTerm;
-
- public static FlattenerState INITIAL = new FlattenerState(1, false);
-
- public FlattenerState(int polarity, bool inTerm) {
- Polarity = polarity;
- InTerm = inTerm;
- }
-
- public FlattenerState TogglePolarity { get {
- return new FlattenerState(-Polarity, InTerm);
- } }
-
- public FlattenerState ZeroPolarity { get {
- return new FlattenerState(0, InTerm);
- } }
-
- public FlattenerState EnterTerm { get {
- return new FlattenerState(Polarity, true);
- } }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- public class TermFormulaFlattener : MutatingVCExprVisitor<FlattenerState> {
-
- public TermFormulaFlattener(VCExpressionGenerator gen):base(gen){
-Contract.Requires(gen != null);
-
- }
-
- private readonly IDictionary<VCExpr/*!*/, VCExprVar/*!*/>/*!*/ Bindings =
- new Dictionary<VCExpr/*!*/, VCExprVar/*!*/> ();
-
- private int varNameCounter = 0;
-
- public VCExpr Flatten(VCExpr expr){
-Contract.Requires(expr != null);
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr/*!*/ res = Mutate(expr, FlattenerState.INITIAL);
- Contract.Assert(res != null);
- while (Bindings.Count > 0) {
- List<VCExprLetBinding/*!*/>/*!*/ letBindings = new List<VCExprLetBinding/*!*/> ();
- foreach (KeyValuePair<VCExpr/*!*/, VCExprVar/*!*/> pair in Bindings){Contract.Assert(cce.NonNullElements(pair));
- letBindings.Add(Gen.LetBinding(pair.Value, pair.Key));}
- Bindings.Clear();
- res = AddBindings(letBindings, res, FlattenerState.INITIAL);
- }
- return res;
- }
-
- private VCExprVar GetVarFor(VCExpr expr){
-Contract.Requires(expr != null);
-Contract.Requires((expr.Type.IsBool));
-Contract.Ensures(Contract.Result<VCExprVar>() != null);
- VCExprVar res;
- if (!Bindings.TryGetValue(expr, out res)) {
- string name = "flt" + varNameCounter;
- varNameCounter = varNameCounter + 1;
- res = Gen.Variable(name, Type.Bool);
- Bindings.Add(expr, res);
- }
- return cce.NonNull(res);
- }
-
- // Remove all let-bindings from the field bindings whose rhs
- // contains any of the specified variables
- private List<VCExprLetBinding/*!*/>/*!*/ RemoveBindingsWithVars(List<VCExprVar/*!*/>/*!*/ boundVars, List<TypeVariable/*!*/>/*!*/ boundTypeVars){
-Contract.Requires(cce.NonNullElements(boundTypeVars));
-Contract.Requires(cce.NonNullElements(boundVars));
-Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprLetBinding>>()));
- List<VCExprLetBinding/*!*/>/*!*/ res = new List<VCExprLetBinding/*!*/> ();
- FreeVariableCollector/*!*/ coll = new FreeVariableCollector ();
-
- foreach (KeyValuePair<VCExpr, VCExprVar> pair in Bindings) {
- Contract.Assert(cce.NonNullElements(pair));
- coll.Collect(pair.Key);
- if (boundVars.Any(var => coll.FreeTermVars.ContainsKey(var)) ||
- boundTypeVars.Any(var => coll.FreeTypeVars.Contains(var)))
- res.Add(Gen.LetBinding(pair.Value, pair.Key));
- coll.Reset();
- }
-
- foreach (VCExprLetBinding b in res){Contract.Assert(b != null);
- Bindings.Remove(b.E);}
-
- return res;
- }
-
- // Add bindings to a formula using an implication or
- // conjunction. The bindings themselves will be flattened as well,
- // which might introduce further bindings
- private VCExpr AddBindings(List<VCExprLetBinding/*!*/>/*!*/ bindings, VCExpr body, FlattenerState state){
-Contract.Requires(body != null);
-Contract.Requires(cce.NonNullElements(bindings));
-Contract.Requires((body.Type.IsBool));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- List<VCExprLetBinding/*!*/>/*!*/ mutatedBindings = FlattenBindings(bindings, state);
- Contract.Assert(mutatedBindings != null);
- VCExpr/*!*/ bindingEquations = Gen.AsEquations(mutatedBindings);
- Contract.Assert(bindingEquations != null);
- switch(state.Polarity) {
- case 1:
- return Gen.Implies(bindingEquations, body);
- case -1:
- return Gen.And(bindingEquations, body);
- case 0:
- // also add explicit quantifiers for the bound variables
- List<VCExprVar/*!*/>/*!*/ vars = new List<VCExprVar/*!*/> ();
- foreach (VCExprLetBinding/*!*/ binding in mutatedBindings){Contract.Assert(binding != null);
- vars.Add(binding.V);}
- return Gen.Forall(vars, new List<VCTrigger/*!*/>(),
- Gen.Implies(bindingEquations, body));
- }
- Contract.Assert(false); throw new cce.UnreachableException();
- }
-
- private List<VCExprLetBinding/*!*/>/*!*/ FlattenBindings(List<VCExprLetBinding/*!*/>/*!*/ bindings, FlattenerState state){
-Contract.Requires(cce.NonNullElements(bindings));
-Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprLetBinding>>()));
- FlattenerState stateInBindings = state.ZeroPolarity;
- List<VCExprLetBinding/*!*/>/*!*/ mutatedBindings = new List<VCExprLetBinding/*!*/> ();
- foreach (VCExprLetBinding/*!*/ b in bindings) {
- Contract.Assert(b != null);
- mutatedBindings.Add(Gen.LetBinding(b.V, Mutate(b.E, stateInBindings)));
- }
- return mutatedBindings;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override bool AvoidVisit(VCExprNAry node, FlattenerState arg)
- {
- return node.Op.Equals(VCExpressionGenerator.AndOp) ||
- node.Op.Equals(VCExpressionGenerator.OrOp);
- }
-
- public override VCExpr Visit(VCExprNAry node, FlattenerState state){
-Contract.Requires(node != null);
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- // track the polarity to know whether implications or conjunctions
- // are to be introduced
-
- if (node.Op.Equals(VCExpressionGenerator.NotOp))
- return Gen.Not(Mutate(node[0], state.TogglePolarity));
-
- if (node.Op.Equals(VCExpressionGenerator.ImpliesOp)) {
- VCExpr newArg0 = Mutate(node[0], state.TogglePolarity);
- VCExpr newArg1 = Mutate(node[1], state);
- return Gen.Implies(newArg0, newArg1);
- }
-
- if (!node.Type.IsBool)
- state = state.EnterTerm;
-
- if (!node.Op.Equals(VCExpressionGenerator.AndOp) &&
- !node.Op.Equals(VCExpressionGenerator.OrOp) &&
- !(node.Op is VCExprLabelOp))
- // standard is to set the polarity to 0 (fits most operators)
- return base.Visit(node, state.ZeroPolarity);
-
- return base.Visit(node, state);
- }
-
- public override VCExpr Visit(VCExprQuantifier node, FlattenerState state){
-Contract.Requires(node != null);
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (state.InTerm)
- return GetVarFor(node);
-
- // we only flatten within the matrix of the quantified formula,
- // not within the triggers (since SMT-solvers do not seem to
- // appreciate triggers with let-binders)
- VCExpr newBody = Mutate(node.Body, state);
-
- // Check whether any of the extracted terms contain variables
- // bound by this quantifier. In this case, we have to add
- // let-binders and remove the extracted terms
- bool cont = true;
- while (cont) {
- List<VCExprLetBinding/*!*/>/*!*/ localBindings =
- RemoveBindingsWithVars(node.BoundVars, node.TypeParameters);
- Contract.Assert(cce.NonNullElements(localBindings));
- if (localBindings.Count > 0)
- newBody = AddBindings(localBindings, newBody, state);
- else
- cont = false;
- }
-
- return Gen.Quantify(node.Quan, node.TypeParameters, node.BoundVars, node.Triggers, node.Infos, newBody);
- }
-
- public override VCExpr Visit(VCExprLet node, FlattenerState state){
-Contract.Requires(node != null);
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (state.InTerm)
- return GetVarFor(node);
-
- VCExprLet prelimRes = (VCExprLet)cce.NonNull(base.Visit(node, state));
-
- List<VCExprLetBinding/*!*/>/*!*/ allBindings = new List<VCExprLetBinding/*!*/> ();
- allBindings.AddRange(prelimRes);
-
- // Check whether any of the extracted terms contain variables
- // bound by this binder. In this case, we have to add
- // let-binders and remove the extracted terms
- bool cont = true;
- while (cont) {
- List<VCExprLetBinding/*!*/>/*!*/ localBindings =
- RemoveBindingsWithVars(prelimRes.BoundVars, new List<TypeVariable/*!*/>());
- if (localBindings.Count > 0)
- allBindings.AddRange(FlattenBindings(localBindings, state));
- else
- cont = false;
- }
-
- return Gen.Let(allBindings, prelimRes.Body);
- }
-
- }
-
+//-----------------------------------------------------------------------------
+//
+// 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;
+using Microsoft.Boogie.VCExprAST;
+
+// Ensure that no formulas (expressions of type boolean that are not
+// just a variable) occur with terms (expressions of some other
+// type). This is done by introducing let-binders for boolean
+// variables.
+
+namespace Microsoft.Boogie.VCExprAST
+{
+
+ public struct FlattenerState {
+ public readonly int Polarity;
+ public readonly bool InTerm;
+
+ public static FlattenerState INITIAL = new FlattenerState(1, false);
+
+ public FlattenerState(int polarity, bool inTerm) {
+ Polarity = polarity;
+ InTerm = inTerm;
+ }
+
+ public FlattenerState TogglePolarity { get {
+ return new FlattenerState(-Polarity, InTerm);
+ } }
+
+ public FlattenerState ZeroPolarity { get {
+ return new FlattenerState(0, InTerm);
+ } }
+
+ public FlattenerState EnterTerm { get {
+ return new FlattenerState(Polarity, true);
+ } }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class TermFormulaFlattener : MutatingVCExprVisitor<FlattenerState> {
+
+ public TermFormulaFlattener(VCExpressionGenerator gen):base(gen){
+Contract.Requires(gen != null);
+
+ }
+
+ private readonly IDictionary<VCExpr/*!*/, VCExprVar/*!*/>/*!*/ Bindings =
+ new Dictionary<VCExpr/*!*/, VCExprVar/*!*/> ();
+
+ private int varNameCounter = 0;
+
+ public VCExpr Flatten(VCExpr expr){
+Contract.Requires(expr != null);
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr/*!*/ res = Mutate(expr, FlattenerState.INITIAL);
+ Contract.Assert(res != null);
+ while (Bindings.Count > 0) {
+ List<VCExprLetBinding/*!*/>/*!*/ letBindings = new List<VCExprLetBinding/*!*/> ();
+ foreach (KeyValuePair<VCExpr/*!*/, VCExprVar/*!*/> pair in Bindings){Contract.Assert(cce.NonNullElements(pair));
+ letBindings.Add(Gen.LetBinding(pair.Value, pair.Key));}
+ Bindings.Clear();
+ res = AddBindings(letBindings, res, FlattenerState.INITIAL);
+ }
+ return res;
+ }
+
+ private VCExprVar GetVarFor(VCExpr expr){
+Contract.Requires(expr != null);
+Contract.Requires((expr.Type.IsBool));
+Contract.Ensures(Contract.Result<VCExprVar>() != null);
+ VCExprVar res;
+ if (!Bindings.TryGetValue(expr, out res)) {
+ string name = "flt" + varNameCounter;
+ varNameCounter = varNameCounter + 1;
+ res = Gen.Variable(name, Type.Bool);
+ Bindings.Add(expr, res);
+ }
+ return cce.NonNull(res);
+ }
+
+ // Remove all let-bindings from the field bindings whose rhs
+ // contains any of the specified variables
+ private List<VCExprLetBinding/*!*/>/*!*/ RemoveBindingsWithVars(List<VCExprVar/*!*/>/*!*/ boundVars, List<TypeVariable/*!*/>/*!*/ boundTypeVars){
+Contract.Requires(cce.NonNullElements(boundTypeVars));
+Contract.Requires(cce.NonNullElements(boundVars));
+Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprLetBinding>>()));
+ List<VCExprLetBinding/*!*/>/*!*/ res = new List<VCExprLetBinding/*!*/> ();
+ FreeVariableCollector/*!*/ coll = new FreeVariableCollector ();
+
+ foreach (KeyValuePair<VCExpr, VCExprVar> pair in Bindings) {
+ Contract.Assert(cce.NonNullElements(pair));
+ coll.Collect(pair.Key);
+ if (boundVars.Any(var => coll.FreeTermVars.ContainsKey(var)) ||
+ boundTypeVars.Any(var => coll.FreeTypeVars.Contains(var)))
+ res.Add(Gen.LetBinding(pair.Value, pair.Key));
+ coll.Reset();
+ }
+
+ foreach (VCExprLetBinding b in res){Contract.Assert(b != null);
+ Bindings.Remove(b.E);}
+
+ return res;
+ }
+
+ // Add bindings to a formula using an implication or
+ // conjunction. The bindings themselves will be flattened as well,
+ // which might introduce further bindings
+ private VCExpr AddBindings(List<VCExprLetBinding/*!*/>/*!*/ bindings, VCExpr body, FlattenerState state){
+Contract.Requires(body != null);
+Contract.Requires(cce.NonNullElements(bindings));
+Contract.Requires((body.Type.IsBool));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ List<VCExprLetBinding/*!*/>/*!*/ mutatedBindings = FlattenBindings(bindings, state);
+ Contract.Assert(mutatedBindings != null);
+ VCExpr/*!*/ bindingEquations = Gen.AsEquations(mutatedBindings);
+ Contract.Assert(bindingEquations != null);
+ switch(state.Polarity) {
+ case 1:
+ return Gen.Implies(bindingEquations, body);
+ case -1:
+ return Gen.And(bindingEquations, body);
+ case 0:
+ // also add explicit quantifiers for the bound variables
+ List<VCExprVar/*!*/>/*!*/ vars = new List<VCExprVar/*!*/> ();
+ foreach (VCExprLetBinding/*!*/ binding in mutatedBindings){Contract.Assert(binding != null);
+ vars.Add(binding.V);}
+ return Gen.Forall(vars, new List<VCTrigger/*!*/>(),
+ Gen.Implies(bindingEquations, body));
+ }
+ Contract.Assert(false); throw new cce.UnreachableException();
+ }
+
+ private List<VCExprLetBinding/*!*/>/*!*/ FlattenBindings(List<VCExprLetBinding/*!*/>/*!*/ bindings, FlattenerState state){
+Contract.Requires(cce.NonNullElements(bindings));
+Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprLetBinding>>()));
+ FlattenerState stateInBindings = state.ZeroPolarity;
+ List<VCExprLetBinding/*!*/>/*!*/ mutatedBindings = new List<VCExprLetBinding/*!*/> ();
+ foreach (VCExprLetBinding/*!*/ b in bindings) {
+ Contract.Assert(b != null);
+ mutatedBindings.Add(Gen.LetBinding(b.V, Mutate(b.E, stateInBindings)));
+ }
+ return mutatedBindings;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override bool AvoidVisit(VCExprNAry node, FlattenerState arg)
+ {
+ return node.Op.Equals(VCExpressionGenerator.AndOp) ||
+ node.Op.Equals(VCExpressionGenerator.OrOp);
+ }
+
+ public override VCExpr Visit(VCExprNAry node, FlattenerState state){
+Contract.Requires(node != null);
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // track the polarity to know whether implications or conjunctions
+ // are to be introduced
+
+ if (node.Op.Equals(VCExpressionGenerator.NotOp))
+ return Gen.Not(Mutate(node[0], state.TogglePolarity));
+
+ if (node.Op.Equals(VCExpressionGenerator.ImpliesOp)) {
+ VCExpr newArg0 = Mutate(node[0], state.TogglePolarity);
+ VCExpr newArg1 = Mutate(node[1], state);
+ return Gen.Implies(newArg0, newArg1);
+ }
+
+ if (!node.Type.IsBool)
+ state = state.EnterTerm;
+
+ if (!node.Op.Equals(VCExpressionGenerator.AndOp) &&
+ !node.Op.Equals(VCExpressionGenerator.OrOp) &&
+ !(node.Op is VCExprLabelOp))
+ // standard is to set the polarity to 0 (fits most operators)
+ return base.Visit(node, state.ZeroPolarity);
+
+ return base.Visit(node, state);
+ }
+
+ public override VCExpr Visit(VCExprQuantifier node, FlattenerState state){
+Contract.Requires(node != null);
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (state.InTerm)
+ return GetVarFor(node);
+
+ // we only flatten within the matrix of the quantified formula,
+ // not within the triggers (since SMT-solvers do not seem to
+ // appreciate triggers with let-binders)
+ VCExpr newBody = Mutate(node.Body, state);
+
+ // Check whether any of the extracted terms contain variables
+ // bound by this quantifier. In this case, we have to add
+ // let-binders and remove the extracted terms
+ bool cont = true;
+ while (cont) {
+ List<VCExprLetBinding/*!*/>/*!*/ localBindings =
+ RemoveBindingsWithVars(node.BoundVars, node.TypeParameters);
+ Contract.Assert(cce.NonNullElements(localBindings));
+ if (localBindings.Count > 0)
+ newBody = AddBindings(localBindings, newBody, state);
+ else
+ cont = false;
+ }
+
+ return Gen.Quantify(node.Quan, node.TypeParameters, node.BoundVars, node.Triggers, node.Infos, newBody);
+ }
+
+ public override VCExpr Visit(VCExprLet node, FlattenerState state){
+Contract.Requires(node != null);
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (state.InTerm)
+ return GetVarFor(node);
+
+ VCExprLet prelimRes = (VCExprLet)cce.NonNull(base.Visit(node, state));
+
+ List<VCExprLetBinding/*!*/>/*!*/ allBindings = new List<VCExprLetBinding/*!*/> ();
+ allBindings.AddRange(prelimRes);
+
+ // Check whether any of the extracted terms contain variables
+ // bound by this binder. In this case, we have to add
+ // let-binders and remove the extracted terms
+ bool cont = true;
+ while (cont) {
+ List<VCExprLetBinding/*!*/>/*!*/ localBindings =
+ RemoveBindingsWithVars(prelimRes.BoundVars, new List<TypeVariable/*!*/>());
+ if (localBindings.Count > 0)
+ allBindings.AddRange(FlattenBindings(localBindings, state));
+ else
+ cont = false;
+ }
+
+ return Gen.Let(allBindings, prelimRes.Body);
+ }
+
+ }
+
} \ No newline at end of file
diff --git a/Source/VCExpr/TypeErasure.cs b/Source/VCExpr/TypeErasure.cs
index 2326ba7a..76340f97 100644
--- a/Source/VCExpr/TypeErasure.cs
+++ b/Source/VCExpr/TypeErasure.cs
@@ -1,1619 +1,1619 @@
-//-----------------------------------------------------------------------------
-//
-// 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;
-using Microsoft.Boogie.VCExprAST;
-
-// different classes for erasing complex types in VCExprs, replacing them
-// with axioms that can be handled by theorem provers and SMT solvers
-
-namespace Microsoft.Boogie.TypeErasure {
- using Microsoft.Boogie.VCExprAST;
-
- // some functionality that is needed in many places (and that should
- // really be provided by the Spec# container classes; maybe one
- // could integrate the functions in a nicer way?)
- public class HelperFuns {
-
- public static Function BoogieFunction(string name, List<TypeVariable/*!*/>/*!*/ typeParams, params Type[] types) {
- Contract.Requires(types != null);
- Contract.Requires(name != null);
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Requires(types.Length > 0);
- Contract.Requires(Contract.ForAll(0, types.Length, i => types[i] != null));
- Contract.Ensures(Contract.Result<Function>() != null);
-
- List<Variable> args = new List<Variable>();
- for (int i = 0; i < types.Length - 1; ++i)
- args.Add(new Formal(Token.NoToken,
- new TypedIdent(Token.NoToken, "arg" + i, cce.NonNull(types[i])),
- true));
- Formal result = new Formal(Token.NoToken,
- new TypedIdent(Token.NoToken, "res",
- cce.NonNull(types)[types.Length - 1]),
- false);
- return new Function(Token.NoToken, name, new List<TypeVariable>(typeParams), args, result);
- }
-
- public static Function BoogieFunction(string name, params Type[] types) {
- Contract.Requires(types != null);
- Contract.Requires(name != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- return BoogieFunction(name, new List<TypeVariable/*!*/>(), types);
- }
-
- // boogie function where all arguments and the result have the same type U
- public static Function UniformBoogieFunction(string name, int arity, Type U) {
- Contract.Requires(U != null);
- Contract.Requires(name != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- Type[]/*!*/ types = new Type[arity + 1];
- for (int i = 0; i < arity + 1; ++i)
- types[i] = U;
- return BoogieFunction(name, types);
- }
-
- public static List<VCExprVar/*!*/>/*!*/ GenVarsForInParams(Function fun, VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Contract.Requires(fun != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
- List<VCExprVar/*!*/>/*!*/ arguments = new List<VCExprVar/*!*/>(fun.InParams.Count);
- foreach (Formal/*!*/ f in fun.InParams) {
- Contract.Assert(f != null);
- VCExprVar/*!*/ var = gen.Variable(f.Name, f.TypedIdent.Type);
- arguments.Add(var);
- }
- return arguments;
- }
-
- public static List<T/*!*/>/*!*/ ToList<T>(params T[] args) where T : class{
- Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<T>>()));
- return new List<T>(args);
- }
-
- public static List<VCExpr/*!*/>/*!*/ ToVCExprList(List<VCExprVar/*!*/>/*!*/ list) {
- Contract.Requires(cce.NonNullElements(list));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
- return new List<VCExpr>(list);
- }
-
- public static List<VCExprVar/*!*/>/*!*/ VarVector(string baseName, int num, Type type, VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Contract.Requires(type != null);
- Contract.Requires(baseName != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
- List<VCExprVar/*!*/>/*!*/ res = new List<VCExprVar/*!*/>(num);
- for (int i = 0; i < num; ++i)
- res.Add(gen.Variable(baseName + i, type));
- return res;
- }
-
- public static List<VCExprVar/*!*/>/*!*/ VarVector(string baseName, List<Type/*!*/>/*!*/ types, VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Contract.Requires(baseName != null);
- Contract.Requires(cce.NonNullElements(types));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
- List<VCExprVar/*!*/>/*!*/ res = new List<VCExprVar/*!*/>(types.Count);
- for (int i = 0; i < types.Count; ++i)
- res.Add(gen.Variable(baseName + i, types[i]));
- return res;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- internal struct TypeCtorRepr {
- // function that represents the application of the type constructor
- // to smaller types
- public readonly Function/*!*/ Ctor;
- // left-inverse functions that extract the subtypes of a compound type
- public readonly List<Function/*!*/>/*!*/ Dtors;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Ctor != null);
- Contract.Invariant(cce.NonNullElements(Dtors));
- }
-
-
- public TypeCtorRepr(Function ctor, List<Function/*!*/>/*!*/ dtors) {
- Contract.Requires(ctor != null);
- Contract.Requires(cce.NonNullElements(dtors));
- Contract.Requires(ctor.InParams.Count == dtors.Count);
- this.Ctor = ctor;
- this.Dtors = dtors;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- // The class responsible for creating and keeping track of all
- // axioms related to the type system. This abstract class is made
- // concrete in two subclasses, one for type erasure with type
- // premisses in quantifiers (the semantic approach), and one for
- // type erasure with explicit type arguments of polymorphic
- // functions (the syntacted approach).
- [ContractClass(typeof(TypeAxiomBuilderContracts))]
- public abstract class TypeAxiomBuilder : ICloneable {
-
- protected readonly VCExpressionGenerator/*!*/ Gen;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Gen != null);
- Contract.Invariant(Ctor != null);
-
- }
-
-
- internal abstract MapTypeAbstractionBuilder/*!*/ MapTypeAbstracter {
- get;
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // Type Axioms
-
- // list in which all typed axioms are collected
- private readonly List<VCExpr/*!*/>/*!*/ AllTypeAxioms;
- [ContractInvariantMethod]
- void AllTypeAxiomsInvariantMethod() {
- Contract.Invariant(cce.NonNullElements(AllTypeAxioms));
- }
-
- // list in which type axioms are incrementally collected
- private readonly List<VCExpr/*!*/>/*!*/ IncTypeAxioms;
- [ContractInvariantMethod]
- void IncTypeAxiomsInvariantMethod() {
- Contract.Invariant(cce.NonNullElements(IncTypeAxioms));
- }
-
- internal void AddTypeAxiom(VCExpr axiom) {
- Contract.Requires(axiom != null);
- AllTypeAxioms.Add(axiom);
- IncTypeAxioms.Add(axiom);
- }
-
- // Return all axioms that were added since the last time NewAxioms
- // was called
- public VCExpr GetNewAxioms() {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr/*!*/ res = Gen.NAry(VCExpressionGenerator.AndOp, IncTypeAxioms);
- IncTypeAxioms.Clear();
- return res;
- }
-
- // mapping from a type to its constructor number/index
- private readonly Function/*!*/ Ctor;
- private BigNum CurrentCtorNum;
-
- private VCExpr GenCtorAssignment(VCExpr typeRepr) {
- Contract.Requires(typeRepr != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (CommandLineOptions.Clo.TypeEncodingMethod
- == CommandLineOptions.TypeEncoding.None)
- return VCExpressionGenerator.True;
-
- VCExpr res = Gen.Eq(Gen.Function(Ctor, typeRepr),
- Gen.Integer(CurrentCtorNum));
- CurrentCtorNum = CurrentCtorNum + BigNum.ONE;
- return res;
- }
-
- private VCExpr GenCtorAssignment(Function typeRepr) {
- Contract.Requires(typeRepr != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (CommandLineOptions.Clo.TypeEncodingMethod
- == CommandLineOptions.TypeEncoding.None)
- return VCExpressionGenerator.True;
-
- List<VCExprVar/*!*/>/*!*/ quantifiedVars = HelperFuns.GenVarsForInParams(typeRepr, Gen);
- VCExpr/*!*/ eq =
- GenCtorAssignment(Gen.Function(typeRepr,
- HelperFuns.ToVCExprList(quantifiedVars)));
-
- if (typeRepr.InParams.Count == 0)
- return eq;
-
- return Gen.Forall(quantifiedVars, new List<VCTrigger/*!*/>(),
- "ctor:" + typeRepr.Name, -1, eq);
- }
-
- // generate an axiom (forall x0, x1, ... :: invFun(fun(x0, x1, ...) == xi)
- protected VCExpr GenLeftInverseAxiom(Function fun, Function invFun, int dtorNum) {
- Contract.Requires(invFun != null);
- Contract.Requires(fun != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCExprVar/*!*/>/*!*/ quantifiedVars = HelperFuns.GenVarsForInParams(fun, Gen);
- Contract.Assert(cce.NonNullElements(quantifiedVars));
-
- VCExpr/*!*/ funApp = Gen.Function(fun, HelperFuns.ToVCExprList(quantifiedVars));
- VCExpr/*!*/ lhs = Gen.Function(invFun, funApp);
- VCExpr/*!*/ rhs = quantifiedVars[dtorNum];
- VCExpr/*!*/ eq = Gen.Eq(lhs, rhs);
-
- List<VCTrigger/*!*/>/*!*/ triggers = HelperFuns.ToList(Gen.Trigger(true, HelperFuns.ToList(funApp)));
- Contract.Assert(cce.NonNullElements(triggers));
- return Gen.Forall(quantifiedVars, triggers, "typeInv:" + invFun.Name, -1, eq);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- // the type of everything that is not int, bool, or a type
- [ContractInvariantMethod]
- void ObjectInvariant2() {
- Contract.Invariant(UDecl != null);
- Contract.Invariant(TDecl != null);
- Contract.Invariant(U != null);
- Contract.Invariant(T != null);
- }
-
- private readonly TypeCtorDecl/*!*/ UDecl;
- public readonly Type/*!*/ U;
-
- // the type of types
- private readonly TypeCtorDecl/*!*/ TDecl;
- public readonly Type/*!*/ T;
-
- public abstract Type/*!*/ TypeAfterErasure(Type/*!*/ type);
- [Pure]
- public abstract bool UnchangedType(Type/*!*/ type);
-
- ///////////////////////////////////////////////////////////////////////////
- // Symbols for representing types
-
- private readonly IDictionary<Type/*!*/, VCExpr/*!*/>/*!*/ BasicTypeReprs;
- [ContractInvariantMethod]
- void BasicTypeReprsInvariantMethod() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(BasicTypeReprs));
- }
-
- private VCExpr GetBasicTypeRepr(Type type) {
- Contract.Requires(type != null);
- Contract.Requires(type.IsBasic || type.IsBv);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr res;
- if (!BasicTypeReprs.TryGetValue(type, out res)) {
- res = Gen.Function(HelperFuns.BoogieFunction(type.ToString() + "Type", T));
- AddTypeAxiom(GenCtorAssignment(res));
- BasicTypeReprs.Add(type, res);
- }
- return cce.NonNull(res);
- }
-
- private readonly IDictionary<TypeCtorDecl/*!*/, TypeCtorRepr/*!*/>/*!*/ TypeCtorReprs;
- [ContractInvariantMethod]
- void TypeCtorReprsInvariantMethod() {
- Contract.Invariant(TypeCtorReprs != null);
- }
-
- internal TypeCtorRepr GetTypeCtorReprStruct(TypeCtorDecl decl) {
- Contract.Requires(decl != null);
- TypeCtorRepr reprSet;
- if (!TypeCtorReprs.TryGetValue(decl, out reprSet)) {
- Function/*!*/ ctor = HelperFuns.UniformBoogieFunction(decl.Name + "Type", decl.Arity, T);
- Contract.Assert(ctor != null);
- AddTypeAxiom(GenCtorAssignment(ctor));
-
- List<Function/*!*/>/*!*/ dtors = new List<Function/*!*/>(decl.Arity);
- for (int i = 0; i < decl.Arity; ++i) {
- Function/*!*/ dtor = HelperFuns.UniformBoogieFunction(decl.Name + "TypeInv" + i, 1, T);
- dtors.Add(dtor);
- AddTypeAxiom(GenLeftInverseAxiom(ctor, dtor, i));
- }
-
- reprSet = new TypeCtorRepr(ctor, dtors);
- TypeCtorReprs.Add(decl, reprSet);
- }
-
- return reprSet;
- }
-
- public Function GetTypeCtorRepr(TypeCtorDecl decl) {
- Contract.Requires(decl != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- return GetTypeCtorReprStruct(decl).Ctor;
- }
-
- public Function GetTypeDtor(TypeCtorDecl decl, int num) {
- Contract.Requires(decl != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- return GetTypeCtorReprStruct(decl).Dtors[num];
- }
-
- // mapping from free type variables to VCExpr variables
- private readonly IDictionary<TypeVariable/*!*/, VCExprVar/*!*/>/*!*/ TypeVariableMapping;
- [ContractInvariantMethod]
- void TypeVariableMappingInvariantMethod() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(TypeVariableMapping));
- }
-
- public VCExprVar Typed2Untyped(TypeVariable var) {
- Contract.Requires(var != null);
- Contract.Ensures(Contract.Result<VCExprVar>() != null);
- VCExprVar res;
- if (!TypeVariableMapping.TryGetValue(var, out res)) {
- res = new VCExprVar(var.Name, T);
- TypeVariableMapping.Add(var, res);
- }
- return cce.NonNull(res);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////
- // Symbols for representing variables and constants
-
- // Globally defined variables
- private readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ Typed2UntypedVariables;
- [ContractInvariantMethod]
- void Typed2UntypedVariablesInvariantMethod() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(Typed2UntypedVariables));
- }
-
- // This method must only be used for free (unbound) variables
- public VCExprVar Typed2Untyped(VCExprVar var) {
- Contract.Requires(var != null);
- Contract.Ensures(Contract.Result<VCExprVar>() != null);
- VCExprVar res = TryTyped2Untyped(var);
- if (res == null) {
- res = Gen.Variable(var.Name, TypeAfterErasure(var.Type));
- Typed2UntypedVariables.Add(var, res);
- AddVarTypeAxiom(res, var.Type);
- }
- return cce.NonNull(res);
- }
-
- /// <summary>
- /// This method is like Typed2Untyped, except in the case where the given variables
- /// doesn't exist in the mapping. For that case, this method returns null whereas
- /// Typed2Untyped creates a new variable that it adds to the mapping.
- /// </summary>
- /// <param name="var"></param>
- /// <returns></returns>
- public VCExprVar TryTyped2Untyped(VCExprVar var) {
- Contract.Requires(var != null);
- VCExprVar res;
- if (Typed2UntypedVariables.TryGetValue(var, out res)) {
- return res;
- } else {
- return null;
- }
- }
-
- protected abstract void AddVarTypeAxiom(VCExprVar/*!*/ var, Type/*!*/ originalType);
-
- ///////////////////////////////////////////////////////////////////////////
- // Translation function from types to their term representation
-
- public VCExpr Type2Term(Type type, IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ varMapping) {
- Contract.Requires(type != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(varMapping));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- //
- if (type.IsBasic || type.IsBv) {
- //
- return GetBasicTypeRepr(type);
- //
- } else if (type.IsCtor) {
- //
- CtorType ctype = type.AsCtor;
- Function/*!*/ repr = GetTypeCtorRepr(ctype.Decl);
- List<VCExpr/*!*/>/*!*/ args = new List<VCExpr/*!*/>(ctype.Arguments.Count);
- foreach (Type/*!*/ t in ctype.Arguments.ToArray()) {
- Contract.Assert(t != null);
- args.Add(Type2Term(t, varMapping));
- }
- return Gen.Function(repr, args);
- //
- } else if (type.IsVariable) {
- //
- VCExpr res;
- if (!varMapping.TryGetValue(type.AsVariable, out res))
- // then the variable is free and we bind it at this point to a term
- // variable
- res = Typed2Untyped(type.AsVariable);
- return cce.NonNull(res);
- //
- } else if (type.IsMap) {
- //
- return Type2Term(MapTypeAbstracter.AbstractMapType(type.AsMap), varMapping);
- //
- } else {
- System.Diagnostics.Debug.Fail("Don't know how to handle this type: " + type);
- Contract.Assert(false);
- throw new cce.UnreachableException(); // please the compiler
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public TypeAxiomBuilder(VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- this.Gen = gen;
- AllTypeAxioms = new List<VCExpr/*!*/>();
- IncTypeAxioms = new List<VCExpr/*!*/>();
- BasicTypeReprs = new Dictionary<Type/*!*/, VCExpr/*!*/>();
- CurrentCtorNum = BigNum.ZERO;
- TypeCtorReprs = new Dictionary<TypeCtorDecl/*!*/, TypeCtorRepr>();
- TypeVariableMapping = new Dictionary<TypeVariable/*!*/, VCExprVar/*!*/>();
- Typed2UntypedVariables = new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>();
-
- TypeCtorDecl/*!*/ uDecl = new TypeCtorDecl(Token.NoToken, "U", 0);
- UDecl = uDecl;
- Type/*!*/ u = new CtorType(Token.NoToken, uDecl, new List<Type>());
- U = u;
-
- TypeCtorDecl/*!*/ tDecl = new TypeCtorDecl(Token.NoToken, "T", 0);
- TDecl = tDecl;
- Type/*!*/ t = new CtorType(Token.NoToken, tDecl, new List<Type>());
- T = t;
-
- Ctor = HelperFuns.BoogieFunction("Ctor", t, Type.Int);
- }
-
- public virtual void Setup() {
- GetBasicTypeRepr(Type.Int);
- GetBasicTypeRepr(Type.Real);
- GetBasicTypeRepr(Type.Bool);
- }
-
- // constructor to allow cloning
- internal TypeAxiomBuilder(TypeAxiomBuilder builder) {
- Contract.Requires(builder != null);
- Gen = builder.Gen;
- AllTypeAxioms = new List<VCExpr/*!*/>(builder.AllTypeAxioms);
- IncTypeAxioms = new List<VCExpr/*!*/>(builder.IncTypeAxioms);
-
- UDecl = builder.UDecl;
- U = builder.U;
-
- TDecl = builder.TDecl;
- T = builder.T;
-
- Ctor = builder.Ctor;
- CurrentCtorNum = builder.CurrentCtorNum;
-
- BasicTypeReprs = new Dictionary<Type/*!*/, VCExpr/*!*/>(builder.BasicTypeReprs);
- TypeCtorReprs = new Dictionary<TypeCtorDecl/*!*/, TypeCtorRepr>(builder.TypeCtorReprs);
-
- TypeVariableMapping =
- new Dictionary<TypeVariable/*!*/, VCExprVar/*!*/>(builder.TypeVariableMapping);
- Typed2UntypedVariables =
- new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>(builder.Typed2UntypedVariables);
- }
-
- public abstract Object/*!*/ Clone();
- }
-
- [ContractClassFor(typeof(TypeAxiomBuilder))]
- public abstract class TypeAxiomBuilderContracts : TypeAxiomBuilder {
- public TypeAxiomBuilderContracts()
- : base((VCExpressionGenerator)null) {
- }
- internal override MapTypeAbstractionBuilder MapTypeAbstracter {
- get {
- Contract.Ensures(Contract.Result<MapTypeAbstractionBuilder>() != null);
- throw new NotImplementedException();
- }
- }
-
- public override Type TypeAfterErasure(Type type) {
- Contract.Requires(type != null);
- Contract.Ensures(Contract.Result<Type>() != null);
-
- throw new NotImplementedException();
- }
-
- public override bool UnchangedType(Type type) {
- Contract.Requires(type != null);
- throw new NotImplementedException();
- }
-
- protected override void AddVarTypeAxiom(VCExprVar var, Type originalType) {
- Contract.Requires(var != null);
- Contract.Requires(originalType != null);
- throw new NotImplementedException();
- }
-
- public override object Clone() {
- Contract.Ensures(Contract.Result<object>() != null);
-
- throw new NotImplementedException();
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- // Subclass of the TypeAxiomBuilder that provides all functionality
- // to deal with native sorts of a theorem prover (that are the only
- // types left after erasing all other types). Currently, these are:
- //
- // U ... sort of all individuals/objects/values
- // T ... sort of all types
- // int ... integers
- // bool ... booleans
-
- [ContractClass(typeof(TypeAxiomBuilderIntBoolUContracts))]
- public abstract class TypeAxiomBuilderIntBoolU : TypeAxiomBuilder {
-
- public TypeAxiomBuilderIntBoolU(VCExpressionGenerator gen)
- : base(gen) {
- Contract.Requires(gen != null);
-
- TypeCasts = new Dictionary<Type/*!*/, TypeCastSet>();
- }
-
- // constructor to allow cloning
- internal TypeAxiomBuilderIntBoolU(TypeAxiomBuilderIntBoolU builder)
- : base(builder) {
- Contract.Requires(builder != null);
-
- TypeCasts = new Dictionary<Type/*!*/, TypeCastSet>(builder.TypeCasts);
- }
-
- public override void Setup() {
- base.Setup();
-
- GetTypeCasts(Type.Int);
- GetTypeCasts(Type.Real);
- GetTypeCasts(Type.Bool);
- }
-
- // generate inverse axioms for casts (castToU(castFromU(x)) = x, under certain premisses)
- protected abstract VCExpr/*!*/ GenReverseCastAxiom(Function/*!*/ castToU, Function/*!*/ castFromU);
-
- protected VCExpr GenReverseCastEq(Function castToU, Function castFromU, out VCExprVar var, out List<VCTrigger/*!*/>/*!*/ triggers) {
- Contract.Requires((castFromU != null));
- Contract.Requires((castToU != null));
- Contract.Ensures((cce.NonNullElements(Contract.ValueAtReturn(out triggers))));
- Contract.Ensures(Contract.ValueAtReturn(out var) != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- var = Gen.Variable("x", U);
-
- VCExpr inner = Gen.Function(castFromU, var);
- VCExpr lhs = Gen.Function(castToU, inner);
- triggers = HelperFuns.ToList(Gen.Trigger(true, HelperFuns.ToList(inner)));
-
- return Gen.Eq(lhs, var);
- }
-
- protected abstract VCExpr/*!*/ GenCastTypeAxioms(Function/*!*/ castToU, Function/*!*/ castFromU);
-
- ///////////////////////////////////////////////////////////////////////////
- // storage of type casts for types that are supposed to be left over in the
- // VCs (like int, bool, bitvectors)
-
- private readonly IDictionary<Type/*!*/, TypeCastSet/*!*/>/*!*/ TypeCasts;
- [ContractInvariantMethod]
- void TypeCastsInvariantMethod() {
- Contract.Invariant(TypeCasts != null);
- }
-
- private TypeCastSet GetTypeCasts(Type type) {
- Contract.Requires(type != null);
- TypeCastSet res;
- if (!TypeCasts.TryGetValue(type, out res)) {
- Function/*!*/ castToU = HelperFuns.BoogieFunction(type.ToString() + "_2_U", type, U);
- Function/*!*/ castFromU = HelperFuns.BoogieFunction("U_2_" + type.ToString(), U, type);
-
- AddTypeAxiom(GenLeftInverseAxiom(castToU, castFromU, 0));
- AddTypeAxiom(GenReverseCastAxiom(castToU, castFromU));
- AddTypeAxiom(GenCastTypeAxioms(castToU, castFromU));
-
- res = new TypeCastSet(castToU, castFromU);
- TypeCasts.Add(type, res);
- }
- return res;
- }
- [Pure]
- public Function CastTo(Type type) {
- Contract.Requires(type != null);
- Contract.Requires(UnchangedType(type));
- Contract.Ensures(Contract.Result<Function>() != null);
- return GetTypeCasts(type).CastFromU;
- }
-
- public Function CastFrom(Type type) {
- Contract.Requires(type != null);
- Contract.Requires((UnchangedType(type)));
- Contract.Ensures(Contract.Result<Function>() != null);
- return GetTypeCasts(type).CastToU;
- }
-
- private struct TypeCastSet {
- public readonly Function/*!*/ CastToU;
- public readonly Function/*!*/ CastFromU;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(CastToU != null);
- Contract.Invariant(CastFromU != null);
- }
-
-
- public TypeCastSet(Function castToU, Function castFromU) {
- Contract.Requires(castFromU != null);
- Contract.Requires(castToU != null);
- CastToU = castToU;
- CastFromU = castFromU;
- }
- }
-
- public bool IsCast(Function fun) {
- Contract.Requires(fun != null);
- if (fun.InParams.Count != 1)
- return false;
- Type/*!*/ inType = cce.NonNull(fun.InParams[0]).TypedIdent.Type;
- if (inType.Equals(U)) {
- Type/*!*/ outType = cce.NonNull(fun.OutParams[0]).TypedIdent.Type;
- if (!TypeCasts.ContainsKey(outType))
- return false;
- return fun.Equals(CastTo(outType));
- } else {
- if (!TypeCasts.ContainsKey(inType))
- return false;
- Type/*!*/ outType = cce.NonNull(fun.OutParams[0]).TypedIdent.Type;
- if (!outType.Equals(U))
- return false;
- return fun.Equals(CastFrom(inType));
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // the only types that we allow in "untyped" expressions are U,
- // Type.Int, Type.Real, and Type.Bool
-
- public override Type TypeAfterErasure(Type type) {
- //Contract.Requires(type != null);
- Contract.Ensures(Contract.Result<Type>() != null);
- if (UnchangedType(type))
- // these types are kept
- return type;
- else
- // all other types are replaced by U
- return U;
- }
-
- [Pure]
- public override bool UnchangedType(Type type) {
- //Contract.Requires(type != null);
- return type.IsInt || type.IsReal || type.IsBool || type.IsBv || (type.IsMap && CommandLineOptions.Clo.MonomorphicArrays);
- }
-
- public VCExpr Cast(VCExpr expr, Type toType) {
- Contract.Requires(toType != null);
- Contract.Requires(expr != null);
- Contract.Requires((expr.Type.Equals(U) || UnchangedType(expr.Type)));
- Contract.Requires((toType.Equals(U) || UnchangedType(toType)));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (expr.Type.Equals(toType))
- return expr;
-
- if (toType.Equals(U)) {
- return Gen.Function(CastFrom(expr.Type), expr);
- } else {
- Contract.Assert(expr.Type.Equals(U));
- return Gen.Function(CastTo(toType), expr);
- }
- }
-
- public List<VCExpr/*!*/>/*!*/ CastSeq(List<VCExpr/*!*/>/*!*/ exprs, Type toType) {
- Contract.Requires(toType != null);
- Contract.Requires(cce.NonNullElements(exprs));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
- List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>(exprs.Count);
- foreach (VCExpr/*!*/ expr in exprs) {
- Contract.Assert(expr != null);
- res.Add(Cast(expr, toType));
- }
- return res;
- }
-
-
- }
-
- [ContractClassFor(typeof(TypeAxiomBuilderIntBoolU))]
- public abstract class TypeAxiomBuilderIntBoolUContracts : TypeAxiomBuilderIntBoolU {
- public TypeAxiomBuilderIntBoolUContracts()
- : base((TypeAxiomBuilderIntBoolU)null) {
- }
- protected override VCExpr GenReverseCastAxiom(Function castToU, Function castFromU) {
- Contract.Requires(castToU != null);
- Contract.Requires(castFromU != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- throw new NotImplementedException();
- }
-
- protected override VCExpr GenCastTypeAxioms(Function castToU, Function castFromU) {
- Contract.Requires(castFromU != null);
- Contract.Requires(castToU != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- throw new NotImplementedException();
- }
-
- internal override MapTypeAbstractionBuilder MapTypeAbstracter {
- get {
- throw new NotImplementedException();
- }
- }
-
- protected override void AddVarTypeAxiom(VCExprVar var, Type originalType) {
- throw new NotImplementedException();
- }
-
- public override object Clone() {
- throw new NotImplementedException();
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // Class for computing most general abstractions of map types. An abstraction
- // of a map type t is a maptype t' in which closed proper subtypes have been replaced
- // with type variables. E.g., an abstraction of <a>[C a, int]a would be <a>[C a, b]a.
- // We subsequently consider most general abstractions as ordinary parametrised types,
- // i.e., "<a>[C a, b]a" would be considered as a type "M b" with polymorphically typed
- // access functions
- //
- // select<a,b>(M b, C a, b) returns (a)
- // store<a,b>(M b, C a, b, a) returns (M b)
- [ContractClass(typeof(MapTypeAbstractionBuilderContracts))]
- internal abstract class MapTypeAbstractionBuilder {
-
- protected readonly TypeAxiomBuilder/*!*/ AxBuilder;
- protected readonly VCExpressionGenerator/*!*/ Gen;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilder != null);
- Contract.Invariant(Gen != null);
- }
-
-
- internal MapTypeAbstractionBuilder(TypeAxiomBuilder axBuilder, VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
- this.AxBuilder = axBuilder;
- this.Gen = gen;
- AbstractionVariables = new List<TypeVariable/*!*/>();
- ClassRepresentations = new Dictionary<MapType/*!*/, MapTypeClassRepresentation>();
- }
-
- // constructor for cloning
- internal MapTypeAbstractionBuilder(TypeAxiomBuilder axBuilder, VCExpressionGenerator gen, MapTypeAbstractionBuilder builder) {
- Contract.Requires(builder != null);
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
- this.AxBuilder = axBuilder;
- this.Gen = gen;
- AbstractionVariables =
- new List<TypeVariable/*!*/>(builder.AbstractionVariables);
- ClassRepresentations =
- new Dictionary<MapType/*!*/, MapTypeClassRepresentation>(builder.ClassRepresentations);
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // Type variables used in the abstractions. We use the same variables in the
- // same order in all abstractions in order to obtain comparable abstractions
- // (equals, hashcode)
-
- private readonly List<TypeVariable/*!*/>/*!*/ AbstractionVariables;
- [ContractInvariantMethod]
- void AbstractionVariablesInvariantMethod() {
- Contract.Invariant(cce.NonNullElements(AbstractionVariables));
- }
-
- private TypeVariable AbstractionVariable(int num) {
- Contract.Requires((num >= 0));
- Contract.Ensures(Contract.Result<TypeVariable>() != null);
- while (AbstractionVariables.Count <= num)
- AbstractionVariables.Add(new TypeVariable(Token.NoToken,
- "aVar" + AbstractionVariables.Count));
- return AbstractionVariables[num];
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // The untyped representation of a class of map types, i.e., of a map type
- // <a0, a1, ...>[A0, A1, ...] R, where the argument types and the result type
- // possibly contain free type variables. For each such class, a separate type
- // constructor and separate select/store functions are introduced.
-
- protected struct MapTypeClassRepresentation {
- public readonly TypeCtorDecl/*!*/ RepresentingType;
- public readonly Function/*!*/ Select;
- public readonly Function/*!*/ Store;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(RepresentingType != null);
- Contract.Invariant(Select != null);
- Contract.Invariant(Store != null);
- }
-
-
- public MapTypeClassRepresentation(TypeCtorDecl representingType, Function select, Function store) {
- Contract.Requires(store != null);
- Contract.Requires(select != null);
- Contract.Requires(representingType != null);
- this.RepresentingType = representingType;
- this.Select = select;
- this.Store = store;
- }
- }
-
- private readonly IDictionary<MapType/*!*/, MapTypeClassRepresentation/*!*/>/*!*/ ClassRepresentations;
- [ContractInvariantMethod]
- void ClassRepresentationsInvariantMethod() {
- Contract.Invariant(ClassRepresentations != null);
- }
-
- protected MapTypeClassRepresentation GetClassRepresentation(MapType abstractedType) {
- Contract.Requires(abstractedType != null);
- MapTypeClassRepresentation res;
- if (!ClassRepresentations.TryGetValue(abstractedType, out res)) {
- int num = ClassRepresentations.Count;
- TypeCtorDecl/*!*/ synonym =
- new TypeCtorDecl(Token.NoToken, "MapType" + num, abstractedType.FreeVariables.Count);
-
- Function/*!*/ select, store;
- GenSelectStoreFunctions(abstractedType, synonym, out select, out store);
-
- res = new MapTypeClassRepresentation(synonym, select, store);
- ClassRepresentations.Add(abstractedType, res);
- }
- return res;
- }
-
- // the actual select and store functions are generated by the
- // concrete subclasses of this class
- protected abstract void GenSelectStoreFunctions(MapType/*!*/ abstractedType, TypeCtorDecl/*!*/ synonymDecl, out Function/*!*/ select, out Function/*!*/ store);
-
- ///////////////////////////////////////////////////////////////////////////
-
- public Function Select(MapType rawType, out List<Type> instantiations) {
- Contract.Requires((rawType != null));
- Contract.Ensures(Contract.ValueAtReturn(out instantiations) != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- return AbstractAndGetRepresentation(rawType, out instantiations).Select;
- }
-
- public Function Store(MapType rawType, out List<Type> instantiations) {
- Contract.Requires((rawType != null));
- Contract.Ensures(Contract.ValueAtReturn(out instantiations) != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- return AbstractAndGetRepresentation(rawType, out instantiations).Store;
- }
-
- private MapTypeClassRepresentation
- AbstractAndGetRepresentation(MapType rawType, out List<Type> instantiations) {
- Contract.Requires((rawType != null));
- Contract.Ensures(Contract.ValueAtReturn(out instantiations) != null);
- instantiations = new List<Type>();
- MapType/*!*/ abstraction = ThinOutMapType(rawType, instantiations);
- return GetClassRepresentation(abstraction);
- }
-
- public CtorType AbstractMapType(MapType rawType) {
- Contract.Requires(rawType != null);
- Contract.Ensures(Contract.Result<CtorType>() != null);
- List<Type>/*!*/ instantiations = new List<Type>();
- MapType/*!*/ abstraction = ThinOutMapType(rawType, instantiations);
-
- MapTypeClassRepresentation repr = GetClassRepresentation(abstraction);
- Contract.Assume(repr.RepresentingType.Arity == instantiations.Count);
- return new CtorType(Token.NoToken, repr.RepresentingType, instantiations);
- }
-
- // TODO: cache the result of this operation
- protected MapType ThinOutMapType(MapType rawType, List<Type> instantiations) {
- Contract.Requires(instantiations != null);
- Contract.Requires(rawType != null);
- Contract.Ensures(Contract.Result<MapType>() != null);
- List<Type>/*!*/ newArguments = new List<Type>();
- foreach (Type/*!*/ subtype in rawType.Arguments.ToList()) {
- Contract.Assert(subtype != null);
- newArguments.Add(ThinOutType(subtype, rawType.TypeParameters,
- instantiations));
- }
- Type/*!*/ newResult = ThinOutType(rawType.Result, rawType.TypeParameters,
- instantiations);
- return new MapType(Token.NoToken, rawType.TypeParameters, newArguments, newResult);
- }
-
- // the instantiations of inserted type variables, the order corresponds to the order in which "AbstractionVariable(int)" delivers variables
- private Type/*!*/ ThinOutType(Type rawType, List<TypeVariable> boundTypeParams, List<Type> instantiations) {
- Contract.Requires(instantiations != null);
- Contract.Requires(boundTypeParams != null);
- Contract.Requires(rawType != null);
- Contract.Ensures(Contract.Result<Type>() != null);
-
- if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(rawType))
- return rawType;
-
- if (rawType.FreeVariables.All(var => !boundTypeParams.Contains(var))) {
- // Bingo!
- // if the type does not contain any bound variables, we can simply
- // replace it with a type variable
- TypeVariable/*!*/ abstractionVar = AbstractionVariable(instantiations.Count);
- Contract.Assume(!boundTypeParams.Contains(abstractionVar));
- instantiations.Add(rawType);
- return abstractionVar;
- }
-
- if (rawType.IsVariable) {
- //
- // then the variable has to be bound, we cannot do anything
- TypeVariable/*!*/ rawVar = rawType.AsVariable;
- Contract.Assume(boundTypeParams.Contains(rawVar));
- return rawVar;
- //
- } else if (rawType.IsMap) {
- //
- // recursively abstract this map type and continue abstracting
- CtorType/*!*/ abstraction = AbstractMapType(rawType.AsMap);
- return ThinOutType(abstraction, boundTypeParams, instantiations);
- //
- } else if (rawType.IsCtor) {
- //
- // traverse the subtypes
- CtorType/*!*/ rawCtorType = rawType.AsCtor;
- List<Type>/*!*/ newArguments = new List<Type>();
- foreach (Type/*!*/ subtype in rawCtorType.Arguments.ToList()) {
- Contract.Assert(subtype != null);
- newArguments.Add(ThinOutType(subtype, boundTypeParams,
- instantiations));
- }
- return new CtorType(Token.NoToken, rawCtorType.Decl, newArguments);
- //
- } else {
- System.Diagnostics.Debug.Fail("Don't know how to handle this type: " + rawType);
- return rawType; // compiler appeasement policy
- }
- }
-
- }
- [ContractClassFor(typeof(MapTypeAbstractionBuilder))]
- internal abstract class MapTypeAbstractionBuilderContracts : MapTypeAbstractionBuilder {
- public MapTypeAbstractionBuilderContracts()
- : base(null, null) {
- }
- protected override void GenSelectStoreFunctions(MapType abstractedType, TypeCtorDecl synonymDecl, out Function select, out Function store) {
- Contract.Requires(abstractedType != null);
- Contract.Requires(synonymDecl != null);
- Contract.Ensures(Contract.ValueAtReturn(out select) != null);
- Contract.Ensures(Contract.ValueAtReturn(out store) != null);
-
- throw new NotImplementedException();
- }
- }
-
-
- //////////////////////////////////////////////////////////////////////////////
-
- public class VariableBindings {
- public readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ VCExprVarBindings;
- public readonly IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ TypeVariableBindings;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(VCExprVarBindings));
- Contract.Invariant(cce.NonNullDictionaryAndValues(TypeVariableBindings));
- }
-
-
- public VariableBindings(IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ vcExprVarBindings,
- IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ typeVariableBindings) {
- Contract.Requires(cce.NonNullDictionaryAndValues(vcExprVarBindings));
- Contract.Requires(cce.NonNullDictionaryAndValues(typeVariableBindings));
- this.VCExprVarBindings = vcExprVarBindings;
- this.TypeVariableBindings = typeVariableBindings;
- }
-
- public VariableBindings() :
- this(new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>(),
- new Dictionary<TypeVariable/*!*/, VCExpr/*!*/>()) {
- }
-
- public VariableBindings Clone() {
- Contract.Ensures(Contract.Result<VariableBindings>() != null);
- IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ newVCExprVarBindings =
- new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>();
- foreach (KeyValuePair<VCExprVar/*!*/, VCExprVar/*!*/> pair in VCExprVarBindings) {
- Contract.Assert(cce.NonNullElements(pair));
- newVCExprVarBindings.Add(pair);
- }
- IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ newTypeVariableBindings =
- new Dictionary<TypeVariable/*!*/, VCExpr/*!*/>();
- foreach (KeyValuePair<TypeVariable/*!*/, VCExpr/*!*/> pair in TypeVariableBindings) {
- Contract.Assert(cce.NonNullElements(pair));
- newTypeVariableBindings.Add(pair);
- }
- return new VariableBindings(newVCExprVarBindings, newTypeVariableBindings);
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- // The central class for turning types VCExprs into untyped
- // VCExprs. This class makes use of the type axiom builder to manage
- // the available types and symbols.
- [ContractClass(typeof(TypeEraserContracts))]
- public abstract class TypeEraser : MutatingVCExprVisitor<VariableBindings/*!*/> {
-
- protected readonly TypeAxiomBuilderIntBoolU/*!*/ AxBuilder;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilder != null);
- }
-
-
- protected abstract OpTypeEraser/*!*/ OpEraser {
- get;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public TypeEraser(TypeAxiomBuilderIntBoolU axBuilder, VCExpressionGenerator gen)
- : base(gen) {
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
- AxBuilder = axBuilder;
- }
-
- public VCExpr Erase(VCExpr expr, int polarity) {
- Contract.Requires(expr != null);
- Contract.Requires((polarity >= -1 && polarity <= 1));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- this.Polarity = polarity;
- return Mutate(expr, new VariableBindings());
- }
-
- internal int Polarity = 1; // 1 for positive, -1 for negative, 0 for both
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override VCExpr Visit(VCExprLiteral node, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- Contract.Assume(node.Type == Type.Bool || node.Type == Type.Int || node.Type == Type.Real);
- return node;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override bool AvoidVisit(VCExprNAry node, VariableBindings arg)
- {
- return node.Op.Equals(VCExpressionGenerator.AndOp) ||
- node.Op.Equals(VCExpressionGenerator.OrOp);
- }
-
- public override VCExpr Visit(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExprOp/*!*/ op = node.Op;
- if (op == VCExpressionGenerator.AndOp || op == VCExpressionGenerator.OrOp)
- // more efficient on large conjunctions/disjunctions
- return base.Visit(node, bindings);
-
- // the visitor that handles all other operators
- return node.Accept<VCExpr/*!*/, VariableBindings/*!*/>(OpEraser, bindings);
- }
-
- // this method is called by MutatingVCExprVisitor.Visit(VCExprNAry, ...)
- protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode, List<VCExpr/*!*/>/*!*/ newSubExprs, bool changed, VariableBindings/*!*/ bindings) {
- //Contract.Requires(originalNode != null);
- //Contract.Requires(cce.NonNullElements(newSubExprs));
- //Contract.Requires(bindings != null);
- Contract.Assume(originalNode.Op == VCExpressionGenerator.AndOp ||
- originalNode.Op == VCExpressionGenerator.OrOp);
- return Gen.Function(originalNode.Op,
- AxBuilder.Cast(newSubExprs[0], Type.Bool),
- AxBuilder.Cast(newSubExprs[1], Type.Bool));
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override VCExpr Visit(VCExprVar node, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExprVar res;
- if (!bindings.VCExprVarBindings.TryGetValue(node, out res))
- return AxBuilder.Typed2Untyped(node);
- return cce.NonNull(res);
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- protected bool IsUniversalQuantifier(VCExprQuantifier node) {
- Contract.Requires(node != null);
- return Polarity == 1 && node.Quan == Quantifier.EX ||
- Polarity == -1 && node.Quan == Quantifier.ALL;
- }
-
- protected List<VCExprVar/*!*/>/*!*/ BoundVarsAfterErasure(List<VCExprVar/*!*/>/*!*/ oldBoundVars,
- // the mapping between old and new variables
- // is added to this bindings-object
- VariableBindings/*!*/ bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(cce.NonNullElements(oldBoundVars));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
-
- List<VCExprVar/*!*/>/*!*/ newBoundVars = new List<VCExprVar/*!*/>(oldBoundVars.Count);
- foreach (VCExprVar/*!*/ var in oldBoundVars) {
- Type/*!*/ newType = AxBuilder.TypeAfterErasure(var.Type);
- VCExprVar/*!*/ newVar = Gen.Variable(var.Name, newType);
- newBoundVars.Add(newVar);
- bindings.VCExprVarBindings.Add(var, newVar);
- }
- return newBoundVars;
- }
-
- // We check whether casts Int2U or Bool2U on the bound variables
- // occur in triggers. In case a trigger like f(Int2U(x)) occurs,
- // it may be better to give variable x the type U and remove the
- // cast. The following method returns true if the quantifier
- // should be translated again with a different typing
- protected bool RedoQuantifier(VCExprQuantifier/*!*/ node,
- VCExprQuantifier/*!*/ newNode,
- // the bound vars that actually occur in the body or
- // in any of the triggers
- List<VCExprVar/*!*/>/*!*/ occurringVars,
- VariableBindings/*!*/ oldBindings,
- out VariableBindings/*!*/ newBindings,
- out List<VCExprVar/*!*/>/*!*/ newBoundVars) {
- Contract.Requires(node != null);
- Contract.Requires(newNode != null);
- Contract.Requires(cce.NonNullElements(occurringVars));
- Contract.Requires(oldBindings != null);
- Contract.Ensures(Contract.ValueAtReturn(out newBindings) != null);
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out newBoundVars)));
- List<VCExprVar/*!*/> castVariables =
- VariableCastCollector.FindCastVariables(node, newNode, AxBuilder);
- if (castVariables.Count == 0) {
- newBindings = oldBindings; // to make the compiler happy
- newBoundVars = newNode.BoundVars; // to make the compiler happy
- return false;
- }
-
- // redo everything with a different typing ...
-
- newBindings = oldBindings.Clone();
- newBoundVars = new List<VCExprVar/*!*/>(node.BoundVars.Count);
- foreach (VCExprVar/*!*/ var in node.BoundVars) {
- Contract.Assert(var != null);
- Type/*!*/ newType =
- castVariables.Contains(var) ? AxBuilder.U
- : AxBuilder.TypeAfterErasure(var.Type);
- Contract.Assert(newType != null);
- VCExprVar/*!*/ newVar = Gen.Variable(var.Name, newType);
- Contract.Assert(newVar != null);
- newBoundVars.Add(newVar);
- newBindings.VCExprVarBindings.Add(var, newVar);
- }
-
- return true;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override VCExpr Visit(VCExprLet node, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VariableBindings/*!*/ newVarBindings = bindings.Clone();
-
- List<VCExprVar/*!*/>/*!*/ newBoundVars = new List<VCExprVar/*!*/>(node.BoundVars.Count);
- foreach (VCExprVar/*!*/ var in node.BoundVars) {
- Type/*!*/ newType = AxBuilder.TypeAfterErasure(var.Type);
- VCExprVar/*!*/ newVar = Gen.Variable(var.Name, newType);
- newBoundVars.Add(newVar);
- newVarBindings.VCExprVarBindings.Add(var, newVar);
- }
-
- List<VCExprLetBinding/*!*/>/*!*/ newbindings = new List<VCExprLetBinding/*!*/>(node.Length);
- for (int i = 0; i < node.Length; ++i) {
- VCExprLetBinding/*!*/ binding = node[i];
- Contract.Assert(binding != null);
- VCExprVar/*!*/ newVar = newBoundVars[i];
- Type/*!*/ newType = newVar.Type;
-
- VCExpr/*!*/ newE = AxBuilder.Cast(Mutate(binding.E, newVarBindings), newType);
- newbindings.Add(Gen.LetBinding(newVar, newE));
- }
-
- VCExpr/*!*/ newbody = Mutate(node.Body, newVarBindings);
- return Gen.Let(newbindings, newbody);
- }
- }
-
- [ContractClassFor(typeof(TypeEraser))]
- public abstract class TypeEraserContracts : TypeEraser {
- public TypeEraserContracts()
- : base(null, null) {
- }
- protected override OpTypeEraser OpEraser {
- get {
- Contract.Ensures(Contract.Result<OpTypeEraser>() != null);
- throw new NotImplementedException();
- }
- }
- }
-
-
- //////////////////////////////////////////////////////////////////////////////
-
- public abstract class OpTypeEraser : StandardVCExprOpVisitor<VCExpr/*!*/, VariableBindings/*!*/> {
-
- protected readonly TypeAxiomBuilderIntBoolU/*!*/ AxBuilder;
-
- protected readonly TypeEraser/*!*/ Eraser;
- protected readonly VCExpressionGenerator/*!*/ Gen;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilder != null);
- Contract.Invariant(Eraser != null);
- Contract.Invariant(Gen != null);
- }
-
-
- public OpTypeEraser(TypeEraser/*!*/ eraser, TypeAxiomBuilderIntBoolU/*!*/ axBuilder, VCExpressionGenerator/*!*/ gen) {
- Contract.Requires(eraser != null);
- Contract.Requires(axBuilder != null);
- Contract.Requires(gen != null);
- this.AxBuilder = axBuilder;
- this.Eraser = eraser;
- this.Gen = gen;
- }
-
- protected override VCExpr StandardResult(VCExprNAry node, VariableBindings bindings) {
- //Contract.Requires(bindings != null);
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- System.Diagnostics.Debug.Fail("Don't know how to erase types in this expression: " + node);
- Contract.Assert(false);
- throw new cce.UnreachableException(); // to please the compiler
- }
-
- private List<VCExpr/*!*/>/*!*/ MutateSeq(VCExprNAry node, VariableBindings bindings, int newPolarity) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
- int oldPolarity = Eraser.Polarity;
- Eraser.Polarity = newPolarity;
- List<VCExpr/*!*/>/*!*/ newArgs = Eraser.MutateSeq(node, bindings);
- Eraser.Polarity = oldPolarity;
- return newArgs;
- }
-
- private VCExpr CastArguments(VCExprNAry node, Type argType, VariableBindings bindings, int newPolarity) {
- Contract.Requires(bindings != null);
- Contract.Requires(argType != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Gen.Function(node.Op,
- AxBuilder.CastSeq(MutateSeq(node, bindings, newPolarity),
- argType));
- }
-
- // Cast the arguments of the node to their old type if necessary and possible; otherwise use
- // their new type (int, real, bool, or U)
- private VCExpr CastArgumentsToOldType(VCExprNAry node, VariableBindings bindings, int newPolarity) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Requires((node.Arity > 0));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- List<VCExpr/*!*/>/*!*/ newArgs = MutateSeq(node, bindings, newPolarity);
- Type/*!*/ oldType = node[0].Type;
- if (AxBuilder.UnchangedType(oldType) &&
- node.Skip(1).All(e => e.Type.Equals(oldType)))
- return Gen.Function(node.Op, AxBuilder.CastSeq(newArgs, oldType));
- else
- return Gen.Function(node.Op, AxBuilder.CastSeq(newArgs, AxBuilder.U));
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- public override VCExpr VisitNotOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Bool, bindings, -Eraser.Polarity);
- }
- public override VCExpr VisitEqOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitNeqOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitImpliesOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- // UGLY: the code for tracking polarities should be factored out
- List<VCExpr/*!*/>/*!*/ newArgs = new List<VCExpr/*!*/>(2);
- Eraser.Polarity = -Eraser.Polarity;
- newArgs.Add(Eraser.Mutate(node[0], bindings));
- Eraser.Polarity = -Eraser.Polarity;
- newArgs.Add(Eraser.Mutate(node[1], bindings));
- return Gen.Function(node.Op, AxBuilder.CastSeq(newArgs, Type.Bool));
- }
- public override VCExpr VisitDistinctOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitLabelOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- // argument of the label operator should always be a formula
- // (at least for Simplify ... should this be ensured at a later point?)
- return CastArguments(node, Type.Bool, bindings, Eraser.Polarity);
- }
- public override VCExpr VisitIfThenElseOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCExpr/*!*/>/*!*/ newArgs = MutateSeq(node, bindings, 0);
- newArgs[0] = AxBuilder.Cast(newArgs[0], Type.Bool);
- Type t = node.Type;
- if (!AxBuilder.UnchangedType(t)) {
- t = AxBuilder.U;
- }
- newArgs[1] = AxBuilder.Cast(newArgs[1], t);
- newArgs[2] = AxBuilder.Cast(newArgs[2], t);
- return Gen.Function(node.Op, newArgs);
- }
- public override VCExpr/*!*/ VisitCustomOp(VCExprNAry/*!*/ node, VariableBindings/*!*/ bindings) {
- Contract.Requires(node != null);
- Contract.Requires(bindings != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- List<VCExpr/*!*/>/*!*/ newArgs = MutateSeq(node, bindings, 0);
- return Gen.Function(node.Op, newArgs);
- }
- public override VCExpr VisitAddOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, node.Type, bindings, 0);
- }
- public override VCExpr VisitSubOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, node.Type, bindings, 0);
- }
- public override VCExpr VisitMulOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, node.Type, bindings, 0);
- }
- public override VCExpr VisitDivOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Int, bindings, 0);
- }
- public override VCExpr VisitModOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Int, bindings, 0);
- }
- public override VCExpr VisitRealDivOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Real, bindings, 0);
- }
- public override VCExpr VisitPowOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, Type.Real, bindings, 0);
- }
- public override VCExpr VisitLtOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitLeOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitGtOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitGeOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitSubtypeOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArguments(node, AxBuilder.U, bindings, 0);
- }
- public override VCExpr VisitToIntOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitToRealOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitBvOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitBvExtractOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return CastArgumentsToOldType(node, bindings, 0);
- }
- public override VCExpr VisitBvConcatOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
- Contract.Requires((node != null));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCExpr/*!*/>/*!*/ newArgs = MutateSeq(node, bindings, 0);
-
- // each argument is cast to its old type
- Contract.Assert(newArgs.Count == node.Arity && newArgs.Count == 2);
- VCExpr/*!*/ arg0 = AxBuilder.Cast(newArgs[0], node[0].Type);
- Contract.Assert(arg0 != null);
- VCExpr/*!*/ arg1 = AxBuilder.Cast(newArgs[1], node[1].Type);
- Contract.Assert(arg1 != null);
- return Gen.Function(node.Op, arg0, arg1);
- }
-
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// Collect all variables x occurring in expressions of the form Int2U(x) or Bool2U(x), and
- /// collect all variables x occurring outside such forms.
- /// </summary>
- internal class VariableCastCollector : TraversingVCExprVisitor<bool, bool> {
- /// <summary>
- /// Determine those bound variables in "oldNode" <em>all</em> of whose relevant uses
- /// have to be cast in potential triggers in "newNode". It is assume that
- /// the bound variables of "oldNode" correspond to the first bound
- /// variables of "newNode".
- /// </summary>
- public static List<VCExprVar/*!*/>/*!*/ FindCastVariables(VCExprQuantifier oldNode, VCExprQuantifier newNode, TypeAxiomBuilderIntBoolU axBuilder) {
- Contract.Requires((axBuilder != null));
- Contract.Requires((newNode != null));
- Contract.Requires((oldNode != null));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
- VariableCastCollector/*!*/ collector = new VariableCastCollector(axBuilder);
- Contract.Assert(collector != null);
- if (newNode.Triggers.Any(trigger => trigger.Pos)) {
- // look in the given triggers
- foreach (VCTrigger/*!*/ trigger in newNode.Triggers) {
- Contract.Assert(trigger != null);
- if (trigger.Pos) {
- foreach (VCExpr/*!*/ expr in trigger.Exprs) {
- Contract.Assert(expr != null);
- collector.Traverse(expr, true);
- }
- }
- }
- } else {
- // look in the body of the quantifier
- collector.Traverse(newNode.Body, true);
- }
-
- List<VCExprVar/*!*/>/*!*/ castVariables = new List<VCExprVar/*!*/>(collector.varsInCasts.Count);
- foreach (VCExprVar/*!*/ castVar in collector.varsInCasts) {
- Contract.Assert(castVar != null);
- int i = newNode.BoundVars.IndexOf(castVar);
- if (0 <= i && i < oldNode.BoundVars.Count && !collector.varsOutsideCasts.ContainsKey(castVar))
- castVariables.Add(oldNode.BoundVars[i]);
- }
- return castVariables;
- }
-
- public VariableCastCollector(TypeAxiomBuilderIntBoolU axBuilder) {
- Contract.Requires(axBuilder != null);
- this.AxBuilder = axBuilder;
- }
-
- readonly List<VCExprVar/*!*/>/*!*/ varsInCasts = new List<VCExprVar/*!*/>();
- readonly Dictionary<VCExprVar/*!*/, object>/*!*/ varsOutsideCasts = new Dictionary<VCExprVar/*!*/, object>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(varsInCasts));
- Contract.Invariant(varsOutsideCasts != null && Contract.ForAll(varsOutsideCasts, voc => voc.Key != null));
- Contract.Invariant(AxBuilder != null);
-
- }
-
-
- readonly TypeAxiomBuilderIntBoolU/*!*/ AxBuilder;
-
- protected override bool StandardResult(VCExpr node, bool arg) {
- //Contract.Requires(node != null);
- return true; // not used
- }
-
- public override bool Visit(VCExprNAry node, bool arg) {
- Contract.Requires(node != null);
- if (node.Op is VCExprBoogieFunctionOp) {
- Function func = ((VCExprBoogieFunctionOp)node.Op).Func;
- Contract.Assert(func != null);
- if ((AxBuilder.IsCast(func)) && node[0] is VCExprVar) {
- VCExprVar castVar = (VCExprVar)node[0];
- if (!varsInCasts.Contains(castVar))
- varsInCasts.Add(castVar);
- return true;
- }
- } else if (node.Op is VCExprNAryOp) {
- VCExpressionGenerator.SingletonOp op = VCExpressionGenerator.SingletonOpDict[node.Op];
- switch (op) {
- // the following operators cannot be used in triggers, so disregard any uses of variables as direct arguments
- case VCExpressionGenerator.SingletonOp.NotOp:
- case VCExpressionGenerator.SingletonOp.EqOp:
- case VCExpressionGenerator.SingletonOp.NeqOp:
- case VCExpressionGenerator.SingletonOp.AndOp:
- case VCExpressionGenerator.SingletonOp.OrOp:
- case VCExpressionGenerator.SingletonOp.ImpliesOp:
- case VCExpressionGenerator.SingletonOp.LtOp:
- case VCExpressionGenerator.SingletonOp.LeOp:
- case VCExpressionGenerator.SingletonOp.GtOp:
- case VCExpressionGenerator.SingletonOp.GeOp:
- foreach (VCExpr n in node) {
- if (!(n is VCExprVar)) { // don't recurse on VCExprVar argument
- n.Accept<bool, bool>(this, arg);
- }
- }
- return true;
- default:
- break;
- }
- }
- return base.Visit(node, arg);
- }
-
- public override bool Visit(VCExprVar node, bool arg) {
- Contract.Requires(node != null);
- if (!varsOutsideCasts.ContainsKey(node))
- varsOutsideCasts.Add(node, null);
- return true;
- }
- }
-
-}
+//-----------------------------------------------------------------------------
+//
+// 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;
+using Microsoft.Boogie.VCExprAST;
+
+// different classes for erasing complex types in VCExprs, replacing them
+// with axioms that can be handled by theorem provers and SMT solvers
+
+namespace Microsoft.Boogie.TypeErasure {
+ using Microsoft.Boogie.VCExprAST;
+
+ // some functionality that is needed in many places (and that should
+ // really be provided by the Spec# container classes; maybe one
+ // could integrate the functions in a nicer way?)
+ public class HelperFuns {
+
+ public static Function BoogieFunction(string name, List<TypeVariable/*!*/>/*!*/ typeParams, params Type[] types) {
+ Contract.Requires(types != null);
+ Contract.Requires(name != null);
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Requires(types.Length > 0);
+ Contract.Requires(Contract.ForAll(0, types.Length, i => types[i] != null));
+ Contract.Ensures(Contract.Result<Function>() != null);
+
+ List<Variable> args = new List<Variable>();
+ for (int i = 0; i < types.Length - 1; ++i)
+ args.Add(new Formal(Token.NoToken,
+ new TypedIdent(Token.NoToken, "arg" + i, cce.NonNull(types[i])),
+ true));
+ Formal result = new Formal(Token.NoToken,
+ new TypedIdent(Token.NoToken, "res",
+ cce.NonNull(types)[types.Length - 1]),
+ false);
+ return new Function(Token.NoToken, name, new List<TypeVariable>(typeParams), args, result);
+ }
+
+ public static Function BoogieFunction(string name, params Type[] types) {
+ Contract.Requires(types != null);
+ Contract.Requires(name != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ return BoogieFunction(name, new List<TypeVariable/*!*/>(), types);
+ }
+
+ // boogie function where all arguments and the result have the same type U
+ public static Function UniformBoogieFunction(string name, int arity, Type U) {
+ Contract.Requires(U != null);
+ Contract.Requires(name != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ Type[]/*!*/ types = new Type[arity + 1];
+ for (int i = 0; i < arity + 1; ++i)
+ types[i] = U;
+ return BoogieFunction(name, types);
+ }
+
+ public static List<VCExprVar/*!*/>/*!*/ GenVarsForInParams(Function fun, VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(fun != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+ List<VCExprVar/*!*/>/*!*/ arguments = new List<VCExprVar/*!*/>(fun.InParams.Count);
+ foreach (Formal/*!*/ f in fun.InParams) {
+ Contract.Assert(f != null);
+ VCExprVar/*!*/ var = gen.Variable(f.Name, f.TypedIdent.Type);
+ arguments.Add(var);
+ }
+ return arguments;
+ }
+
+ public static List<T/*!*/>/*!*/ ToList<T>(params T[] args) where T : class{
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<T>>()));
+ return new List<T>(args);
+ }
+
+ public static List<VCExpr/*!*/>/*!*/ ToVCExprList(List<VCExprVar/*!*/>/*!*/ list) {
+ Contract.Requires(cce.NonNullElements(list));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
+ return new List<VCExpr>(list);
+ }
+
+ public static List<VCExprVar/*!*/>/*!*/ VarVector(string baseName, int num, Type type, VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(type != null);
+ Contract.Requires(baseName != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+ List<VCExprVar/*!*/>/*!*/ res = new List<VCExprVar/*!*/>(num);
+ for (int i = 0; i < num; ++i)
+ res.Add(gen.Variable(baseName + i, type));
+ return res;
+ }
+
+ public static List<VCExprVar/*!*/>/*!*/ VarVector(string baseName, List<Type/*!*/>/*!*/ types, VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(baseName != null);
+ Contract.Requires(cce.NonNullElements(types));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+ List<VCExprVar/*!*/>/*!*/ res = new List<VCExprVar/*!*/>(types.Count);
+ for (int i = 0; i < types.Count; ++i)
+ res.Add(gen.Variable(baseName + i, types[i]));
+ return res;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ internal struct TypeCtorRepr {
+ // function that represents the application of the type constructor
+ // to smaller types
+ public readonly Function/*!*/ Ctor;
+ // left-inverse functions that extract the subtypes of a compound type
+ public readonly List<Function/*!*/>/*!*/ Dtors;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Ctor != null);
+ Contract.Invariant(cce.NonNullElements(Dtors));
+ }
+
+
+ public TypeCtorRepr(Function ctor, List<Function/*!*/>/*!*/ dtors) {
+ Contract.Requires(ctor != null);
+ Contract.Requires(cce.NonNullElements(dtors));
+ Contract.Requires(ctor.InParams.Count == dtors.Count);
+ this.Ctor = ctor;
+ this.Dtors = dtors;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ // The class responsible for creating and keeping track of all
+ // axioms related to the type system. This abstract class is made
+ // concrete in two subclasses, one for type erasure with type
+ // premisses in quantifiers (the semantic approach), and one for
+ // type erasure with explicit type arguments of polymorphic
+ // functions (the syntacted approach).
+ [ContractClass(typeof(TypeAxiomBuilderContracts))]
+ public abstract class TypeAxiomBuilder : ICloneable {
+
+ protected readonly VCExpressionGenerator/*!*/ Gen;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Gen != null);
+ Contract.Invariant(Ctor != null);
+
+ }
+
+
+ internal abstract MapTypeAbstractionBuilder/*!*/ MapTypeAbstracter {
+ get;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Type Axioms
+
+ // list in which all typed axioms are collected
+ private readonly List<VCExpr/*!*/>/*!*/ AllTypeAxioms;
+ [ContractInvariantMethod]
+ void AllTypeAxiomsInvariantMethod() {
+ Contract.Invariant(cce.NonNullElements(AllTypeAxioms));
+ }
+
+ // list in which type axioms are incrementally collected
+ private readonly List<VCExpr/*!*/>/*!*/ IncTypeAxioms;
+ [ContractInvariantMethod]
+ void IncTypeAxiomsInvariantMethod() {
+ Contract.Invariant(cce.NonNullElements(IncTypeAxioms));
+ }
+
+ internal void AddTypeAxiom(VCExpr axiom) {
+ Contract.Requires(axiom != null);
+ AllTypeAxioms.Add(axiom);
+ IncTypeAxioms.Add(axiom);
+ }
+
+ // Return all axioms that were added since the last time NewAxioms
+ // was called
+ public VCExpr GetNewAxioms() {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr/*!*/ res = Gen.NAry(VCExpressionGenerator.AndOp, IncTypeAxioms);
+ IncTypeAxioms.Clear();
+ return res;
+ }
+
+ // mapping from a type to its constructor number/index
+ private readonly Function/*!*/ Ctor;
+ private BigNum CurrentCtorNum;
+
+ private VCExpr GenCtorAssignment(VCExpr typeRepr) {
+ Contract.Requires(typeRepr != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (CommandLineOptions.Clo.TypeEncodingMethod
+ == CommandLineOptions.TypeEncoding.None)
+ return VCExpressionGenerator.True;
+
+ VCExpr res = Gen.Eq(Gen.Function(Ctor, typeRepr),
+ Gen.Integer(CurrentCtorNum));
+ CurrentCtorNum = CurrentCtorNum + BigNum.ONE;
+ return res;
+ }
+
+ private VCExpr GenCtorAssignment(Function typeRepr) {
+ Contract.Requires(typeRepr != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (CommandLineOptions.Clo.TypeEncodingMethod
+ == CommandLineOptions.TypeEncoding.None)
+ return VCExpressionGenerator.True;
+
+ List<VCExprVar/*!*/>/*!*/ quantifiedVars = HelperFuns.GenVarsForInParams(typeRepr, Gen);
+ VCExpr/*!*/ eq =
+ GenCtorAssignment(Gen.Function(typeRepr,
+ HelperFuns.ToVCExprList(quantifiedVars)));
+
+ if (typeRepr.InParams.Count == 0)
+ return eq;
+
+ return Gen.Forall(quantifiedVars, new List<VCTrigger/*!*/>(),
+ "ctor:" + typeRepr.Name, -1, eq);
+ }
+
+ // generate an axiom (forall x0, x1, ... :: invFun(fun(x0, x1, ...) == xi)
+ protected VCExpr GenLeftInverseAxiom(Function fun, Function invFun, int dtorNum) {
+ Contract.Requires(invFun != null);
+ Contract.Requires(fun != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCExprVar/*!*/>/*!*/ quantifiedVars = HelperFuns.GenVarsForInParams(fun, Gen);
+ Contract.Assert(cce.NonNullElements(quantifiedVars));
+
+ VCExpr/*!*/ funApp = Gen.Function(fun, HelperFuns.ToVCExprList(quantifiedVars));
+ VCExpr/*!*/ lhs = Gen.Function(invFun, funApp);
+ VCExpr/*!*/ rhs = quantifiedVars[dtorNum];
+ VCExpr/*!*/ eq = Gen.Eq(lhs, rhs);
+
+ List<VCTrigger/*!*/>/*!*/ triggers = HelperFuns.ToList(Gen.Trigger(true, HelperFuns.ToList(funApp)));
+ Contract.Assert(cce.NonNullElements(triggers));
+ return Gen.Forall(quantifiedVars, triggers, "typeInv:" + invFun.Name, -1, eq);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ // the type of everything that is not int, bool, or a type
+ [ContractInvariantMethod]
+ void ObjectInvariant2() {
+ Contract.Invariant(UDecl != null);
+ Contract.Invariant(TDecl != null);
+ Contract.Invariant(U != null);
+ Contract.Invariant(T != null);
+ }
+
+ private readonly TypeCtorDecl/*!*/ UDecl;
+ public readonly Type/*!*/ U;
+
+ // the type of types
+ private readonly TypeCtorDecl/*!*/ TDecl;
+ public readonly Type/*!*/ T;
+
+ public abstract Type/*!*/ TypeAfterErasure(Type/*!*/ type);
+ [Pure]
+ public abstract bool UnchangedType(Type/*!*/ type);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Symbols for representing types
+
+ private readonly IDictionary<Type/*!*/, VCExpr/*!*/>/*!*/ BasicTypeReprs;
+ [ContractInvariantMethod]
+ void BasicTypeReprsInvariantMethod() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(BasicTypeReprs));
+ }
+
+ private VCExpr GetBasicTypeRepr(Type type) {
+ Contract.Requires(type != null);
+ Contract.Requires(type.IsBasic || type.IsBv);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr res;
+ if (!BasicTypeReprs.TryGetValue(type, out res)) {
+ res = Gen.Function(HelperFuns.BoogieFunction(type.ToString() + "Type", T));
+ AddTypeAxiom(GenCtorAssignment(res));
+ BasicTypeReprs.Add(type, res);
+ }
+ return cce.NonNull(res);
+ }
+
+ private readonly IDictionary<TypeCtorDecl/*!*/, TypeCtorRepr/*!*/>/*!*/ TypeCtorReprs;
+ [ContractInvariantMethod]
+ void TypeCtorReprsInvariantMethod() {
+ Contract.Invariant(TypeCtorReprs != null);
+ }
+
+ internal TypeCtorRepr GetTypeCtorReprStruct(TypeCtorDecl decl) {
+ Contract.Requires(decl != null);
+ TypeCtorRepr reprSet;
+ if (!TypeCtorReprs.TryGetValue(decl, out reprSet)) {
+ Function/*!*/ ctor = HelperFuns.UniformBoogieFunction(decl.Name + "Type", decl.Arity, T);
+ Contract.Assert(ctor != null);
+ AddTypeAxiom(GenCtorAssignment(ctor));
+
+ List<Function/*!*/>/*!*/ dtors = new List<Function/*!*/>(decl.Arity);
+ for (int i = 0; i < decl.Arity; ++i) {
+ Function/*!*/ dtor = HelperFuns.UniformBoogieFunction(decl.Name + "TypeInv" + i, 1, T);
+ dtors.Add(dtor);
+ AddTypeAxiom(GenLeftInverseAxiom(ctor, dtor, i));
+ }
+
+ reprSet = new TypeCtorRepr(ctor, dtors);
+ TypeCtorReprs.Add(decl, reprSet);
+ }
+
+ return reprSet;
+ }
+
+ public Function GetTypeCtorRepr(TypeCtorDecl decl) {
+ Contract.Requires(decl != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ return GetTypeCtorReprStruct(decl).Ctor;
+ }
+
+ public Function GetTypeDtor(TypeCtorDecl decl, int num) {
+ Contract.Requires(decl != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ return GetTypeCtorReprStruct(decl).Dtors[num];
+ }
+
+ // mapping from free type variables to VCExpr variables
+ private readonly IDictionary<TypeVariable/*!*/, VCExprVar/*!*/>/*!*/ TypeVariableMapping;
+ [ContractInvariantMethod]
+ void TypeVariableMappingInvariantMethod() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(TypeVariableMapping));
+ }
+
+ public VCExprVar Typed2Untyped(TypeVariable var) {
+ Contract.Requires(var != null);
+ Contract.Ensures(Contract.Result<VCExprVar>() != null);
+ VCExprVar res;
+ if (!TypeVariableMapping.TryGetValue(var, out res)) {
+ res = new VCExprVar(var.Name, T);
+ TypeVariableMapping.Add(var, res);
+ }
+ return cce.NonNull(res);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Symbols for representing variables and constants
+
+ // Globally defined variables
+ private readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ Typed2UntypedVariables;
+ [ContractInvariantMethod]
+ void Typed2UntypedVariablesInvariantMethod() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(Typed2UntypedVariables));
+ }
+
+ // This method must only be used for free (unbound) variables
+ public VCExprVar Typed2Untyped(VCExprVar var) {
+ Contract.Requires(var != null);
+ Contract.Ensures(Contract.Result<VCExprVar>() != null);
+ VCExprVar res = TryTyped2Untyped(var);
+ if (res == null) {
+ res = Gen.Variable(var.Name, TypeAfterErasure(var.Type));
+ Typed2UntypedVariables.Add(var, res);
+ AddVarTypeAxiom(res, var.Type);
+ }
+ return cce.NonNull(res);
+ }
+
+ /// <summary>
+ /// This method is like Typed2Untyped, except in the case where the given variables
+ /// doesn't exist in the mapping. For that case, this method returns null whereas
+ /// Typed2Untyped creates a new variable that it adds to the mapping.
+ /// </summary>
+ /// <param name="var"></param>
+ /// <returns></returns>
+ public VCExprVar TryTyped2Untyped(VCExprVar var) {
+ Contract.Requires(var != null);
+ VCExprVar res;
+ if (Typed2UntypedVariables.TryGetValue(var, out res)) {
+ return res;
+ } else {
+ return null;
+ }
+ }
+
+ protected abstract void AddVarTypeAxiom(VCExprVar/*!*/ var, Type/*!*/ originalType);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Translation function from types to their term representation
+
+ public VCExpr Type2Term(Type type, IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ varMapping) {
+ Contract.Requires(type != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(varMapping));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ //
+ if (type.IsBasic || type.IsBv) {
+ //
+ return GetBasicTypeRepr(type);
+ //
+ } else if (type.IsCtor) {
+ //
+ CtorType ctype = type.AsCtor;
+ Function/*!*/ repr = GetTypeCtorRepr(ctype.Decl);
+ List<VCExpr/*!*/>/*!*/ args = new List<VCExpr/*!*/>(ctype.Arguments.Count);
+ foreach (Type/*!*/ t in ctype.Arguments.ToArray()) {
+ Contract.Assert(t != null);
+ args.Add(Type2Term(t, varMapping));
+ }
+ return Gen.Function(repr, args);
+ //
+ } else if (type.IsVariable) {
+ //
+ VCExpr res;
+ if (!varMapping.TryGetValue(type.AsVariable, out res))
+ // then the variable is free and we bind it at this point to a term
+ // variable
+ res = Typed2Untyped(type.AsVariable);
+ return cce.NonNull(res);
+ //
+ } else if (type.IsMap) {
+ //
+ return Type2Term(MapTypeAbstracter.AbstractMapType(type.AsMap), varMapping);
+ //
+ } else {
+ System.Diagnostics.Debug.Fail("Don't know how to handle this type: " + type);
+ Contract.Assert(false);
+ throw new cce.UnreachableException(); // please the compiler
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public TypeAxiomBuilder(VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ this.Gen = gen;
+ AllTypeAxioms = new List<VCExpr/*!*/>();
+ IncTypeAxioms = new List<VCExpr/*!*/>();
+ BasicTypeReprs = new Dictionary<Type/*!*/, VCExpr/*!*/>();
+ CurrentCtorNum = BigNum.ZERO;
+ TypeCtorReprs = new Dictionary<TypeCtorDecl/*!*/, TypeCtorRepr>();
+ TypeVariableMapping = new Dictionary<TypeVariable/*!*/, VCExprVar/*!*/>();
+ Typed2UntypedVariables = new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>();
+
+ TypeCtorDecl/*!*/ uDecl = new TypeCtorDecl(Token.NoToken, "U", 0);
+ UDecl = uDecl;
+ Type/*!*/ u = new CtorType(Token.NoToken, uDecl, new List<Type>());
+ U = u;
+
+ TypeCtorDecl/*!*/ tDecl = new TypeCtorDecl(Token.NoToken, "T", 0);
+ TDecl = tDecl;
+ Type/*!*/ t = new CtorType(Token.NoToken, tDecl, new List<Type>());
+ T = t;
+
+ Ctor = HelperFuns.BoogieFunction("Ctor", t, Type.Int);
+ }
+
+ public virtual void Setup() {
+ GetBasicTypeRepr(Type.Int);
+ GetBasicTypeRepr(Type.Real);
+ GetBasicTypeRepr(Type.Bool);
+ }
+
+ // constructor to allow cloning
+ internal TypeAxiomBuilder(TypeAxiomBuilder builder) {
+ Contract.Requires(builder != null);
+ Gen = builder.Gen;
+ AllTypeAxioms = new List<VCExpr/*!*/>(builder.AllTypeAxioms);
+ IncTypeAxioms = new List<VCExpr/*!*/>(builder.IncTypeAxioms);
+
+ UDecl = builder.UDecl;
+ U = builder.U;
+
+ TDecl = builder.TDecl;
+ T = builder.T;
+
+ Ctor = builder.Ctor;
+ CurrentCtorNum = builder.CurrentCtorNum;
+
+ BasicTypeReprs = new Dictionary<Type/*!*/, VCExpr/*!*/>(builder.BasicTypeReprs);
+ TypeCtorReprs = new Dictionary<TypeCtorDecl/*!*/, TypeCtorRepr>(builder.TypeCtorReprs);
+
+ TypeVariableMapping =
+ new Dictionary<TypeVariable/*!*/, VCExprVar/*!*/>(builder.TypeVariableMapping);
+ Typed2UntypedVariables =
+ new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>(builder.Typed2UntypedVariables);
+ }
+
+ public abstract Object/*!*/ Clone();
+ }
+
+ [ContractClassFor(typeof(TypeAxiomBuilder))]
+ public abstract class TypeAxiomBuilderContracts : TypeAxiomBuilder {
+ public TypeAxiomBuilderContracts()
+ : base((VCExpressionGenerator)null) {
+ }
+ internal override MapTypeAbstractionBuilder MapTypeAbstracter {
+ get {
+ Contract.Ensures(Contract.Result<MapTypeAbstractionBuilder>() != null);
+ throw new NotImplementedException();
+ }
+ }
+
+ public override Type TypeAfterErasure(Type type) {
+ Contract.Requires(type != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ throw new NotImplementedException();
+ }
+
+ public override bool UnchangedType(Type type) {
+ Contract.Requires(type != null);
+ throw new NotImplementedException();
+ }
+
+ protected override void AddVarTypeAxiom(VCExprVar var, Type originalType) {
+ Contract.Requires(var != null);
+ Contract.Requires(originalType != null);
+ throw new NotImplementedException();
+ }
+
+ public override object Clone() {
+ Contract.Ensures(Contract.Result<object>() != null);
+
+ throw new NotImplementedException();
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ // Subclass of the TypeAxiomBuilder that provides all functionality
+ // to deal with native sorts of a theorem prover (that are the only
+ // types left after erasing all other types). Currently, these are:
+ //
+ // U ... sort of all individuals/objects/values
+ // T ... sort of all types
+ // int ... integers
+ // bool ... booleans
+
+ [ContractClass(typeof(TypeAxiomBuilderIntBoolUContracts))]
+ public abstract class TypeAxiomBuilderIntBoolU : TypeAxiomBuilder {
+
+ public TypeAxiomBuilderIntBoolU(VCExpressionGenerator gen)
+ : base(gen) {
+ Contract.Requires(gen != null);
+
+ TypeCasts = new Dictionary<Type/*!*/, TypeCastSet>();
+ }
+
+ // constructor to allow cloning
+ internal TypeAxiomBuilderIntBoolU(TypeAxiomBuilderIntBoolU builder)
+ : base(builder) {
+ Contract.Requires(builder != null);
+
+ TypeCasts = new Dictionary<Type/*!*/, TypeCastSet>(builder.TypeCasts);
+ }
+
+ public override void Setup() {
+ base.Setup();
+
+ GetTypeCasts(Type.Int);
+ GetTypeCasts(Type.Real);
+ GetTypeCasts(Type.Bool);
+ }
+
+ // generate inverse axioms for casts (castToU(castFromU(x)) = x, under certain premisses)
+ protected abstract VCExpr/*!*/ GenReverseCastAxiom(Function/*!*/ castToU, Function/*!*/ castFromU);
+
+ protected VCExpr GenReverseCastEq(Function castToU, Function castFromU, out VCExprVar var, out List<VCTrigger/*!*/>/*!*/ triggers) {
+ Contract.Requires((castFromU != null));
+ Contract.Requires((castToU != null));
+ Contract.Ensures((cce.NonNullElements(Contract.ValueAtReturn(out triggers))));
+ Contract.Ensures(Contract.ValueAtReturn(out var) != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ var = Gen.Variable("x", U);
+
+ VCExpr inner = Gen.Function(castFromU, var);
+ VCExpr lhs = Gen.Function(castToU, inner);
+ triggers = HelperFuns.ToList(Gen.Trigger(true, HelperFuns.ToList(inner)));
+
+ return Gen.Eq(lhs, var);
+ }
+
+ protected abstract VCExpr/*!*/ GenCastTypeAxioms(Function/*!*/ castToU, Function/*!*/ castFromU);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // storage of type casts for types that are supposed to be left over in the
+ // VCs (like int, bool, bitvectors)
+
+ private readonly IDictionary<Type/*!*/, TypeCastSet/*!*/>/*!*/ TypeCasts;
+ [ContractInvariantMethod]
+ void TypeCastsInvariantMethod() {
+ Contract.Invariant(TypeCasts != null);
+ }
+
+ private TypeCastSet GetTypeCasts(Type type) {
+ Contract.Requires(type != null);
+ TypeCastSet res;
+ if (!TypeCasts.TryGetValue(type, out res)) {
+ Function/*!*/ castToU = HelperFuns.BoogieFunction(type.ToString() + "_2_U", type, U);
+ Function/*!*/ castFromU = HelperFuns.BoogieFunction("U_2_" + type.ToString(), U, type);
+
+ AddTypeAxiom(GenLeftInverseAxiom(castToU, castFromU, 0));
+ AddTypeAxiom(GenReverseCastAxiom(castToU, castFromU));
+ AddTypeAxiom(GenCastTypeAxioms(castToU, castFromU));
+
+ res = new TypeCastSet(castToU, castFromU);
+ TypeCasts.Add(type, res);
+ }
+ return res;
+ }
+ [Pure]
+ public Function CastTo(Type type) {
+ Contract.Requires(type != null);
+ Contract.Requires(UnchangedType(type));
+ Contract.Ensures(Contract.Result<Function>() != null);
+ return GetTypeCasts(type).CastFromU;
+ }
+
+ public Function CastFrom(Type type) {
+ Contract.Requires(type != null);
+ Contract.Requires((UnchangedType(type)));
+ Contract.Ensures(Contract.Result<Function>() != null);
+ return GetTypeCasts(type).CastToU;
+ }
+
+ private struct TypeCastSet {
+ public readonly Function/*!*/ CastToU;
+ public readonly Function/*!*/ CastFromU;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(CastToU != null);
+ Contract.Invariant(CastFromU != null);
+ }
+
+
+ public TypeCastSet(Function castToU, Function castFromU) {
+ Contract.Requires(castFromU != null);
+ Contract.Requires(castToU != null);
+ CastToU = castToU;
+ CastFromU = castFromU;
+ }
+ }
+
+ public bool IsCast(Function fun) {
+ Contract.Requires(fun != null);
+ if (fun.InParams.Count != 1)
+ return false;
+ Type/*!*/ inType = cce.NonNull(fun.InParams[0]).TypedIdent.Type;
+ if (inType.Equals(U)) {
+ Type/*!*/ outType = cce.NonNull(fun.OutParams[0]).TypedIdent.Type;
+ if (!TypeCasts.ContainsKey(outType))
+ return false;
+ return fun.Equals(CastTo(outType));
+ } else {
+ if (!TypeCasts.ContainsKey(inType))
+ return false;
+ Type/*!*/ outType = cce.NonNull(fun.OutParams[0]).TypedIdent.Type;
+ if (!outType.Equals(U))
+ return false;
+ return fun.Equals(CastFrom(inType));
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // the only types that we allow in "untyped" expressions are U,
+ // Type.Int, Type.Real, and Type.Bool
+
+ public override Type TypeAfterErasure(Type type) {
+ //Contract.Requires(type != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+ if (UnchangedType(type))
+ // these types are kept
+ return type;
+ else
+ // all other types are replaced by U
+ return U;
+ }
+
+ [Pure]
+ public override bool UnchangedType(Type type) {
+ //Contract.Requires(type != null);
+ return type.IsInt || type.IsReal || type.IsBool || type.IsBv || (type.IsMap && CommandLineOptions.Clo.MonomorphicArrays);
+ }
+
+ public VCExpr Cast(VCExpr expr, Type toType) {
+ Contract.Requires(toType != null);
+ Contract.Requires(expr != null);
+ Contract.Requires((expr.Type.Equals(U) || UnchangedType(expr.Type)));
+ Contract.Requires((toType.Equals(U) || UnchangedType(toType)));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (expr.Type.Equals(toType))
+ return expr;
+
+ if (toType.Equals(U)) {
+ return Gen.Function(CastFrom(expr.Type), expr);
+ } else {
+ Contract.Assert(expr.Type.Equals(U));
+ return Gen.Function(CastTo(toType), expr);
+ }
+ }
+
+ public List<VCExpr/*!*/>/*!*/ CastSeq(List<VCExpr/*!*/>/*!*/ exprs, Type toType) {
+ Contract.Requires(toType != null);
+ Contract.Requires(cce.NonNullElements(exprs));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
+ List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>(exprs.Count);
+ foreach (VCExpr/*!*/ expr in exprs) {
+ Contract.Assert(expr != null);
+ res.Add(Cast(expr, toType));
+ }
+ return res;
+ }
+
+
+ }
+
+ [ContractClassFor(typeof(TypeAxiomBuilderIntBoolU))]
+ public abstract class TypeAxiomBuilderIntBoolUContracts : TypeAxiomBuilderIntBoolU {
+ public TypeAxiomBuilderIntBoolUContracts()
+ : base((TypeAxiomBuilderIntBoolU)null) {
+ }
+ protected override VCExpr GenReverseCastAxiom(Function castToU, Function castFromU) {
+ Contract.Requires(castToU != null);
+ Contract.Requires(castFromU != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ throw new NotImplementedException();
+ }
+
+ protected override VCExpr GenCastTypeAxioms(Function castToU, Function castFromU) {
+ Contract.Requires(castFromU != null);
+ Contract.Requires(castToU != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ throw new NotImplementedException();
+ }
+
+ internal override MapTypeAbstractionBuilder MapTypeAbstracter {
+ get {
+ throw new NotImplementedException();
+ }
+ }
+
+ protected override void AddVarTypeAxiom(VCExprVar var, Type originalType) {
+ throw new NotImplementedException();
+ }
+
+ public override object Clone() {
+ throw new NotImplementedException();
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Class for computing most general abstractions of map types. An abstraction
+ // of a map type t is a maptype t' in which closed proper subtypes have been replaced
+ // with type variables. E.g., an abstraction of <a>[C a, int]a would be <a>[C a, b]a.
+ // We subsequently consider most general abstractions as ordinary parametrised types,
+ // i.e., "<a>[C a, b]a" would be considered as a type "M b" with polymorphically typed
+ // access functions
+ //
+ // select<a,b>(M b, C a, b) returns (a)
+ // store<a,b>(M b, C a, b, a) returns (M b)
+ [ContractClass(typeof(MapTypeAbstractionBuilderContracts))]
+ internal abstract class MapTypeAbstractionBuilder {
+
+ protected readonly TypeAxiomBuilder/*!*/ AxBuilder;
+ protected readonly VCExpressionGenerator/*!*/ Gen;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilder != null);
+ Contract.Invariant(Gen != null);
+ }
+
+
+ internal MapTypeAbstractionBuilder(TypeAxiomBuilder axBuilder, VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+ this.AxBuilder = axBuilder;
+ this.Gen = gen;
+ AbstractionVariables = new List<TypeVariable/*!*/>();
+ ClassRepresentations = new Dictionary<MapType/*!*/, MapTypeClassRepresentation>();
+ }
+
+ // constructor for cloning
+ internal MapTypeAbstractionBuilder(TypeAxiomBuilder axBuilder, VCExpressionGenerator gen, MapTypeAbstractionBuilder builder) {
+ Contract.Requires(builder != null);
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+ this.AxBuilder = axBuilder;
+ this.Gen = gen;
+ AbstractionVariables =
+ new List<TypeVariable/*!*/>(builder.AbstractionVariables);
+ ClassRepresentations =
+ new Dictionary<MapType/*!*/, MapTypeClassRepresentation>(builder.ClassRepresentations);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Type variables used in the abstractions. We use the same variables in the
+ // same order in all abstractions in order to obtain comparable abstractions
+ // (equals, hashcode)
+
+ private readonly List<TypeVariable/*!*/>/*!*/ AbstractionVariables;
+ [ContractInvariantMethod]
+ void AbstractionVariablesInvariantMethod() {
+ Contract.Invariant(cce.NonNullElements(AbstractionVariables));
+ }
+
+ private TypeVariable AbstractionVariable(int num) {
+ Contract.Requires((num >= 0));
+ Contract.Ensures(Contract.Result<TypeVariable>() != null);
+ while (AbstractionVariables.Count <= num)
+ AbstractionVariables.Add(new TypeVariable(Token.NoToken,
+ "aVar" + AbstractionVariables.Count));
+ return AbstractionVariables[num];
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The untyped representation of a class of map types, i.e., of a map type
+ // <a0, a1, ...>[A0, A1, ...] R, where the argument types and the result type
+ // possibly contain free type variables. For each such class, a separate type
+ // constructor and separate select/store functions are introduced.
+
+ protected struct MapTypeClassRepresentation {
+ public readonly TypeCtorDecl/*!*/ RepresentingType;
+ public readonly Function/*!*/ Select;
+ public readonly Function/*!*/ Store;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(RepresentingType != null);
+ Contract.Invariant(Select != null);
+ Contract.Invariant(Store != null);
+ }
+
+
+ public MapTypeClassRepresentation(TypeCtorDecl representingType, Function select, Function store) {
+ Contract.Requires(store != null);
+ Contract.Requires(select != null);
+ Contract.Requires(representingType != null);
+ this.RepresentingType = representingType;
+ this.Select = select;
+ this.Store = store;
+ }
+ }
+
+ private readonly IDictionary<MapType/*!*/, MapTypeClassRepresentation/*!*/>/*!*/ ClassRepresentations;
+ [ContractInvariantMethod]
+ void ClassRepresentationsInvariantMethod() {
+ Contract.Invariant(ClassRepresentations != null);
+ }
+
+ protected MapTypeClassRepresentation GetClassRepresentation(MapType abstractedType) {
+ Contract.Requires(abstractedType != null);
+ MapTypeClassRepresentation res;
+ if (!ClassRepresentations.TryGetValue(abstractedType, out res)) {
+ int num = ClassRepresentations.Count;
+ TypeCtorDecl/*!*/ synonym =
+ new TypeCtorDecl(Token.NoToken, "MapType" + num, abstractedType.FreeVariables.Count);
+
+ Function/*!*/ select, store;
+ GenSelectStoreFunctions(abstractedType, synonym, out select, out store);
+
+ res = new MapTypeClassRepresentation(synonym, select, store);
+ ClassRepresentations.Add(abstractedType, res);
+ }
+ return res;
+ }
+
+ // the actual select and store functions are generated by the
+ // concrete subclasses of this class
+ protected abstract void GenSelectStoreFunctions(MapType/*!*/ abstractedType, TypeCtorDecl/*!*/ synonymDecl, out Function/*!*/ select, out Function/*!*/ store);
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ public Function Select(MapType rawType, out List<Type> instantiations) {
+ Contract.Requires((rawType != null));
+ Contract.Ensures(Contract.ValueAtReturn(out instantiations) != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ return AbstractAndGetRepresentation(rawType, out instantiations).Select;
+ }
+
+ public Function Store(MapType rawType, out List<Type> instantiations) {
+ Contract.Requires((rawType != null));
+ Contract.Ensures(Contract.ValueAtReturn(out instantiations) != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ return AbstractAndGetRepresentation(rawType, out instantiations).Store;
+ }
+
+ private MapTypeClassRepresentation
+ AbstractAndGetRepresentation(MapType rawType, out List<Type> instantiations) {
+ Contract.Requires((rawType != null));
+ Contract.Ensures(Contract.ValueAtReturn(out instantiations) != null);
+ instantiations = new List<Type>();
+ MapType/*!*/ abstraction = ThinOutMapType(rawType, instantiations);
+ return GetClassRepresentation(abstraction);
+ }
+
+ public CtorType AbstractMapType(MapType rawType) {
+ Contract.Requires(rawType != null);
+ Contract.Ensures(Contract.Result<CtorType>() != null);
+ List<Type>/*!*/ instantiations = new List<Type>();
+ MapType/*!*/ abstraction = ThinOutMapType(rawType, instantiations);
+
+ MapTypeClassRepresentation repr = GetClassRepresentation(abstraction);
+ Contract.Assume(repr.RepresentingType.Arity == instantiations.Count);
+ return new CtorType(Token.NoToken, repr.RepresentingType, instantiations);
+ }
+
+ // TODO: cache the result of this operation
+ protected MapType ThinOutMapType(MapType rawType, List<Type> instantiations) {
+ Contract.Requires(instantiations != null);
+ Contract.Requires(rawType != null);
+ Contract.Ensures(Contract.Result<MapType>() != null);
+ List<Type>/*!*/ newArguments = new List<Type>();
+ foreach (Type/*!*/ subtype in rawType.Arguments.ToList()) {
+ Contract.Assert(subtype != null);
+ newArguments.Add(ThinOutType(subtype, rawType.TypeParameters,
+ instantiations));
+ }
+ Type/*!*/ newResult = ThinOutType(rawType.Result, rawType.TypeParameters,
+ instantiations);
+ return new MapType(Token.NoToken, rawType.TypeParameters, newArguments, newResult);
+ }
+
+ // the instantiations of inserted type variables, the order corresponds to the order in which "AbstractionVariable(int)" delivers variables
+ private Type/*!*/ ThinOutType(Type rawType, List<TypeVariable> boundTypeParams, List<Type> instantiations) {
+ Contract.Requires(instantiations != null);
+ Contract.Requires(boundTypeParams != null);
+ Contract.Requires(rawType != null);
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(rawType))
+ return rawType;
+
+ if (rawType.FreeVariables.All(var => !boundTypeParams.Contains(var))) {
+ // Bingo!
+ // if the type does not contain any bound variables, we can simply
+ // replace it with a type variable
+ TypeVariable/*!*/ abstractionVar = AbstractionVariable(instantiations.Count);
+ Contract.Assume(!boundTypeParams.Contains(abstractionVar));
+ instantiations.Add(rawType);
+ return abstractionVar;
+ }
+
+ if (rawType.IsVariable) {
+ //
+ // then the variable has to be bound, we cannot do anything
+ TypeVariable/*!*/ rawVar = rawType.AsVariable;
+ Contract.Assume(boundTypeParams.Contains(rawVar));
+ return rawVar;
+ //
+ } else if (rawType.IsMap) {
+ //
+ // recursively abstract this map type and continue abstracting
+ CtorType/*!*/ abstraction = AbstractMapType(rawType.AsMap);
+ return ThinOutType(abstraction, boundTypeParams, instantiations);
+ //
+ } else if (rawType.IsCtor) {
+ //
+ // traverse the subtypes
+ CtorType/*!*/ rawCtorType = rawType.AsCtor;
+ List<Type>/*!*/ newArguments = new List<Type>();
+ foreach (Type/*!*/ subtype in rawCtorType.Arguments.ToList()) {
+ Contract.Assert(subtype != null);
+ newArguments.Add(ThinOutType(subtype, boundTypeParams,
+ instantiations));
+ }
+ return new CtorType(Token.NoToken, rawCtorType.Decl, newArguments);
+ //
+ } else {
+ System.Diagnostics.Debug.Fail("Don't know how to handle this type: " + rawType);
+ return rawType; // compiler appeasement policy
+ }
+ }
+
+ }
+ [ContractClassFor(typeof(MapTypeAbstractionBuilder))]
+ internal abstract class MapTypeAbstractionBuilderContracts : MapTypeAbstractionBuilder {
+ public MapTypeAbstractionBuilderContracts()
+ : base(null, null) {
+ }
+ protected override void GenSelectStoreFunctions(MapType abstractedType, TypeCtorDecl synonymDecl, out Function select, out Function store) {
+ Contract.Requires(abstractedType != null);
+ Contract.Requires(synonymDecl != null);
+ Contract.Ensures(Contract.ValueAtReturn(out select) != null);
+ Contract.Ensures(Contract.ValueAtReturn(out store) != null);
+
+ throw new NotImplementedException();
+ }
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class VariableBindings {
+ public readonly IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ VCExprVarBindings;
+ public readonly IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ TypeVariableBindings;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(VCExprVarBindings));
+ Contract.Invariant(cce.NonNullDictionaryAndValues(TypeVariableBindings));
+ }
+
+
+ public VariableBindings(IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ vcExprVarBindings,
+ IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ typeVariableBindings) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(vcExprVarBindings));
+ Contract.Requires(cce.NonNullDictionaryAndValues(typeVariableBindings));
+ this.VCExprVarBindings = vcExprVarBindings;
+ this.TypeVariableBindings = typeVariableBindings;
+ }
+
+ public VariableBindings() :
+ this(new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>(),
+ new Dictionary<TypeVariable/*!*/, VCExpr/*!*/>()) {
+ }
+
+ public VariableBindings Clone() {
+ Contract.Ensures(Contract.Result<VariableBindings>() != null);
+ IDictionary<VCExprVar/*!*/, VCExprVar/*!*/>/*!*/ newVCExprVarBindings =
+ new Dictionary<VCExprVar/*!*/, VCExprVar/*!*/>();
+ foreach (KeyValuePair<VCExprVar/*!*/, VCExprVar/*!*/> pair in VCExprVarBindings) {
+ Contract.Assert(cce.NonNullElements(pair));
+ newVCExprVarBindings.Add(pair);
+ }
+ IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ newTypeVariableBindings =
+ new Dictionary<TypeVariable/*!*/, VCExpr/*!*/>();
+ foreach (KeyValuePair<TypeVariable/*!*/, VCExpr/*!*/> pair in TypeVariableBindings) {
+ Contract.Assert(cce.NonNullElements(pair));
+ newTypeVariableBindings.Add(pair);
+ }
+ return new VariableBindings(newVCExprVarBindings, newTypeVariableBindings);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ // The central class for turning types VCExprs into untyped
+ // VCExprs. This class makes use of the type axiom builder to manage
+ // the available types and symbols.
+ [ContractClass(typeof(TypeEraserContracts))]
+ public abstract class TypeEraser : MutatingVCExprVisitor<VariableBindings/*!*/> {
+
+ protected readonly TypeAxiomBuilderIntBoolU/*!*/ AxBuilder;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilder != null);
+ }
+
+
+ protected abstract OpTypeEraser/*!*/ OpEraser {
+ get;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public TypeEraser(TypeAxiomBuilderIntBoolU axBuilder, VCExpressionGenerator gen)
+ : base(gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+ AxBuilder = axBuilder;
+ }
+
+ public VCExpr Erase(VCExpr expr, int polarity) {
+ Contract.Requires(expr != null);
+ Contract.Requires((polarity >= -1 && polarity <= 1));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ this.Polarity = polarity;
+ return Mutate(expr, new VariableBindings());
+ }
+
+ internal int Polarity = 1; // 1 for positive, -1 for negative, 0 for both
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr Visit(VCExprLiteral node, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ Contract.Assume(node.Type == Type.Bool || node.Type == Type.Int || node.Type == Type.Real);
+ return node;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override bool AvoidVisit(VCExprNAry node, VariableBindings arg)
+ {
+ return node.Op.Equals(VCExpressionGenerator.AndOp) ||
+ node.Op.Equals(VCExpressionGenerator.OrOp);
+ }
+
+ public override VCExpr Visit(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExprOp/*!*/ op = node.Op;
+ if (op == VCExpressionGenerator.AndOp || op == VCExpressionGenerator.OrOp)
+ // more efficient on large conjunctions/disjunctions
+ return base.Visit(node, bindings);
+
+ // the visitor that handles all other operators
+ return node.Accept<VCExpr/*!*/, VariableBindings/*!*/>(OpEraser, bindings);
+ }
+
+ // this method is called by MutatingVCExprVisitor.Visit(VCExprNAry, ...)
+ protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode, List<VCExpr/*!*/>/*!*/ newSubExprs, bool changed, VariableBindings/*!*/ bindings) {
+ //Contract.Requires(originalNode != null);
+ //Contract.Requires(cce.NonNullElements(newSubExprs));
+ //Contract.Requires(bindings != null);
+ Contract.Assume(originalNode.Op == VCExpressionGenerator.AndOp ||
+ originalNode.Op == VCExpressionGenerator.OrOp);
+ return Gen.Function(originalNode.Op,
+ AxBuilder.Cast(newSubExprs[0], Type.Bool),
+ AxBuilder.Cast(newSubExprs[1], Type.Bool));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr Visit(VCExprVar node, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExprVar res;
+ if (!bindings.VCExprVarBindings.TryGetValue(node, out res))
+ return AxBuilder.Typed2Untyped(node);
+ return cce.NonNull(res);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected bool IsUniversalQuantifier(VCExprQuantifier node) {
+ Contract.Requires(node != null);
+ return Polarity == 1 && node.Quan == Quantifier.EX ||
+ Polarity == -1 && node.Quan == Quantifier.ALL;
+ }
+
+ protected List<VCExprVar/*!*/>/*!*/ BoundVarsAfterErasure(List<VCExprVar/*!*/>/*!*/ oldBoundVars,
+ // the mapping between old and new variables
+ // is added to this bindings-object
+ VariableBindings/*!*/ bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(cce.NonNullElements(oldBoundVars));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+
+ List<VCExprVar/*!*/>/*!*/ newBoundVars = new List<VCExprVar/*!*/>(oldBoundVars.Count);
+ foreach (VCExprVar/*!*/ var in oldBoundVars) {
+ Type/*!*/ newType = AxBuilder.TypeAfterErasure(var.Type);
+ VCExprVar/*!*/ newVar = Gen.Variable(var.Name, newType);
+ newBoundVars.Add(newVar);
+ bindings.VCExprVarBindings.Add(var, newVar);
+ }
+ return newBoundVars;
+ }
+
+ // We check whether casts Int2U or Bool2U on the bound variables
+ // occur in triggers. In case a trigger like f(Int2U(x)) occurs,
+ // it may be better to give variable x the type U and remove the
+ // cast. The following method returns true if the quantifier
+ // should be translated again with a different typing
+ protected bool RedoQuantifier(VCExprQuantifier/*!*/ node,
+ VCExprQuantifier/*!*/ newNode,
+ // the bound vars that actually occur in the body or
+ // in any of the triggers
+ List<VCExprVar/*!*/>/*!*/ occurringVars,
+ VariableBindings/*!*/ oldBindings,
+ out VariableBindings/*!*/ newBindings,
+ out List<VCExprVar/*!*/>/*!*/ newBoundVars) {
+ Contract.Requires(node != null);
+ Contract.Requires(newNode != null);
+ Contract.Requires(cce.NonNullElements(occurringVars));
+ Contract.Requires(oldBindings != null);
+ Contract.Ensures(Contract.ValueAtReturn(out newBindings) != null);
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out newBoundVars)));
+ List<VCExprVar/*!*/> castVariables =
+ VariableCastCollector.FindCastVariables(node, newNode, AxBuilder);
+ if (castVariables.Count == 0) {
+ newBindings = oldBindings; // to make the compiler happy
+ newBoundVars = newNode.BoundVars; // to make the compiler happy
+ return false;
+ }
+
+ // redo everything with a different typing ...
+
+ newBindings = oldBindings.Clone();
+ newBoundVars = new List<VCExprVar/*!*/>(node.BoundVars.Count);
+ foreach (VCExprVar/*!*/ var in node.BoundVars) {
+ Contract.Assert(var != null);
+ Type/*!*/ newType =
+ castVariables.Contains(var) ? AxBuilder.U
+ : AxBuilder.TypeAfterErasure(var.Type);
+ Contract.Assert(newType != null);
+ VCExprVar/*!*/ newVar = Gen.Variable(var.Name, newType);
+ Contract.Assert(newVar != null);
+ newBoundVars.Add(newVar);
+ newBindings.VCExprVarBindings.Add(var, newVar);
+ }
+
+ return true;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr Visit(VCExprLet node, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VariableBindings/*!*/ newVarBindings = bindings.Clone();
+
+ List<VCExprVar/*!*/>/*!*/ newBoundVars = new List<VCExprVar/*!*/>(node.BoundVars.Count);
+ foreach (VCExprVar/*!*/ var in node.BoundVars) {
+ Type/*!*/ newType = AxBuilder.TypeAfterErasure(var.Type);
+ VCExprVar/*!*/ newVar = Gen.Variable(var.Name, newType);
+ newBoundVars.Add(newVar);
+ newVarBindings.VCExprVarBindings.Add(var, newVar);
+ }
+
+ List<VCExprLetBinding/*!*/>/*!*/ newbindings = new List<VCExprLetBinding/*!*/>(node.Length);
+ for (int i = 0; i < node.Length; ++i) {
+ VCExprLetBinding/*!*/ binding = node[i];
+ Contract.Assert(binding != null);
+ VCExprVar/*!*/ newVar = newBoundVars[i];
+ Type/*!*/ newType = newVar.Type;
+
+ VCExpr/*!*/ newE = AxBuilder.Cast(Mutate(binding.E, newVarBindings), newType);
+ newbindings.Add(Gen.LetBinding(newVar, newE));
+ }
+
+ VCExpr/*!*/ newbody = Mutate(node.Body, newVarBindings);
+ return Gen.Let(newbindings, newbody);
+ }
+ }
+
+ [ContractClassFor(typeof(TypeEraser))]
+ public abstract class TypeEraserContracts : TypeEraser {
+ public TypeEraserContracts()
+ : base(null, null) {
+ }
+ protected override OpTypeEraser OpEraser {
+ get {
+ Contract.Ensures(Contract.Result<OpTypeEraser>() != null);
+ throw new NotImplementedException();
+ }
+ }
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public abstract class OpTypeEraser : StandardVCExprOpVisitor<VCExpr/*!*/, VariableBindings/*!*/> {
+
+ protected readonly TypeAxiomBuilderIntBoolU/*!*/ AxBuilder;
+
+ protected readonly TypeEraser/*!*/ Eraser;
+ protected readonly VCExpressionGenerator/*!*/ Gen;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilder != null);
+ Contract.Invariant(Eraser != null);
+ Contract.Invariant(Gen != null);
+ }
+
+
+ public OpTypeEraser(TypeEraser/*!*/ eraser, TypeAxiomBuilderIntBoolU/*!*/ axBuilder, VCExpressionGenerator/*!*/ gen) {
+ Contract.Requires(eraser != null);
+ Contract.Requires(axBuilder != null);
+ Contract.Requires(gen != null);
+ this.AxBuilder = axBuilder;
+ this.Eraser = eraser;
+ this.Gen = gen;
+ }
+
+ protected override VCExpr StandardResult(VCExprNAry node, VariableBindings bindings) {
+ //Contract.Requires(bindings != null);
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ System.Diagnostics.Debug.Fail("Don't know how to erase types in this expression: " + node);
+ Contract.Assert(false);
+ throw new cce.UnreachableException(); // to please the compiler
+ }
+
+ private List<VCExpr/*!*/>/*!*/ MutateSeq(VCExprNAry node, VariableBindings bindings, int newPolarity) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
+ int oldPolarity = Eraser.Polarity;
+ Eraser.Polarity = newPolarity;
+ List<VCExpr/*!*/>/*!*/ newArgs = Eraser.MutateSeq(node, bindings);
+ Eraser.Polarity = oldPolarity;
+ return newArgs;
+ }
+
+ private VCExpr CastArguments(VCExprNAry node, Type argType, VariableBindings bindings, int newPolarity) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(argType != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Gen.Function(node.Op,
+ AxBuilder.CastSeq(MutateSeq(node, bindings, newPolarity),
+ argType));
+ }
+
+ // Cast the arguments of the node to their old type if necessary and possible; otherwise use
+ // their new type (int, real, bool, or U)
+ private VCExpr CastArgumentsToOldType(VCExprNAry node, VariableBindings bindings, int newPolarity) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Requires((node.Arity > 0));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ List<VCExpr/*!*/>/*!*/ newArgs = MutateSeq(node, bindings, newPolarity);
+ Type/*!*/ oldType = node[0].Type;
+ if (AxBuilder.UnchangedType(oldType) &&
+ node.Skip(1).All(e => e.Type.Equals(oldType)))
+ return Gen.Function(node.Op, AxBuilder.CastSeq(newArgs, oldType));
+ else
+ return Gen.Function(node.Op, AxBuilder.CastSeq(newArgs, AxBuilder.U));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr VisitNotOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, Type.Bool, bindings, -Eraser.Polarity);
+ }
+ public override VCExpr VisitEqOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitNeqOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitImpliesOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // UGLY: the code for tracking polarities should be factored out
+ List<VCExpr/*!*/>/*!*/ newArgs = new List<VCExpr/*!*/>(2);
+ Eraser.Polarity = -Eraser.Polarity;
+ newArgs.Add(Eraser.Mutate(node[0], bindings));
+ Eraser.Polarity = -Eraser.Polarity;
+ newArgs.Add(Eraser.Mutate(node[1], bindings));
+ return Gen.Function(node.Op, AxBuilder.CastSeq(newArgs, Type.Bool));
+ }
+ public override VCExpr VisitDistinctOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitLabelOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // argument of the label operator should always be a formula
+ // (at least for Simplify ... should this be ensured at a later point?)
+ return CastArguments(node, Type.Bool, bindings, Eraser.Polarity);
+ }
+ public override VCExpr VisitIfThenElseOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCExpr/*!*/>/*!*/ newArgs = MutateSeq(node, bindings, 0);
+ newArgs[0] = AxBuilder.Cast(newArgs[0], Type.Bool);
+ Type t = node.Type;
+ if (!AxBuilder.UnchangedType(t)) {
+ t = AxBuilder.U;
+ }
+ newArgs[1] = AxBuilder.Cast(newArgs[1], t);
+ newArgs[2] = AxBuilder.Cast(newArgs[2], t);
+ return Gen.Function(node.Op, newArgs);
+ }
+ public override VCExpr/*!*/ VisitCustomOp(VCExprNAry/*!*/ node, VariableBindings/*!*/ bindings) {
+ Contract.Requires(node != null);
+ Contract.Requires(bindings != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ List<VCExpr/*!*/>/*!*/ newArgs = MutateSeq(node, bindings, 0);
+ return Gen.Function(node.Op, newArgs);
+ }
+ public override VCExpr VisitAddOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, node.Type, bindings, 0);
+ }
+ public override VCExpr VisitSubOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, node.Type, bindings, 0);
+ }
+ public override VCExpr VisitMulOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, node.Type, bindings, 0);
+ }
+ public override VCExpr VisitDivOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, Type.Int, bindings, 0);
+ }
+ public override VCExpr VisitModOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, Type.Int, bindings, 0);
+ }
+ public override VCExpr VisitRealDivOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, Type.Real, bindings, 0);
+ }
+ public override VCExpr VisitPowOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, Type.Real, bindings, 0);
+ }
+ public override VCExpr VisitLtOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitLeOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitGtOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitGeOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitSubtypeOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArguments(node, AxBuilder.U, bindings, 0);
+ }
+ public override VCExpr VisitToIntOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitToRealOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitBvOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitBvExtractOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return CastArgumentsToOldType(node, bindings, 0);
+ }
+ public override VCExpr VisitBvConcatOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+ Contract.Requires((node != null));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCExpr/*!*/>/*!*/ newArgs = MutateSeq(node, bindings, 0);
+
+ // each argument is cast to its old type
+ Contract.Assert(newArgs.Count == node.Arity && newArgs.Count == 2);
+ VCExpr/*!*/ arg0 = AxBuilder.Cast(newArgs[0], node[0].Type);
+ Contract.Assert(arg0 != null);
+ VCExpr/*!*/ arg1 = AxBuilder.Cast(newArgs[1], node[1].Type);
+ Contract.Assert(arg1 != null);
+ return Gen.Function(node.Op, arg0, arg1);
+ }
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ /// <summary>
+ /// Collect all variables x occurring in expressions of the form Int2U(x) or Bool2U(x), and
+ /// collect all variables x occurring outside such forms.
+ /// </summary>
+ internal class VariableCastCollector : TraversingVCExprVisitor<bool, bool> {
+ /// <summary>
+ /// Determine those bound variables in "oldNode" <em>all</em> of whose relevant uses
+ /// have to be cast in potential triggers in "newNode". It is assume that
+ /// the bound variables of "oldNode" correspond to the first bound
+ /// variables of "newNode".
+ /// </summary>
+ public static List<VCExprVar/*!*/>/*!*/ FindCastVariables(VCExprQuantifier oldNode, VCExprQuantifier newNode, TypeAxiomBuilderIntBoolU axBuilder) {
+ Contract.Requires((axBuilder != null));
+ Contract.Requires((newNode != null));
+ Contract.Requires((oldNode != null));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+ VariableCastCollector/*!*/ collector = new VariableCastCollector(axBuilder);
+ Contract.Assert(collector != null);
+ if (newNode.Triggers.Any(trigger => trigger.Pos)) {
+ // look in the given triggers
+ foreach (VCTrigger/*!*/ trigger in newNode.Triggers) {
+ Contract.Assert(trigger != null);
+ if (trigger.Pos) {
+ foreach (VCExpr/*!*/ expr in trigger.Exprs) {
+ Contract.Assert(expr != null);
+ collector.Traverse(expr, true);
+ }
+ }
+ }
+ } else {
+ // look in the body of the quantifier
+ collector.Traverse(newNode.Body, true);
+ }
+
+ List<VCExprVar/*!*/>/*!*/ castVariables = new List<VCExprVar/*!*/>(collector.varsInCasts.Count);
+ foreach (VCExprVar/*!*/ castVar in collector.varsInCasts) {
+ Contract.Assert(castVar != null);
+ int i = newNode.BoundVars.IndexOf(castVar);
+ if (0 <= i && i < oldNode.BoundVars.Count && !collector.varsOutsideCasts.ContainsKey(castVar))
+ castVariables.Add(oldNode.BoundVars[i]);
+ }
+ return castVariables;
+ }
+
+ public VariableCastCollector(TypeAxiomBuilderIntBoolU axBuilder) {
+ Contract.Requires(axBuilder != null);
+ this.AxBuilder = axBuilder;
+ }
+
+ readonly List<VCExprVar/*!*/>/*!*/ varsInCasts = new List<VCExprVar/*!*/>();
+ readonly Dictionary<VCExprVar/*!*/, object>/*!*/ varsOutsideCasts = new Dictionary<VCExprVar/*!*/, object>();
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(varsInCasts));
+ Contract.Invariant(varsOutsideCasts != null && Contract.ForAll(varsOutsideCasts, voc => voc.Key != null));
+ Contract.Invariant(AxBuilder != null);
+
+ }
+
+
+ readonly TypeAxiomBuilderIntBoolU/*!*/ AxBuilder;
+
+ protected override bool StandardResult(VCExpr node, bool arg) {
+ //Contract.Requires(node != null);
+ return true; // not used
+ }
+
+ public override bool Visit(VCExprNAry node, bool arg) {
+ Contract.Requires(node != null);
+ if (node.Op is VCExprBoogieFunctionOp) {
+ Function func = ((VCExprBoogieFunctionOp)node.Op).Func;
+ Contract.Assert(func != null);
+ if ((AxBuilder.IsCast(func)) && node[0] is VCExprVar) {
+ VCExprVar castVar = (VCExprVar)node[0];
+ if (!varsInCasts.Contains(castVar))
+ varsInCasts.Add(castVar);
+ return true;
+ }
+ } else if (node.Op is VCExprNAryOp) {
+ VCExpressionGenerator.SingletonOp op = VCExpressionGenerator.SingletonOpDict[node.Op];
+ switch (op) {
+ // the following operators cannot be used in triggers, so disregard any uses of variables as direct arguments
+ case VCExpressionGenerator.SingletonOp.NotOp:
+ case VCExpressionGenerator.SingletonOp.EqOp:
+ case VCExpressionGenerator.SingletonOp.NeqOp:
+ case VCExpressionGenerator.SingletonOp.AndOp:
+ case VCExpressionGenerator.SingletonOp.OrOp:
+ case VCExpressionGenerator.SingletonOp.ImpliesOp:
+ case VCExpressionGenerator.SingletonOp.LtOp:
+ case VCExpressionGenerator.SingletonOp.LeOp:
+ case VCExpressionGenerator.SingletonOp.GtOp:
+ case VCExpressionGenerator.SingletonOp.GeOp:
+ foreach (VCExpr n in node) {
+ if (!(n is VCExprVar)) { // don't recurse on VCExprVar argument
+ n.Accept<bool, bool>(this, arg);
+ }
+ }
+ return true;
+ default:
+ break;
+ }
+ }
+ return base.Visit(node, arg);
+ }
+
+ public override bool Visit(VCExprVar node, bool arg) {
+ Contract.Requires(node != null);
+ if (!varsOutsideCasts.ContainsKey(node))
+ varsOutsideCasts.Add(node, null);
+ return true;
+ }
+ }
+
+}
diff --git a/Source/VCExpr/TypeErasureArguments.cs b/Source/VCExpr/TypeErasureArguments.cs
index 8885cbc7..1ee79c17 100644
--- a/Source/VCExpr/TypeErasureArguments.cs
+++ b/Source/VCExpr/TypeErasureArguments.cs
@@ -1,754 +1,754 @@
-//-----------------------------------------------------------------------------
-//
-// 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;
-using Microsoft.Boogie.VCExprAST;
-
-// Erasure of types using explicit type parameters for functions
-
-namespace Microsoft.Boogie.TypeErasure {
- using Microsoft.Boogie.VCExprAST;
- using HFNS = Microsoft.Boogie.VCExprAST.HelperFuns;
-
- public class TypeAxiomBuilderArguments : TypeAxiomBuilderIntBoolU {
-
- public TypeAxiomBuilderArguments(VCExpressionGenerator gen)
- : base(gen) {
- Contract.Requires(gen != null);
-
- Typed2UntypedFunctions = new Dictionary<Function/*!*/, Function/*!*/>();
- }
-
- // constructor to allow cloning
- [NotDelayed]
- internal TypeAxiomBuilderArguments(TypeAxiomBuilderArguments builder)
- : base(builder) {
- Contract.Requires(builder != null);
- Typed2UntypedFunctions =
- new Dictionary<Function/*!*/, Function/*!*/>(builder.Typed2UntypedFunctions);
-
-
- MapTypeAbstracterAttr =
- builder.MapTypeAbstracterAttr == null ?
- null : new MapTypeAbstractionBuilderArguments(this, builder.Gen,
- builder.MapTypeAbstracterAttr);
- }
-
- public override Object Clone() {
- Contract.Ensures(Contract.Result<Object>() != null);
- return new TypeAxiomBuilderArguments(this);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
- // generate axioms of the kind "forall x:U. {Int2U(U2Int(x))} Int2U(U2Int(x))==x"
- // (this makes use of the assumption that only well-typed terms are generated
- // by the SMT-solver, i.e., that U2Int is only applied to terms that actually
- // are of type int)
- protected override VCExpr GenReverseCastAxiom(Function castToU, Function castFromU) {
- //Contract.Requires(castFromU != null);
- //Contract.Requires(castToU != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCTrigger/*!*/>/*!*/ triggers;
- VCExprVar/*!*/ var;
- VCExpr/*!*/ eq = GenReverseCastEq(castToU, castFromU, out var, out triggers);
- return Gen.Forall(HelperFuns.ToList(var), triggers, "cast:" + castFromU.Name, -1, eq);
- }
-
- protected override VCExpr GenCastTypeAxioms(Function castToU, Function castFromU) {
- //Contract.Requires(castFromU != null);
- //Contract.Requires(castToU != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- // nothing
- return VCExpressionGenerator.True;
- }
-
- private MapTypeAbstractionBuilderArguments MapTypeAbstracterAttr = null;
-
- internal override MapTypeAbstractionBuilder/*!*/ MapTypeAbstracter {
- get {
- Contract.Ensures(Contract.Result<MapTypeAbstractionBuilder>() != null);
-
- if (MapTypeAbstracterAttr == null)
- MapTypeAbstracterAttr = new MapTypeAbstractionBuilderArguments(this, Gen);
- return MapTypeAbstracterAttr;
- }
- }
-
- protected override void AddVarTypeAxiom(VCExprVar var, Type originalType) {
- //Contract.Requires(originalType != null);
- //Contract.Requires(var != null);
- // no axioms are needed for variable or function types
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Symbols for representing functions
-
- // Globally defined functions
- private readonly IDictionary<Function/*!*/, Function/*!*/>/*!*/ Typed2UntypedFunctions;
- [ContractInvariantMethod]
- void Typed2UntypedFunctionsInvariantMethod() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(Typed2UntypedFunctions));
- }
-
- public Function Typed2Untyped(Function fun) {
- Contract.Requires(fun != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- Function res;
- if (!Typed2UntypedFunctions.TryGetValue(fun, out res)) {
- Contract.Assert(fun.OutParams.Count == 1);
-
- // if all of the parameters are int or bool, the function does
- // not have to be changed
- if (fun.InParams.All(param => UnchangedType(cce.NonNull(param).TypedIdent.Type)) &&
- UnchangedType(cce.NonNull(fun.OutParams[0]).TypedIdent.Type)) {
- res = fun;
- } else {
- Type[]/*!*/ types = new Type[fun.TypeParameters.Count + fun.InParams.Count + 1];
-
- int i = 0;
- // the first arguments are the explicit type parameters
- for (int j = 0; j < fun.TypeParameters.Count; ++j) {
- types[i] = T;
- i = i + 1;
- }
- // followed by the actual parameters
- foreach (Variable/*!*/ x in fun.InParams) {
- Contract.Assert(x != null);
- types[i] = TypeAfterErasure(x.TypedIdent.Type);
- i = i + 1;
- }
-
- types[types.Length - 1] = TypeAfterErasure(cce.NonNull(fun.OutParams[0]).TypedIdent.Type);
-
- res = HelperFuns.BoogieFunction(fun.Name, types);
- res.Attributes = fun.Attributes;
- }
-
- Typed2UntypedFunctions.Add(fun, res);
- }
- return cce.NonNull(res);
- }
-
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- internal class MapTypeAbstractionBuilderArguments : MapTypeAbstractionBuilder {
-
- private readonly TypeAxiomBuilderArguments/*!*/ AxBuilderArguments;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilderArguments != null);
- }
-
-
- internal MapTypeAbstractionBuilderArguments(TypeAxiomBuilderArguments axBuilder, VCExpressionGenerator gen)
- : base(axBuilder, gen) {
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
-
- this.AxBuilderArguments = axBuilder;
- }
-
- // constructor for cloning
- internal MapTypeAbstractionBuilderArguments(TypeAxiomBuilderArguments axBuilder, VCExpressionGenerator gen, MapTypeAbstractionBuilderArguments builder)
- : base(axBuilder, gen, builder) {
- Contract.Requires(builder != null);
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
- this.AxBuilderArguments = axBuilder;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- protected override void GenSelectStoreFunctions(MapType abstractedType, TypeCtorDecl synonym, out Function/*!*/ select, out Function/*!*/ store) {
- //Contract.Requires(synonym != null);
-//Contract.Requires(abstractedType != null);
-Contract.Ensures(Contract.ValueAtReturn(out select) != null);
-Contract.Ensures(Contract.ValueAtReturn(out store) != null);
- Contract.Assert(synonym.Name != null);
- string/*!*/ baseName = synonym.Name;
- int typeParamNum = abstractedType.FreeVariables.Count +
- abstractedType.TypeParameters.Count;
-
- int arity = typeParamNum + abstractedType.Arguments.Count;
-
- Type/*!*/[]/*!*/ selectTypes = new Type/*!*/ [arity + 2];
- Type/*!*/[]/*!*/ storeTypes = new Type/*!*/ [arity + 3];
-
- int i = 0;
- // Fill in the free variables and type parameters
- for (; i < typeParamNum; i++) {
- selectTypes[i] = AxBuilder.T;
- storeTypes[i] = AxBuilder.T;
- }
- // Fill in the map type
- if (CommandLineOptions.Clo.MonomorphicArrays) {
- selectTypes[i] = abstractedType;
- storeTypes[i] = abstractedType;
- } else {
- selectTypes[i] = AxBuilder.U;
- storeTypes[i] = AxBuilder.U;
- }
- i++;
- // Fill in the index types
- foreach (Type/*!*/ type in abstractedType.Arguments) {
- Contract.Assert(type != null);
- if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(type)) {
- selectTypes[i] = type;
- storeTypes[i] = type;
- } else {
- selectTypes[i] = AxBuilder.U;
- storeTypes[i] = AxBuilder.U;
- }
- i++;
- }
- // Fill in the output type for select function which also happens
- // to be the type of the last argument to the store function
- if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(abstractedType.Result)) {
- selectTypes[i] = abstractedType.Result;
- storeTypes[i] = abstractedType.Result;
- } else {
- selectTypes[i] = AxBuilder.U;
- storeTypes[i] = AxBuilder.U;
- }
- i++;
- // Fill in the map type which is the output of the store function
- if (CommandLineOptions.Clo.MonomorphicArrays)
- storeTypes[i] = abstractedType;
- else
- storeTypes[i] = AxBuilder.U;
- Contract.Assert(cce.NonNullElements<Type>(selectTypes));
- Contract.Assert(cce.NonNullElements<Type>(storeTypes));
-
- select = HelperFuns.BoogieFunction(baseName + "Select", selectTypes);
- store = HelperFuns.BoogieFunction(baseName + "Store", storeTypes);
-
- if (CommandLineOptions.Clo.UseArrayTheory) {
- select.AddAttribute("builtin", "select");
- store.AddAttribute("builtin", "store");
- } else {
- AxBuilder.AddTypeAxiom(GenMapAxiom0(select, store,
- abstractedType.TypeParameters.Count, abstractedType.FreeVariables.Count));
- AxBuilder.AddTypeAxiom(GenMapAxiom1(select, store,
- abstractedType.TypeParameters.Count, abstractedType.FreeVariables.Count));
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // The normal axioms of the theory of arrays (right now without extensionality)
-
- private VCExpr Select(Function select, List<VCExprVar/*!*/>/*!*/ types, VCExpr map, List<VCExprVar/*!*/>/*!*/ indexes) {
- Contract.Requires(map != null);
- Contract.Requires(select != null);
- Contract.Requires(cce.NonNullElements(indexes));
- Contract.Requires(cce.NonNullElements(types));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCExpr/*!*/>/*!*/ selectArgs = new List<VCExpr/*!*/>();
- selectArgs.AddRange(HelperFuns.ToVCExprList(types));
- selectArgs.Add(map);
- selectArgs.AddRange(HelperFuns.ToVCExprList(indexes));
- return Gen.Function(select, selectArgs);
- }
-
- private VCExpr Store(Function store, List<VCExprVar/*!*/>/*!*/ types, VCExpr map, List<VCExprVar/*!*/>/*!*/ indexes, VCExpr val) {
- Contract.Requires(val != null);
- Contract.Requires(map != null);
- Contract.Requires(store != null);
- Contract.Requires(cce.NonNullElements(indexes));
- Contract.Requires(cce.NonNullElements(types));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCExpr/*!*/>/*!*/ storeArgs = new List<VCExpr/*!*/>();
- storeArgs.AddRange(HelperFuns.ToVCExprList(types));
- storeArgs.Add(map);
- storeArgs.AddRange(HelperFuns.ToVCExprList(indexes));
- storeArgs.Add(val);
- return Gen.Function(store, storeArgs);
- }
-
- private VCExpr/*!*/ GenMapAxiom0(Function/*!*/ select, Function/*!*/ store,
- // bound type variables in the map type
- int mapTypeParamNum,
- // free type variables in the map
- // type (abstraction)
- int mapAbstractionVarNum) {
- Contract.Requires(select != null);
- Contract.Requires(store != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- int arity = select.InParams.Count - 1 - mapTypeParamNum - mapAbstractionVarNum;
- List<VCExprVar/*!*/>/*!*/ types =
- HelperFuns.VarVector("t", mapTypeParamNum + mapAbstractionVarNum,
- AxBuilder.T, Gen);
-
- List<Type/*!*/> indexTypes = new List<Type/*!*/>();
- for (int i = mapTypeParamNum + mapAbstractionVarNum + 1; i < select.InParams.Count; i++) {
- indexTypes.Add(cce.NonNull(select.InParams[i]).TypedIdent.Type);
- }
- Contract.Assert(arity == indexTypes.Count);
-
- List<VCExprVar/*!*/>/*!*/ indexes = HelperFuns.VarVector("x", indexTypes, Gen);
-
- VCExprVar/*!*/ m = Gen.Variable("m", AxBuilder.U);
- Contract.Assert(m != null);
- VCExprVar/*!*/ val = Gen.Variable("val", cce.NonNull(select.OutParams[0]).TypedIdent.Type);
- Contract.Assert(val != null);
-
- VCExpr/*!*/ storeExpr = Store(store, types, m, indexes, val);
- Contract.Assert(storeExpr != null);
- VCExpr/*!*/ selectExpr = Select(select, types, storeExpr, indexes);
- Contract.Assert(selectExpr != null);
-
- List<VCExprVar/*!*/>/*!*/ quantifiedVars = new List<VCExprVar/*!*/>();
- quantifiedVars.AddRange(types);
- quantifiedVars.Add(val);
- quantifiedVars.Add(m);
- quantifiedVars.AddRange(indexes);
-
- VCExpr/*!*/ eq = Gen.Eq(selectExpr, val);
- Contract.Assert(eq != null);
- return Gen.Forall(quantifiedVars, new List<VCTrigger/*!*/>(), "mapAx0:" + select.Name, 0, eq);
- }
-
- private VCExpr/*!*/ GenMapAxiom1(Function/*!*/ select, Function/*!*/ store,
- // bound type variables in the map
- // type
- int mapTypeParamNum,
- // free type variables in the map
- // type (abstraction)
- int mapAbstractionVarNum) {
- Contract.Requires(select != null);
- Contract.Requires(store != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- int arity = select.InParams.Count - 1 - mapTypeParamNum - mapAbstractionVarNum;
-
- List<VCExprVar/*!*/>/*!*/ freeTypeVars =
- HelperFuns.VarVector("u", mapAbstractionVarNum, AxBuilder.T, Gen);
- List<VCExprVar/*!*/>/*!*/ boundTypeVars0 =
- HelperFuns.VarVector("s", mapTypeParamNum, AxBuilder.T, Gen);
- List<VCExprVar/*!*/>/*!*/ boundTypeVars1 =
- HelperFuns.VarVector("t", mapTypeParamNum, AxBuilder.T, Gen);
-
- List<VCExprVar/*!*/>/*!*/ types0 = new List<VCExprVar/*!*/>(boundTypeVars0);
- types0.AddRange(freeTypeVars);
-
- List<VCExprVar/*!*/>/*!*/ types1 = new List<VCExprVar/*!*/>(boundTypeVars1);
- types1.AddRange(freeTypeVars);
-
- List<Type/*!*/> indexTypes = new List<Type/*!*/>();
- for (int i = mapTypeParamNum + mapAbstractionVarNum + 1; i < select.InParams.Count; i++) {
- indexTypes.Add(cce.NonNull(select.InParams[i]).TypedIdent.Type);
- }
- Contract.Assert(arity == indexTypes.Count);
-
- List<VCExprVar/*!*/>/*!*/ indexes0 = HelperFuns.VarVector("x", indexTypes, Gen);
- List<VCExprVar/*!*/>/*!*/ indexes1 = HelperFuns.VarVector("y", indexTypes, Gen);
-
- VCExprVar/*!*/ m = Gen.Variable("m", AxBuilder.U);
- Contract.Assert(m != null);
- VCExprVar/*!*/ val = Gen.Variable("val", cce.NonNull(select.OutParams[0]).TypedIdent.Type);
- Contract.Assert(val != null);
-
- VCExpr/*!*/ storeExpr = Store(store, types0, m, indexes0, val);
- Contract.Assert(storeExpr != null);
- VCExpr/*!*/ selectWithoutStoreExpr = Select(select, types1, m, indexes1);
- Contract.Assert(selectWithoutStoreExpr != null);
- VCExpr/*!*/ selectExpr = Select(select, types1, storeExpr, indexes1);
- Contract.Assert(selectExpr != null);
-
- VCExpr/*!*/ selectEq = Gen.Eq(selectExpr, selectWithoutStoreExpr);
- Contract.Assert(selectEq != null);
-
- List<VCExprVar/*!*/>/*!*/ quantifiedVars = new List<VCExprVar/*!*/>();
- quantifiedVars.AddRange(freeTypeVars);
- quantifiedVars.AddRange(boundTypeVars0);
- quantifiedVars.AddRange(boundTypeVars1);
- quantifiedVars.Add(val);
- quantifiedVars.Add(m);
- quantifiedVars.AddRange(indexes0);
- quantifiedVars.AddRange(indexes1);
-
- List<VCTrigger/*!*/>/*!*/ triggers = new List<VCTrigger/*!*/>();
-
- // different value arguments or different type arguments are sufficient
- // to conclude that that value of the map at some point (after an update)
- // has not changed
-
- List<VCExpr/*!*/>/*!*/ indexEqs = new List<VCExpr/*!*/>();
- for (int i = 0; i < mapTypeParamNum; ++i)
- indexEqs.Add(Gen.Eq(boundTypeVars0[i], boundTypeVars1[i]));
- for (int i = 0; i < arity; ++i)
- indexEqs.Add(Gen.Eq(indexes0[i], indexes1[i]));
-
- VCExpr/*!*/ axiom = VCExpressionGenerator.True;
- int n = 0;
- foreach (VCExpr/*!*/ indexesEq in indexEqs) {
- Contract.Assert(indexesEq != null);
- VCExpr/*!*/ matrix = Gen.Or(indexesEq, selectEq);
- Contract.Assert(matrix != null);
- VCExpr/*!*/ conjunct = Gen.Forall(quantifiedVars, triggers, "mapAx1:" + select.Name + ":" + n, 0, matrix);
- Contract.Assert(conjunct != null);
- axiom = Gen.AndSimp(axiom, conjunct);
- n = n + 1;
- }
-
- return axiom;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- public class TypeEraserArguments : TypeEraser {
-
- private readonly TypeAxiomBuilderArguments/*!*/ AxBuilderArguments;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilderArguments != null);
- }
-
-
- private OpTypeEraser OpEraserAttr = null;
- protected override OpTypeEraser/*!*/ OpEraser {
- get {
- Contract.Ensures(Contract.Result<OpTypeEraser>() != null);
-
- if (OpEraserAttr == null)
- OpEraserAttr = new OpTypeEraserArguments(this, AxBuilderArguments, Gen);
- return OpEraserAttr;
- }
- }
-
- public TypeEraserArguments(TypeAxiomBuilderArguments axBuilder, VCExpressionGenerator gen) :base(axBuilder, gen){
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
-
- this.AxBuilderArguments = axBuilder;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override VCExpr Visit(VCExprQuantifier node, VariableBindings oldBindings) {
- Contract.Requires(oldBindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VariableBindings/*!*/ bindings = oldBindings.Clone();
-
- // bound term variables are replaced with bound term variables
- // typed in a simpler way
- List<VCExprVar/*!*/>/*!*/ newBoundVars =
- BoundVarsAfterErasure(node.BoundVars, bindings);
-
- // type variables are replaced with ordinary quantified variables
- GenBoundVarsForTypeParams(node.TypeParameters, newBoundVars, bindings);
- VCExpr/*!*/ newNode = HandleQuantifier(node, newBoundVars, bindings);
- Contract.Assert(newNode != null);
-
- if (!(newNode is VCExprQuantifier) || !IsUniversalQuantifier(node))
- return newNode;
-
- VariableBindings/*!*/ bindings2;
- if (!RedoQuantifier(node, (VCExprQuantifier)newNode, node.BoundVars, oldBindings,
- out bindings2, out newBoundVars))
- return newNode;
-
- GenBoundVarsForTypeParams(node.TypeParameters, newBoundVars, bindings2);
- return HandleQuantifier(node, newBoundVars, bindings2);
- }
-
- private void GenBoundVarsForTypeParams(List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ newBoundVars, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Requires(cce.NonNullElements(newBoundVars));
- foreach (TypeVariable/*!*/ tvar in typeParams) {
- Contract.Assert(tvar != null);
- VCExprVar/*!*/ var = Gen.Variable(tvar.Name, AxBuilder.T);
- Contract.Assert(var != null);
- newBoundVars.Add(var);
- bindings.TypeVariableBindings.Add(tvar, var);
- }
- }
-
- private VCExpr HandleQuantifier(VCExprQuantifier node, List<VCExprVar/*!*/>/*!*/ newBoundVars, VariableBindings bindings){
-Contract.Requires(bindings != null);
-Contract.Requires(node != null);
-Contract.Requires(cce.NonNullElements(newBoundVars));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCTrigger/*!*/>/*!*/ newTriggers = MutateTriggers(node.Triggers, bindings);
- Contract.Assert(cce.NonNullElements(newTriggers));
- VCExpr/*!*/ newBody = Mutate(node.Body, bindings);
- Contract.Assert(newBody != null);
- newBody = AxBuilder.Cast(newBody, Type.Bool);
-
- if (newBoundVars.Count == 0) // might happen that no bound variables are left
- return newBody;
- return Gen.Quantify(node.Quan, new List<TypeVariable/*!*/>(), newBoundVars,
- newTriggers, node.Infos, newBody);
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- public class OpTypeEraserArguments : OpTypeEraser {
-
- protected readonly TypeAxiomBuilderArguments/*!*/ AxBuilderArguments;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilderArguments != null);
- }
-
-
- public OpTypeEraserArguments(TypeEraserArguments eraser, TypeAxiomBuilderArguments axBuilder, VCExpressionGenerator gen) :base(eraser, axBuilder, gen){
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
- Contract.Requires(eraser != null);
- this.AxBuilderArguments = axBuilder;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- private VCExpr AssembleOpExpression(OpTypesPair opTypes, IEnumerable<VCExpr/*!*/>/*!*/ oldArgs, VariableBindings bindings){
-Contract.Requires(bindings != null);
-Contract.Requires(cce.NonNullElements(oldArgs));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- // UGLY: the code for tracking polarities should be factored out
- int oldPolarity = Eraser.Polarity;
- Eraser.Polarity = 0;
-
- List<VCExpr/*!*/>/*!*/ newArgs = new List<VCExpr/*!*/> ();
- // explicit type parameters
- foreach (Type/*!*/ t in opTypes.Types){
- Contract.Assert(newArgs != null);
- newArgs.Add(AxBuilder.Type2Term(t, bindings.TypeVariableBindings));}
-
- // and the actual value parameters
- Function/*!*/ newFun = ((VCExprBoogieFunctionOp)opTypes.Op).Func;
- // ^ we only allow this operator at this point
- int i = opTypes.Types.Count;
- foreach (VCExpr/*!*/ arg in oldArgs) {
- Contract.Assert(arg != null);
- newArgs.Add(AxBuilder.Cast(Eraser.Mutate(arg, bindings),
- cce.NonNull(newFun.InParams[i]).TypedIdent.Type));
- i = i + 1;
- }
-
- Eraser.Polarity = oldPolarity;
- return Gen.Function(opTypes.Op, newArgs);
- }
-
- // for the time being, we store both the types of the arguments and the explicit
- // type parameters (for most operators, this is more than actually necessary)
- private OpTypesPair OriginalOpTypes(VCExprNAry node){
-Contract.Requires(node != null);
- List<Type/*!*/>/*!*/ originalTypes = new List<Type/*!*/> ();
- foreach (VCExpr/*!*/ expr in node) {
- Contract.Assert(expr != null);
- originalTypes.Add(expr.Type);
- }
- originalTypes.AddRange(node.TypeArguments);
- return new OpTypesPair (node.Op, originalTypes);
- }
-
- private VCExpr EqualTypes(Type t0, Type t1, VariableBindings bindings){
-Contract.Requires(bindings != null);
-Contract.Requires(t1 != null);
-Contract.Requires(t0 != null);
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (t0.Equals(t1))
- return VCExpressionGenerator.True;
- VCExpr/*!*/ t0Expr = AxBuilder.Type2Term(t0, bindings.TypeVariableBindings);
- Contract.Assert(t0Expr != null);
- VCExpr/*!*/ t1Expr = AxBuilder.Type2Term(t1, bindings.TypeVariableBindings);
- Contract.Assert(t1Expr != null);
- return Gen.Eq(t0Expr, t1Expr);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- public override VCExpr VisitEqOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
-Contract.Requires((node != null));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- // we also have to state that the types are equal, because the
- // translation does not contain any information about the
- // relationship between values and types
- return Gen.AndSimp(base.VisitEqOp(node, bindings),
- EqualTypes(node[0].Type, node[1].Type, bindings));
- }
-
- public override VCExpr VisitNeqOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires((bindings != null));
-Contract.Requires((node != null));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- // we also have to state that the types are (un)equal, because the
- // translation does not contain any information about the
- // relationship between values and types
- return Gen.OrSimp(base.VisitNeqOp(node, bindings),
- Gen.Not(EqualTypes(node[0].Type, node[1].Type, bindings)));
- }
-
- public override VCExpr VisitSubtypeOp(VCExprNAry node, VariableBindings bindings) {
-Contract.Requires((bindings != null));
-Contract.Requires((node != null));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- // UGLY: the code for tracking polarities should be factored out
- int oldPolarity = Eraser.Polarity;
- Eraser.Polarity = 0;
-
- VCExpr/*!*/ res =
- Gen.Function(VCExpressionGenerator.Subtype3Op,
- AxBuilder.Type2Term(node[0].Type,
- bindings.TypeVariableBindings),
- AxBuilder.Cast(Eraser.Mutate(node[0], bindings),
- AxBuilder.U),
- AxBuilder.Cast(Eraser.Mutate(node[1], bindings),
- AxBuilder.U));
-
- Eraser.Polarity = oldPolarity;
- return res;
- }
-
- public override VCExpr VisitSelectOp(VCExprNAry node, VariableBindings bindings) {
-Contract.Requires((bindings != null));
-Contract.Requires((node != null));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- OpTypesPair originalOpTypes = OriginalOpTypes(node);
- OpTypesPair newOpTypes;
-
- if (!NewOpCache.TryGetValue(originalOpTypes, out newOpTypes)) {
- MapType/*!*/ rawType = node[0].Type.AsMap;
- Contract.Assert(rawType != null);
- List<Type>/*!*/ abstractionInstantiation;
- Function/*!*/ select =
- AxBuilder.MapTypeAbstracter.Select(rawType, out abstractionInstantiation);
- Contract.Assert(abstractionInstantiation != null);
- newOpTypes = TypesPairForSelectStore(node, select, abstractionInstantiation);
- NewOpCache.Add(originalOpTypes, newOpTypes);
- }
-
- return AssembleOpExpression(newOpTypes, node, bindings);
- }
-
- public override VCExpr VisitStoreOp(VCExprNAry node, VariableBindings bindings) {
-Contract.Requires((bindings != null));
-Contract.Requires((node != null));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- OpTypesPair originalOpTypes = OriginalOpTypes(node);
- OpTypesPair newOpTypes;
-
- if (!NewOpCache.TryGetValue(originalOpTypes, out newOpTypes)) {
- MapType/*!*/ rawType = node[0].Type.AsMap;
- List<Type>/*!*/ abstractionInstantiation;
- Function/*!*/ store =
- AxBuilder.MapTypeAbstracter.Store(rawType, out abstractionInstantiation);
-
- newOpTypes = TypesPairForSelectStore(node, store, abstractionInstantiation);
- NewOpCache.Add(originalOpTypes, newOpTypes);
- }
-
- return AssembleOpExpression(newOpTypes, node, bindings);
- }
-
- private OpTypesPair TypesPairForSelectStore(VCExprNAry/*!*/ node, Function/*!*/ untypedOp,
- // instantiation of the abstract map type parameters
- List<Type>/*!*/ abstractionInstantiation) {
- Contract.Requires(node != null);
- Contract.Requires(untypedOp != null);
- Contract.Requires(abstractionInstantiation != null);
-
- List<Type/*!*/>/*!*/ inferredTypeArgs = new List<Type/*!*/> ();
- foreach (Type/*!*/ t in node.TypeArguments){Contract.Assert(t != null);
-// inferredTypeArgs.Add(AxBuilder.MapTypeAbstracter.AbstractMapTypeRecursively(t));
- inferredTypeArgs.Add(t);}
- foreach (Type/*!*/ t in abstractionInstantiation) {
- Contract.Assert(t != null);
- inferredTypeArgs.Add(t);}
-
- Contract.Assert(untypedOp.InParams.Count == inferredTypeArgs.Count + node.Arity);
- return new OpTypesPair (Gen.BoogieFunctionOp(untypedOp), inferredTypeArgs);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- public override VCExpr VisitBoogieFunctionOp(VCExprNAry node, VariableBindings bindings) {
-Contract.Requires((bindings != null));
-Contract.Requires((node != null));
-Contract.Ensures(Contract.Result<VCExpr>() != null);
- OpTypesPair originalOpTypes = OriginalOpTypes(node);
- OpTypesPair newOpTypes;
-
- if (!NewOpCache.TryGetValue(originalOpTypes, out newOpTypes)) {
- Function/*!*/ oriFun = ((VCExprBoogieFunctionOp)node.Op).Func;
- Contract.Assert(oriFun != null);
- List<Type/*!*/>/*!*/ inferredTypeArgs = new List<Type/*!*/> ();
- foreach (Type/*!*/ t in node.TypeArguments){Contract.Assert(t != null);
-// inferredTypeArgs.Add(AxBuilder.MapTypeAbstracter.AbstractMapTypeRecursively(t));
- inferredTypeArgs.Add(t);}
-
- VCExprOp/*!*/ newOp = Gen.BoogieFunctionOp(AxBuilderArguments.Typed2Untyped(oriFun));
- newOpTypes = new OpTypesPair (newOp, inferredTypeArgs);
-
- NewOpCache.Add(originalOpTypes, newOpTypes);
- }
-
- return AssembleOpExpression(newOpTypes, node, bindings);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- // cache from the typed operators to the untyped operators with
- // explicit type arguments. the keys are pairs of the typed
- // operator and the actual types of the argument expressions, the
- // values are pairs of the new operators and the types that have
- // to be given as explicit type arguments
- private readonly IDictionary<OpTypesPair, OpTypesPair>/*!*/ NewOpCache =
- new Dictionary<OpTypesPair, OpTypesPair>();
-
- private struct OpTypesPair {
- public readonly VCExprOp/*!*/ Op;
- public readonly List<Type/*!*/>/*!*/ Types;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Op != null);
- Contract.Invariant(cce.NonNullElements(Types));
- }
-
-
- public OpTypesPair(VCExprOp op, List<Type/*!*/>/*!*/ types) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(types));
- this.Op = op;
- this.Types = types;
- this.HashCode = HFNS.PolyHash(op.GetHashCode(), 17, types);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (that is OpTypesPair) {
- OpTypesPair thatPair = (OpTypesPair)that;
- return this.Op.Equals(thatPair.Op) &&
- HFNS.SameElements(this.Types, thatPair.Types);
- }
- return false;
- }
-
- private readonly int HashCode;
-
- [Pure]
- public override int GetHashCode() {
- return HashCode;
- }
- }
- }
+//-----------------------------------------------------------------------------
+//
+// 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;
+using Microsoft.Boogie.VCExprAST;
+
+// Erasure of types using explicit type parameters for functions
+
+namespace Microsoft.Boogie.TypeErasure {
+ using Microsoft.Boogie.VCExprAST;
+ using HFNS = Microsoft.Boogie.VCExprAST.HelperFuns;
+
+ public class TypeAxiomBuilderArguments : TypeAxiomBuilderIntBoolU {
+
+ public TypeAxiomBuilderArguments(VCExpressionGenerator gen)
+ : base(gen) {
+ Contract.Requires(gen != null);
+
+ Typed2UntypedFunctions = new Dictionary<Function/*!*/, Function/*!*/>();
+ }
+
+ // constructor to allow cloning
+ [NotDelayed]
+ internal TypeAxiomBuilderArguments(TypeAxiomBuilderArguments builder)
+ : base(builder) {
+ Contract.Requires(builder != null);
+ Typed2UntypedFunctions =
+ new Dictionary<Function/*!*/, Function/*!*/>(builder.Typed2UntypedFunctions);
+
+
+ MapTypeAbstracterAttr =
+ builder.MapTypeAbstracterAttr == null ?
+ null : new MapTypeAbstractionBuilderArguments(this, builder.Gen,
+ builder.MapTypeAbstracterAttr);
+ }
+
+ public override Object Clone() {
+ Contract.Ensures(Contract.Result<Object>() != null);
+ return new TypeAxiomBuilderArguments(this);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ // generate axioms of the kind "forall x:U. {Int2U(U2Int(x))} Int2U(U2Int(x))==x"
+ // (this makes use of the assumption that only well-typed terms are generated
+ // by the SMT-solver, i.e., that U2Int is only applied to terms that actually
+ // are of type int)
+ protected override VCExpr GenReverseCastAxiom(Function castToU, Function castFromU) {
+ //Contract.Requires(castFromU != null);
+ //Contract.Requires(castToU != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCTrigger/*!*/>/*!*/ triggers;
+ VCExprVar/*!*/ var;
+ VCExpr/*!*/ eq = GenReverseCastEq(castToU, castFromU, out var, out triggers);
+ return Gen.Forall(HelperFuns.ToList(var), triggers, "cast:" + castFromU.Name, -1, eq);
+ }
+
+ protected override VCExpr GenCastTypeAxioms(Function castToU, Function castFromU) {
+ //Contract.Requires(castFromU != null);
+ //Contract.Requires(castToU != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // nothing
+ return VCExpressionGenerator.True;
+ }
+
+ private MapTypeAbstractionBuilderArguments MapTypeAbstracterAttr = null;
+
+ internal override MapTypeAbstractionBuilder/*!*/ MapTypeAbstracter {
+ get {
+ Contract.Ensures(Contract.Result<MapTypeAbstractionBuilder>() != null);
+
+ if (MapTypeAbstracterAttr == null)
+ MapTypeAbstracterAttr = new MapTypeAbstractionBuilderArguments(this, Gen);
+ return MapTypeAbstracterAttr;
+ }
+ }
+
+ protected override void AddVarTypeAxiom(VCExprVar var, Type originalType) {
+ //Contract.Requires(originalType != null);
+ //Contract.Requires(var != null);
+ // no axioms are needed for variable or function types
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Symbols for representing functions
+
+ // Globally defined functions
+ private readonly IDictionary<Function/*!*/, Function/*!*/>/*!*/ Typed2UntypedFunctions;
+ [ContractInvariantMethod]
+ void Typed2UntypedFunctionsInvariantMethod() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(Typed2UntypedFunctions));
+ }
+
+ public Function Typed2Untyped(Function fun) {
+ Contract.Requires(fun != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ Function res;
+ if (!Typed2UntypedFunctions.TryGetValue(fun, out res)) {
+ Contract.Assert(fun.OutParams.Count == 1);
+
+ // if all of the parameters are int or bool, the function does
+ // not have to be changed
+ if (fun.InParams.All(param => UnchangedType(cce.NonNull(param).TypedIdent.Type)) &&
+ UnchangedType(cce.NonNull(fun.OutParams[0]).TypedIdent.Type)) {
+ res = fun;
+ } else {
+ Type[]/*!*/ types = new Type[fun.TypeParameters.Count + fun.InParams.Count + 1];
+
+ int i = 0;
+ // the first arguments are the explicit type parameters
+ for (int j = 0; j < fun.TypeParameters.Count; ++j) {
+ types[i] = T;
+ i = i + 1;
+ }
+ // followed by the actual parameters
+ foreach (Variable/*!*/ x in fun.InParams) {
+ Contract.Assert(x != null);
+ types[i] = TypeAfterErasure(x.TypedIdent.Type);
+ i = i + 1;
+ }
+
+ types[types.Length - 1] = TypeAfterErasure(cce.NonNull(fun.OutParams[0]).TypedIdent.Type);
+
+ res = HelperFuns.BoogieFunction(fun.Name, types);
+ res.Attributes = fun.Attributes;
+ }
+
+ Typed2UntypedFunctions.Add(fun, res);
+ }
+ return cce.NonNull(res);
+ }
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ internal class MapTypeAbstractionBuilderArguments : MapTypeAbstractionBuilder {
+
+ private readonly TypeAxiomBuilderArguments/*!*/ AxBuilderArguments;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilderArguments != null);
+ }
+
+
+ internal MapTypeAbstractionBuilderArguments(TypeAxiomBuilderArguments axBuilder, VCExpressionGenerator gen)
+ : base(axBuilder, gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+
+ this.AxBuilderArguments = axBuilder;
+ }
+
+ // constructor for cloning
+ internal MapTypeAbstractionBuilderArguments(TypeAxiomBuilderArguments axBuilder, VCExpressionGenerator gen, MapTypeAbstractionBuilderArguments builder)
+ : base(axBuilder, gen, builder) {
+ Contract.Requires(builder != null);
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+ this.AxBuilderArguments = axBuilder;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected override void GenSelectStoreFunctions(MapType abstractedType, TypeCtorDecl synonym, out Function/*!*/ select, out Function/*!*/ store) {
+ //Contract.Requires(synonym != null);
+//Contract.Requires(abstractedType != null);
+Contract.Ensures(Contract.ValueAtReturn(out select) != null);
+Contract.Ensures(Contract.ValueAtReturn(out store) != null);
+ Contract.Assert(synonym.Name != null);
+ string/*!*/ baseName = synonym.Name;
+ int typeParamNum = abstractedType.FreeVariables.Count +
+ abstractedType.TypeParameters.Count;
+
+ int arity = typeParamNum + abstractedType.Arguments.Count;
+
+ Type/*!*/[]/*!*/ selectTypes = new Type/*!*/ [arity + 2];
+ Type/*!*/[]/*!*/ storeTypes = new Type/*!*/ [arity + 3];
+
+ int i = 0;
+ // Fill in the free variables and type parameters
+ for (; i < typeParamNum; i++) {
+ selectTypes[i] = AxBuilder.T;
+ storeTypes[i] = AxBuilder.T;
+ }
+ // Fill in the map type
+ if (CommandLineOptions.Clo.MonomorphicArrays) {
+ selectTypes[i] = abstractedType;
+ storeTypes[i] = abstractedType;
+ } else {
+ selectTypes[i] = AxBuilder.U;
+ storeTypes[i] = AxBuilder.U;
+ }
+ i++;
+ // Fill in the index types
+ foreach (Type/*!*/ type in abstractedType.Arguments) {
+ Contract.Assert(type != null);
+ if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(type)) {
+ selectTypes[i] = type;
+ storeTypes[i] = type;
+ } else {
+ selectTypes[i] = AxBuilder.U;
+ storeTypes[i] = AxBuilder.U;
+ }
+ i++;
+ }
+ // Fill in the output type for select function which also happens
+ // to be the type of the last argument to the store function
+ if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(abstractedType.Result)) {
+ selectTypes[i] = abstractedType.Result;
+ storeTypes[i] = abstractedType.Result;
+ } else {
+ selectTypes[i] = AxBuilder.U;
+ storeTypes[i] = AxBuilder.U;
+ }
+ i++;
+ // Fill in the map type which is the output of the store function
+ if (CommandLineOptions.Clo.MonomorphicArrays)
+ storeTypes[i] = abstractedType;
+ else
+ storeTypes[i] = AxBuilder.U;
+ Contract.Assert(cce.NonNullElements<Type>(selectTypes));
+ Contract.Assert(cce.NonNullElements<Type>(storeTypes));
+
+ select = HelperFuns.BoogieFunction(baseName + "Select", selectTypes);
+ store = HelperFuns.BoogieFunction(baseName + "Store", storeTypes);
+
+ if (CommandLineOptions.Clo.UseArrayTheory) {
+ select.AddAttribute("builtin", "select");
+ store.AddAttribute("builtin", "store");
+ } else {
+ AxBuilder.AddTypeAxiom(GenMapAxiom0(select, store,
+ abstractedType.TypeParameters.Count, abstractedType.FreeVariables.Count));
+ AxBuilder.AddTypeAxiom(GenMapAxiom1(select, store,
+ abstractedType.TypeParameters.Count, abstractedType.FreeVariables.Count));
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The normal axioms of the theory of arrays (right now without extensionality)
+
+ private VCExpr Select(Function select, List<VCExprVar/*!*/>/*!*/ types, VCExpr map, List<VCExprVar/*!*/>/*!*/ indexes) {
+ Contract.Requires(map != null);
+ Contract.Requires(select != null);
+ Contract.Requires(cce.NonNullElements(indexes));
+ Contract.Requires(cce.NonNullElements(types));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCExpr/*!*/>/*!*/ selectArgs = new List<VCExpr/*!*/>();
+ selectArgs.AddRange(HelperFuns.ToVCExprList(types));
+ selectArgs.Add(map);
+ selectArgs.AddRange(HelperFuns.ToVCExprList(indexes));
+ return Gen.Function(select, selectArgs);
+ }
+
+ private VCExpr Store(Function store, List<VCExprVar/*!*/>/*!*/ types, VCExpr map, List<VCExprVar/*!*/>/*!*/ indexes, VCExpr val) {
+ Contract.Requires(val != null);
+ Contract.Requires(map != null);
+ Contract.Requires(store != null);
+ Contract.Requires(cce.NonNullElements(indexes));
+ Contract.Requires(cce.NonNullElements(types));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCExpr/*!*/>/*!*/ storeArgs = new List<VCExpr/*!*/>();
+ storeArgs.AddRange(HelperFuns.ToVCExprList(types));
+ storeArgs.Add(map);
+ storeArgs.AddRange(HelperFuns.ToVCExprList(indexes));
+ storeArgs.Add(val);
+ return Gen.Function(store, storeArgs);
+ }
+
+ private VCExpr/*!*/ GenMapAxiom0(Function/*!*/ select, Function/*!*/ store,
+ // bound type variables in the map type
+ int mapTypeParamNum,
+ // free type variables in the map
+ // type (abstraction)
+ int mapAbstractionVarNum) {
+ Contract.Requires(select != null);
+ Contract.Requires(store != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ int arity = select.InParams.Count - 1 - mapTypeParamNum - mapAbstractionVarNum;
+ List<VCExprVar/*!*/>/*!*/ types =
+ HelperFuns.VarVector("t", mapTypeParamNum + mapAbstractionVarNum,
+ AxBuilder.T, Gen);
+
+ List<Type/*!*/> indexTypes = new List<Type/*!*/>();
+ for (int i = mapTypeParamNum + mapAbstractionVarNum + 1; i < select.InParams.Count; i++) {
+ indexTypes.Add(cce.NonNull(select.InParams[i]).TypedIdent.Type);
+ }
+ Contract.Assert(arity == indexTypes.Count);
+
+ List<VCExprVar/*!*/>/*!*/ indexes = HelperFuns.VarVector("x", indexTypes, Gen);
+
+ VCExprVar/*!*/ m = Gen.Variable("m", AxBuilder.U);
+ Contract.Assert(m != null);
+ VCExprVar/*!*/ val = Gen.Variable("val", cce.NonNull(select.OutParams[0]).TypedIdent.Type);
+ Contract.Assert(val != null);
+
+ VCExpr/*!*/ storeExpr = Store(store, types, m, indexes, val);
+ Contract.Assert(storeExpr != null);
+ VCExpr/*!*/ selectExpr = Select(select, types, storeExpr, indexes);
+ Contract.Assert(selectExpr != null);
+
+ List<VCExprVar/*!*/>/*!*/ quantifiedVars = new List<VCExprVar/*!*/>();
+ quantifiedVars.AddRange(types);
+ quantifiedVars.Add(val);
+ quantifiedVars.Add(m);
+ quantifiedVars.AddRange(indexes);
+
+ VCExpr/*!*/ eq = Gen.Eq(selectExpr, val);
+ Contract.Assert(eq != null);
+ return Gen.Forall(quantifiedVars, new List<VCTrigger/*!*/>(), "mapAx0:" + select.Name, 0, eq);
+ }
+
+ private VCExpr/*!*/ GenMapAxiom1(Function/*!*/ select, Function/*!*/ store,
+ // bound type variables in the map
+ // type
+ int mapTypeParamNum,
+ // free type variables in the map
+ // type (abstraction)
+ int mapAbstractionVarNum) {
+ Contract.Requires(select != null);
+ Contract.Requires(store != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ int arity = select.InParams.Count - 1 - mapTypeParamNum - mapAbstractionVarNum;
+
+ List<VCExprVar/*!*/>/*!*/ freeTypeVars =
+ HelperFuns.VarVector("u", mapAbstractionVarNum, AxBuilder.T, Gen);
+ List<VCExprVar/*!*/>/*!*/ boundTypeVars0 =
+ HelperFuns.VarVector("s", mapTypeParamNum, AxBuilder.T, Gen);
+ List<VCExprVar/*!*/>/*!*/ boundTypeVars1 =
+ HelperFuns.VarVector("t", mapTypeParamNum, AxBuilder.T, Gen);
+
+ List<VCExprVar/*!*/>/*!*/ types0 = new List<VCExprVar/*!*/>(boundTypeVars0);
+ types0.AddRange(freeTypeVars);
+
+ List<VCExprVar/*!*/>/*!*/ types1 = new List<VCExprVar/*!*/>(boundTypeVars1);
+ types1.AddRange(freeTypeVars);
+
+ List<Type/*!*/> indexTypes = new List<Type/*!*/>();
+ for (int i = mapTypeParamNum + mapAbstractionVarNum + 1; i < select.InParams.Count; i++) {
+ indexTypes.Add(cce.NonNull(select.InParams[i]).TypedIdent.Type);
+ }
+ Contract.Assert(arity == indexTypes.Count);
+
+ List<VCExprVar/*!*/>/*!*/ indexes0 = HelperFuns.VarVector("x", indexTypes, Gen);
+ List<VCExprVar/*!*/>/*!*/ indexes1 = HelperFuns.VarVector("y", indexTypes, Gen);
+
+ VCExprVar/*!*/ m = Gen.Variable("m", AxBuilder.U);
+ Contract.Assert(m != null);
+ VCExprVar/*!*/ val = Gen.Variable("val", cce.NonNull(select.OutParams[0]).TypedIdent.Type);
+ Contract.Assert(val != null);
+
+ VCExpr/*!*/ storeExpr = Store(store, types0, m, indexes0, val);
+ Contract.Assert(storeExpr != null);
+ VCExpr/*!*/ selectWithoutStoreExpr = Select(select, types1, m, indexes1);
+ Contract.Assert(selectWithoutStoreExpr != null);
+ VCExpr/*!*/ selectExpr = Select(select, types1, storeExpr, indexes1);
+ Contract.Assert(selectExpr != null);
+
+ VCExpr/*!*/ selectEq = Gen.Eq(selectExpr, selectWithoutStoreExpr);
+ Contract.Assert(selectEq != null);
+
+ List<VCExprVar/*!*/>/*!*/ quantifiedVars = new List<VCExprVar/*!*/>();
+ quantifiedVars.AddRange(freeTypeVars);
+ quantifiedVars.AddRange(boundTypeVars0);
+ quantifiedVars.AddRange(boundTypeVars1);
+ quantifiedVars.Add(val);
+ quantifiedVars.Add(m);
+ quantifiedVars.AddRange(indexes0);
+ quantifiedVars.AddRange(indexes1);
+
+ List<VCTrigger/*!*/>/*!*/ triggers = new List<VCTrigger/*!*/>();
+
+ // different value arguments or different type arguments are sufficient
+ // to conclude that that value of the map at some point (after an update)
+ // has not changed
+
+ List<VCExpr/*!*/>/*!*/ indexEqs = new List<VCExpr/*!*/>();
+ for (int i = 0; i < mapTypeParamNum; ++i)
+ indexEqs.Add(Gen.Eq(boundTypeVars0[i], boundTypeVars1[i]));
+ for (int i = 0; i < arity; ++i)
+ indexEqs.Add(Gen.Eq(indexes0[i], indexes1[i]));
+
+ VCExpr/*!*/ axiom = VCExpressionGenerator.True;
+ int n = 0;
+ foreach (VCExpr/*!*/ indexesEq in indexEqs) {
+ Contract.Assert(indexesEq != null);
+ VCExpr/*!*/ matrix = Gen.Or(indexesEq, selectEq);
+ Contract.Assert(matrix != null);
+ VCExpr/*!*/ conjunct = Gen.Forall(quantifiedVars, triggers, "mapAx1:" + select.Name + ":" + n, 0, matrix);
+ Contract.Assert(conjunct != null);
+ axiom = Gen.AndSimp(axiom, conjunct);
+ n = n + 1;
+ }
+
+ return axiom;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class TypeEraserArguments : TypeEraser {
+
+ private readonly TypeAxiomBuilderArguments/*!*/ AxBuilderArguments;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilderArguments != null);
+ }
+
+
+ private OpTypeEraser OpEraserAttr = null;
+ protected override OpTypeEraser/*!*/ OpEraser {
+ get {
+ Contract.Ensures(Contract.Result<OpTypeEraser>() != null);
+
+ if (OpEraserAttr == null)
+ OpEraserAttr = new OpTypeEraserArguments(this, AxBuilderArguments, Gen);
+ return OpEraserAttr;
+ }
+ }
+
+ public TypeEraserArguments(TypeAxiomBuilderArguments axBuilder, VCExpressionGenerator gen) :base(axBuilder, gen){
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+
+ this.AxBuilderArguments = axBuilder;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr Visit(VCExprQuantifier node, VariableBindings oldBindings) {
+ Contract.Requires(oldBindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VariableBindings/*!*/ bindings = oldBindings.Clone();
+
+ // bound term variables are replaced with bound term variables
+ // typed in a simpler way
+ List<VCExprVar/*!*/>/*!*/ newBoundVars =
+ BoundVarsAfterErasure(node.BoundVars, bindings);
+
+ // type variables are replaced with ordinary quantified variables
+ GenBoundVarsForTypeParams(node.TypeParameters, newBoundVars, bindings);
+ VCExpr/*!*/ newNode = HandleQuantifier(node, newBoundVars, bindings);
+ Contract.Assert(newNode != null);
+
+ if (!(newNode is VCExprQuantifier) || !IsUniversalQuantifier(node))
+ return newNode;
+
+ VariableBindings/*!*/ bindings2;
+ if (!RedoQuantifier(node, (VCExprQuantifier)newNode, node.BoundVars, oldBindings,
+ out bindings2, out newBoundVars))
+ return newNode;
+
+ GenBoundVarsForTypeParams(node.TypeParameters, newBoundVars, bindings2);
+ return HandleQuantifier(node, newBoundVars, bindings2);
+ }
+
+ private void GenBoundVarsForTypeParams(List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ newBoundVars, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Requires(cce.NonNullElements(newBoundVars));
+ foreach (TypeVariable/*!*/ tvar in typeParams) {
+ Contract.Assert(tvar != null);
+ VCExprVar/*!*/ var = Gen.Variable(tvar.Name, AxBuilder.T);
+ Contract.Assert(var != null);
+ newBoundVars.Add(var);
+ bindings.TypeVariableBindings.Add(tvar, var);
+ }
+ }
+
+ private VCExpr HandleQuantifier(VCExprQuantifier node, List<VCExprVar/*!*/>/*!*/ newBoundVars, VariableBindings bindings){
+Contract.Requires(bindings != null);
+Contract.Requires(node != null);
+Contract.Requires(cce.NonNullElements(newBoundVars));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCTrigger/*!*/>/*!*/ newTriggers = MutateTriggers(node.Triggers, bindings);
+ Contract.Assert(cce.NonNullElements(newTriggers));
+ VCExpr/*!*/ newBody = Mutate(node.Body, bindings);
+ Contract.Assert(newBody != null);
+ newBody = AxBuilder.Cast(newBody, Type.Bool);
+
+ if (newBoundVars.Count == 0) // might happen that no bound variables are left
+ return newBody;
+ return Gen.Quantify(node.Quan, new List<TypeVariable/*!*/>(), newBoundVars,
+ newTriggers, node.Infos, newBody);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class OpTypeEraserArguments : OpTypeEraser {
+
+ protected readonly TypeAxiomBuilderArguments/*!*/ AxBuilderArguments;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilderArguments != null);
+ }
+
+
+ public OpTypeEraserArguments(TypeEraserArguments eraser, TypeAxiomBuilderArguments axBuilder, VCExpressionGenerator gen) :base(eraser, axBuilder, gen){
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+ Contract.Requires(eraser != null);
+ this.AxBuilderArguments = axBuilder;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ private VCExpr AssembleOpExpression(OpTypesPair opTypes, IEnumerable<VCExpr/*!*/>/*!*/ oldArgs, VariableBindings bindings){
+Contract.Requires(bindings != null);
+Contract.Requires(cce.NonNullElements(oldArgs));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // UGLY: the code for tracking polarities should be factored out
+ int oldPolarity = Eraser.Polarity;
+ Eraser.Polarity = 0;
+
+ List<VCExpr/*!*/>/*!*/ newArgs = new List<VCExpr/*!*/> ();
+ // explicit type parameters
+ foreach (Type/*!*/ t in opTypes.Types){
+ Contract.Assert(newArgs != null);
+ newArgs.Add(AxBuilder.Type2Term(t, bindings.TypeVariableBindings));}
+
+ // and the actual value parameters
+ Function/*!*/ newFun = ((VCExprBoogieFunctionOp)opTypes.Op).Func;
+ // ^ we only allow this operator at this point
+ int i = opTypes.Types.Count;
+ foreach (VCExpr/*!*/ arg in oldArgs) {
+ Contract.Assert(arg != null);
+ newArgs.Add(AxBuilder.Cast(Eraser.Mutate(arg, bindings),
+ cce.NonNull(newFun.InParams[i]).TypedIdent.Type));
+ i = i + 1;
+ }
+
+ Eraser.Polarity = oldPolarity;
+ return Gen.Function(opTypes.Op, newArgs);
+ }
+
+ // for the time being, we store both the types of the arguments and the explicit
+ // type parameters (for most operators, this is more than actually necessary)
+ private OpTypesPair OriginalOpTypes(VCExprNAry node){
+Contract.Requires(node != null);
+ List<Type/*!*/>/*!*/ originalTypes = new List<Type/*!*/> ();
+ foreach (VCExpr/*!*/ expr in node) {
+ Contract.Assert(expr != null);
+ originalTypes.Add(expr.Type);
+ }
+ originalTypes.AddRange(node.TypeArguments);
+ return new OpTypesPair (node.Op, originalTypes);
+ }
+
+ private VCExpr EqualTypes(Type t0, Type t1, VariableBindings bindings){
+Contract.Requires(bindings != null);
+Contract.Requires(t1 != null);
+Contract.Requires(t0 != null);
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (t0.Equals(t1))
+ return VCExpressionGenerator.True;
+ VCExpr/*!*/ t0Expr = AxBuilder.Type2Term(t0, bindings.TypeVariableBindings);
+ Contract.Assert(t0Expr != null);
+ VCExpr/*!*/ t1Expr = AxBuilder.Type2Term(t1, bindings.TypeVariableBindings);
+ Contract.Assert(t1Expr != null);
+ return Gen.Eq(t0Expr, t1Expr);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr VisitEqOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+Contract.Requires((node != null));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // we also have to state that the types are equal, because the
+ // translation does not contain any information about the
+ // relationship between values and types
+ return Gen.AndSimp(base.VisitEqOp(node, bindings),
+ EqualTypes(node[0].Type, node[1].Type, bindings));
+ }
+
+ public override VCExpr VisitNeqOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires((bindings != null));
+Contract.Requires((node != null));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // we also have to state that the types are (un)equal, because the
+ // translation does not contain any information about the
+ // relationship between values and types
+ return Gen.OrSimp(base.VisitNeqOp(node, bindings),
+ Gen.Not(EqualTypes(node[0].Type, node[1].Type, bindings)));
+ }
+
+ public override VCExpr VisitSubtypeOp(VCExprNAry node, VariableBindings bindings) {
+Contract.Requires((bindings != null));
+Contract.Requires((node != null));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // UGLY: the code for tracking polarities should be factored out
+ int oldPolarity = Eraser.Polarity;
+ Eraser.Polarity = 0;
+
+ VCExpr/*!*/ res =
+ Gen.Function(VCExpressionGenerator.Subtype3Op,
+ AxBuilder.Type2Term(node[0].Type,
+ bindings.TypeVariableBindings),
+ AxBuilder.Cast(Eraser.Mutate(node[0], bindings),
+ AxBuilder.U),
+ AxBuilder.Cast(Eraser.Mutate(node[1], bindings),
+ AxBuilder.U));
+
+ Eraser.Polarity = oldPolarity;
+ return res;
+ }
+
+ public override VCExpr VisitSelectOp(VCExprNAry node, VariableBindings bindings) {
+Contract.Requires((bindings != null));
+Contract.Requires((node != null));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ OpTypesPair originalOpTypes = OriginalOpTypes(node);
+ OpTypesPair newOpTypes;
+
+ if (!NewOpCache.TryGetValue(originalOpTypes, out newOpTypes)) {
+ MapType/*!*/ rawType = node[0].Type.AsMap;
+ Contract.Assert(rawType != null);
+ List<Type>/*!*/ abstractionInstantiation;
+ Function/*!*/ select =
+ AxBuilder.MapTypeAbstracter.Select(rawType, out abstractionInstantiation);
+ Contract.Assert(abstractionInstantiation != null);
+ newOpTypes = TypesPairForSelectStore(node, select, abstractionInstantiation);
+ NewOpCache.Add(originalOpTypes, newOpTypes);
+ }
+
+ return AssembleOpExpression(newOpTypes, node, bindings);
+ }
+
+ public override VCExpr VisitStoreOp(VCExprNAry node, VariableBindings bindings) {
+Contract.Requires((bindings != null));
+Contract.Requires((node != null));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ OpTypesPair originalOpTypes = OriginalOpTypes(node);
+ OpTypesPair newOpTypes;
+
+ if (!NewOpCache.TryGetValue(originalOpTypes, out newOpTypes)) {
+ MapType/*!*/ rawType = node[0].Type.AsMap;
+ List<Type>/*!*/ abstractionInstantiation;
+ Function/*!*/ store =
+ AxBuilder.MapTypeAbstracter.Store(rawType, out abstractionInstantiation);
+
+ newOpTypes = TypesPairForSelectStore(node, store, abstractionInstantiation);
+ NewOpCache.Add(originalOpTypes, newOpTypes);
+ }
+
+ return AssembleOpExpression(newOpTypes, node, bindings);
+ }
+
+ private OpTypesPair TypesPairForSelectStore(VCExprNAry/*!*/ node, Function/*!*/ untypedOp,
+ // instantiation of the abstract map type parameters
+ List<Type>/*!*/ abstractionInstantiation) {
+ Contract.Requires(node != null);
+ Contract.Requires(untypedOp != null);
+ Contract.Requires(abstractionInstantiation != null);
+
+ List<Type/*!*/>/*!*/ inferredTypeArgs = new List<Type/*!*/> ();
+ foreach (Type/*!*/ t in node.TypeArguments){Contract.Assert(t != null);
+// inferredTypeArgs.Add(AxBuilder.MapTypeAbstracter.AbstractMapTypeRecursively(t));
+ inferredTypeArgs.Add(t);}
+ foreach (Type/*!*/ t in abstractionInstantiation) {
+ Contract.Assert(t != null);
+ inferredTypeArgs.Add(t);}
+
+ Contract.Assert(untypedOp.InParams.Count == inferredTypeArgs.Count + node.Arity);
+ return new OpTypesPair (Gen.BoogieFunctionOp(untypedOp), inferredTypeArgs);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr VisitBoogieFunctionOp(VCExprNAry node, VariableBindings bindings) {
+Contract.Requires((bindings != null));
+Contract.Requires((node != null));
+Contract.Ensures(Contract.Result<VCExpr>() != null);
+ OpTypesPair originalOpTypes = OriginalOpTypes(node);
+ OpTypesPair newOpTypes;
+
+ if (!NewOpCache.TryGetValue(originalOpTypes, out newOpTypes)) {
+ Function/*!*/ oriFun = ((VCExprBoogieFunctionOp)node.Op).Func;
+ Contract.Assert(oriFun != null);
+ List<Type/*!*/>/*!*/ inferredTypeArgs = new List<Type/*!*/> ();
+ foreach (Type/*!*/ t in node.TypeArguments){Contract.Assert(t != null);
+// inferredTypeArgs.Add(AxBuilder.MapTypeAbstracter.AbstractMapTypeRecursively(t));
+ inferredTypeArgs.Add(t);}
+
+ VCExprOp/*!*/ newOp = Gen.BoogieFunctionOp(AxBuilderArguments.Typed2Untyped(oriFun));
+ newOpTypes = new OpTypesPair (newOp, inferredTypeArgs);
+
+ NewOpCache.Add(originalOpTypes, newOpTypes);
+ }
+
+ return AssembleOpExpression(newOpTypes, node, bindings);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ // cache from the typed operators to the untyped operators with
+ // explicit type arguments. the keys are pairs of the typed
+ // operator and the actual types of the argument expressions, the
+ // values are pairs of the new operators and the types that have
+ // to be given as explicit type arguments
+ private readonly IDictionary<OpTypesPair, OpTypesPair>/*!*/ NewOpCache =
+ new Dictionary<OpTypesPair, OpTypesPair>();
+
+ private struct OpTypesPair {
+ public readonly VCExprOp/*!*/ Op;
+ public readonly List<Type/*!*/>/*!*/ Types;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Op != null);
+ Contract.Invariant(cce.NonNullElements(Types));
+ }
+
+
+ public OpTypesPair(VCExprOp op, List<Type/*!*/>/*!*/ types) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(types));
+ this.Op = op;
+ this.Types = types;
+ this.HashCode = HFNS.PolyHash(op.GetHashCode(), 17, types);
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (that is OpTypesPair) {
+ OpTypesPair thatPair = (OpTypesPair)that;
+ return this.Op.Equals(thatPair.Op) &&
+ HFNS.SameElements(this.Types, thatPair.Types);
+ }
+ return false;
+ }
+
+ private readonly int HashCode;
+
+ [Pure]
+ public override int GetHashCode() {
+ return HashCode;
+ }
+ }
+ }
} \ No newline at end of file
diff --git a/Source/VCExpr/TypeErasurePremisses.cs b/Source/VCExpr/TypeErasurePremisses.cs
index d4b36b68..6077f327 100644
--- a/Source/VCExpr/TypeErasurePremisses.cs
+++ b/Source/VCExpr/TypeErasurePremisses.cs
@@ -1,1337 +1,1337 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-using Microsoft.Boogie.VCExprAST;
-
-// Erasure of types using premisses (forall x :: type(x)=T ==> p(x))
-
-namespace Microsoft.Boogie.TypeErasure
-{
- using Microsoft.Boogie.VCExprAST;
-
- // When using type premisses, we can distinguish two kinds of type
- // parameters of a function or map: parameters that occur in the
- // formal argument types of the function are "implicit" because they
- // can be inferred from the actual argument types; parameters that
- // only occur in the result type of the function are "explicit"
- // because they are not inferrable and have to be given to the
- // function as additional arguments.
- //
- // The following structure is used to store the untyped version of a
- // typed function, together with the lists of implicit and explicit
- // type parameters (in the same order as they occur in the signature
- // of the original function).
-
- internal struct UntypedFunction
- {
- public readonly Function/*!*/ Fun;
- // type parameters that can be extracted from the value parameters
- public readonly List<TypeVariable/*!*/>/*!*/ ImplicitTypeParams;
- // type parameters that have to be given explicitly
- public readonly List<TypeVariable/*!*/>/*!*/ ExplicitTypeParams;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Fun != null);
- Contract.Invariant(cce.NonNullElements(ImplicitTypeParams));
- Contract.Invariant(cce.NonNullElements(ExplicitTypeParams));
- }
-
-
- public UntypedFunction(Function/*!*/ fun,
- List<TypeVariable/*!*/>/*!*/ implicitTypeParams,
- List<TypeVariable/*!*/>/*!*/ explicitTypeParams) {
- Contract.Requires(fun != null);
- Contract.Requires(cce.NonNullElements(implicitTypeParams));
- Contract.Requires(cce.NonNullElements(explicitTypeParams));
- Fun = fun;
- ImplicitTypeParams = implicitTypeParams;
- ExplicitTypeParams = explicitTypeParams;
- }
- }
-
- public class TypeAxiomBuilderPremisses : TypeAxiomBuilderIntBoolU
- {
-
- public TypeAxiomBuilderPremisses(VCExpressionGenerator gen)
- : base(gen) {
- Contract.Requires(gen != null);
-
- TypeFunction = HelperFuns.BoogieFunction("dummy", Type.Int);
- Typed2UntypedFunctions = new Dictionary<Function/*!*/, UntypedFunction>();
- MapTypeAbstracterAttr = null;
- }
-
- // constructor to allow cloning
- [NotDelayed]
- internal TypeAxiomBuilderPremisses(TypeAxiomBuilderPremisses builder)
- : base(builder) {
- Contract.Requires(builder != null);
- TypeFunction = builder.TypeFunction;
- Typed2UntypedFunctions =
- new Dictionary<Function/*!*/, UntypedFunction>(builder.Typed2UntypedFunctions);
-
- MapTypeAbstracterAttr =
- builder.MapTypeAbstracterAttr == null ?
- null : new MapTypeAbstractionBuilderPremisses(this, builder.Gen,
- builder.MapTypeAbstracterAttr);
- }
-
- public override Object Clone() {
- Contract.Ensures(Contract.Result<Object>() != null);
- return new TypeAxiomBuilderPremisses(this);
- }
-
- public override void Setup() {
- TypeFunction = HelperFuns.BoogieFunction("type", U, T);
- base.Setup();
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // generate axioms of the kind "forall x:U. {Int2U(U2Int(x))}
- // type(x)=int ==> Int2U(U2Int(x))==x"
- protected override VCExpr GenReverseCastAxiom(Function castToU, Function castFromU) {
- //Contract.Requires(castFromU != null);
- //Contract.Requires(castToU != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCTrigger/*!*/>/*!*/ triggers;
- VCExprVar/*!*/ var;
- VCExpr/*!*/ eq = GenReverseCastEq(castToU, castFromU, out var, out triggers);
- Contract.Assert(cce.NonNullElements(triggers));
- Contract.Assert(var != null);
- Contract.Assert(eq != null);
- VCExpr/*!*/ premiss;
- if (CommandLineOptions.Clo.TypeEncodingMethod
- == CommandLineOptions.TypeEncoding.None)
- premiss = VCExpressionGenerator.True;
- else
- premiss = GenVarTypeAxiom(var, cce.NonNull(castFromU.OutParams[0]).TypedIdent.Type,
- // we don't have any bindings available
- new Dictionary<TypeVariable/*!*/, VCExpr/*!*/>());
- VCExpr/*!*/ matrix = Gen.ImpliesSimp(premiss, eq);
- Contract.Assert(matrix != null);
- return Gen.Forall(HelperFuns.ToList(var), triggers, "cast:" + castFromU.Name, -1, matrix);
- }
-
- protected override VCExpr GenCastTypeAxioms(Function castToU, Function castFromU) {
- //Contract.Requires(castFromU != null);
- //Contract.Requires(castToU != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- Type/*!*/ fromType = cce.NonNull(castToU.InParams[0]).TypedIdent.Type;
- return GenFunctionAxiom(castToU, new List<TypeVariable/*!*/>(), new List<TypeVariable/*!*/>(),
- HelperFuns.ToList(fromType), fromType);
- }
-
- private MapTypeAbstractionBuilderPremisses MapTypeAbstracterAttr;
-
- internal override MapTypeAbstractionBuilder/*!*/ MapTypeAbstracter {
- get {
- Contract.Ensures(Contract.Result<MapTypeAbstractionBuilder>() != null);
-
- if (MapTypeAbstracterAttr == null)
- MapTypeAbstracterAttr = new MapTypeAbstractionBuilderPremisses(this, Gen);
- return MapTypeAbstracterAttr;
- }
- }
-
- internal MapTypeAbstractionBuilderPremisses/*!*/ MapTypeAbstracterPremisses {
- get {
- Contract.Ensures(Contract.Result<MapTypeAbstractionBuilderPremisses>() != null);
-
- return (MapTypeAbstractionBuilderPremisses)MapTypeAbstracter;
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // function that maps individuals to their type
- // the field is overwritten with its actual value in "Setup"
- private Function/*!*/ TypeFunction;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(TypeFunction != null);
- }
-
-
- public VCExpr TypeOf(VCExpr expr) {
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Gen.Function(TypeFunction, expr);
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // Generate type premisses and type parameter bindings for quantifiers, functions, procedures
-
- // let-bindings to extract the instantiations of type parameters
- public List<VCExprLetBinding/*!*/>/*!*/
- GenTypeParamBindings(// the original bound variables and (implicit) type parameters
- List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ oldBoundVars,
- // VariableBindings to which the translation
- // TypeVariable -> VCExprVar is added
- VariableBindings/*!*/ bindings,
- bool addTypeVarsToBindings) {
- Contract.Requires(typeParams != null);
- Contract.Requires(cce.NonNullElements(oldBoundVars));
- Contract.Requires(bindings != null);
-
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprLetBinding>>()));
-
- // type variables are replaced with ordinary variables that are bound using a
- // let-expression
- if (addTypeVarsToBindings) {
- foreach (TypeVariable/*!*/ tvar in typeParams) {
- Contract.Assert(tvar != null);
- bindings.TypeVariableBindings.Add(tvar, Gen.Variable(tvar.Name, T));
- }
- }
-
- // extract the values of type variables from the term variables
- List<VCExprVar/*!*/>/*!*/ UtypedVars = new List<VCExprVar/*!*/>(oldBoundVars.Count);
- List<Type/*!*/>/*!*/ originalTypes = new List<Type/*!*/>(oldBoundVars.Count);
- foreach (VCExprVar var in oldBoundVars) {
- VCExprVar/*!*/ newVar = bindings.VCExprVarBindings[var];
- if (newVar.Type.Equals(U)) {
- UtypedVars.Add(newVar);
- originalTypes.Add(var.Type);
- }
- }
-
- UtypedVars.TrimExcess();
- originalTypes.TrimExcess();
-
- return BestTypeVarExtractors(typeParams, originalTypes, UtypedVars, bindings);
- }
-
-
- public VCExpr/*!*/ AddTypePremisses(List<VCExprLetBinding/*!*/>/*!*/ typeVarBindings,
- VCExpr/*!*/ typePremisses, bool universal,
- VCExpr/*!*/ body) {
- Contract.Requires(cce.NonNullElements(typeVarBindings));
- Contract.Requires(typePremisses != null);
- Contract.Requires(body != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExpr/*!*/ bodyWithPremisses;
- if (universal)
- bodyWithPremisses = Gen.ImpliesSimp(typePremisses, body);
- else
- bodyWithPremisses = Gen.AndSimp(typePremisses, body);
-
- return Gen.Let(typeVarBindings, bodyWithPremisses);
- }
-
-
- ///////////////////////////////////////////////////////////////////////////
- // Extract the instantiations of type variables from the concrete types of
- // term variables. E.g., for a function f<a>(x : C a), we would extract the
- // instantiation of "a" by looking at the concrete type of "x".
-
- public List<VCExprLetBinding/*!*/>/*!*/
- BestTypeVarExtractors(List<TypeVariable/*!*/>/*!*/ vars, List<Type/*!*/>/*!*/ types,
- List<VCExprVar/*!*/>/*!*/ concreteTypeSources,
- VariableBindings/*!*/ bindings) {
- Contract.Requires(cce.NonNullElements(vars));
- Contract.Requires(cce.NonNullElements(types));
- Contract.Requires(cce.NonNullElements(concreteTypeSources));
- Contract.Requires(bindings != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprLetBinding>>()));
-
- List<VCExprLetBinding/*!*/>/*!*/ typeParamBindings = new List<VCExprLetBinding/*!*/>();
- foreach (TypeVariable/*!*/ var in vars) {
- Contract.Assert(var != null);
- VCExpr extractor = BestTypeVarExtractor(var, types, concreteTypeSources);
- if (extractor != null)
- typeParamBindings.Add(
- Gen.LetBinding((VCExprVar)bindings.TypeVariableBindings[var],
- extractor));
- }
- return typeParamBindings;
- }
-
- private VCExpr BestTypeVarExtractor(TypeVariable/*!*/ var, List<Type/*!*/>/*!*/ types,
- List<VCExprVar/*!*/>/*!*/ concreteTypeSources) {
- Contract.Requires(var != null);
- Contract.Requires(cce.NonNullElements(types));
- Contract.Requires(cce.NonNullElements(concreteTypeSources));
- List<VCExpr/*!*/> allExtractors = TypeVarExtractors(var, types, concreteTypeSources);
- Contract.Assert(cce.NonNullElements(allExtractors));
- if (allExtractors.Count == 0)
- return null;
-
- VCExpr bestExtractor = allExtractors[0];
- int bestExtractorSize = SizeComputingVisitor.ComputeSize(bestExtractor);
- for (int i = 1; i < allExtractors.Count; ++i) {
- int newSize = SizeComputingVisitor.ComputeSize(allExtractors[i]);
- if (newSize < bestExtractorSize) {
- bestExtractor = allExtractors[i];
- bestExtractorSize = newSize;
- }
- }
-
- return bestExtractor;
- }
-
- private List<VCExpr/*!*/>/*!*/ TypeVarExtractors(TypeVariable/*!*/ var, List<Type/*!*/>/*!*/ types,
- List<VCExprVar/*!*/>/*!*/ concreteTypeSources) {
- Contract.Requires(var != null);
- Contract.Requires(cce.NonNullElements(types));
- Contract.Requires(cce.NonNullElements(concreteTypeSources));
- Contract.Requires((types.Count == concreteTypeSources.Count));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
- List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>();
- for (int i = 0; i < types.Count; ++i)
- TypeVarExtractors(var, types[i], TypeOf(concreteTypeSources[i]), res);
-
- return res;
- }
-
- private void TypeVarExtractors(TypeVariable var, Type completeType, VCExpr innerTerm, List<VCExpr/*!*/>/*!*/ extractors) {
- Contract.Requires(innerTerm != null);
- Contract.Requires(completeType != null);
- Contract.Requires(var != null);
- Contract.Requires(cce.NonNullElements(extractors));
- if (completeType.IsVariable) {
- if (var.Equals(completeType)) {
- extractors.Add(innerTerm);
- } // else nothing
- } else if (completeType.IsBasic) {
- // nothing
- } else if (completeType.IsCtor) {
- CtorType/*!*/ ctorType = completeType.AsCtor;
- if (ctorType.Arguments.Count > 0) {
- // otherwise there are no chances of extracting any
- // instantiations from this type
- TypeCtorRepr repr = GetTypeCtorReprStruct(ctorType.Decl);
- for (int i = 0; i < ctorType.Arguments.Count; ++i) {
- VCExpr/*!*/ newInnerTerm = Gen.Function(repr.Dtors[i], innerTerm);
- Contract.Assert(newInnerTerm != null);
- TypeVarExtractors(var, ctorType.Arguments[i], newInnerTerm, extractors);
- }
- }
- } else if (completeType.IsMap) {
- TypeVarExtractors(var, MapTypeAbstracter.AbstractMapType(completeType.AsMap),
- innerTerm, extractors);
- } else {
- System.Diagnostics.Debug.Fail("Don't know how to handle this type: " + completeType);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Symbols for representing functions
-
- // Globally defined functions
- private readonly IDictionary<Function/*!*/, UntypedFunction/*!*/>/*!*/ Typed2UntypedFunctions;
- [ContractInvariantMethod]
- void Typed2UntypedFunctionsInvariantMethod() {
- Contract.Invariant(Typed2UntypedFunctions != null);
- }
-
- // distinguish between implicit and explicit type parameters
- internal static void SeparateTypeParams(List<Type/*!*/>/*!*/ valueArgumentTypes,
- List<TypeVariable>/*!*/ allTypeParams,
- out List<TypeVariable/*!*/>/*!*/ implicitParams,
- out List<TypeVariable/*!*/>/*!*/ explicitParams) {
- Contract.Requires(cce.NonNullElements(valueArgumentTypes));
- Contract.Requires(allTypeParams != null);
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out implicitParams)));
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out explicitParams)));
- List<TypeVariable>/*!*/ varsInInParamTypes = new List<TypeVariable>();
- foreach (Type/*!*/ t in valueArgumentTypes) {
- Contract.Assert(t != null);
- varsInInParamTypes.AppendWithoutDups(t.FreeVariables);
- }
-
- implicitParams = new List<TypeVariable/*!*/>(allTypeParams.Count);
- explicitParams = new List<TypeVariable/*!*/>(allTypeParams.Count);
-
- foreach (TypeVariable/*!*/ var in allTypeParams) {
- Contract.Assert(var != null);
- if (varsInInParamTypes.Contains(var))
- implicitParams.Add(var);
- else
- explicitParams.Add(var);
- }
-
- implicitParams.TrimExcess();
- explicitParams.TrimExcess();
- }
-
- internal UntypedFunction Typed2Untyped(Function fun) {
- Contract.Requires(fun != null);
- UntypedFunction res;
- if (!Typed2UntypedFunctions.TryGetValue(fun, out res)) {
- Contract.Assert(fun.OutParams.Count == 1);
-
- // if all of the parameters are int or bool, the function does
- // not have to be changed
- if (fun.InParams.All(param => UnchangedType(cce.NonNull(param).TypedIdent.Type)) &&
- UnchangedType(cce.NonNull(fun.OutParams[0]).TypedIdent.Type) &&
- fun.TypeParameters.Count == 0) {
- res = new UntypedFunction(fun, new List<TypeVariable/*!*/>(), new List<TypeVariable/*!*/>());
- } else {
- List<Type/*!*/>/*!*/ argTypes = new List<Type/*!*/>();
- foreach (Variable/*!*/ v in fun.InParams) {
- Contract.Assert(v != null);
- argTypes.Add(v.TypedIdent.Type);
- }
-
- List<TypeVariable/*!*/>/*!*/ implicitParams, explicitParams;
- SeparateTypeParams(argTypes, fun.TypeParameters, out implicitParams, out explicitParams);
-
- Type[]/*!*/ types = new Type[explicitParams.Count + fun.InParams.Count + 1];
- int i = 0;
- for (int j = 0; j < explicitParams.Count; ++j) {
- types[i] = T;
- i = i + 1;
- }
- for (int j = 0; j < fun.InParams.Count; ++i, ++j)
- types[i] = TypeAfterErasure(cce.NonNull(fun.InParams[j]).TypedIdent.Type);
- types[types.Length - 1] = TypeAfterErasure(cce.NonNull(fun.OutParams[0]).TypedIdent.Type);
-
- Function/*!*/ untypedFun = HelperFuns.BoogieFunction(fun.Name, types);
- Contract.Assert(untypedFun != null);
- untypedFun.Attributes = fun.Attributes;
- res = new UntypedFunction(untypedFun, implicitParams, explicitParams);
- if (U.Equals(types[types.Length - 1]))
- AddTypeAxiom(GenFunctionAxiom(res, fun));
- }
-
- Typed2UntypedFunctions.Add(fun, res);
- }
- return res;
- }
-
- private VCExpr GenFunctionAxiom(UntypedFunction fun, Function originalFun) {
- Contract.Requires(originalFun != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<Type/*!*/>/*!*/ originalInTypes = new List<Type/*!*/>(originalFun.InParams.Count);
- foreach (Formal/*!*/ f in originalFun.InParams)
- originalInTypes.Add(f.TypedIdent.Type);
-
- return GenFunctionAxiom(fun.Fun, fun.ImplicitTypeParams, fun.ExplicitTypeParams,
- originalInTypes,
- cce.NonNull(originalFun.OutParams[0]).TypedIdent.Type);
- }
-
- internal VCExpr/*!*/ GenFunctionAxiom(Function/*!*/ fun,
- List<TypeVariable/*!*/>/*!*/ implicitTypeParams,
- List<TypeVariable/*!*/>/*!*/ explicitTypeParams,
- List<Type/*!*/>/*!*/ originalInTypes,
- Type/*!*/ originalResultType) {
- Contract.Requires(cce.NonNullElements(implicitTypeParams));
- Contract.Requires(fun != null);
- Contract.Requires(cce.NonNullElements(explicitTypeParams));
- Contract.Requires(cce.NonNullElements(originalInTypes));
- Contract.Requires(originalResultType != null);
- Contract.Requires(originalInTypes.Count + explicitTypeParams.Count == fun.InParams.Count);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.None) {
- return VCExpressionGenerator.True;
- }
-
- List<VCExprVar/*!*/>/*!*/ typedInputVars = new List<VCExprVar/*!*/>(originalInTypes.Count);
- int i = 0;
- foreach (Type/*!*/ t in originalInTypes) {
- Contract.Assert(t != null);
- typedInputVars.Add(Gen.Variable("arg" + i, t));
- i = i + 1;
- }
-
- VariableBindings/*!*/ bindings = new VariableBindings();
-
- // type parameters that have to be given explicitly are replaced
- // with universally quantified type variables
- List<VCExprVar/*!*/>/*!*/ boundVars = new List<VCExprVar/*!*/>(explicitTypeParams.Count + typedInputVars.Count);
- foreach (TypeVariable/*!*/ var in explicitTypeParams) {
- Contract.Assert(var != null);
- VCExprVar/*!*/ newVar = Gen.Variable(var.Name, T);
- boundVars.Add(newVar);
- bindings.TypeVariableBindings.Add(var, newVar);
- }
-
- // bound term variables are replaced with bound term variables typed in
- // a simpler way
- foreach (VCExprVar/*!*/ var in typedInputVars) {
- Contract.Assert(var != null);
- Type/*!*/ newType = TypeAfterErasure(var.Type);
- Contract.Assert(newType != null);
- VCExprVar/*!*/ newVar = Gen.Variable(var.Name, newType);
- Contract.Assert(newVar != null);
- boundVars.Add(newVar);
- bindings.VCExprVarBindings.Add(var, newVar);
- }
-
- List<VCExprLetBinding/*!*/> typeVarBindings =
- GenTypeParamBindings(implicitTypeParams, typedInputVars, bindings, true);
- Contract.Assert(cce.NonNullElements(typeVarBindings));
-
- VCExpr/*!*/ funApp = Gen.Function(fun, HelperFuns.ToVCExprList(boundVars));
- Contract.Assert(funApp != null);
- VCExpr/*!*/ conclusion = Gen.Eq(TypeOf(funApp),
- Type2Term(originalResultType, bindings.TypeVariableBindings));
- Contract.Assert(conclusion != null);
- VCExpr conclusionWithPremisses =
- // leave out antecedents of function type axioms ... they don't appear necessary,
- // because a function can always be extended to all U-values (right?)
- // AddTypePremisses(typeVarBindings, typePremisses, true, conclusion);
- Gen.Let(typeVarBindings, conclusion);
-
- if (boundVars.Count > 0) {
- List<VCTrigger/*!*/> triggers = HelperFuns.ToList(Gen.Trigger(true, HelperFuns.ToList(funApp)));
- Contract.Assert(cce.NonNullElements(triggers));
- return Gen.Forall(boundVars, triggers, "funType:" + fun.Name, -1, conclusionWithPremisses);
- } else {
- return conclusionWithPremisses;
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- protected override void AddVarTypeAxiom(VCExprVar var, Type originalType) {
- //Contract.Requires(originalType != null);
- //Contract.Requires(var != null);
- if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.None) return;
- AddTypeAxiom(GenVarTypeAxiom(var, originalType,
- // we don't have any bindings available
- new Dictionary<TypeVariable/*!*/, VCExpr/*!*/>()));
- }
-
- public VCExpr GenVarTypeAxiom(VCExprVar var, Type originalType, IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ varMapping) {
- Contract.Requires(var != null);
- Contract.Requires(originalType != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(varMapping));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- if (!var.Type.Equals(originalType)) {
- VCExpr/*!*/ typeRepr = Type2Term(originalType, varMapping);
- return Gen.Eq(TypeOf(var), typeRepr);
- }
- return VCExpressionGenerator.True;
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- internal class MapTypeAbstractionBuilderPremisses : MapTypeAbstractionBuilder
- {
-
- private readonly TypeAxiomBuilderPremisses/*!*/ AxBuilderPremisses;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilderPremisses != null);
- }
-
-
- internal MapTypeAbstractionBuilderPremisses(TypeAxiomBuilderPremisses axBuilder, VCExpressionGenerator gen)
- : base(axBuilder, gen) {
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
-
- this.AxBuilderPremisses = axBuilder;
- }
-
- // constructor for cloning
- internal MapTypeAbstractionBuilderPremisses(TypeAxiomBuilderPremisses axBuilder, VCExpressionGenerator gen, MapTypeAbstractionBuilderPremisses builder)
- : base(axBuilder, gen, builder) {
- Contract.Requires(builder != null);
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
-
- this.AxBuilderPremisses = axBuilder;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // Determine the type parameters of a map type that have to be
- // given explicitly when applying the select function (the
- // parameters that only occur in the result type of the
- // map). These parameters are given as a list of indexes sorted in
- // ascending order; the index i refers to the i'th bound variable
- // in a type <a0, a1, ..., an>[...]...
- public List<int>/*!*/ ExplicitSelectTypeParams(MapType type) {
- Contract.Requires(type != null);
- Contract.Ensures(Contract.Result<List<int>>() != null);
-
- List<int> res;
- if (!explicitSelectTypeParamsCache.TryGetValue(type, out res)) {
- List<TypeVariable/*!*/>/*!*/ explicitParams, implicitParams;
- TypeAxiomBuilderPremisses.SeparateTypeParams(type.Arguments.ToList(),
- type.TypeParameters,
- out implicitParams,
- out explicitParams);
- res = new List<int>(explicitParams.Count);
- foreach (TypeVariable/*!*/ var in explicitParams) {
- Contract.Assert(var != null);
- res.Add(type.TypeParameters.IndexOf(var));
- }
- explicitSelectTypeParamsCache.Add(type, res);
- }
- return cce.NonNull(res);
- }
-
- private IDictionary<MapType/*!*/, List<int>/*!*/>/*!*/ explicitSelectTypeParamsCache =
- new Dictionary<MapType/*!*/, List<int>/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvarant() {
- Contract.Invariant(cce.NonNullDictionaryAndValues(explicitSelectTypeParamsCache));
- }
-
-
- ////////////////////////////////////////////////////////////////////////////
-
- protected override void GenSelectStoreFunctions(MapType abstractedType, TypeCtorDecl synonym, out Function/*!*/ select, out Function/*!*/ store) {
- //Contract.Requires(synonym != null);
- //Contract.Requires(abstractedType != null);
- Contract.Ensures(Contract.ValueAtReturn(out select) != null);
- Contract.Ensures(Contract.ValueAtReturn(out store) != null);
- Type/*!*/ mapTypeSynonym;
- List<TypeVariable/*!*/>/*!*/ typeParams;
- List<Type/*!*/>/*!*/ originalInTypes;
- GenTypeAxiomParams(abstractedType, synonym, out mapTypeSynonym,
- out typeParams, out originalInTypes);
-
- // select
- List<TypeVariable/*!*/>/*!*/ explicitSelectParams, implicitSelectParams;
- select = CreateAccessFun(typeParams, originalInTypes,
- abstractedType.Result, synonym.Name + "Select",
- out implicitSelectParams, out explicitSelectParams);
-
- // store, which gets one further argument: the assigned rhs
- originalInTypes.Add(abstractedType.Result);
-
- List<TypeVariable/*!*/>/*!*/ explicitStoreParams, implicitStoreParams;
- store = CreateAccessFun(typeParams, originalInTypes,
- mapTypeSynonym, synonym.Name + "Store",
- out implicitStoreParams, out explicitStoreParams);
-
- // the store function does not have any explicit type parameters
- Contract.Assert(explicitStoreParams.Count == 0);
-
- if (CommandLineOptions.Clo.UseArrayTheory) {
- select.AddAttribute("builtin", "select");
- store.AddAttribute("builtin", "store");
- } else {
- AxBuilder.AddTypeAxiom(GenMapAxiom0(select, store,
- abstractedType.Result,
- implicitSelectParams, explicitSelectParams,
- originalInTypes));
- AxBuilder.AddTypeAxiom(GenMapAxiom1(select, store,
- abstractedType.Result,
- explicitSelectParams));
- }
- }
-
- protected void GenTypeAxiomParams(MapType/*!*/ abstractedType, TypeCtorDecl/*!*/ synonymDecl,
- out Type/*!*/ mapTypeSynonym,
- out List<TypeVariable/*!*/>/*!*/ typeParams,
- out List<Type/*!*/>/*!*/ originalIndexTypes) {
- Contract.Requires(abstractedType != null);
- Contract.Requires(synonymDecl != null);
- Contract.Ensures(Contract.ValueAtReturn(out mapTypeSynonym) != null);
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out typeParams)));
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out originalIndexTypes)));
- typeParams = new List<TypeVariable/*!*/>();
- typeParams.AddRange(abstractedType.TypeParameters);
- typeParams.AddRange(abstractedType.FreeVariables);
-
- originalIndexTypes = new List<Type/*!*/>(abstractedType.Arguments.Count + 1);
- List<Type>/*!*/ mapTypeParams = new List<Type>();
- foreach (TypeVariable/*!*/ var in abstractedType.FreeVariables) {
- Contract.Assert(var != null);
- mapTypeParams.Add(var);
- }
-
- if (CommandLineOptions.Clo.MonomorphicArrays)
- mapTypeSynonym = abstractedType;
- else
- mapTypeSynonym = new CtorType(Token.NoToken, synonymDecl, mapTypeParams);
-
- originalIndexTypes.Add(mapTypeSynonym);
- originalIndexTypes.AddRange(abstractedType.Arguments.ToList());
- }
-
- // method to actually create the select or store function
- private Function/*!*/ CreateAccessFun(List<TypeVariable/*!*/>/*!*/ originalTypeParams,
- List<Type/*!*/>/*!*/ originalInTypes,
- Type/*!*/ originalResult,
- string/*!*/ name,
- out List<TypeVariable/*!*/>/*!*/ implicitTypeParams, out List<TypeVariable/*!*/>/*!*/ explicitTypeParams) {
- Contract.Requires(cce.NonNullElements(originalTypeParams));
- Contract.Requires(cce.NonNullElements(originalInTypes));
- Contract.Requires(originalResult != null);
- Contract.Requires(name != null);
- Contract.Ensures(Contract.Result<Function>() != null);
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out implicitTypeParams)));
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out explicitTypeParams)));
-
- // select and store are basically handled like normal functions: the type
- // parameters are split into the implicit parameters, and into the parameters
- // that have to be given explicitly
- TypeAxiomBuilderPremisses.SeparateTypeParams(originalInTypes,
- new List<TypeVariable>(originalTypeParams),
- out implicitTypeParams,
- out explicitTypeParams);
-
- Type[]/*!*/ ioTypes = new Type[explicitTypeParams.Count + originalInTypes.Count + 1];
- int i = 0;
- for (; i < explicitTypeParams.Count; ++i)
- ioTypes[i] = AxBuilder.T;
- foreach (Type/*!*/ type in originalInTypes) {
- Contract.Assert(type != null);
- if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(type))
- ioTypes[i] = type;
- else
- ioTypes[i] = AxBuilder.U;
- i++;
- }
- if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(originalResult))
- ioTypes[i] = originalResult;
- else
- ioTypes[i] = AxBuilder.U;
-
- Function/*!*/ res = HelperFuns.BoogieFunction(name, ioTypes);
- Contract.Assert(res != null);
-
- if (AxBuilder.U.Equals(ioTypes[i])) {
- AxBuilder.AddTypeAxiom(
- AxBuilderPremisses.GenFunctionAxiom(res,
- implicitTypeParams, explicitTypeParams,
- originalInTypes, originalResult));
- }
- return res;
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // The normal axioms of the theory of arrays (without extensionality)
-
- private VCExpr/*!*/ Select(Function/*!*/ select,
- // in general, the select function has to
- // receive explicit type parameters (which
- // are here already represented as VCExpr
- // of type T)
- List<VCExpr/*!*/>/*!*/ typeParams,
- VCExpr/*!*/ map,
- List<VCExprVar/*!*/>/*!*/ indexes) {
- Contract.Requires(select != null);
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Requires(map != null);
- Contract.Requires(cce.NonNullElements(indexes));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- List<VCExpr/*!*/>/*!*/ selectArgs = new List<VCExpr/*!*/>(typeParams.Count + indexes.Count + 1);
- selectArgs.AddRange(typeParams);
- selectArgs.Add(map);
- selectArgs.AddRange(HelperFuns.ToVCExprList(indexes));
- return Gen.Function(select, selectArgs);
- }
-
- private VCExpr Store(Function store, VCExpr map, List<VCExprVar/*!*/>/*!*/ indexes, VCExpr val) {
- Contract.Requires(val != null);
- Contract.Requires(map != null);
- Contract.Requires(store != null);
- Contract.Requires(cce.NonNullElements(indexes));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCExpr/*!*/>/*!*/ storeArgs = new List<VCExpr/*!*/>(indexes.Count + 2);
- storeArgs.Add(map);
- storeArgs.AddRange(HelperFuns.ToVCExprList(indexes));
- storeArgs.Add(val);
- return Gen.Function(store, storeArgs);
- }
-
- /// <summary>
- /// Generate:
- /// (forall m, indexes, val ::
- /// type(val) == T ==>
- /// select(store(m, indexes, val), indexes) == val)
- /// where the quantifier body is also enclosed in a let that defines portions of T, if needed.
- /// </summary>
- private VCExpr GenMapAxiom0(Function select, Function store, Type mapResult, List<TypeVariable/*!*/>/*!*/ implicitTypeParamsSelect, List<TypeVariable/*!*/>/*!*/ explicitTypeParamsSelect, List<Type/*!*/>/*!*/ originalInTypes) {
- Contract.Requires(mapResult != null);
- Contract.Requires(store != null);
- Contract.Requires(select != null);
- Contract.Requires(cce.NonNullElements(implicitTypeParamsSelect));
- Contract.Requires(cce.NonNullElements(originalInTypes));
- Contract.Requires(cce.NonNullElements(explicitTypeParamsSelect));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- int arity = store.InParams.Count - 2;
- List<VCExprVar/*!*/> inParams = new List<VCExprVar/*!*/>();
- List<VCExprVar/*!*/> quantifiedVars = new List<VCExprVar/*!*/>(store.InParams.Count);
- VariableBindings bindings = new VariableBindings();
-
- // bound variable: m
- VCExprVar typedM = Gen.Variable("m", originalInTypes[0]);
- VCExprVar m = Gen.Variable("m", AxBuilder.U);
- inParams.Add(typedM);
- quantifiedVars.Add(m);
- bindings.VCExprVarBindings.Add(typedM, m);
-
- // bound variables: indexes
- List<Type/*!*/> origIndexTypes = new List<Type/*!*/>(arity);
- List<Type/*!*/> indexTypes = new List<Type/*!*/>(arity);
- for (int i = 1; i < store.InParams.Count - 1; i++) {
- origIndexTypes.Add(originalInTypes[i]);
- indexTypes.Add(cce.NonNull(store.InParams[i]).TypedIdent.Type);
- }
- Contract.Assert(arity == indexTypes.Count);
- List<VCExprVar/*!*/> typedArgs = HelperFuns.VarVector("arg", origIndexTypes, Gen);
- Contract.Assert(cce.NonNullElements(typedArgs));
- List<VCExprVar/*!*/> indexes = HelperFuns.VarVector("x", indexTypes, Gen);
- Contract.Assert(cce.NonNullElements(indexes));
- Contract.Assert(typedArgs.Count == indexes.Count);
- inParams.AddRange(typedArgs);
- quantifiedVars.AddRange(indexes);
- for (int i = 0; i < arity; i++) {
- bindings.VCExprVarBindings.Add(typedArgs[i], indexes[i]);
- }
-
- // bound variable: val
- VCExprVar typedVal = Gen.Variable("val", mapResult);
- VCExprVar val = Gen.Variable("val", cce.NonNull(select.OutParams[0]).TypedIdent.Type);
- quantifiedVars.Add(val);
- bindings.VCExprVarBindings.Add(typedVal, val);
-
- // add all type parameters into bindings
- foreach (TypeVariable tp in implicitTypeParamsSelect) {
- VCExprVar tVar = Gen.Variable(tp.Name, AxBuilderPremisses.T);
- bindings.TypeVariableBindings.Add(tp, tVar);
- }
- List<VCExpr/*!*/> typeParams = new List<VCExpr/*!*/>(explicitTypeParamsSelect.Count);
- foreach (TypeVariable tp in explicitTypeParamsSelect) {
- VCExprVar tVar = Gen.Variable(tp.Name, AxBuilderPremisses.T);
- bindings.TypeVariableBindings.Add(tp, tVar);
- // ... and record these explicit type-parameter arguments in typeParams
- typeParams.Add(tVar);
- }
-
- VCExpr/*!*/ storeExpr = Store(store, m, indexes, val);
- Contract.Assert(storeExpr != null);
- VCExpr/*!*/ selectExpr = Select(select, typeParams, storeExpr, indexes);
- Contract.Assert(selectExpr != null);
-
- // Create let-binding definitions for all type parameters.
- // The implicit ones can be phrased in terms of the types of the ordinary in-parameters, and
- // we want to make sure that they don't get phrased in terms of the out-parameter, so we pass
- // in inParams here.
- List<VCExprLetBinding/*!*/> letBindings_Implicit =
- AxBuilderPremisses.GenTypeParamBindings(implicitTypeParamsSelect, inParams, bindings, false);
- Contract.Assert(cce.NonNullElements(letBindings_Implicit));
- // The explicit ones, by definition, can only be phrased in terms of the result, so we pass
- // in List(typedVal) here.
- List<VCExprLetBinding/*!*/> letBindings_Explicit =
- AxBuilderPremisses.GenTypeParamBindings(explicitTypeParamsSelect, HelperFuns.ToList(typedVal), bindings, false);
- Contract.Assert(cce.NonNullElements(letBindings_Explicit));
-
- // generate: select(store(m, indices, val)) == val
- VCExpr/*!*/ eq = Gen.Eq(selectExpr, val);
- Contract.Assert(eq != null);
- // generate: type(val) == T, where T is the type of val
- VCExpr/*!*/ ante = Gen.Eq(
- AxBuilderPremisses.TypeOf(val),
- AxBuilderPremisses.Type2Term(mapResult, bindings.TypeVariableBindings));
- Contract.Assert(ante != null);
- VCExpr body;
- if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.None ||
- !AxBuilder.U.Equals(cce.NonNull(select.OutParams[0]).TypedIdent.Type)) {
- body = Gen.Let(letBindings_Explicit, eq);
- } else {
- body = Gen.Let(letBindings_Implicit, Gen.Let(letBindings_Explicit, Gen.ImpliesSimp(ante, eq)));
- }
- return Gen.Forall(quantifiedVars, new List<VCTrigger/*!*/>(), "mapAx0:" + select.Name, 0, body);
- }
-
- private VCExpr GenMapAxiom1(Function select, Function store, Type mapResult, List<TypeVariable/*!*/>/*!*/ explicitSelectParams) {
- Contract.Requires(mapResult != null);
- Contract.Requires(store != null);
- Contract.Requires(select != null);
- Contract.Requires(cce.NonNullElements(explicitSelectParams));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- int arity = store.InParams.Count - 2;
-
- List<Type/*!*/> indexTypes = new List<Type/*!*/>();
- for (int i = 1; i < store.InParams.Count - 1; i++) {
- indexTypes.Add(cce.NonNull(store.InParams[i]).TypedIdent.Type);
- }
- Contract.Assert(indexTypes.Count == arity);
-
- List<VCExprVar/*!*/>/*!*/ indexes0 = HelperFuns.VarVector("x", indexTypes, Gen);
- Contract.Assert(cce.NonNullElements(indexes0));
- List<VCExprVar/*!*/>/*!*/ indexes1 = HelperFuns.VarVector("y", indexTypes, Gen);
- Contract.Assert(cce.NonNullElements(indexes1));
- VCExprVar/*!*/ m = Gen.Variable("m", AxBuilder.U);
- Contract.Assert(m != null);
- VCExprVar/*!*/ val = Gen.Variable("val", cce.NonNull(select.OutParams[0]).TypedIdent.Type);
- Contract.Assert(val != null);
-
- // extract the explicit type parameters from the actual result type ...
- VCExprVar/*!*/ typedVal = Gen.Variable("val", mapResult);
- Contract.Assert(typedVal != null);
- VariableBindings/*!*/ bindings = new VariableBindings();
- bindings.VCExprVarBindings.Add(typedVal, val);
-
- List<VCExprLetBinding/*!*/>/*!*/ letBindings =
- AxBuilderPremisses.GenTypeParamBindings(explicitSelectParams,
- HelperFuns.ToList(typedVal),
- bindings, true);
- Contract.Assert(cce.NonNullElements(letBindings));
-
- // ... and quantify the introduced term variables for type
- // parameters universally
- List<VCExprVar/*!*/>/*!*/ typeParams = new List<VCExprVar/*!*/>(explicitSelectParams.Count);
- List<VCExpr/*!*/>/*!*/ typeParamsExpr = new List<VCExpr/*!*/>(explicitSelectParams.Count);
- foreach (TypeVariable/*!*/ var in explicitSelectParams) {
- Contract.Assert(var != null);
- VCExprVar/*!*/ newVar = (VCExprVar)bindings.TypeVariableBindings[var];
- Contract.Assert(newVar != null);
- typeParams.Add(newVar);
- typeParamsExpr.Add(newVar);
- }
-
- VCExpr/*!*/ storeExpr = Store(store, m, indexes0, val);
- Contract.Assert(storeExpr != null);
- VCExpr/*!*/ selectWithoutStoreExpr = Select(select, typeParamsExpr, m, indexes1);
- Contract.Assert(selectWithoutStoreExpr != null);
- VCExpr/*!*/ selectExpr = Select(select, typeParamsExpr, storeExpr, indexes1);
- Contract.Assert(selectExpr != null);
-
- VCExpr/*!*/ selectEq = Gen.Eq(selectExpr, selectWithoutStoreExpr);
- Contract.Assert(selectEq != null);
-
- List<VCExprVar/*!*/>/*!*/ quantifiedVars = new List<VCExprVar/*!*/>(indexes0.Count + indexes1.Count + 2);
- quantifiedVars.Add(val);
- quantifiedVars.Add(m);
- quantifiedVars.AddRange(indexes0);
- quantifiedVars.AddRange(indexes1);
- quantifiedVars.AddRange(typeParams);
-
- List<VCTrigger/*!*/>/*!*/ triggers = new List<VCTrigger/*!*/>();
- Contract.Assert(cce.NonNullElements(triggers));
-
- VCExpr/*!*/ axiom = VCExpressionGenerator.True;
- Contract.Assert(axiom != null);
-
- // first non-interference criterium: the queried location is
- // different from the assigned location
- for (int i = 0; i < arity; ++i) {
- VCExpr/*!*/ indexesEq = Gen.Eq(indexes0[i], indexes1[i]);
- VCExpr/*!*/ matrix = Gen.Or(indexesEq, selectEq);
- VCExpr/*!*/ conjunct = Gen.Forall(quantifiedVars, triggers, "mapAx1:" + select.Name + ":" + i, 0, matrix);
- Contract.Assert(indexesEq != null);
- Contract.Assert(matrix != null);
- Contract.Assert(conjunct != null);
- axiom = Gen.AndSimp(axiom, conjunct);
- }
-
- // second non-interference criterion: the queried type is
- // different from the assigned type
- VCExpr/*!*/ typesEq = VCExpressionGenerator.True;
- foreach (VCExprLetBinding/*!*/ b in letBindings) {
- Contract.Assert(b != null);
- typesEq = Gen.AndSimp(typesEq, Gen.Eq(b.V, b.E));
- }
- VCExpr/*!*/ matrix2 = Gen.Or(typesEq, selectEq);
- VCExpr/*!*/ conjunct2 = Gen.Forall(quantifiedVars, triggers, "mapAx2:" + select.Name, 0, matrix2);
- axiom = Gen.AndSimp(axiom, conjunct2);
-
- return axiom;
- }
-
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- public class TypeEraserPremisses : TypeEraser
- {
-
- private readonly TypeAxiomBuilderPremisses/*!*/ AxBuilderPremisses;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilderPremisses != null);
- }
-
-
- private OpTypeEraser OpEraserAttr = null;
- protected override OpTypeEraser/*!*/ OpEraser {
- get {
- Contract.Ensures(Contract.Result<OpTypeEraser>() != null);
-
- if (OpEraserAttr == null)
- OpEraserAttr = new OpTypeEraserPremisses(this, AxBuilderPremisses, Gen);
- return OpEraserAttr;
- }
- }
-
- public TypeEraserPremisses(TypeAxiomBuilderPremisses axBuilder, VCExpressionGenerator gen)
- : base(axBuilder, gen) {
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
-
- this.AxBuilderPremisses = axBuilder;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public override VCExpr Visit(VCExprQuantifier node, VariableBindings oldBindings) {
- Contract.Requires(oldBindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VariableBindings bindings = oldBindings.Clone();
-
- // determine the bound vars that actually occur in the body or
- // in any of the triggers (if some variables do not occur, we
- // need to take special care of type parameters that only occur
- // in the types of such variables)
- FreeVariableCollector coll = new FreeVariableCollector();
- coll.Collect(node.Body);
- foreach (VCTrigger trigger in node.Triggers) {
- if (trigger.Pos)
- foreach (VCExpr/*!*/ e in trigger.Exprs) {
- Contract.Assert(e != null);
-
- coll.Collect(e);
- }
- }
-
- List<VCExprVar/*!*/> occurringVars = new List<VCExprVar/*!*/>(node.BoundVars.Count);
- foreach (VCExprVar var in node.BoundVars)
- if (coll.FreeTermVars.ContainsKey(var))
- occurringVars.Add(var);
-
- occurringVars.TrimExcess();
-
- // bound term variables are replaced with bound term variables typed in
- // a simpler way
- List<VCExprVar/*!*/>/*!*/ newBoundVars =
- BoundVarsAfterErasure(occurringVars, bindings);
- Contract.Assert(cce.NonNullElements(newBoundVars));
- VCExpr/*!*/ newNode = HandleQuantifier(node, occurringVars,
- newBoundVars, bindings);
- Contract.Assert(newNode != null);
-
- if (!(newNode is VCExprQuantifier) || !IsUniversalQuantifier(node))
- return newNode;
-
- VariableBindings bindings2;
- if (!RedoQuantifier(node, (VCExprQuantifier)newNode, occurringVars, oldBindings,
- out bindings2, out newBoundVars))
- return newNode;
-
- return HandleQuantifier(node, occurringVars,
- newBoundVars, bindings2);
- }
-
- private VCExpr/*!*/ GenTypePremisses(List<VCExprVar/*!*/>/*!*/ oldBoundVars,
- List<VCExprVar/*!*/>/*!*/ newBoundVars,
- IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/
- typeVarTranslation,
- List<VCExprLetBinding/*!*/>/*!*/ typeVarBindings,
- out List<VCTrigger/*!*/>/*!*/ triggers) {
- Contract.Requires(cce.NonNullElements(oldBoundVars));
- Contract.Requires(cce.NonNullElements(newBoundVars));
- Contract.Requires(cce.NonNullDictionaryAndValues(typeVarTranslation));
- Contract.Requires(cce.NonNullElements(typeVarBindings));
- Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out triggers)));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- // build a substitution of the type variables that it can be checked
- // whether type premisses are trivial
- VCExprSubstitution/*!*/ typeParamSubstitution = new VCExprSubstitution();
- foreach (VCExprLetBinding/*!*/ binding in typeVarBindings) {
- Contract.Assert(binding != null);
- typeParamSubstitution[binding.V] = binding.E;
- }
- SubstitutingVCExprVisitor/*!*/ substituter = new SubstitutingVCExprVisitor(Gen);
- Contract.Assert(substituter != null);
-
- List<VCExpr/*!*/>/*!*/ typePremisses = new List<VCExpr/*!*/>(newBoundVars.Count);
- triggers = new List<VCTrigger/*!*/>(newBoundVars.Count);
-
- for (int i = 0; i < newBoundVars.Count; ++i) {
- VCExprVar/*!*/ oldVar = oldBoundVars[i];
- Contract.Assert(oldVar != null);
- VCExprVar/*!*/ newVar = newBoundVars[i];
- Contract.Assert(newVar != null);
-
- VCExpr/*!*/ typePremiss =
- AxBuilderPremisses.GenVarTypeAxiom(newVar, oldVar.Type,
- typeVarTranslation);
- Contract.Assert(typePremiss != null);
- if (!IsTriviallyTrue(substituter.Mutate(typePremiss,
- typeParamSubstitution))) {
- typePremisses.Add(typePremiss);
- // generate a negative trigger for the variable occurrence
- // in the type premiss
- triggers.Add(Gen.Trigger(false,
- HelperFuns.ToList(AxBuilderPremisses.TypeOf(newVar))));
- }
- }
-
- typePremisses.TrimExcess();
- triggers.TrimExcess();
-
- return Gen.NAry(VCExpressionGenerator.AndOp, typePremisses);
- }
-
- // these optimisations should maybe be moved into a separate
- // visitor (peep-hole optimisations)
- private bool IsTriviallyTrue(VCExpr expr) {
- Contract.Requires(expr != null);
- if (expr.Equals(VCExpressionGenerator.True))
- return true;
-
- if (expr is VCExprNAry) {
- VCExprNAry/*!*/ naryExpr = (VCExprNAry)expr;
- Contract.Assert(naryExpr != null);
- if (naryExpr.Op.Equals(VCExpressionGenerator.EqOp) &&
- naryExpr[0].Equals(naryExpr[1]))
- return true;
- }
-
- return false;
- }
-
- private VCExpr HandleQuantifier(VCExprQuantifier node, List<VCExprVar/*!*/>/*!*/ occurringVars/*!*/, List<VCExprVar/*!*/>/*!*/ newBoundVars, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Requires(cce.NonNullElements(occurringVars/*!*/));
- Contract.Requires(cce.NonNullElements(newBoundVars));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<VCExprLetBinding/*!*/>/*!*/ typeVarBindings =
- AxBuilderPremisses.GenTypeParamBindings(node.TypeParameters, occurringVars, bindings, true);
- Contract.Assert(typeVarBindings != null);
- // Check whether some of the type parameters could not be
- // determined from the bound variable types. In this case, we
- // quantify explicitly over these variables
- if (typeVarBindings.Count < node.TypeParameters.Count) {
- foreach (TypeVariable/*!*/ var in node.TypeParameters) {
- Contract.Assert(var != null);
- if (typeVarBindings.All(b => !b.V.Equals(var)))
- newBoundVars.Add((VCExprVar)bindings.TypeVariableBindings[var]);
- }
- }
-
- // the lists of old and new bound variables for which type
- // antecedents are to be generated
- List<VCExprVar/*!*/>/*!*/ varsWithTypeSpecs = new List<VCExprVar/*!*/>();
- List<VCExprVar/*!*/>/*!*/ newVarsWithTypeSpecs = new List<VCExprVar/*!*/>();
- if (!IsUniversalQuantifier(node) ||
- CommandLineOptions.Clo.TypeEncodingMethod
- == CommandLineOptions.TypeEncoding.Predicates) {
- foreach (VCExprVar/*!*/ oldVar in occurringVars) {
- Contract.Assert(oldVar != null);
- varsWithTypeSpecs.Add(oldVar);
- newVarsWithTypeSpecs.Add(bindings.VCExprVarBindings[oldVar]);
- }
- } // else, no type antecedents are created for any variables
-
- List<VCTrigger/*!*/>/*!*/ furtherTriggers;
- VCExpr/*!*/ typePremisses =
- GenTypePremisses(varsWithTypeSpecs, newVarsWithTypeSpecs,
- bindings.TypeVariableBindings,
- typeVarBindings, out furtherTriggers);
-
- Contract.Assert(cce.NonNullElements(furtherTriggers));
- Contract.Assert(typePremisses != null);
- List<VCTrigger/*!*/>/*!*/ newTriggers = MutateTriggers(node.Triggers, bindings);
- Contract.Assert(cce.NonNullElements(newTriggers));
- newTriggers.AddRange(furtherTriggers);
- newTriggers = AddLets2Triggers(newTriggers, typeVarBindings);
-
- VCExpr/*!*/ newBody = Mutate(node.Body, bindings);
- Contract.Assert(newBody != null);
-
- // assemble the new quantified formula
-
- if (CommandLineOptions.Clo.TypeEncodingMethod
- == CommandLineOptions.TypeEncoding.None) {
- typePremisses = VCExpressionGenerator.True;
- }
-
- VCExpr/*!*/ bodyWithPremisses =
- AxBuilderPremisses.AddTypePremisses(typeVarBindings, typePremisses,
- node.Quan == Quantifier.ALL,
- AxBuilder.Cast(newBody, Type.Bool));
- Contract.Assert(bodyWithPremisses != null);
- if (newBoundVars.Count == 0) // might happen that no bound variables are left
- return bodyWithPremisses;
-
- foreach (VCExprVar/*!*/ v in newBoundVars) {
- Contract.Assert(v != null);
- if (v.Type == AxBuilderPremisses.U) {
- newTriggers.Add(Gen.Trigger(false, AxBuilderPremisses.Cast(v, Type.Int)));
- newTriggers.Add(Gen.Trigger(false, AxBuilderPremisses.Cast(v, Type.Bool)));
- }
- }
-
- return Gen.Quantify(node.Quan, new List<TypeVariable/*!*/>(), newBoundVars,
- newTriggers, node.Infos, bodyWithPremisses);
- }
-
- // check whether we need to add let-binders for any of the type
- // parameters to the triggers (otherwise, the triggers will
- // contain unbound/dangling variables for such parameters)
- private List<VCTrigger/*!*/>/*!*/ AddLets2Triggers(List<VCTrigger/*!*/>/*!*/ triggers/*!*/, List<VCExprLetBinding/*!*/>/*!*/ typeVarBindings) {
- Contract.Requires(cce.NonNullElements(triggers/*!*/));
- Contract.Requires(cce.NonNullElements(typeVarBindings));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCTrigger>>()));
- List<VCTrigger/*!*/>/*!*/ triggersWithLets = new List<VCTrigger/*!*/>(triggers.Count);
-
- foreach (VCTrigger/*!*/ t in triggers) {
- Contract.Assert(t != null);
- List<VCExpr/*!*/>/*!*/ exprsWithLets = new List<VCExpr/*!*/>(t.Exprs.Count);
-
- bool changed = false;
- foreach (VCExpr/*!*/ e in t.Exprs) {
- Contract.Assert(e != null);
- Dictionary<VCExprVar/*!*/, object>/*!*/ freeVars =
- FreeVariableCollector.FreeTermVariables(e);
- Contract.Assert(freeVars != null && cce.NonNullElements(freeVars.Keys));
- if (typeVarBindings.Any(b => freeVars.ContainsKey(b.V))) {
- exprsWithLets.Add(Gen.Let(typeVarBindings, e));
- changed = true;
- } else {
- exprsWithLets.Add(e);
- }
- }
-
- if (changed)
- triggersWithLets.Add(Gen.Trigger(t.Pos, exprsWithLets));
- else
- triggersWithLets.Add(t);
- }
-
- return triggersWithLets;
- }
-
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- public class OpTypeEraserPremisses : OpTypeEraser
- {
-
- private TypeAxiomBuilderPremisses/*!*/ AxBuilderPremisses;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(AxBuilderPremisses != null);
- }
-
-
- public OpTypeEraserPremisses(TypeEraserPremisses eraser, TypeAxiomBuilderPremisses axBuilder, VCExpressionGenerator gen)
- : base(eraser, axBuilder, gen) {
- Contract.Requires(gen != null);
- Contract.Requires(axBuilder != null);
- Contract.Requires(eraser != null);
- this.AxBuilderPremisses = axBuilder;
- }
-
- private VCExpr HandleFunctionOp(Function newFun, List<Type/*!*/>/*!*/ typeArgs/*!*/, IEnumerable<VCExpr/*!*/>/*!*/ oldArgs, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(newFun != null);
- Contract.Requires(cce.NonNullElements(typeArgs/*!*/));
- Contract.Requires(cce.NonNullElements(oldArgs));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- // UGLY: the code for tracking polarities should be factored out
- int oldPolarity = Eraser.Polarity;
- Eraser.Polarity = 0;
-
- List<VCExpr/*!*/>/*!*/ newArgs = new List<VCExpr/*!*/>(typeArgs.Count);
-
- // translate the explicit type arguments
- foreach (Type/*!*/ t in typeArgs) {
- Contract.Assert(t != null);
- newArgs.Add(AxBuilder.Type2Term(t, bindings.TypeVariableBindings));
- }
-
- // recursively translate the value arguments
- foreach (VCExpr/*!*/ arg in oldArgs) {
- Contract.Assert(arg != null);
- Type/*!*/ newType = cce.NonNull(newFun.InParams[newArgs.Count]).TypedIdent.Type;
- newArgs.Add(AxBuilder.Cast(Eraser.Mutate(arg, bindings), newType));
- }
-
- Eraser.Polarity = oldPolarity;
- return Gen.Function(newFun, newArgs);
- }
-
- public override VCExpr/*!*/ VisitSelectOp(VCExprNAry/*!*/ node,
- VariableBindings/*!*/ bindings) {
- Contract.Requires(node != null); Contract.Requires(bindings != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- MapType/*!*/ mapType = node[0].Type.AsMap;
- Contract.Assert(mapType != null);
- List<Type>/*!*/ instantiations; // not used
- Function/*!*/ select =
- AxBuilder.MapTypeAbstracter.Select(mapType, out instantiations);
- Contract.Assert(select != null);
-
- List<int>/*!*/ explicitTypeParams =
- AxBuilderPremisses.MapTypeAbstracterPremisses
- .ExplicitSelectTypeParams(mapType);
- Contract.Assert(select.InParams.Count == explicitTypeParams.Count + node.Arity);
-
- List<Type/*!*/>/*!*/ typeArgs = new List<Type/*!*/>(explicitTypeParams.Count);
- foreach (int i in explicitTypeParams)
- typeArgs.Add(node.TypeArguments[i]);
- return HandleFunctionOp(select, typeArgs, node, bindings);
- }
-
- public override VCExpr VisitStoreOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- List<Type>/*!*/ instantiations; // not used
- Function/*!*/ store =
- AxBuilder.MapTypeAbstracter.Store(node[0].Type.AsMap, out instantiations);
- Contract.Assert(store != null);
- return HandleFunctionOp(store,
- // the store function never has explicit
- // type parameters
- new List<Type/*!*/>(),
- node, bindings);
- }
-
- public override VCExpr VisitBoogieFunctionOp(VCExprNAry node, VariableBindings bindings) {
- Contract.Requires(bindings != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- Function/*!*/ oriFun = ((VCExprBoogieFunctionOp)node.Op).Func;
- Contract.Assert(oriFun != null);
- UntypedFunction untypedFun = AxBuilderPremisses.Typed2Untyped(oriFun);
- Contract.Assert(untypedFun.Fun.InParams.Count ==
- untypedFun.ExplicitTypeParams.Count + node.Arity);
-
- List<Type/*!*/>/*!*/ typeArgs =
- ExtractTypeArgs(node,
- oriFun.TypeParameters, untypedFun.ExplicitTypeParams);
- return HandleFunctionOp(untypedFun.Fun, typeArgs, node, bindings);
- }
-
- private List<Type/*!*/>/*!*/ ExtractTypeArgs(VCExprNAry node, List<TypeVariable> allTypeParams, List<TypeVariable/*!*/>/*!*/ explicitTypeParams) {
- Contract.Requires(allTypeParams != null);
- Contract.Requires(node != null);
- Contract.Requires(cce.NonNullElements(explicitTypeParams));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
- List<Type/*!*/>/*!*/ res = new List<Type/*!*/>(explicitTypeParams.Count);
- foreach (TypeVariable/*!*/ var in explicitTypeParams) {
- Contract.Assert(var != null);
- // this lookup could be optimised
- res.Add(node.TypeArguments[allTypeParams.IndexOf(var)]);
- }
- return res;
- }
- }
-
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+using Microsoft.Boogie.VCExprAST;
+
+// Erasure of types using premisses (forall x :: type(x)=T ==> p(x))
+
+namespace Microsoft.Boogie.TypeErasure
+{
+ using Microsoft.Boogie.VCExprAST;
+
+ // When using type premisses, we can distinguish two kinds of type
+ // parameters of a function or map: parameters that occur in the
+ // formal argument types of the function are "implicit" because they
+ // can be inferred from the actual argument types; parameters that
+ // only occur in the result type of the function are "explicit"
+ // because they are not inferrable and have to be given to the
+ // function as additional arguments.
+ //
+ // The following structure is used to store the untyped version of a
+ // typed function, together with the lists of implicit and explicit
+ // type parameters (in the same order as they occur in the signature
+ // of the original function).
+
+ internal struct UntypedFunction
+ {
+ public readonly Function/*!*/ Fun;
+ // type parameters that can be extracted from the value parameters
+ public readonly List<TypeVariable/*!*/>/*!*/ ImplicitTypeParams;
+ // type parameters that have to be given explicitly
+ public readonly List<TypeVariable/*!*/>/*!*/ ExplicitTypeParams;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Fun != null);
+ Contract.Invariant(cce.NonNullElements(ImplicitTypeParams));
+ Contract.Invariant(cce.NonNullElements(ExplicitTypeParams));
+ }
+
+
+ public UntypedFunction(Function/*!*/ fun,
+ List<TypeVariable/*!*/>/*!*/ implicitTypeParams,
+ List<TypeVariable/*!*/>/*!*/ explicitTypeParams) {
+ Contract.Requires(fun != null);
+ Contract.Requires(cce.NonNullElements(implicitTypeParams));
+ Contract.Requires(cce.NonNullElements(explicitTypeParams));
+ Fun = fun;
+ ImplicitTypeParams = implicitTypeParams;
+ ExplicitTypeParams = explicitTypeParams;
+ }
+ }
+
+ public class TypeAxiomBuilderPremisses : TypeAxiomBuilderIntBoolU
+ {
+
+ public TypeAxiomBuilderPremisses(VCExpressionGenerator gen)
+ : base(gen) {
+ Contract.Requires(gen != null);
+
+ TypeFunction = HelperFuns.BoogieFunction("dummy", Type.Int);
+ Typed2UntypedFunctions = new Dictionary<Function/*!*/, UntypedFunction>();
+ MapTypeAbstracterAttr = null;
+ }
+
+ // constructor to allow cloning
+ [NotDelayed]
+ internal TypeAxiomBuilderPremisses(TypeAxiomBuilderPremisses builder)
+ : base(builder) {
+ Contract.Requires(builder != null);
+ TypeFunction = builder.TypeFunction;
+ Typed2UntypedFunctions =
+ new Dictionary<Function/*!*/, UntypedFunction>(builder.Typed2UntypedFunctions);
+
+ MapTypeAbstracterAttr =
+ builder.MapTypeAbstracterAttr == null ?
+ null : new MapTypeAbstractionBuilderPremisses(this, builder.Gen,
+ builder.MapTypeAbstracterAttr);
+ }
+
+ public override Object Clone() {
+ Contract.Ensures(Contract.Result<Object>() != null);
+ return new TypeAxiomBuilderPremisses(this);
+ }
+
+ public override void Setup() {
+ TypeFunction = HelperFuns.BoogieFunction("type", U, T);
+ base.Setup();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // generate axioms of the kind "forall x:U. {Int2U(U2Int(x))}
+ // type(x)=int ==> Int2U(U2Int(x))==x"
+ protected override VCExpr GenReverseCastAxiom(Function castToU, Function castFromU) {
+ //Contract.Requires(castFromU != null);
+ //Contract.Requires(castToU != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCTrigger/*!*/>/*!*/ triggers;
+ VCExprVar/*!*/ var;
+ VCExpr/*!*/ eq = GenReverseCastEq(castToU, castFromU, out var, out triggers);
+ Contract.Assert(cce.NonNullElements(triggers));
+ Contract.Assert(var != null);
+ Contract.Assert(eq != null);
+ VCExpr/*!*/ premiss;
+ if (CommandLineOptions.Clo.TypeEncodingMethod
+ == CommandLineOptions.TypeEncoding.None)
+ premiss = VCExpressionGenerator.True;
+ else
+ premiss = GenVarTypeAxiom(var, cce.NonNull(castFromU.OutParams[0]).TypedIdent.Type,
+ // we don't have any bindings available
+ new Dictionary<TypeVariable/*!*/, VCExpr/*!*/>());
+ VCExpr/*!*/ matrix = Gen.ImpliesSimp(premiss, eq);
+ Contract.Assert(matrix != null);
+ return Gen.Forall(HelperFuns.ToList(var), triggers, "cast:" + castFromU.Name, -1, matrix);
+ }
+
+ protected override VCExpr GenCastTypeAxioms(Function castToU, Function castFromU) {
+ //Contract.Requires(castFromU != null);
+ //Contract.Requires(castToU != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ Type/*!*/ fromType = cce.NonNull(castToU.InParams[0]).TypedIdent.Type;
+ return GenFunctionAxiom(castToU, new List<TypeVariable/*!*/>(), new List<TypeVariable/*!*/>(),
+ HelperFuns.ToList(fromType), fromType);
+ }
+
+ private MapTypeAbstractionBuilderPremisses MapTypeAbstracterAttr;
+
+ internal override MapTypeAbstractionBuilder/*!*/ MapTypeAbstracter {
+ get {
+ Contract.Ensures(Contract.Result<MapTypeAbstractionBuilder>() != null);
+
+ if (MapTypeAbstracterAttr == null)
+ MapTypeAbstracterAttr = new MapTypeAbstractionBuilderPremisses(this, Gen);
+ return MapTypeAbstracterAttr;
+ }
+ }
+
+ internal MapTypeAbstractionBuilderPremisses/*!*/ MapTypeAbstracterPremisses {
+ get {
+ Contract.Ensures(Contract.Result<MapTypeAbstractionBuilderPremisses>() != null);
+
+ return (MapTypeAbstractionBuilderPremisses)MapTypeAbstracter;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // function that maps individuals to their type
+ // the field is overwritten with its actual value in "Setup"
+ private Function/*!*/ TypeFunction;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(TypeFunction != null);
+ }
+
+
+ public VCExpr TypeOf(VCExpr expr) {
+ Contract.Requires(expr != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Gen.Function(TypeFunction, expr);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Generate type premisses and type parameter bindings for quantifiers, functions, procedures
+
+ // let-bindings to extract the instantiations of type parameters
+ public List<VCExprLetBinding/*!*/>/*!*/
+ GenTypeParamBindings(// the original bound variables and (implicit) type parameters
+ List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ oldBoundVars,
+ // VariableBindings to which the translation
+ // TypeVariable -> VCExprVar is added
+ VariableBindings/*!*/ bindings,
+ bool addTypeVarsToBindings) {
+ Contract.Requires(typeParams != null);
+ Contract.Requires(cce.NonNullElements(oldBoundVars));
+ Contract.Requires(bindings != null);
+
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprLetBinding>>()));
+
+ // type variables are replaced with ordinary variables that are bound using a
+ // let-expression
+ if (addTypeVarsToBindings) {
+ foreach (TypeVariable/*!*/ tvar in typeParams) {
+ Contract.Assert(tvar != null);
+ bindings.TypeVariableBindings.Add(tvar, Gen.Variable(tvar.Name, T));
+ }
+ }
+
+ // extract the values of type variables from the term variables
+ List<VCExprVar/*!*/>/*!*/ UtypedVars = new List<VCExprVar/*!*/>(oldBoundVars.Count);
+ List<Type/*!*/>/*!*/ originalTypes = new List<Type/*!*/>(oldBoundVars.Count);
+ foreach (VCExprVar var in oldBoundVars) {
+ VCExprVar/*!*/ newVar = bindings.VCExprVarBindings[var];
+ if (newVar.Type.Equals(U)) {
+ UtypedVars.Add(newVar);
+ originalTypes.Add(var.Type);
+ }
+ }
+
+ UtypedVars.TrimExcess();
+ originalTypes.TrimExcess();
+
+ return BestTypeVarExtractors(typeParams, originalTypes, UtypedVars, bindings);
+ }
+
+
+ public VCExpr/*!*/ AddTypePremisses(List<VCExprLetBinding/*!*/>/*!*/ typeVarBindings,
+ VCExpr/*!*/ typePremisses, bool universal,
+ VCExpr/*!*/ body) {
+ Contract.Requires(cce.NonNullElements(typeVarBindings));
+ Contract.Requires(typePremisses != null);
+ Contract.Requires(body != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExpr/*!*/ bodyWithPremisses;
+ if (universal)
+ bodyWithPremisses = Gen.ImpliesSimp(typePremisses, body);
+ else
+ bodyWithPremisses = Gen.AndSimp(typePremisses, body);
+
+ return Gen.Let(typeVarBindings, bodyWithPremisses);
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Extract the instantiations of type variables from the concrete types of
+ // term variables. E.g., for a function f<a>(x : C a), we would extract the
+ // instantiation of "a" by looking at the concrete type of "x".
+
+ public List<VCExprLetBinding/*!*/>/*!*/
+ BestTypeVarExtractors(List<TypeVariable/*!*/>/*!*/ vars, List<Type/*!*/>/*!*/ types,
+ List<VCExprVar/*!*/>/*!*/ concreteTypeSources,
+ VariableBindings/*!*/ bindings) {
+ Contract.Requires(cce.NonNullElements(vars));
+ Contract.Requires(cce.NonNullElements(types));
+ Contract.Requires(cce.NonNullElements(concreteTypeSources));
+ Contract.Requires(bindings != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprLetBinding>>()));
+
+ List<VCExprLetBinding/*!*/>/*!*/ typeParamBindings = new List<VCExprLetBinding/*!*/>();
+ foreach (TypeVariable/*!*/ var in vars) {
+ Contract.Assert(var != null);
+ VCExpr extractor = BestTypeVarExtractor(var, types, concreteTypeSources);
+ if (extractor != null)
+ typeParamBindings.Add(
+ Gen.LetBinding((VCExprVar)bindings.TypeVariableBindings[var],
+ extractor));
+ }
+ return typeParamBindings;
+ }
+
+ private VCExpr BestTypeVarExtractor(TypeVariable/*!*/ var, List<Type/*!*/>/*!*/ types,
+ List<VCExprVar/*!*/>/*!*/ concreteTypeSources) {
+ Contract.Requires(var != null);
+ Contract.Requires(cce.NonNullElements(types));
+ Contract.Requires(cce.NonNullElements(concreteTypeSources));
+ List<VCExpr/*!*/> allExtractors = TypeVarExtractors(var, types, concreteTypeSources);
+ Contract.Assert(cce.NonNullElements(allExtractors));
+ if (allExtractors.Count == 0)
+ return null;
+
+ VCExpr bestExtractor = allExtractors[0];
+ int bestExtractorSize = SizeComputingVisitor.ComputeSize(bestExtractor);
+ for (int i = 1; i < allExtractors.Count; ++i) {
+ int newSize = SizeComputingVisitor.ComputeSize(allExtractors[i]);
+ if (newSize < bestExtractorSize) {
+ bestExtractor = allExtractors[i];
+ bestExtractorSize = newSize;
+ }
+ }
+
+ return bestExtractor;
+ }
+
+ private List<VCExpr/*!*/>/*!*/ TypeVarExtractors(TypeVariable/*!*/ var, List<Type/*!*/>/*!*/ types,
+ List<VCExprVar/*!*/>/*!*/ concreteTypeSources) {
+ Contract.Requires(var != null);
+ Contract.Requires(cce.NonNullElements(types));
+ Contract.Requires(cce.NonNullElements(concreteTypeSources));
+ Contract.Requires((types.Count == concreteTypeSources.Count));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
+ List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>();
+ for (int i = 0; i < types.Count; ++i)
+ TypeVarExtractors(var, types[i], TypeOf(concreteTypeSources[i]), res);
+
+ return res;
+ }
+
+ private void TypeVarExtractors(TypeVariable var, Type completeType, VCExpr innerTerm, List<VCExpr/*!*/>/*!*/ extractors) {
+ Contract.Requires(innerTerm != null);
+ Contract.Requires(completeType != null);
+ Contract.Requires(var != null);
+ Contract.Requires(cce.NonNullElements(extractors));
+ if (completeType.IsVariable) {
+ if (var.Equals(completeType)) {
+ extractors.Add(innerTerm);
+ } // else nothing
+ } else if (completeType.IsBasic) {
+ // nothing
+ } else if (completeType.IsCtor) {
+ CtorType/*!*/ ctorType = completeType.AsCtor;
+ if (ctorType.Arguments.Count > 0) {
+ // otherwise there are no chances of extracting any
+ // instantiations from this type
+ TypeCtorRepr repr = GetTypeCtorReprStruct(ctorType.Decl);
+ for (int i = 0; i < ctorType.Arguments.Count; ++i) {
+ VCExpr/*!*/ newInnerTerm = Gen.Function(repr.Dtors[i], innerTerm);
+ Contract.Assert(newInnerTerm != null);
+ TypeVarExtractors(var, ctorType.Arguments[i], newInnerTerm, extractors);
+ }
+ }
+ } else if (completeType.IsMap) {
+ TypeVarExtractors(var, MapTypeAbstracter.AbstractMapType(completeType.AsMap),
+ innerTerm, extractors);
+ } else {
+ System.Diagnostics.Debug.Fail("Don't know how to handle this type: " + completeType);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Symbols for representing functions
+
+ // Globally defined functions
+ private readonly IDictionary<Function/*!*/, UntypedFunction/*!*/>/*!*/ Typed2UntypedFunctions;
+ [ContractInvariantMethod]
+ void Typed2UntypedFunctionsInvariantMethod() {
+ Contract.Invariant(Typed2UntypedFunctions != null);
+ }
+
+ // distinguish between implicit and explicit type parameters
+ internal static void SeparateTypeParams(List<Type/*!*/>/*!*/ valueArgumentTypes,
+ List<TypeVariable>/*!*/ allTypeParams,
+ out List<TypeVariable/*!*/>/*!*/ implicitParams,
+ out List<TypeVariable/*!*/>/*!*/ explicitParams) {
+ Contract.Requires(cce.NonNullElements(valueArgumentTypes));
+ Contract.Requires(allTypeParams != null);
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out implicitParams)));
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out explicitParams)));
+ List<TypeVariable>/*!*/ varsInInParamTypes = new List<TypeVariable>();
+ foreach (Type/*!*/ t in valueArgumentTypes) {
+ Contract.Assert(t != null);
+ varsInInParamTypes.AppendWithoutDups(t.FreeVariables);
+ }
+
+ implicitParams = new List<TypeVariable/*!*/>(allTypeParams.Count);
+ explicitParams = new List<TypeVariable/*!*/>(allTypeParams.Count);
+
+ foreach (TypeVariable/*!*/ var in allTypeParams) {
+ Contract.Assert(var != null);
+ if (varsInInParamTypes.Contains(var))
+ implicitParams.Add(var);
+ else
+ explicitParams.Add(var);
+ }
+
+ implicitParams.TrimExcess();
+ explicitParams.TrimExcess();
+ }
+
+ internal UntypedFunction Typed2Untyped(Function fun) {
+ Contract.Requires(fun != null);
+ UntypedFunction res;
+ if (!Typed2UntypedFunctions.TryGetValue(fun, out res)) {
+ Contract.Assert(fun.OutParams.Count == 1);
+
+ // if all of the parameters are int or bool, the function does
+ // not have to be changed
+ if (fun.InParams.All(param => UnchangedType(cce.NonNull(param).TypedIdent.Type)) &&
+ UnchangedType(cce.NonNull(fun.OutParams[0]).TypedIdent.Type) &&
+ fun.TypeParameters.Count == 0) {
+ res = new UntypedFunction(fun, new List<TypeVariable/*!*/>(), new List<TypeVariable/*!*/>());
+ } else {
+ List<Type/*!*/>/*!*/ argTypes = new List<Type/*!*/>();
+ foreach (Variable/*!*/ v in fun.InParams) {
+ Contract.Assert(v != null);
+ argTypes.Add(v.TypedIdent.Type);
+ }
+
+ List<TypeVariable/*!*/>/*!*/ implicitParams, explicitParams;
+ SeparateTypeParams(argTypes, fun.TypeParameters, out implicitParams, out explicitParams);
+
+ Type[]/*!*/ types = new Type[explicitParams.Count + fun.InParams.Count + 1];
+ int i = 0;
+ for (int j = 0; j < explicitParams.Count; ++j) {
+ types[i] = T;
+ i = i + 1;
+ }
+ for (int j = 0; j < fun.InParams.Count; ++i, ++j)
+ types[i] = TypeAfterErasure(cce.NonNull(fun.InParams[j]).TypedIdent.Type);
+ types[types.Length - 1] = TypeAfterErasure(cce.NonNull(fun.OutParams[0]).TypedIdent.Type);
+
+ Function/*!*/ untypedFun = HelperFuns.BoogieFunction(fun.Name, types);
+ Contract.Assert(untypedFun != null);
+ untypedFun.Attributes = fun.Attributes;
+ res = new UntypedFunction(untypedFun, implicitParams, explicitParams);
+ if (U.Equals(types[types.Length - 1]))
+ AddTypeAxiom(GenFunctionAxiom(res, fun));
+ }
+
+ Typed2UntypedFunctions.Add(fun, res);
+ }
+ return res;
+ }
+
+ private VCExpr GenFunctionAxiom(UntypedFunction fun, Function originalFun) {
+ Contract.Requires(originalFun != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<Type/*!*/>/*!*/ originalInTypes = new List<Type/*!*/>(originalFun.InParams.Count);
+ foreach (Formal/*!*/ f in originalFun.InParams)
+ originalInTypes.Add(f.TypedIdent.Type);
+
+ return GenFunctionAxiom(fun.Fun, fun.ImplicitTypeParams, fun.ExplicitTypeParams,
+ originalInTypes,
+ cce.NonNull(originalFun.OutParams[0]).TypedIdent.Type);
+ }
+
+ internal VCExpr/*!*/ GenFunctionAxiom(Function/*!*/ fun,
+ List<TypeVariable/*!*/>/*!*/ implicitTypeParams,
+ List<TypeVariable/*!*/>/*!*/ explicitTypeParams,
+ List<Type/*!*/>/*!*/ originalInTypes,
+ Type/*!*/ originalResultType) {
+ Contract.Requires(cce.NonNullElements(implicitTypeParams));
+ Contract.Requires(fun != null);
+ Contract.Requires(cce.NonNullElements(explicitTypeParams));
+ Contract.Requires(cce.NonNullElements(originalInTypes));
+ Contract.Requires(originalResultType != null);
+ Contract.Requires(originalInTypes.Count + explicitTypeParams.Count == fun.InParams.Count);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.None) {
+ return VCExpressionGenerator.True;
+ }
+
+ List<VCExprVar/*!*/>/*!*/ typedInputVars = new List<VCExprVar/*!*/>(originalInTypes.Count);
+ int i = 0;
+ foreach (Type/*!*/ t in originalInTypes) {
+ Contract.Assert(t != null);
+ typedInputVars.Add(Gen.Variable("arg" + i, t));
+ i = i + 1;
+ }
+
+ VariableBindings/*!*/ bindings = new VariableBindings();
+
+ // type parameters that have to be given explicitly are replaced
+ // with universally quantified type variables
+ List<VCExprVar/*!*/>/*!*/ boundVars = new List<VCExprVar/*!*/>(explicitTypeParams.Count + typedInputVars.Count);
+ foreach (TypeVariable/*!*/ var in explicitTypeParams) {
+ Contract.Assert(var != null);
+ VCExprVar/*!*/ newVar = Gen.Variable(var.Name, T);
+ boundVars.Add(newVar);
+ bindings.TypeVariableBindings.Add(var, newVar);
+ }
+
+ // bound term variables are replaced with bound term variables typed in
+ // a simpler way
+ foreach (VCExprVar/*!*/ var in typedInputVars) {
+ Contract.Assert(var != null);
+ Type/*!*/ newType = TypeAfterErasure(var.Type);
+ Contract.Assert(newType != null);
+ VCExprVar/*!*/ newVar = Gen.Variable(var.Name, newType);
+ Contract.Assert(newVar != null);
+ boundVars.Add(newVar);
+ bindings.VCExprVarBindings.Add(var, newVar);
+ }
+
+ List<VCExprLetBinding/*!*/> typeVarBindings =
+ GenTypeParamBindings(implicitTypeParams, typedInputVars, bindings, true);
+ Contract.Assert(cce.NonNullElements(typeVarBindings));
+
+ VCExpr/*!*/ funApp = Gen.Function(fun, HelperFuns.ToVCExprList(boundVars));
+ Contract.Assert(funApp != null);
+ VCExpr/*!*/ conclusion = Gen.Eq(TypeOf(funApp),
+ Type2Term(originalResultType, bindings.TypeVariableBindings));
+ Contract.Assert(conclusion != null);
+ VCExpr conclusionWithPremisses =
+ // leave out antecedents of function type axioms ... they don't appear necessary,
+ // because a function can always be extended to all U-values (right?)
+ // AddTypePremisses(typeVarBindings, typePremisses, true, conclusion);
+ Gen.Let(typeVarBindings, conclusion);
+
+ if (boundVars.Count > 0) {
+ List<VCTrigger/*!*/> triggers = HelperFuns.ToList(Gen.Trigger(true, HelperFuns.ToList(funApp)));
+ Contract.Assert(cce.NonNullElements(triggers));
+ return Gen.Forall(boundVars, triggers, "funType:" + fun.Name, -1, conclusionWithPremisses);
+ } else {
+ return conclusionWithPremisses;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected override void AddVarTypeAxiom(VCExprVar var, Type originalType) {
+ //Contract.Requires(originalType != null);
+ //Contract.Requires(var != null);
+ if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.None) return;
+ AddTypeAxiom(GenVarTypeAxiom(var, originalType,
+ // we don't have any bindings available
+ new Dictionary<TypeVariable/*!*/, VCExpr/*!*/>()));
+ }
+
+ public VCExpr GenVarTypeAxiom(VCExprVar var, Type originalType, IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/ varMapping) {
+ Contract.Requires(var != null);
+ Contract.Requires(originalType != null);
+ Contract.Requires(cce.NonNullDictionaryAndValues(varMapping));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ if (!var.Type.Equals(originalType)) {
+ VCExpr/*!*/ typeRepr = Type2Term(originalType, varMapping);
+ return Gen.Eq(TypeOf(var), typeRepr);
+ }
+ return VCExpressionGenerator.True;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ internal class MapTypeAbstractionBuilderPremisses : MapTypeAbstractionBuilder
+ {
+
+ private readonly TypeAxiomBuilderPremisses/*!*/ AxBuilderPremisses;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilderPremisses != null);
+ }
+
+
+ internal MapTypeAbstractionBuilderPremisses(TypeAxiomBuilderPremisses axBuilder, VCExpressionGenerator gen)
+ : base(axBuilder, gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+
+ this.AxBuilderPremisses = axBuilder;
+ }
+
+ // constructor for cloning
+ internal MapTypeAbstractionBuilderPremisses(TypeAxiomBuilderPremisses axBuilder, VCExpressionGenerator gen, MapTypeAbstractionBuilderPremisses builder)
+ : base(axBuilder, gen, builder) {
+ Contract.Requires(builder != null);
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+
+ this.AxBuilderPremisses = axBuilder;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Determine the type parameters of a map type that have to be
+ // given explicitly when applying the select function (the
+ // parameters that only occur in the result type of the
+ // map). These parameters are given as a list of indexes sorted in
+ // ascending order; the index i refers to the i'th bound variable
+ // in a type <a0, a1, ..., an>[...]...
+ public List<int>/*!*/ ExplicitSelectTypeParams(MapType type) {
+ Contract.Requires(type != null);
+ Contract.Ensures(Contract.Result<List<int>>() != null);
+
+ List<int> res;
+ if (!explicitSelectTypeParamsCache.TryGetValue(type, out res)) {
+ List<TypeVariable/*!*/>/*!*/ explicitParams, implicitParams;
+ TypeAxiomBuilderPremisses.SeparateTypeParams(type.Arguments.ToList(),
+ type.TypeParameters,
+ out implicitParams,
+ out explicitParams);
+ res = new List<int>(explicitParams.Count);
+ foreach (TypeVariable/*!*/ var in explicitParams) {
+ Contract.Assert(var != null);
+ res.Add(type.TypeParameters.IndexOf(var));
+ }
+ explicitSelectTypeParamsCache.Add(type, res);
+ }
+ return cce.NonNull(res);
+ }
+
+ private IDictionary<MapType/*!*/, List<int>/*!*/>/*!*/ explicitSelectTypeParamsCache =
+ new Dictionary<MapType/*!*/, List<int>/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvarant() {
+ Contract.Invariant(cce.NonNullDictionaryAndValues(explicitSelectTypeParamsCache));
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ protected override void GenSelectStoreFunctions(MapType abstractedType, TypeCtorDecl synonym, out Function/*!*/ select, out Function/*!*/ store) {
+ //Contract.Requires(synonym != null);
+ //Contract.Requires(abstractedType != null);
+ Contract.Ensures(Contract.ValueAtReturn(out select) != null);
+ Contract.Ensures(Contract.ValueAtReturn(out store) != null);
+ Type/*!*/ mapTypeSynonym;
+ List<TypeVariable/*!*/>/*!*/ typeParams;
+ List<Type/*!*/>/*!*/ originalInTypes;
+ GenTypeAxiomParams(abstractedType, synonym, out mapTypeSynonym,
+ out typeParams, out originalInTypes);
+
+ // select
+ List<TypeVariable/*!*/>/*!*/ explicitSelectParams, implicitSelectParams;
+ select = CreateAccessFun(typeParams, originalInTypes,
+ abstractedType.Result, synonym.Name + "Select",
+ out implicitSelectParams, out explicitSelectParams);
+
+ // store, which gets one further argument: the assigned rhs
+ originalInTypes.Add(abstractedType.Result);
+
+ List<TypeVariable/*!*/>/*!*/ explicitStoreParams, implicitStoreParams;
+ store = CreateAccessFun(typeParams, originalInTypes,
+ mapTypeSynonym, synonym.Name + "Store",
+ out implicitStoreParams, out explicitStoreParams);
+
+ // the store function does not have any explicit type parameters
+ Contract.Assert(explicitStoreParams.Count == 0);
+
+ if (CommandLineOptions.Clo.UseArrayTheory) {
+ select.AddAttribute("builtin", "select");
+ store.AddAttribute("builtin", "store");
+ } else {
+ AxBuilder.AddTypeAxiom(GenMapAxiom0(select, store,
+ abstractedType.Result,
+ implicitSelectParams, explicitSelectParams,
+ originalInTypes));
+ AxBuilder.AddTypeAxiom(GenMapAxiom1(select, store,
+ abstractedType.Result,
+ explicitSelectParams));
+ }
+ }
+
+ protected void GenTypeAxiomParams(MapType/*!*/ abstractedType, TypeCtorDecl/*!*/ synonymDecl,
+ out Type/*!*/ mapTypeSynonym,
+ out List<TypeVariable/*!*/>/*!*/ typeParams,
+ out List<Type/*!*/>/*!*/ originalIndexTypes) {
+ Contract.Requires(abstractedType != null);
+ Contract.Requires(synonymDecl != null);
+ Contract.Ensures(Contract.ValueAtReturn(out mapTypeSynonym) != null);
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out typeParams)));
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out originalIndexTypes)));
+ typeParams = new List<TypeVariable/*!*/>();
+ typeParams.AddRange(abstractedType.TypeParameters);
+ typeParams.AddRange(abstractedType.FreeVariables);
+
+ originalIndexTypes = new List<Type/*!*/>(abstractedType.Arguments.Count + 1);
+ List<Type>/*!*/ mapTypeParams = new List<Type>();
+ foreach (TypeVariable/*!*/ var in abstractedType.FreeVariables) {
+ Contract.Assert(var != null);
+ mapTypeParams.Add(var);
+ }
+
+ if (CommandLineOptions.Clo.MonomorphicArrays)
+ mapTypeSynonym = abstractedType;
+ else
+ mapTypeSynonym = new CtorType(Token.NoToken, synonymDecl, mapTypeParams);
+
+ originalIndexTypes.Add(mapTypeSynonym);
+ originalIndexTypes.AddRange(abstractedType.Arguments.ToList());
+ }
+
+ // method to actually create the select or store function
+ private Function/*!*/ CreateAccessFun(List<TypeVariable/*!*/>/*!*/ originalTypeParams,
+ List<Type/*!*/>/*!*/ originalInTypes,
+ Type/*!*/ originalResult,
+ string/*!*/ name,
+ out List<TypeVariable/*!*/>/*!*/ implicitTypeParams, out List<TypeVariable/*!*/>/*!*/ explicitTypeParams) {
+ Contract.Requires(cce.NonNullElements(originalTypeParams));
+ Contract.Requires(cce.NonNullElements(originalInTypes));
+ Contract.Requires(originalResult != null);
+ Contract.Requires(name != null);
+ Contract.Ensures(Contract.Result<Function>() != null);
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out implicitTypeParams)));
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out explicitTypeParams)));
+
+ // select and store are basically handled like normal functions: the type
+ // parameters are split into the implicit parameters, and into the parameters
+ // that have to be given explicitly
+ TypeAxiomBuilderPremisses.SeparateTypeParams(originalInTypes,
+ new List<TypeVariable>(originalTypeParams),
+ out implicitTypeParams,
+ out explicitTypeParams);
+
+ Type[]/*!*/ ioTypes = new Type[explicitTypeParams.Count + originalInTypes.Count + 1];
+ int i = 0;
+ for (; i < explicitTypeParams.Count; ++i)
+ ioTypes[i] = AxBuilder.T;
+ foreach (Type/*!*/ type in originalInTypes) {
+ Contract.Assert(type != null);
+ if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(type))
+ ioTypes[i] = type;
+ else
+ ioTypes[i] = AxBuilder.U;
+ i++;
+ }
+ if (CommandLineOptions.Clo.Monomorphize && AxBuilder.UnchangedType(originalResult))
+ ioTypes[i] = originalResult;
+ else
+ ioTypes[i] = AxBuilder.U;
+
+ Function/*!*/ res = HelperFuns.BoogieFunction(name, ioTypes);
+ Contract.Assert(res != null);
+
+ if (AxBuilder.U.Equals(ioTypes[i])) {
+ AxBuilder.AddTypeAxiom(
+ AxBuilderPremisses.GenFunctionAxiom(res,
+ implicitTypeParams, explicitTypeParams,
+ originalInTypes, originalResult));
+ }
+ return res;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The normal axioms of the theory of arrays (without extensionality)
+
+ private VCExpr/*!*/ Select(Function/*!*/ select,
+ // in general, the select function has to
+ // receive explicit type parameters (which
+ // are here already represented as VCExpr
+ // of type T)
+ List<VCExpr/*!*/>/*!*/ typeParams,
+ VCExpr/*!*/ map,
+ List<VCExprVar/*!*/>/*!*/ indexes) {
+ Contract.Requires(select != null);
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Requires(map != null);
+ Contract.Requires(cce.NonNullElements(indexes));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ List<VCExpr/*!*/>/*!*/ selectArgs = new List<VCExpr/*!*/>(typeParams.Count + indexes.Count + 1);
+ selectArgs.AddRange(typeParams);
+ selectArgs.Add(map);
+ selectArgs.AddRange(HelperFuns.ToVCExprList(indexes));
+ return Gen.Function(select, selectArgs);
+ }
+
+ private VCExpr Store(Function store, VCExpr map, List<VCExprVar/*!*/>/*!*/ indexes, VCExpr val) {
+ Contract.Requires(val != null);
+ Contract.Requires(map != null);
+ Contract.Requires(store != null);
+ Contract.Requires(cce.NonNullElements(indexes));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCExpr/*!*/>/*!*/ storeArgs = new List<VCExpr/*!*/>(indexes.Count + 2);
+ storeArgs.Add(map);
+ storeArgs.AddRange(HelperFuns.ToVCExprList(indexes));
+ storeArgs.Add(val);
+ return Gen.Function(store, storeArgs);
+ }
+
+ /// <summary>
+ /// Generate:
+ /// (forall m, indexes, val ::
+ /// type(val) == T ==>
+ /// select(store(m, indexes, val), indexes) == val)
+ /// where the quantifier body is also enclosed in a let that defines portions of T, if needed.
+ /// </summary>
+ private VCExpr GenMapAxiom0(Function select, Function store, Type mapResult, List<TypeVariable/*!*/>/*!*/ implicitTypeParamsSelect, List<TypeVariable/*!*/>/*!*/ explicitTypeParamsSelect, List<Type/*!*/>/*!*/ originalInTypes) {
+ Contract.Requires(mapResult != null);
+ Contract.Requires(store != null);
+ Contract.Requires(select != null);
+ Contract.Requires(cce.NonNullElements(implicitTypeParamsSelect));
+ Contract.Requires(cce.NonNullElements(originalInTypes));
+ Contract.Requires(cce.NonNullElements(explicitTypeParamsSelect));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ int arity = store.InParams.Count - 2;
+ List<VCExprVar/*!*/> inParams = new List<VCExprVar/*!*/>();
+ List<VCExprVar/*!*/> quantifiedVars = new List<VCExprVar/*!*/>(store.InParams.Count);
+ VariableBindings bindings = new VariableBindings();
+
+ // bound variable: m
+ VCExprVar typedM = Gen.Variable("m", originalInTypes[0]);
+ VCExprVar m = Gen.Variable("m", AxBuilder.U);
+ inParams.Add(typedM);
+ quantifiedVars.Add(m);
+ bindings.VCExprVarBindings.Add(typedM, m);
+
+ // bound variables: indexes
+ List<Type/*!*/> origIndexTypes = new List<Type/*!*/>(arity);
+ List<Type/*!*/> indexTypes = new List<Type/*!*/>(arity);
+ for (int i = 1; i < store.InParams.Count - 1; i++) {
+ origIndexTypes.Add(originalInTypes[i]);
+ indexTypes.Add(cce.NonNull(store.InParams[i]).TypedIdent.Type);
+ }
+ Contract.Assert(arity == indexTypes.Count);
+ List<VCExprVar/*!*/> typedArgs = HelperFuns.VarVector("arg", origIndexTypes, Gen);
+ Contract.Assert(cce.NonNullElements(typedArgs));
+ List<VCExprVar/*!*/> indexes = HelperFuns.VarVector("x", indexTypes, Gen);
+ Contract.Assert(cce.NonNullElements(indexes));
+ Contract.Assert(typedArgs.Count == indexes.Count);
+ inParams.AddRange(typedArgs);
+ quantifiedVars.AddRange(indexes);
+ for (int i = 0; i < arity; i++) {
+ bindings.VCExprVarBindings.Add(typedArgs[i], indexes[i]);
+ }
+
+ // bound variable: val
+ VCExprVar typedVal = Gen.Variable("val", mapResult);
+ VCExprVar val = Gen.Variable("val", cce.NonNull(select.OutParams[0]).TypedIdent.Type);
+ quantifiedVars.Add(val);
+ bindings.VCExprVarBindings.Add(typedVal, val);
+
+ // add all type parameters into bindings
+ foreach (TypeVariable tp in implicitTypeParamsSelect) {
+ VCExprVar tVar = Gen.Variable(tp.Name, AxBuilderPremisses.T);
+ bindings.TypeVariableBindings.Add(tp, tVar);
+ }
+ List<VCExpr/*!*/> typeParams = new List<VCExpr/*!*/>(explicitTypeParamsSelect.Count);
+ foreach (TypeVariable tp in explicitTypeParamsSelect) {
+ VCExprVar tVar = Gen.Variable(tp.Name, AxBuilderPremisses.T);
+ bindings.TypeVariableBindings.Add(tp, tVar);
+ // ... and record these explicit type-parameter arguments in typeParams
+ typeParams.Add(tVar);
+ }
+
+ VCExpr/*!*/ storeExpr = Store(store, m, indexes, val);
+ Contract.Assert(storeExpr != null);
+ VCExpr/*!*/ selectExpr = Select(select, typeParams, storeExpr, indexes);
+ Contract.Assert(selectExpr != null);
+
+ // Create let-binding definitions for all type parameters.
+ // The implicit ones can be phrased in terms of the types of the ordinary in-parameters, and
+ // we want to make sure that they don't get phrased in terms of the out-parameter, so we pass
+ // in inParams here.
+ List<VCExprLetBinding/*!*/> letBindings_Implicit =
+ AxBuilderPremisses.GenTypeParamBindings(implicitTypeParamsSelect, inParams, bindings, false);
+ Contract.Assert(cce.NonNullElements(letBindings_Implicit));
+ // The explicit ones, by definition, can only be phrased in terms of the result, so we pass
+ // in List(typedVal) here.
+ List<VCExprLetBinding/*!*/> letBindings_Explicit =
+ AxBuilderPremisses.GenTypeParamBindings(explicitTypeParamsSelect, HelperFuns.ToList(typedVal), bindings, false);
+ Contract.Assert(cce.NonNullElements(letBindings_Explicit));
+
+ // generate: select(store(m, indices, val)) == val
+ VCExpr/*!*/ eq = Gen.Eq(selectExpr, val);
+ Contract.Assert(eq != null);
+ // generate: type(val) == T, where T is the type of val
+ VCExpr/*!*/ ante = Gen.Eq(
+ AxBuilderPremisses.TypeOf(val),
+ AxBuilderPremisses.Type2Term(mapResult, bindings.TypeVariableBindings));
+ Contract.Assert(ante != null);
+ VCExpr body;
+ if (CommandLineOptions.Clo.TypeEncodingMethod == CommandLineOptions.TypeEncoding.None ||
+ !AxBuilder.U.Equals(cce.NonNull(select.OutParams[0]).TypedIdent.Type)) {
+ body = Gen.Let(letBindings_Explicit, eq);
+ } else {
+ body = Gen.Let(letBindings_Implicit, Gen.Let(letBindings_Explicit, Gen.ImpliesSimp(ante, eq)));
+ }
+ return Gen.Forall(quantifiedVars, new List<VCTrigger/*!*/>(), "mapAx0:" + select.Name, 0, body);
+ }
+
+ private VCExpr GenMapAxiom1(Function select, Function store, Type mapResult, List<TypeVariable/*!*/>/*!*/ explicitSelectParams) {
+ Contract.Requires(mapResult != null);
+ Contract.Requires(store != null);
+ Contract.Requires(select != null);
+ Contract.Requires(cce.NonNullElements(explicitSelectParams));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ int arity = store.InParams.Count - 2;
+
+ List<Type/*!*/> indexTypes = new List<Type/*!*/>();
+ for (int i = 1; i < store.InParams.Count - 1; i++) {
+ indexTypes.Add(cce.NonNull(store.InParams[i]).TypedIdent.Type);
+ }
+ Contract.Assert(indexTypes.Count == arity);
+
+ List<VCExprVar/*!*/>/*!*/ indexes0 = HelperFuns.VarVector("x", indexTypes, Gen);
+ Contract.Assert(cce.NonNullElements(indexes0));
+ List<VCExprVar/*!*/>/*!*/ indexes1 = HelperFuns.VarVector("y", indexTypes, Gen);
+ Contract.Assert(cce.NonNullElements(indexes1));
+ VCExprVar/*!*/ m = Gen.Variable("m", AxBuilder.U);
+ Contract.Assert(m != null);
+ VCExprVar/*!*/ val = Gen.Variable("val", cce.NonNull(select.OutParams[0]).TypedIdent.Type);
+ Contract.Assert(val != null);
+
+ // extract the explicit type parameters from the actual result type ...
+ VCExprVar/*!*/ typedVal = Gen.Variable("val", mapResult);
+ Contract.Assert(typedVal != null);
+ VariableBindings/*!*/ bindings = new VariableBindings();
+ bindings.VCExprVarBindings.Add(typedVal, val);
+
+ List<VCExprLetBinding/*!*/>/*!*/ letBindings =
+ AxBuilderPremisses.GenTypeParamBindings(explicitSelectParams,
+ HelperFuns.ToList(typedVal),
+ bindings, true);
+ Contract.Assert(cce.NonNullElements(letBindings));
+
+ // ... and quantify the introduced term variables for type
+ // parameters universally
+ List<VCExprVar/*!*/>/*!*/ typeParams = new List<VCExprVar/*!*/>(explicitSelectParams.Count);
+ List<VCExpr/*!*/>/*!*/ typeParamsExpr = new List<VCExpr/*!*/>(explicitSelectParams.Count);
+ foreach (TypeVariable/*!*/ var in explicitSelectParams) {
+ Contract.Assert(var != null);
+ VCExprVar/*!*/ newVar = (VCExprVar)bindings.TypeVariableBindings[var];
+ Contract.Assert(newVar != null);
+ typeParams.Add(newVar);
+ typeParamsExpr.Add(newVar);
+ }
+
+ VCExpr/*!*/ storeExpr = Store(store, m, indexes0, val);
+ Contract.Assert(storeExpr != null);
+ VCExpr/*!*/ selectWithoutStoreExpr = Select(select, typeParamsExpr, m, indexes1);
+ Contract.Assert(selectWithoutStoreExpr != null);
+ VCExpr/*!*/ selectExpr = Select(select, typeParamsExpr, storeExpr, indexes1);
+ Contract.Assert(selectExpr != null);
+
+ VCExpr/*!*/ selectEq = Gen.Eq(selectExpr, selectWithoutStoreExpr);
+ Contract.Assert(selectEq != null);
+
+ List<VCExprVar/*!*/>/*!*/ quantifiedVars = new List<VCExprVar/*!*/>(indexes0.Count + indexes1.Count + 2);
+ quantifiedVars.Add(val);
+ quantifiedVars.Add(m);
+ quantifiedVars.AddRange(indexes0);
+ quantifiedVars.AddRange(indexes1);
+ quantifiedVars.AddRange(typeParams);
+
+ List<VCTrigger/*!*/>/*!*/ triggers = new List<VCTrigger/*!*/>();
+ Contract.Assert(cce.NonNullElements(triggers));
+
+ VCExpr/*!*/ axiom = VCExpressionGenerator.True;
+ Contract.Assert(axiom != null);
+
+ // first non-interference criterium: the queried location is
+ // different from the assigned location
+ for (int i = 0; i < arity; ++i) {
+ VCExpr/*!*/ indexesEq = Gen.Eq(indexes0[i], indexes1[i]);
+ VCExpr/*!*/ matrix = Gen.Or(indexesEq, selectEq);
+ VCExpr/*!*/ conjunct = Gen.Forall(quantifiedVars, triggers, "mapAx1:" + select.Name + ":" + i, 0, matrix);
+ Contract.Assert(indexesEq != null);
+ Contract.Assert(matrix != null);
+ Contract.Assert(conjunct != null);
+ axiom = Gen.AndSimp(axiom, conjunct);
+ }
+
+ // second non-interference criterion: the queried type is
+ // different from the assigned type
+ VCExpr/*!*/ typesEq = VCExpressionGenerator.True;
+ foreach (VCExprLetBinding/*!*/ b in letBindings) {
+ Contract.Assert(b != null);
+ typesEq = Gen.AndSimp(typesEq, Gen.Eq(b.V, b.E));
+ }
+ VCExpr/*!*/ matrix2 = Gen.Or(typesEq, selectEq);
+ VCExpr/*!*/ conjunct2 = Gen.Forall(quantifiedVars, triggers, "mapAx2:" + select.Name, 0, matrix2);
+ axiom = Gen.AndSimp(axiom, conjunct2);
+
+ return axiom;
+ }
+
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ public class TypeEraserPremisses : TypeEraser
+ {
+
+ private readonly TypeAxiomBuilderPremisses/*!*/ AxBuilderPremisses;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilderPremisses != null);
+ }
+
+
+ private OpTypeEraser OpEraserAttr = null;
+ protected override OpTypeEraser/*!*/ OpEraser {
+ get {
+ Contract.Ensures(Contract.Result<OpTypeEraser>() != null);
+
+ if (OpEraserAttr == null)
+ OpEraserAttr = new OpTypeEraserPremisses(this, AxBuilderPremisses, Gen);
+ return OpEraserAttr;
+ }
+ }
+
+ public TypeEraserPremisses(TypeAxiomBuilderPremisses axBuilder, VCExpressionGenerator gen)
+ : base(axBuilder, gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+
+ this.AxBuilderPremisses = axBuilder;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public override VCExpr Visit(VCExprQuantifier node, VariableBindings oldBindings) {
+ Contract.Requires(oldBindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VariableBindings bindings = oldBindings.Clone();
+
+ // determine the bound vars that actually occur in the body or
+ // in any of the triggers (if some variables do not occur, we
+ // need to take special care of type parameters that only occur
+ // in the types of such variables)
+ FreeVariableCollector coll = new FreeVariableCollector();
+ coll.Collect(node.Body);
+ foreach (VCTrigger trigger in node.Triggers) {
+ if (trigger.Pos)
+ foreach (VCExpr/*!*/ e in trigger.Exprs) {
+ Contract.Assert(e != null);
+
+ coll.Collect(e);
+ }
+ }
+
+ List<VCExprVar/*!*/> occurringVars = new List<VCExprVar/*!*/>(node.BoundVars.Count);
+ foreach (VCExprVar var in node.BoundVars)
+ if (coll.FreeTermVars.ContainsKey(var))
+ occurringVars.Add(var);
+
+ occurringVars.TrimExcess();
+
+ // bound term variables are replaced with bound term variables typed in
+ // a simpler way
+ List<VCExprVar/*!*/>/*!*/ newBoundVars =
+ BoundVarsAfterErasure(occurringVars, bindings);
+ Contract.Assert(cce.NonNullElements(newBoundVars));
+ VCExpr/*!*/ newNode = HandleQuantifier(node, occurringVars,
+ newBoundVars, bindings);
+ Contract.Assert(newNode != null);
+
+ if (!(newNode is VCExprQuantifier) || !IsUniversalQuantifier(node))
+ return newNode;
+
+ VariableBindings bindings2;
+ if (!RedoQuantifier(node, (VCExprQuantifier)newNode, occurringVars, oldBindings,
+ out bindings2, out newBoundVars))
+ return newNode;
+
+ return HandleQuantifier(node, occurringVars,
+ newBoundVars, bindings2);
+ }
+
+ private VCExpr/*!*/ GenTypePremisses(List<VCExprVar/*!*/>/*!*/ oldBoundVars,
+ List<VCExprVar/*!*/>/*!*/ newBoundVars,
+ IDictionary<TypeVariable/*!*/, VCExpr/*!*/>/*!*/
+ typeVarTranslation,
+ List<VCExprLetBinding/*!*/>/*!*/ typeVarBindings,
+ out List<VCTrigger/*!*/>/*!*/ triggers) {
+ Contract.Requires(cce.NonNullElements(oldBoundVars));
+ Contract.Requires(cce.NonNullElements(newBoundVars));
+ Contract.Requires(cce.NonNullDictionaryAndValues(typeVarTranslation));
+ Contract.Requires(cce.NonNullElements(typeVarBindings));
+ Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out triggers)));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ // build a substitution of the type variables that it can be checked
+ // whether type premisses are trivial
+ VCExprSubstitution/*!*/ typeParamSubstitution = new VCExprSubstitution();
+ foreach (VCExprLetBinding/*!*/ binding in typeVarBindings) {
+ Contract.Assert(binding != null);
+ typeParamSubstitution[binding.V] = binding.E;
+ }
+ SubstitutingVCExprVisitor/*!*/ substituter = new SubstitutingVCExprVisitor(Gen);
+ Contract.Assert(substituter != null);
+
+ List<VCExpr/*!*/>/*!*/ typePremisses = new List<VCExpr/*!*/>(newBoundVars.Count);
+ triggers = new List<VCTrigger/*!*/>(newBoundVars.Count);
+
+ for (int i = 0; i < newBoundVars.Count; ++i) {
+ VCExprVar/*!*/ oldVar = oldBoundVars[i];
+ Contract.Assert(oldVar != null);
+ VCExprVar/*!*/ newVar = newBoundVars[i];
+ Contract.Assert(newVar != null);
+
+ VCExpr/*!*/ typePremiss =
+ AxBuilderPremisses.GenVarTypeAxiom(newVar, oldVar.Type,
+ typeVarTranslation);
+ Contract.Assert(typePremiss != null);
+ if (!IsTriviallyTrue(substituter.Mutate(typePremiss,
+ typeParamSubstitution))) {
+ typePremisses.Add(typePremiss);
+ // generate a negative trigger for the variable occurrence
+ // in the type premiss
+ triggers.Add(Gen.Trigger(false,
+ HelperFuns.ToList(AxBuilderPremisses.TypeOf(newVar))));
+ }
+ }
+
+ typePremisses.TrimExcess();
+ triggers.TrimExcess();
+
+ return Gen.NAry(VCExpressionGenerator.AndOp, typePremisses);
+ }
+
+ // these optimisations should maybe be moved into a separate
+ // visitor (peep-hole optimisations)
+ private bool IsTriviallyTrue(VCExpr expr) {
+ Contract.Requires(expr != null);
+ if (expr.Equals(VCExpressionGenerator.True))
+ return true;
+
+ if (expr is VCExprNAry) {
+ VCExprNAry/*!*/ naryExpr = (VCExprNAry)expr;
+ Contract.Assert(naryExpr != null);
+ if (naryExpr.Op.Equals(VCExpressionGenerator.EqOp) &&
+ naryExpr[0].Equals(naryExpr[1]))
+ return true;
+ }
+
+ return false;
+ }
+
+ private VCExpr HandleQuantifier(VCExprQuantifier node, List<VCExprVar/*!*/>/*!*/ occurringVars/*!*/, List<VCExprVar/*!*/>/*!*/ newBoundVars, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Requires(cce.NonNullElements(occurringVars/*!*/));
+ Contract.Requires(cce.NonNullElements(newBoundVars));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<VCExprLetBinding/*!*/>/*!*/ typeVarBindings =
+ AxBuilderPremisses.GenTypeParamBindings(node.TypeParameters, occurringVars, bindings, true);
+ Contract.Assert(typeVarBindings != null);
+ // Check whether some of the type parameters could not be
+ // determined from the bound variable types. In this case, we
+ // quantify explicitly over these variables
+ if (typeVarBindings.Count < node.TypeParameters.Count) {
+ foreach (TypeVariable/*!*/ var in node.TypeParameters) {
+ Contract.Assert(var != null);
+ if (typeVarBindings.All(b => !b.V.Equals(var)))
+ newBoundVars.Add((VCExprVar)bindings.TypeVariableBindings[var]);
+ }
+ }
+
+ // the lists of old and new bound variables for which type
+ // antecedents are to be generated
+ List<VCExprVar/*!*/>/*!*/ varsWithTypeSpecs = new List<VCExprVar/*!*/>();
+ List<VCExprVar/*!*/>/*!*/ newVarsWithTypeSpecs = new List<VCExprVar/*!*/>();
+ if (!IsUniversalQuantifier(node) ||
+ CommandLineOptions.Clo.TypeEncodingMethod
+ == CommandLineOptions.TypeEncoding.Predicates) {
+ foreach (VCExprVar/*!*/ oldVar in occurringVars) {
+ Contract.Assert(oldVar != null);
+ varsWithTypeSpecs.Add(oldVar);
+ newVarsWithTypeSpecs.Add(bindings.VCExprVarBindings[oldVar]);
+ }
+ } // else, no type antecedents are created for any variables
+
+ List<VCTrigger/*!*/>/*!*/ furtherTriggers;
+ VCExpr/*!*/ typePremisses =
+ GenTypePremisses(varsWithTypeSpecs, newVarsWithTypeSpecs,
+ bindings.TypeVariableBindings,
+ typeVarBindings, out furtherTriggers);
+
+ Contract.Assert(cce.NonNullElements(furtherTriggers));
+ Contract.Assert(typePremisses != null);
+ List<VCTrigger/*!*/>/*!*/ newTriggers = MutateTriggers(node.Triggers, bindings);
+ Contract.Assert(cce.NonNullElements(newTriggers));
+ newTriggers.AddRange(furtherTriggers);
+ newTriggers = AddLets2Triggers(newTriggers, typeVarBindings);
+
+ VCExpr/*!*/ newBody = Mutate(node.Body, bindings);
+ Contract.Assert(newBody != null);
+
+ // assemble the new quantified formula
+
+ if (CommandLineOptions.Clo.TypeEncodingMethod
+ == CommandLineOptions.TypeEncoding.None) {
+ typePremisses = VCExpressionGenerator.True;
+ }
+
+ VCExpr/*!*/ bodyWithPremisses =
+ AxBuilderPremisses.AddTypePremisses(typeVarBindings, typePremisses,
+ node.Quan == Quantifier.ALL,
+ AxBuilder.Cast(newBody, Type.Bool));
+ Contract.Assert(bodyWithPremisses != null);
+ if (newBoundVars.Count == 0) // might happen that no bound variables are left
+ return bodyWithPremisses;
+
+ foreach (VCExprVar/*!*/ v in newBoundVars) {
+ Contract.Assert(v != null);
+ if (v.Type == AxBuilderPremisses.U) {
+ newTriggers.Add(Gen.Trigger(false, AxBuilderPremisses.Cast(v, Type.Int)));
+ newTriggers.Add(Gen.Trigger(false, AxBuilderPremisses.Cast(v, Type.Bool)));
+ }
+ }
+
+ return Gen.Quantify(node.Quan, new List<TypeVariable/*!*/>(), newBoundVars,
+ newTriggers, node.Infos, bodyWithPremisses);
+ }
+
+ // check whether we need to add let-binders for any of the type
+ // parameters to the triggers (otherwise, the triggers will
+ // contain unbound/dangling variables for such parameters)
+ private List<VCTrigger/*!*/>/*!*/ AddLets2Triggers(List<VCTrigger/*!*/>/*!*/ triggers/*!*/, List<VCExprLetBinding/*!*/>/*!*/ typeVarBindings) {
+ Contract.Requires(cce.NonNullElements(triggers/*!*/));
+ Contract.Requires(cce.NonNullElements(typeVarBindings));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCTrigger>>()));
+ List<VCTrigger/*!*/>/*!*/ triggersWithLets = new List<VCTrigger/*!*/>(triggers.Count);
+
+ foreach (VCTrigger/*!*/ t in triggers) {
+ Contract.Assert(t != null);
+ List<VCExpr/*!*/>/*!*/ exprsWithLets = new List<VCExpr/*!*/>(t.Exprs.Count);
+
+ bool changed = false;
+ foreach (VCExpr/*!*/ e in t.Exprs) {
+ Contract.Assert(e != null);
+ Dictionary<VCExprVar/*!*/, object>/*!*/ freeVars =
+ FreeVariableCollector.FreeTermVariables(e);
+ Contract.Assert(freeVars != null && cce.NonNullElements(freeVars.Keys));
+ if (typeVarBindings.Any(b => freeVars.ContainsKey(b.V))) {
+ exprsWithLets.Add(Gen.Let(typeVarBindings, e));
+ changed = true;
+ } else {
+ exprsWithLets.Add(e);
+ }
+ }
+
+ if (changed)
+ triggersWithLets.Add(Gen.Trigger(t.Pos, exprsWithLets));
+ else
+ triggersWithLets.Add(t);
+ }
+
+ return triggersWithLets;
+ }
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class OpTypeEraserPremisses : OpTypeEraser
+ {
+
+ private TypeAxiomBuilderPremisses/*!*/ AxBuilderPremisses;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(AxBuilderPremisses != null);
+ }
+
+
+ public OpTypeEraserPremisses(TypeEraserPremisses eraser, TypeAxiomBuilderPremisses axBuilder, VCExpressionGenerator gen)
+ : base(eraser, axBuilder, gen) {
+ Contract.Requires(gen != null);
+ Contract.Requires(axBuilder != null);
+ Contract.Requires(eraser != null);
+ this.AxBuilderPremisses = axBuilder;
+ }
+
+ private VCExpr HandleFunctionOp(Function newFun, List<Type/*!*/>/*!*/ typeArgs/*!*/, IEnumerable<VCExpr/*!*/>/*!*/ oldArgs, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(newFun != null);
+ Contract.Requires(cce.NonNullElements(typeArgs/*!*/));
+ Contract.Requires(cce.NonNullElements(oldArgs));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // UGLY: the code for tracking polarities should be factored out
+ int oldPolarity = Eraser.Polarity;
+ Eraser.Polarity = 0;
+
+ List<VCExpr/*!*/>/*!*/ newArgs = new List<VCExpr/*!*/>(typeArgs.Count);
+
+ // translate the explicit type arguments
+ foreach (Type/*!*/ t in typeArgs) {
+ Contract.Assert(t != null);
+ newArgs.Add(AxBuilder.Type2Term(t, bindings.TypeVariableBindings));
+ }
+
+ // recursively translate the value arguments
+ foreach (VCExpr/*!*/ arg in oldArgs) {
+ Contract.Assert(arg != null);
+ Type/*!*/ newType = cce.NonNull(newFun.InParams[newArgs.Count]).TypedIdent.Type;
+ newArgs.Add(AxBuilder.Cast(Eraser.Mutate(arg, bindings), newType));
+ }
+
+ Eraser.Polarity = oldPolarity;
+ return Gen.Function(newFun, newArgs);
+ }
+
+ public override VCExpr/*!*/ VisitSelectOp(VCExprNAry/*!*/ node,
+ VariableBindings/*!*/ bindings) {
+ Contract.Requires(node != null); Contract.Requires(bindings != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ MapType/*!*/ mapType = node[0].Type.AsMap;
+ Contract.Assert(mapType != null);
+ List<Type>/*!*/ instantiations; // not used
+ Function/*!*/ select =
+ AxBuilder.MapTypeAbstracter.Select(mapType, out instantiations);
+ Contract.Assert(select != null);
+
+ List<int>/*!*/ explicitTypeParams =
+ AxBuilderPremisses.MapTypeAbstracterPremisses
+ .ExplicitSelectTypeParams(mapType);
+ Contract.Assert(select.InParams.Count == explicitTypeParams.Count + node.Arity);
+
+ List<Type/*!*/>/*!*/ typeArgs = new List<Type/*!*/>(explicitTypeParams.Count);
+ foreach (int i in explicitTypeParams)
+ typeArgs.Add(node.TypeArguments[i]);
+ return HandleFunctionOp(select, typeArgs, node, bindings);
+ }
+
+ public override VCExpr VisitStoreOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ List<Type>/*!*/ instantiations; // not used
+ Function/*!*/ store =
+ AxBuilder.MapTypeAbstracter.Store(node[0].Type.AsMap, out instantiations);
+ Contract.Assert(store != null);
+ return HandleFunctionOp(store,
+ // the store function never has explicit
+ // type parameters
+ new List<Type/*!*/>(),
+ node, bindings);
+ }
+
+ public override VCExpr VisitBoogieFunctionOp(VCExprNAry node, VariableBindings bindings) {
+ Contract.Requires(bindings != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ Function/*!*/ oriFun = ((VCExprBoogieFunctionOp)node.Op).Func;
+ Contract.Assert(oriFun != null);
+ UntypedFunction untypedFun = AxBuilderPremisses.Typed2Untyped(oriFun);
+ Contract.Assert(untypedFun.Fun.InParams.Count ==
+ untypedFun.ExplicitTypeParams.Count + node.Arity);
+
+ List<Type/*!*/>/*!*/ typeArgs =
+ ExtractTypeArgs(node,
+ oriFun.TypeParameters, untypedFun.ExplicitTypeParams);
+ return HandleFunctionOp(untypedFun.Fun, typeArgs, node, bindings);
+ }
+
+ private List<Type/*!*/>/*!*/ ExtractTypeArgs(VCExprNAry node, List<TypeVariable> allTypeParams, List<TypeVariable/*!*/>/*!*/ explicitTypeParams) {
+ Contract.Requires(allTypeParams != null);
+ Contract.Requires(node != null);
+ Contract.Requires(cce.NonNullElements(explicitTypeParams));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
+ List<Type/*!*/>/*!*/ res = new List<Type/*!*/>(explicitTypeParams.Count);
+ foreach (TypeVariable/*!*/ var in explicitTypeParams) {
+ Contract.Assert(var != null);
+ // this lookup could be optimised
+ res.Add(node.TypeArguments[allTypeParams.IndexOf(var)]);
+ }
+ return res;
+ }
+ }
+
+
+}
diff --git a/Source/VCExpr/VCExpr.csproj b/Source/VCExpr/VCExpr.csproj
index acacb4d1..1ad99bc1 100644
--- a/Source/VCExpr/VCExpr.csproj
+++ b/Source/VCExpr/VCExpr.csproj
@@ -1,223 +1,223 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>VCExpr</RootNamespace>
- <AssemblyName>VCExpr</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly>
- </CodeContractsCustomRewriterAssembly>
- <CodeContractsCustomRewriterClass>
- </CodeContractsCustomRewriterClass>
- <CodeContractsLibPaths>
- </CodeContractsLibPaths>
- <CodeContractsExtraRewriteOptions>
- </CodeContractsExtraRewriteOptions>
- <CodeContractsExtraAnalysisOptions>
- </CodeContractsExtraAnalysisOptions>
- <CodeContractsBaseLineFile>
- </CodeContractsBaseLineFile>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for VCExpr.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\VCExpr.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- <WarningLevel>4</WarningLevel>
- <Optimize>false</Optimize>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\QED\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="..\version.cs">
- <Link>version.cs</Link>
- </Compile>
- <Compile Include="BigLiteralAbstracter.cs" />
- <Compile Include="Boogie2VCExpr.cs" />
- <Compile Include="Clustering.cs" />
- <Compile Include="LetBindingSorter.cs" />
- <Compile Include="NameClashResolver.cs" />
- <Compile Include="SimplifyLikeLineariser.cs" />
- <Compile Include="TermFormulaFlattening.cs" />
- <Compile Include="TypeErasure.cs" />
- <Compile Include="TypeErasureArguments.cs" />
- <Compile Include="TypeErasurePremisses.cs" />
- <Compile Include="VCExprAST.cs" />
- <Compile Include="VCExprASTPrinter.cs" />
- <Compile Include="VCExprASTVisitors.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>VCExpr</RootNamespace>
+ <AssemblyName>VCExpr</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <TargetFrameworkProfile Condition=" '$(OS)' == 'Windows_NT'" >Client</TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly>
+ </CodeContractsCustomRewriterAssembly>
+ <CodeContractsCustomRewriterClass>
+ </CodeContractsCustomRewriterClass>
+ <CodeContractsLibPaths>
+ </CodeContractsLibPaths>
+ <CodeContractsExtraRewriteOptions>
+ </CodeContractsExtraRewriteOptions>
+ <CodeContractsExtraAnalysisOptions>
+ </CodeContractsExtraAnalysisOptions>
+ <CodeContractsBaseLineFile>
+ </CodeContractsBaseLineFile>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\z3apidebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisRuleAssemblies>
+ </CodeAnalysisRuleAssemblies>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>Migrated rules for VCExpr.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Checked\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\VCExpr.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly />
+ <CodeContractsCustomRewriterClass />
+ <CodeContractsLibPaths />
+ <CodeContractsExtraRewriteOptions />
+ <CodeContractsExtraAnalysisOptions />
+ <CodeContractsBaseLineFile />
+ <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QED|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\QED\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\version.cs">
+ <Link>version.cs</Link>
+ </Compile>
+ <Compile Include="BigLiteralAbstracter.cs" />
+ <Compile Include="Boogie2VCExpr.cs" />
+ <Compile Include="Clustering.cs" />
+ <Compile Include="LetBindingSorter.cs" />
+ <Compile Include="NameClashResolver.cs" />
+ <Compile Include="SimplifyLikeLineariser.cs" />
+ <Compile Include="TermFormulaFlattening.cs" />
+ <Compile Include="TypeErasure.cs" />
+ <Compile Include="TypeErasureArguments.cs" />
+ <Compile Include="TypeErasurePremisses.cs" />
+ <Compile Include="VCExprAST.cs" />
+ <Compile Include="VCExprASTPrinter.cs" />
+ <Compile Include="VCExprASTVisitors.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Basetypes\Basetypes.csproj">
+ <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
+ <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
+ <Name>CodeContractsExtender</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Core\Core.csproj">
+ <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
+ <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
+ <Name>ParserHelper</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Properties\" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/Source/VCExpr/VCExprAST.cs b/Source/VCExpr/VCExprAST.cs
index 15573f5b..0a9ba6b3 100644
--- a/Source/VCExpr/VCExprAST.cs
+++ b/Source/VCExpr/VCExprAST.cs
@@ -1,2130 +1,2130 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-
-// Prover-independent syntax trees for representing verification conditions
-// The language can be seen as a simple polymorphically typed first-order logic,
-// very similar to the expression language of Boogie
-
-namespace Microsoft.Boogie {
- using Microsoft.Boogie.VCExprAST;
-
- public class VCExpressionGenerator {
- public static readonly VCExpr False = new VCExprLiteral(Type.Bool);
- public static readonly VCExpr True = new VCExprLiteral(Type.Bool);
-
- private Function ControlFlowFunction = null;
- public VCExpr ControlFlowFunctionApplication(VCExpr e1, VCExpr e2) {
- Contract.Requires(e1 != null);
- Contract.Requires(e2 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- if (ControlFlowFunction == null) {
- Formal/*!*/ first = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Int), true);
- Formal/*!*/ second = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Int), true);
- List<Variable> inputs = new List<Variable>();
- inputs.Add(first);
- inputs.Add(second);
- Formal/*!*/ returnVar = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Int), false);
- ControlFlowFunction = new Function(Token.NoToken, "ControlFlow", inputs, returnVar);
- }
- List<VCExpr/*!*/> args = new List<VCExpr/*!*/>();
- args.Add(e1);
- args.Add(e2);
- return Function(BoogieFunctionOp(ControlFlowFunction), args);
- }
-
- public VCExpr/*!*/ Integer(BigNum x) {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return new VCExprIntLit(x);
- }
-
- public VCExpr/*!*/ Real(BigDec x) {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return new VCExprRealLit(x);
- }
-
- public VCExpr/*!*/ Function(VCExprOp/*!*/ op,
- List<VCExpr/*!*/>/*!*/ arguments,
- List<Type/*!*/>/*!*/ typeArguments) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(arguments));
- Contract.Requires(cce.NonNullElements(typeArguments));
- if (typeArguments.Count > 0)
- return new VCExprMultiAry(op, arguments, typeArguments);
-
- switch (arguments.Count) {
- case 0:
- return new VCExprNullary(op);
- case 1:
- return new VCExprUnary(op, arguments);
- case 2:
- return new VCExprBinary(op, arguments);
- default:
- return new VCExprMultiAry(op, arguments);
- }
- }
-
- public VCExpr/*!*/ Function(VCExprOp/*!*/ op, List<VCExpr/*!*/>/*!*/ arguments) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(arguments));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return Function(op, arguments, VCExprNAry.EMPTY_TYPE_LIST);
- }
-
- public VCExpr/*!*/ Function(VCExprOp/*!*/ op, params VCExpr[]/*!*/ arguments) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(arguments));
-
- return Function(op,
- HelperFuns.ToNonNullList(arguments),
- VCExprNAry.EMPTY_TYPE_LIST);
- }
-
- public VCExpr/*!*/ Function(VCExprOp/*!*/ op, VCExpr[]/*!*/ arguments, Type[]/*!*/ typeArguments) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(arguments));
- Contract.Requires(cce.NonNullElements(typeArguments));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
-
- return Function(op,
- HelperFuns.ToNonNullList(arguments),
- HelperFuns.ToNonNullList(typeArguments));
- }
-
- public VCExpr/*!*/ Function(Function/*!*/ op, List<VCExpr/*!*/>/*!*/ arguments) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(arguments));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return Function(BoogieFunctionOp(op), arguments, VCExprNAry.EMPTY_TYPE_LIST);
- }
-
- public VCExpr/*!*/ Function(Function/*!*/ op, params VCExpr[]/*!*/ arguments) {
- Contract.Requires(cce.NonNullElements(arguments));
- Contract.Requires(op != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return Function(BoogieFunctionOp(op), arguments);
- }
-
-
- // The following method should really be called "ReduceLeft". It must
- // only be used for the binary operators "and" and "or"
- public VCExpr/*!*/ NAry(VCExprOp/*!*/ op, List<VCExpr/*!*/>/*!*/ args) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return NAry(op, args.ToArray());
- }
-
- public VCExpr/*!*/ NAry(VCExprOp/*!*/ op, params VCExpr[]/*!*/ args) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(args));
- Contract.Requires(op == AndOp || op == OrOp);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- bool and = (op == AndOp);
-
- VCExpr/*!*/ e = and ? True : False;
- foreach (VCExpr a in args) {
- e = and ? AndSimp(e, cce.NonNull(a)) : OrSimp(e, cce.NonNull(a));
- }
- return e;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
- public static readonly VCExprOp NotOp = new VCExprNAryOp(1, Type.Bool);
- public static readonly VCExprOp EqOp = new VCExprNAryOp(2, Type.Bool);
- public static readonly VCExprOp NeqOp = new VCExprNAryOp(2, Type.Bool);
- public static readonly VCExprOp AndOp = new VCExprNAryOp(2, Type.Bool);
- public static readonly VCExprOp OrOp = new VCExprNAryOp(2, Type.Bool);
- public static readonly VCExprOp ImpliesOp = new VCExprNAryOp(2, Type.Bool);
-
- public VCExprDistinctOp DistinctOp(int arity) {
- Contract.Ensures(Contract.Result<VCExprDistinctOp>() != null);
-
- return new VCExprDistinctOp(arity);
- }
-
- public VCExpr/*!*/ Not(List<VCExpr/*!*/>/*!*/ args) {
- Contract.Requires(args != null);
- Contract.Requires(args.Count == 1);
- Contract.Requires(args[0] != null);
- return Function(NotOp, args);
- }
-
- public VCExpr/*!*/ Not(VCExpr/*!*/ e0) {
- Contract.Requires(e0 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return Function(NotOp, e0);
- }
- public VCExpr/*!*/ Eq(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
- return Function(EqOp, e0, e1);
- }
- public VCExpr/*!*/ Neq(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
- Contract.Requires(e0 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return Function(NeqOp, e0, e1);
- }
- public VCExpr/*!*/ And(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
- Contract.Requires(e0 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(AndOp, e0, e1);
- }
- public VCExpr/*!*/ Gt(VCExpr/*!*/ e0, VCExpr/*!*/ e1)
- {
- Contract.Requires(e0 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- return Function(GtOp, e0, e1);
- }
- public VCExpr/*!*/ Add(VCExpr/*!*/ e0, VCExpr/*!*/ e1)
- {
- Contract.Requires(e0 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- VCExprOp op = cce.NonNull(cce.NonNull(e0).Type).IsInt ? AddIOp : AddROp;
- return Function(op, e0, e1);
- }
- public VCExpr/*!*/ Or(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
- Contract.Requires(e0 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(OrOp, e0, e1);
- }
- public VCExpr/*!*/ Implies(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
- Contract.Requires(e0 != null);
- Contract.Requires(e1 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(ImpliesOp, e0, e1);
- }
- public VCExpr/*!*/ Distinct(List<VCExpr/*!*/>/*!*/ args) {
- Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- if (args.Count <= 1)
- // trivial case
- return True;
- return Function(DistinctOp(args.Count), args);
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // Versions of the propositional operators that automatically simplify in
- // certain cases (for example, if one of the operators is True or False)
-
- public VCExpr NotSimp(VCExpr e0) {
- Contract.Requires(e0 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (e0.Equals(True))
- return False;
- if (e0.Equals(False))
- return True;
- return Not(e0);
- }
- public VCExpr AndSimp(VCExpr e0, VCExpr e1) {
- Contract.Requires(e1 != null);
- Contract.Requires(e0 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (e0.Equals(True))
- return e1;
- if (e1.Equals(True))
- return e0;
- if (e0.Equals(False) || e1.Equals(False))
- return False;
- return And(e0, e1);
- }
- public VCExpr OrSimp(VCExpr e0, VCExpr e1) {
- Contract.Requires(e1 != null);
- Contract.Requires(e0 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (e0.Equals(False))
- return e1;
- if (e1.Equals(False))
- return e0;
- if (e0.Equals(True) || e1.Equals(True))
- return True;
- return Or(e0, e1);
- }
- public VCExpr ImpliesSimp(VCExpr e0, VCExpr e1, bool aggressive = true) {
- Contract.Requires(e1 != null);
- Contract.Requires(e0 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (e0.Equals(True))
- return e1;
- if (e1.Equals(False))
- return NotSimp(e0);
- if (e0.Equals(False) || e1.Equals(True))
- return True;
- // attempt to save on the depth of expressions (to reduce chances of stack overflows)
- while (aggressive && e1 is VCExprBinary) {
- VCExprBinary n = (VCExprBinary)e1;
- if (n.Op == ImpliesOp) {
- if (AndSize(n[0]) <= AndSize(e0)) {
- // combine the antecedents
- e0 = And(e0, n[0]);
- e1 = n[1];
- continue;
- }
- }
- break;
- }
- return Implies(e0, e1);
- }
-
- ///<summary>
- /// Returns some measure of the number of conjuncts in e. This could be the total number of conjuncts in all
- /// top-most layers of the expression, or it can simply be the length of the left-prong of this and-tree. The
- /// important thing is that: AndSize(e0) >= AndSize(31) ==> AndSize(And(e0,e1)) > AndSize(e0).
- ///</summary>
- int AndSize(VCExpr e) {
- Contract.Requires(e != null);
- int n = 1;
- while (true) {
- VCExprNAry nary = e as VCExprNAry;
- if (nary != null && nary.Op == AndOp && 2 <= nary.Arity) {
- e = nary[0];
- n++;
- } else {
- return n;
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // Further operators
-
- public static readonly VCExprOp AddIOp = new VCExprNAryOp(2, Type.Int);
- public static readonly VCExprOp AddROp = new VCExprNAryOp(2, Type.Real);
- public static readonly VCExprOp SubIOp = new VCExprNAryOp(2, Type.Int);
- public static readonly VCExprOp SubROp = new VCExprNAryOp(2, Type.Real);
- public static readonly VCExprOp MulIOp = new VCExprNAryOp(2, Type.Int);
- public static readonly VCExprOp MulROp = new VCExprNAryOp(2, Type.Real);
- public static readonly VCExprOp DivIOp = new VCExprNAryOp(2, Type.Int);
- public static readonly VCExprOp DivROp = new VCExprNAryOp(2, Type.Real);
- public static readonly VCExprOp ModOp = new VCExprNAryOp(2, Type.Int);
- public static readonly VCExprOp PowOp = new VCExprNAryOp(2, Type.Real);
- public static readonly VCExprOp LtOp = new VCExprNAryOp(2, Type.Bool);
- public static readonly VCExprOp LeOp = new VCExprNAryOp(2, Type.Bool);
- public static readonly VCExprOp GtOp = new VCExprNAryOp(2, Type.Bool);
- public static readonly VCExprOp GeOp = new VCExprNAryOp(2, Type.Bool);
- public static readonly VCExprOp SubtypeOp = new VCExprNAryOp(2, Type.Bool);
- // ternary version of the subtype operator, the first argument of which gives
- // the type of the compared terms
- public static readonly VCExprOp Subtype3Op = new VCExprNAryOp(3, Type.Bool);
- public static readonly VCExprOp IfThenElseOp = new VCExprIfThenElseOp();
- public static readonly VCExprOp ToIntOp = new VCExprNAryOp(1, Type.Int);
- public static readonly VCExprOp ToRealOp = new VCExprNAryOp(1, Type.Real);
-
- public static readonly VCExprOp TickleBoolOp = new VCExprCustomOp("tickleBool", 1, Type.Bool);
-
- public static readonly VCExprOp TimeoutDiagnosticsOp = new VCExprCustomOp("timeoutDiagnostics", 1, Type.Bool);
-
- public VCExprOp BoogieFunctionOp(Function func) {
- Contract.Requires(func != null);
- Contract.Ensures(Contract.Result<VCExprOp>() != null);
- return new VCExprBoogieFunctionOp(func);
- }
-
- // Bitvector nodes
-
- public VCExpr Bitvector(BvConst bv) {
- Contract.Requires(bv != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprBvOp(bv.Bits), Integer(bv.Value));
- }
-
- public VCExpr BvExtract(VCExpr bv, int bits, int start, int end) {
- Contract.Requires(bv != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprBvExtractOp(start, end, bits), bv);
- }
-
- public VCExpr BvConcat(VCExpr bv1, VCExpr bv2) {
- Contract.Requires(bv2 != null);
- Contract.Requires(bv1 != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprBvConcatOp(bv1.Type.BvBits, bv2.Type.BvBits), bv1, bv2);
- }
-
- public VCExpr AtMost(VCExpr smaller, VCExpr greater) {
- Contract.Requires(greater != null);
- Contract.Requires(smaller != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(SubtypeOp, smaller, greater);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- // Dispatcher for the visitor
-
- // the declared singleton operators
- internal enum SingletonOp {
- NotOp,
- EqOp,
- NeqOp,
- AndOp,
- OrOp,
- ImpliesOp,
- AddOp,
- SubOp,
- MulOp,
- DivOp,
- ModOp,
- RealDivOp,
- PowOp,
- LtOp,
- LeOp,
- GtOp,
- GeOp,
- SubtypeOp,
- Subtype3Op,
- BvConcatOp,
- ToIntOp,
- ToRealOp
- };
- internal static Dictionary<VCExprOp/*!*/, SingletonOp>/*!*/ SingletonOpDict;
- [ContractInvariantMethod]
- void MiscInvariant() {
- Contract.Invariant(SingletonOpDict != null);
- }
-
-
- static VCExpressionGenerator() {
- SingletonOpDict = new Dictionary<VCExprOp/*!*/, SingletonOp>();
- SingletonOpDict.Add(NotOp, SingletonOp.NotOp);
- SingletonOpDict.Add(EqOp, SingletonOp.EqOp);
- SingletonOpDict.Add(NeqOp, SingletonOp.NeqOp);
- SingletonOpDict.Add(AndOp, SingletonOp.AndOp);
- SingletonOpDict.Add(OrOp, SingletonOp.OrOp);
- SingletonOpDict.Add(ImpliesOp, SingletonOp.ImpliesOp);
- SingletonOpDict.Add(AddIOp, SingletonOp.AddOp);
- SingletonOpDict.Add(AddROp, SingletonOp.AddOp);
- SingletonOpDict.Add(SubIOp, SingletonOp.SubOp);
- SingletonOpDict.Add(SubROp, SingletonOp.SubOp);
- SingletonOpDict.Add(MulIOp, SingletonOp.MulOp);
- SingletonOpDict.Add(MulROp, SingletonOp.MulOp);
- SingletonOpDict.Add(DivIOp, SingletonOp.DivOp);
- SingletonOpDict.Add(DivROp, SingletonOp.RealDivOp);
- SingletonOpDict.Add(ModOp, SingletonOp.ModOp);
- SingletonOpDict.Add(PowOp, SingletonOp.PowOp);
- SingletonOpDict.Add(LtOp, SingletonOp.LtOp);
- SingletonOpDict.Add(LeOp, SingletonOp.LeOp);
- SingletonOpDict.Add(GtOp, SingletonOp.GtOp);
- SingletonOpDict.Add(GeOp, SingletonOp.GeOp);
- SingletonOpDict.Add(SubtypeOp, SingletonOp.SubtypeOp);
- SingletonOpDict.Add(Subtype3Op, SingletonOp.Subtype3Op);
- SingletonOpDict.Add(ToIntOp, SingletonOp.ToIntOp);
- SingletonOpDict.Add(ToRealOp, SingletonOp.ToRealOp);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-
-
- // Let-bindings
-
- public VCExprLetBinding LetBinding(VCExprVar v, VCExpr e) {
- Contract.Requires(e != null);
- Contract.Requires(v != null);
- Contract.Ensures(Contract.Result<VCExprLetBinding>() != null);
- return new VCExprLetBinding(v, e);
- }
-
- // A "real" let expression. All let-bindings happen simultaneously, i.e.,
- // at this level the order of the bindings does not matter. It is possible to
- // create expressions like "let x = y, y = 5 in ...". All bound variables are
- // bound in all bound terms/formulas and can occur there, but the dependencies
- // have to be acyclic
- public VCExpr Let(List<VCExprLetBinding> bindings, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(cce.NonNullElements(bindings));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (bindings.Count == 0)
- // no empty let-bindings
- return body;
- return new VCExprLet(bindings, body);
- }
-
- public VCExpr Let(VCExpr body, params VCExprLetBinding[] bindings) {
- Contract.Requires(body != null);
- Contract.Requires((cce.NonNullElements(bindings)));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Let(HelperFuns.ToNonNullList(bindings), body);
- }
-
-
- /// <summary>
- /// In contrast to the previous method, the following methods are not a general LET.
- /// Instead, it
- /// is a boolean "LET b = P in Q", where P and Q are predicates, that is allowed to be
- /// encoded as "(b == P) ==> Q" or even as "(P ==> b) ==> Q"
- /// (or "(P ==> b) and Q" in negative positions).
- /// The method assumes that the variables in the bindings are unique in the entire formula
- /// to be produced, which allows the implementation to ignore scope issues in the event that
- /// it needs to generate an alternate expression for LET.
- /// </summary>
-
-
- // Turn let-bindings let v = E in ... into implications E ==> v
- public VCExpr AsImplications(List<VCExprLetBinding> bindings) {
- Contract.Requires(cce.NonNullElements(bindings));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr/*!*/ antecedents = True;
- foreach (VCExprLetBinding b in bindings)
- // turn "LET_binding v = E" into "v <== E"
- antecedents = AndSimp(antecedents, Implies(b.E, b.V));
- return antecedents;
- }
-
- // Turn let-bindings let v = E in ... into equations v == E
- public VCExpr AsEquations(List<VCExprLetBinding> bindings) {
- Contract.Requires(cce.NonNullElements(bindings));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr/*!*/ antecedents = True;
- foreach (VCExprLetBinding b in bindings)
- // turn "LET_binding v = E" into "v <== E"
- antecedents = AndSimp(antecedents, Eq(b.E, b.V));
- return antecedents;
- }
-
-
-
- // Maps
-
- public VCExpr Select(params VCExpr[] allArgs) {
- Contract.Requires(allArgs != null);
- Contract.Requires((cce.NonNullElements(allArgs)));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprSelectOp(allArgs.Length - 1, 0),
- HelperFuns.ToNonNullList(allArgs),
- VCExprNAry.EMPTY_TYPE_LIST);
- }
-
- public VCExpr Select(VCExpr[] allArgs, Type[] typeArgs) {
- Contract.Requires(1 <= allArgs.Length);
- Contract.Requires(cce.NonNullElements(allArgs));
- Contract.Requires(cce.NonNullElements(typeArgs));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprSelectOp(allArgs.Length - 1, typeArgs.Length),
- allArgs, typeArgs);
- }
-
- public VCExpr Select(List<VCExpr> allArgs, List<Type> typeArgs) {
- Contract.Requires(cce.NonNullElements(typeArgs));
- Contract.Requires(cce.NonNullElements(allArgs));
- Contract.Requires((1 <= allArgs.Count));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprSelectOp(allArgs.Count - 1, typeArgs.Count),
- allArgs, typeArgs);
- }
-
- public VCExpr Store(params VCExpr[] allArgs) {
- Contract.Requires(allArgs != null);
- Contract.Requires(cce.NonNullElements(allArgs));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprStoreOp(allArgs.Length - 2, 0),
- HelperFuns.ToNonNullList(allArgs),
- VCExprNAry.EMPTY_TYPE_LIST);
- }
-
- public VCExpr Store(VCExpr[] allArgs, Type[] typeArgs) {
- Contract.Requires(typeArgs != null);
- Contract.Requires(allArgs != null);
- Contract.Requires((2 <= allArgs.Length));
- Contract.Requires(cce.NonNullElements(allArgs));
- Contract.Requires(cce.NonNullElements(typeArgs));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprStoreOp(allArgs.Length - 2, typeArgs.Length),
- allArgs, typeArgs);
- }
-
- public VCExpr Store(List<VCExpr> allArgs, List<Type/*!*/>/*!*/ typeArgs) {
- Contract.Requires(cce.NonNullElements(typeArgs));
- Contract.Requires(cce.NonNullElements(allArgs));
- Contract.Requires((2 <= allArgs.Count));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(new VCExprStoreOp(allArgs.Count - 2, typeArgs.Count),
- allArgs, typeArgs);
- }
-
-
- // Labels
-
- public VCExprLabelOp LabelOp(bool pos, string l) {
- Contract.Requires(l != null);
- Contract.Ensures(Contract.Result<VCExprLabelOp>() != null);
- return new VCExprLabelOp(pos, l);
- }
-
- public VCExpr LabelNeg(string label, VCExpr e) {
- Contract.Requires(e != null);
- Contract.Requires(label != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- if (e.Equals(True)) {
- return e; // don't bother putting negative labels around True (which will expose the True to further peephole optimizations)
- }
- return Function(LabelOp(false, label), e);
- }
- public VCExpr LabelPos(string label, VCExpr e) {
- Contract.Requires(e != null);
- Contract.Requires(label != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Function(LabelOp(true, label), e);
- }
-
- // Quantifiers
-
- public VCExpr Quantify(Quantifier quan, List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCQuantifierInfos infos, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(infos != null);
- Contract.Requires(cce.NonNullElements(triggers));
- Contract.Requires(cce.NonNullElements(vars));
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return new VCExprQuantifier(quan, typeParams, vars, triggers, infos, body);
- }
-
- public VCExpr Forall(List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCQuantifierInfos infos, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(infos != null);
- Contract.Requires(cce.NonNullElements(triggers));
- Contract.Requires(cce.NonNullElements(vars));
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Quantify(Quantifier.ALL, typeParams, vars, triggers, infos, body);
- }
- public VCExpr Forall(List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, string qid, int weight, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(qid != null);
- Contract.Requires(cce.NonNullElements(triggers));
- Contract.Requires(cce.NonNullElements(vars));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- QKeyValue kv = null;
- if (0 <= weight) {
- kv = new QKeyValue(Token.NoToken, "weight", new List<object>() { new LiteralExpr(Token.NoToken, BigNum.FromInt(0)) }, null);
- }
- return Quantify(Quantifier.ALL, new List<TypeVariable/*!*/>(), vars,
- triggers, new VCQuantifierInfos(qid, -1, false, kv), body);
- }
- public VCExpr Forall(List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(cce.NonNullElements(triggers));
- Contract.Requires(cce.NonNullElements(vars));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Quantify(Quantifier.ALL, new List<TypeVariable/*!*/>(), vars,
- triggers, new VCQuantifierInfos(null, -1, false, null), body);
- }
- public VCExpr Forall(VCExprVar var, VCTrigger trigger, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(trigger != null);
- Contract.Requires(var != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Forall(HelperFuns.ToNonNullList(var), HelperFuns.ToNonNullList(trigger), body);
- }
- public VCExpr Exists(List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCQuantifierInfos infos, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(infos != null);
- Contract.Requires(cce.NonNullElements(triggers));
- Contract.Requires(cce.NonNullElements(vars));
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Quantify(Quantifier.EX, typeParams, vars, triggers, infos, body);
- }
- public VCExpr Exists(List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(cce.NonNullElements(triggers));
- Contract.Requires(cce.NonNullElements(vars));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Quantify(Quantifier.EX, new List<TypeVariable/*!*/>(), vars,
- triggers, new VCQuantifierInfos(null, -1, false, null), body);
- }
- public VCExpr Exists(VCExprVar var, VCTrigger trigger, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(trigger != null);
- Contract.Requires(var != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return Exists(HelperFuns.ToNonNullList(var), HelperFuns.ToNonNullList(trigger), body);
- }
-
- public VCTrigger Trigger(bool pos, List<VCExpr> exprs) {
- Contract.Requires(cce.NonNullElements(exprs));
- Contract.Ensures(Contract.Result<VCTrigger>() != null);
- return new VCTrigger(pos, exprs);
- }
-
- public VCTrigger Trigger(bool pos, params VCExpr[] exprs) {
- Contract.Requires(exprs != null);
- Contract.Requires((Contract.ForAll(0, exprs.Length, i => exprs[i] != null)));
- Contract.Ensures(Contract.Result<VCTrigger>() != null);
- return Trigger(pos, HelperFuns.ToNonNullList(exprs));
- }
-
- // Reference to a bound or free variable
-
- public VCExprVar Variable(string name, Type type) {
- Contract.Requires(type != null);
- Contract.Requires(name != null);
- Contract.Ensures(Contract.Result<VCExprVar>() != null);
- return new VCExprVar(name, type);
- }
- }
-}
-
-namespace Microsoft.Boogie.VCExprAST {
-
- public class HelperFuns {
- public static bool SameElements(IEnumerable a, IEnumerable b) {
- Contract.Requires(b != null);
- Contract.Requires(a != null);
- IEnumerator ia = a.GetEnumerator();
- IEnumerator ib = b.GetEnumerator();
- while (true) {
- if (ia.MoveNext()) {
- if (ib.MoveNext()) {
- if (!cce.NonNull(ia.Current).Equals(ib.Current))
- return false;
- } else {
- return false;
- }
- } else {
- return !ib.MoveNext();
- }
- }
- }
-
- public static int PolyHash(int init, int factor, IEnumerable a) {
- Contract.Requires(a != null);
- int res = init;
- foreach (object x in a)
- res = res * factor + (cce.NonNull(x)).GetHashCode();
- return res;
- }
-
- public static List<T> ToList<T>(IEnumerable<T> l) {
- Contract.Requires(l != null);
- Contract.Ensures(Contract.Result<List<T>>() != null);
- List<T>/*!*/ res = new List<T>();
- foreach (T x in l)
- res.Add(x);
- return res;
- }
-
- public static List<Type> ToTypeSeq(VCExpr[] exprs, int startIndex) {
- Contract.Requires(exprs != null);
- Contract.Requires((Contract.ForAll(0, exprs.Length, i => exprs[i] != null)));
- Contract.Ensures(Contract.Result<List<Type>>() != null);
- List<Type>/*!*/ res = new List<Type>();
- for (int i = startIndex; i < exprs.Length; ++i)
- res.Add(cce.NonNull(exprs[i]).Type);
- return res;
- }
-
- public static List<T/*!*/>/*!*/ ToNonNullList<T>(params T[] args) where T : class {
- Contract.Requires(args != null);
- List<T/*!*/>/*!*/ res = new List<T>(args.Length);
- foreach (T t in args)
- res.Add(cce.NonNull(t));
- return res;
- }
-
- public static IDictionary<A, B> Clone<A, B>(IDictionary<A, B> dict) {
- Contract.Requires(dict != null);
- Contract.Ensures(Contract.Result<IDictionary<A, B>>() != null);
- IDictionary<A, B> res = new Dictionary<A, B>(dict.Count);
- foreach (KeyValuePair<A, B> pair in dict)
- res.Add(pair);
- return res;
- }
- }
-
- [ContractClassFor(typeof(VCExpr))]
- public abstract class VCExprContracts : VCExpr {
- public override Type Type {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
- throw new NotImplementedException();
- }
-
- }
- public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
- Contract.Requires(visitor != null);
- throw new NotImplementedException();
- }
- }
-
- [ContractClass(typeof(VCExprContracts))]
- public abstract class VCExpr {
- public abstract Type Type {
- get;
- }
-
- public abstract Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg);
-
- [Pure]
- public override string ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- StringWriter sw = new StringWriter();
- VCExprPrinter printer = new VCExprPrinter();
- printer.Print(this, sw);
- return cce.NonNull(sw.ToString());
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // Literal expressions
-
- public class VCExprLiteral : VCExpr {
- private readonly Type LitType;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(LitType != null);
- }
-
- public override Type Type {
- get {
- return LitType;
- }
- }
- internal VCExprLiteral(Type type) {
- Contract.Requires(type != null);
- this.LitType = type;
- }
- public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this, arg);
- }
- }
-
- public class VCExprIntLit : VCExprLiteral {
- public readonly BigNum Val;
- internal VCExprIntLit(BigNum val)
- : base(Type.Int) {
- this.Val = val;
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprIntLit)
- return Val == ((VCExprIntLit)that).Val;
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Val.GetHashCode() * 72321;
- }
- }
-
- public class VCExprRealLit : VCExprLiteral {
- public readonly BigDec Val;
- internal VCExprRealLit(BigDec val)
- : base(Type.Real) {
- this.Val = val;
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprRealLit)
- return Val == ((VCExprRealLit)that).Val;
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Val.GetHashCode() * 72321;
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // Operator expressions with fixed arity
- [ContractClassFor(typeof(VCExprNAry))]
- public abstract class VCExprNAryContracts : VCExprNAry {
- public VCExprNAryContracts()
- : base(null) {
- }
- public override VCExpr this[int index] {
- get {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- throw new NotImplementedException();
- }
- }
- }
-
- [ContractClass(typeof(VCExprNAryContracts))]
- public abstract class VCExprNAry : VCExpr, IEnumerable<VCExpr/*!*/> {
- public readonly VCExprOp Op;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Op != null);
- Contract.Invariant(cce.NonNullElements(EMPTY_TYPE_LIST));
- Contract.Invariant(cce.NonNullElements(EMPTY_VCEXPR_LIST));
- }
-
- public int Arity {
- get {
- return Op.Arity;
- }
- }
- public int TypeParamArity {
- get {
- return Op.TypeParamArity;
- }
- }
- public int Length {
- get {
- return Arity;
- }
- }
- // the sub-expressions of the expression
- public abstract VCExpr/*!*/ this[int index] {
- get;
- }
-
- // the type arguments
- public abstract List<Type/*!*/>/*!*/ TypeArguments {
- get;
- }
-
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- public IEnumerator<VCExpr/*!*/>/*!*/ GetEnumerator() {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerator<VCExpr>>()));
- for (int i = 0; i < Arity; ++i)
- yield return this[i];
- }
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- IEnumerator System.Collections.IEnumerable.GetEnumerator() {
- Contract.Ensures(Contract.Result<IEnumerator>() != null);
- for (int i = 0; i < Arity; ++i)
- yield return this[i];
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprNAry) {
- // we compare the subterms iteratively (not recursively)
- // to avoid stack overflows
-
- VCExprNAryEnumerator enum0 = new VCExprNAryEnumerator(this);
- VCExprNAryEnumerator enum1 = new VCExprNAryEnumerator((VCExprNAry)that);
-
- while (true) {
- bool next0 = enum0.MoveNext();
- bool next1 = enum1.MoveNext();
- if (next0 != next1)
- return false;
- if (!next0)
- return true;
-
- VCExprNAry nextExprNAry0 = enum0.Current as VCExprNAry;
- VCExprNAry nextExprNAry1 = enum1.Current as VCExprNAry;
-
- if ((nextExprNAry0 == null) != (nextExprNAry1 == null))
- return false;
- if (nextExprNAry0 != null && nextExprNAry1 != null) {
- if (!nextExprNAry0.Op.Equals(nextExprNAry1.Op))
- return false;
- } else {
- if (!cce.NonNull(enum0.Current).Equals(enum1.Current))
- return false;
- }
- }
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return HelperFuns.PolyHash(Op.GetHashCode() * 123 + Arity * 61521,
- 3, this);
- }
-
- internal VCExprNAry(VCExprOp op) {
- Contract.Requires(op != null);
- this.Op = op;
- }
- public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this, arg);
- }
- public Result Accept<Result, Arg>(IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- Contract.Requires(visitor != null);
- return Op.Accept(this, visitor, arg);
- }
-
- internal static readonly List<Type/*!*/>/*!*/ EMPTY_TYPE_LIST = new List<Type/*!*/>();
- internal static readonly List<VCExpr/*!*/>/*!*/ EMPTY_VCEXPR_LIST = new List<VCExpr/*!*/>();
-
- public IEnumerable<VCExpr> UniformArguments
- {
- get
- {
- var enumerator = new VCExprNAryUniformOpEnumerator(this);
- while (enumerator.MoveNext()) {
- VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
- if (naryExpr == null || !naryExpr.Op.Equals(this.Op)) {
- yield return (VCExpr)enumerator.Current;
- }
- }
- }
- }
- }
-
- // We give specialised implementations for nullary, unary and binary expressions
-
- internal class VCExprNullary : VCExprNAry {
- private readonly Type ExprType;
- [ContractInvariantMethod]
- void loneinvariant() {
- Contract.Invariant(ExprType != null);
- }
-
- public override Type Type {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
- return ExprType;
- }
- }
- public override VCExpr this[int index] {
- get {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- Contract.Assert(false);
- throw new cce.UnreachableException(); // no arguments
- }
- }
-
- // the type arguments
- public override List<Type/*!*/>/*!*/ TypeArguments {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
- return EMPTY_TYPE_LIST;
- }
- }
-
- internal VCExprNullary(VCExprOp op)
- : base(op) {
- Contract.Requires(op != null);
- Contract.Requires(op.Arity == 0 && op.TypeParamArity == 0);
- this.ExprType = op.InferType(EMPTY_VCEXPR_LIST, EMPTY_TYPE_LIST);
- }
- }
-
- internal class VCExprUnary : VCExprNAry {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Argument != null);
- Contract.Invariant(ExprType != null);
-
- }
-
- private readonly VCExpr/*!*/ Argument;
- private readonly Type/*!*/ ExprType;
- public override Type/*!*/ Type {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
- return ExprType;
- }
- }
- public override VCExpr/*!*/ this[int index] {
- get {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- Contract.Assume(index == 0);
- return Argument;
- }
- }
-
- // the type arguments
- public override List<Type/*!*/>/*!*/ TypeArguments {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
- return EMPTY_TYPE_LIST;
- }
- }
-
- internal VCExprUnary(VCExprOp op, List<VCExpr> arguments)
- : base(op) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(arguments));
- Contract.Requires(op.Arity == 1 && op.TypeParamArity == 0 && arguments.Count == 1);
-
- this.Argument = arguments[0];
- this.ExprType =
- op.InferType(arguments, EMPTY_TYPE_LIST);
- }
-
- internal VCExprUnary(VCExprOp op, VCExpr argument)
- : base(op) {
- Contract.Requires(argument != null);
- Contract.Requires(op != null);
- Contract.Requires(op.Arity == 1 && op.TypeParamArity == 0);
-
- this.Argument = argument;
- // PR: could be optimised so that the argument does
- // not have to be boxed in an array each time
- this.ExprType =
- op.InferType(HelperFuns.ToNonNullList(argument), EMPTY_TYPE_LIST);
- }
- }
-
- internal class VCExprBinary : VCExprNAry {
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Argument0 != null);
- Contract.Invariant(Argument1 != null);
- Contract.Invariant(ExprType != null);
- }
-
- private readonly VCExpr Argument0;
- private readonly VCExpr Argument1;
- private readonly Type ExprType;
- public override Type Type {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
- return ExprType;
- }
- }
- public override VCExpr this[int index] {
- get {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- switch (index) {
- case 0:
- return Argument0;
- case 1:
- return Argument1;
- default: {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
- }
- }
-
- // the type arguments
- public override List<Type/*!*/>/*!*/ TypeArguments {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
- return EMPTY_TYPE_LIST;
- }
- }
-
- internal VCExprBinary(VCExprOp op, List<VCExpr> arguments)
- : base(op) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(arguments));
- Contract.Requires(op.Arity == 2 && op.TypeParamArity == 0 && arguments.Count == 2);
-
- this.Argument0 = arguments[0];
- this.Argument1 = arguments[1];
- this.ExprType = op.InferType(arguments, EMPTY_TYPE_LIST);
- }
-
- internal VCExprBinary(VCExprOp op, VCExpr argument0, VCExpr argument1)
- : base(op) {
- Contract.Requires(argument1 != null);
- Contract.Requires(argument0 != null);
- Contract.Requires(op != null);
- Contract.Requires(op.Arity == 2 && op.TypeParamArity == 0);
- this.Argument0 = argument0;
- this.Argument1 = argument1;
- // PR: could be optimised so that the arguments do
- // not have to be boxed in an array each time
- this.ExprType =
- op.InferType(HelperFuns.ToNonNullList(argument0, argument1),
- EMPTY_TYPE_LIST);
- }
- }
-
- internal class VCExprMultiAry : VCExprNAry {
- private readonly List<VCExpr/*!*/>/*!*/ Arguments;
- private readonly List<Type/*!*/>/*!*/ TypeArgumentsAttr;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(Arguments));
- Contract.Invariant(cce.NonNullElements(TypeArgumentsAttr));
- Contract.Invariant(ExprType != null);
- }
-
-
- private readonly Type/*!*/ ExprType;
- public override Type/*!*/ Type {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
- return ExprType;
- }
- }
- public override VCExpr/*!*/ this[int index] {
- get {
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- Contract.Assume(index >= 0 && index < Arity);
- return cce.NonNull(Arguments)[index];
- }
- }
-
- // the type arguments
- public override List<Type/*!*/>/*!*/ TypeArguments {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
- return TypeArgumentsAttr;
- }
- }
-
- internal VCExprMultiAry(VCExprOp op, List<VCExpr> arguments)
- : base(op) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(arguments));
- this.Arguments = arguments;
- this.TypeArgumentsAttr = EMPTY_TYPE_LIST;
- this.ExprType = op.InferType(arguments, TypeArgumentsAttr);
- }
- internal VCExprMultiAry(VCExprOp op, List<VCExpr> arguments, List<Type/*!*/>/*!*/ typeArguments)
- : base(op) {
- Contract.Requires(op != null);
- Contract.Requires(cce.NonNullElements(typeArguments));
- Contract.Requires(cce.NonNullElements(arguments));
- Contract.Requires(arguments.Count > 2 || typeArguments.Count > 0);
- Contract.Requires(op.Arity == arguments.Count);
- Contract.Requires(op.TypeParamArity == typeArguments.Count);
- this.Arguments = arguments;
- this.TypeArgumentsAttr = typeArguments;
- this.ExprType = op.InferType(arguments, typeArguments);
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // The various operators available
- [ContractClass(typeof(VCExprOpContracts))]
- public abstract class VCExprOp {
- // the number of value parameters
- public abstract int Arity {
- get;
- }
- // the number of type parameters
- public abstract int TypeParamArity {
- get;
- }
-
- public abstract Type/*!*/ InferType(List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs);
-
- public virtual Result Accept<Result, Arg>(VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- Contract.Requires(visitor != null);
- Contract.Requires(expr != null);
- VCExpressionGenerator.SingletonOp op;
- if (VCExpressionGenerator.SingletonOpDict.TryGetValue(this, out op)) {
- switch (op) {
- case VCExpressionGenerator.SingletonOp.NotOp:
- return visitor.VisitNotOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.EqOp:
- return visitor.VisitEqOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.NeqOp:
- return visitor.VisitNeqOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.AndOp:
- return visitor.VisitAndOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.OrOp:
- return visitor.VisitOrOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.ImpliesOp:
- return visitor.VisitImpliesOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.AddOp:
- return visitor.VisitAddOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.SubOp:
- return visitor.VisitSubOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.MulOp:
- return visitor.VisitMulOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.DivOp:
- return visitor.VisitDivOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.ModOp:
- return visitor.VisitModOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.RealDivOp:
- return visitor.VisitRealDivOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.PowOp:
- return visitor.VisitPowOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.LtOp:
- return visitor.VisitLtOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.LeOp:
- return visitor.VisitLeOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.GtOp:
- return visitor.VisitGtOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.GeOp:
- return visitor.VisitGeOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.SubtypeOp:
- return visitor.VisitSubtypeOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.Subtype3Op:
- return visitor.VisitSubtype3Op(expr, arg);
- case VCExpressionGenerator.SingletonOp.BvConcatOp:
- return visitor.VisitBvConcatOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.ToIntOp:
- return visitor.VisitToIntOp(expr, arg);
- case VCExpressionGenerator.SingletonOp.ToRealOp:
- return visitor.VisitToRealOp(expr, arg);
- default:
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- } else {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- }
- }
- [ContractClassFor(typeof(VCExprOp))]
- abstract class VCExprOpContracts : VCExprOp {
- public override Type InferType(List<VCExpr> args, List<Type> typeArgs) {
- Contract.Requires(cce.NonNullElements(args));
- Contract.Requires(cce.NonNullElements(typeArgs));
- Contract.Ensures(Contract.Result<Type>() != null);
-
- throw new NotImplementedException();
- }
- }
-
- public class VCExprNAryOp : VCExprOp {
- private readonly Type OpType;
- private readonly int OpArity;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(OpType != null);
- }
-
- public override int Arity {
- get {
- return OpArity;
- }
- }
- public override int TypeParamArity {
- get {
- return 0;
- }
- }
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- return OpType;
- }
-
- internal VCExprNAryOp(int arity, Type type) {
- Contract.Requires(type != null);
- this.OpArity = arity;
- this.OpType = type;
- }
- }
-
- public class VCExprDistinctOp : VCExprNAryOp {
- internal VCExprDistinctOp(int arity)
- : base(arity, Type.Bool) {
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprDistinctOp)
- return Arity == ((VCExprDistinctOp)that).Arity;
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Arity * 917632481;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitDistinctOp(expr, arg);
- }
- }
-
- public class VCExprLabelOp : VCExprOp {
- public override int Arity {
- get {
- return 1;
- }
- }
- public override int TypeParamArity {
- get {
- return 0;
- }
- }
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- return args[0].Type;
- }
-
- public readonly bool pos;
- public readonly string label;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(label != null);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprLabelOp) {
- VCExprLabelOp/*!*/ thatOp = (VCExprLabelOp)that;
- return this.pos == thatOp.pos && this.label.Equals(thatOp.label);
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return (pos ? 9817231 : 7198639) + label.GetHashCode();
- }
-
- internal VCExprLabelOp(bool pos, string l) {
- Contract.Requires(l != null);
- this.pos = pos;
- this.label = pos ? "+" + l : "@" + l;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitLabelOp(expr, arg);
- }
- }
-
- public class VCExprSelectOp : VCExprOp {
- private readonly int MapArity;
- private readonly int MapTypeParamArity;
- public override int Arity {
- get {
- return MapArity + 1;
- }
- }
- public override int TypeParamArity {
- get {
- return MapTypeParamArity;
- }
- }
-
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- MapType/*!*/ mapType = args[0].Type.AsMap;
- Contract.Assert(TypeParamArity == mapType.TypeParameters.Count);
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
- for (int i = 0; i < TypeParamArity; ++i)
- subst.Add(mapType.TypeParameters[i], typeArgs[i]);
- return mapType.Result.Substitute(subst);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprSelectOp)
- return Arity == ((VCExprSelectOp)that).Arity &&
- TypeParamArity == ((VCExprSelectOp)that).TypeParamArity;
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Arity * 1212481 + TypeParamArity * 298741;
- }
-
- internal VCExprSelectOp(int arity, int typeParamArity) {
- Contract.Requires(0 <= arity && 0 <= typeParamArity);
- this.MapArity = arity;
- this.MapTypeParamArity = typeParamArity;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitSelectOp(expr, arg);
- }
- }
-
- public class VCExprStoreOp : VCExprOp {
- private readonly int MapArity;
- private readonly int MapTypeParamArity;
- public override int Arity {
- get {
- return MapArity + 2;
- }
- }
- // stores never need explicit type parameters, because also the
- // rhs is a value argument
- public override int TypeParamArity {
- get {
- return MapTypeParamArity;
- }
- }
-
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- return args[0].Type;
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprStoreOp)
- return Arity == ((VCExprStoreOp)that).Arity;
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Arity * 91361821;
- }
-
- internal VCExprStoreOp(int arity, int typeParamArity) {
- Contract.Requires(0 <= arity && 0 <= typeParamArity);
- this.MapArity = arity;
- this.MapTypeParamArity = typeParamArity;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitStoreOp(expr, arg);
- }
- }
-
- public class VCExprIfThenElseOp : VCExprOp {
- public override int Arity {
- get {
- return 3;
- }
- }
- public override int TypeParamArity {
- get {
- return 0;
- }
- }
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- return args[1].Type;
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprIfThenElseOp)
- return true;
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return 1;
- }
-
- internal VCExprIfThenElseOp() {
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitIfThenElseOp(expr, arg);
- }
- }
-
- public class VCExprCustomOp : VCExprOp {
- public readonly string/*!*/ Name;
- int arity;
- public readonly Type/*!*/ Type;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Name != null);
- Contract.Invariant(Type != null);
- }
-
- public VCExprCustomOp(string/*!*/ name, int arity, Type/*!*/ type) {
- Contract.Requires(name != null);
- Contract.Requires(type != null);
- this.Name = name;
- this.arity = arity;
- this.Type = type;
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- VCExprCustomOp t = that as VCExprCustomOp;
- if (t == null)
- return false;
- return this.Name == t.Name && this.arity == t.arity && this.Type == t.Type;
- }
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override int GetHashCode() {
- int h = Name.GetHashCode();
- h = 7823 * h + arity;
- h = 7823 * h + Type.GetHashCode();
- return h;
- }
- public override int Arity {
- get {
- return arity;
- }
- }
- public override int TypeParamArity {
- get {
- return 0;
- }
- }
- public override Type/*!*/ InferType(List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires((cce.NonNullElements(args)));
- //Contract.Requires((cce.NonNullElements(typeArgs)));
- Contract.Ensures(Contract.Result<Type>() != null);
- return Type;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry/*!*/ expr, IVCExprOpVisitor<Result, Arg>/*!*/ visitor, Arg arg) {
- //Contract.Requires(expr != null);
- //Contract.Requires(visitor != null);
- return visitor.VisitCustomOp(expr, arg);
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // Bitvector operators
-
- public class VCExprBvOp : VCExprOp {
- public readonly int Bits;
-
- public override int Arity {
- get {
- return 1;
- }
- }
- public override int TypeParamArity {
- get {
- return 0;
- }
- }
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- return Type.GetBvType(Bits);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprBvOp)
- return this.Bits == ((VCExprBvOp)that).Bits;
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Bits * 81748912;
- }
-
- internal VCExprBvOp(int bits) {
- this.Bits = bits;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitBvOp(expr, arg);
- }
- }
-
- public class VCExprBvExtractOp : VCExprOp {
- public readonly int Start;
- public readonly int End;
- public readonly int Total; // the number of bits from which the End-Start bits are extracted
-
- public override int Arity {
- get {
- return 1;
- }
- }
- public override int TypeParamArity {
- get {
- return 0;
- }
- }
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- return Type.GetBvType(End - Start);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprBvExtractOp) {
- VCExprBvExtractOp/*!*/ thatExtract = (VCExprBvExtractOp)that;
- return this.Start == thatExtract.Start && this.End == thatExtract.End && this.Total == thatExtract.Total;
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Start * 81912 + End * 978132 + Total * 571289;
- }
-
- internal VCExprBvExtractOp(int start, int end, int total) {
- Contract.Requires(0 <= start && start <= end && end <= total);
- this.Start = start;
- this.End = end;
- this.Total = total;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitBvExtractOp(expr, arg);
- }
- }
-
- public class VCExprBvConcatOp : VCExprOp {
- public readonly int LeftSize;
- public readonly int RightSize;
-
- public override int Arity {
- get {
- return 2;
- }
- }
- public override int TypeParamArity {
- get {
- return 0;
- }
- }
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- return Type.GetBvType(args[0].Type.BvBits + args[1].Type.BvBits);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprBvConcatOp) {
- VCExprBvConcatOp thatConcat = (VCExprBvConcatOp)that;
- return this.LeftSize == thatConcat.LeftSize && this.RightSize == thatConcat.RightSize;
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return LeftSize * 81912 + RightSize * 978132;
- }
-
- internal VCExprBvConcatOp(int leftSize, int rightSize) {
- Contract.Requires(0 <= leftSize && 0 <= rightSize);
- this.LeftSize = leftSize;
- this.RightSize = rightSize;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitBvConcatOp(expr, arg);
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // References to user-defined Boogie functions
-
- public class VCExprBoogieFunctionOp : VCExprOp {
- public readonly Function Func;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Func != null);
- }
-
-
- public override int Arity {
- get {
- return Func.InParams.Count;
- }
- }
- public override int TypeParamArity {
- get {
- return Func.TypeParameters.Count;
- }
- }
- public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
- //Contract.Requires(cce.NonNullElements(typeArgs));
- //Contract.Requires(cce.NonNullElements(args));
- Contract.Ensures(Contract.Result<Type>() != null);
- Contract.Assert(TypeParamArity == Func.TypeParameters.Count);
- if (TypeParamArity == 0)
- return cce.NonNull(Func.OutParams[0]).TypedIdent.Type;
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst = new Dictionary<TypeVariable/*!*/, Type/*!*/>(TypeParamArity);
- for (int i = 0; i < TypeParamArity; ++i)
- subst.Add(Func.TypeParameters[i], typeArgs[i]);
- return cce.NonNull(Func.OutParams[0]).TypedIdent.Type.Substitute(subst);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprBoogieFunctionOp)
- return this.Func.Equals(((VCExprBoogieFunctionOp)that).Func);
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Func.GetHashCode() + 18731;
- }
-
- // we require that the result type of the expression is specified, because we
- // do not want to perform full type inference at this point
- internal VCExprBoogieFunctionOp(Function func) {
- Contract.Requires(func != null);
- this.Func = func;
- }
- public override Result Accept<Result, Arg>
- (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- //Contract.Requires(expr != null);
- return visitor.VisitBoogieFunctionOp(expr, arg);
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // Binders (quantifiers and let-expressions). We introduce our own class for
- // term variables, but use the Boogie-AST class for type variables
-
- public class VCExprVar : VCExpr {
- // the name of the variable. Note that the name is not used for comparison,
- // i.e., there can be two distinct variables with the same name
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Name != null);
- Contract.Invariant(VarType != null);
- }
-
- public readonly string/*!*/ Name;
- private readonly Type/*!*/ VarType;
- public override Type/*!*/ Type {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
- return VarType;
- }
- }
-
- internal VCExprVar(string name, Type type) {
- Contract.Requires(type != null);
- Contract.Requires(name != null);
- this.Name = name;
- this.VarType = type;
- }
- public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this, arg);
- }
- }
-
- public class VCExprConstant : VCExprVar
- {
- internal VCExprConstant(string name, Type type) : base(name,type) {
- Contract.Requires(type != null);
- Contract.Requires(name != null);
- }
- }
-
- public abstract class VCExprBinder : VCExpr {
- public readonly VCExpr/*!*/ Body;
- public readonly List<TypeVariable/*!*/>/*!*/ TypeParameters;
- public readonly List<VCExprVar/*!*/>/*!*/ BoundVars;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Body != null);
- Contract.Invariant(cce.NonNullElements(TypeParameters));
- Contract.Invariant(cce.NonNullElements(BoundVars));
- }
-
-
- public override Type/*!*/ Type {
- get {
- Contract.Ensures(Contract.Result<Type>() != null);
-
- return Body.Type;
- }
- }
-
- internal VCExprBinder(List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ boundVars, VCExpr body) {
- Contract.Requires(body != null);
- Contract.Requires(cce.NonNullElements(boundVars));
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Requires(boundVars.Count + typeParams.Count > 0); // only nontrivial binders ...
- this.TypeParameters = typeParams;
- this.BoundVars = boundVars;
- this.Body = body;
- }
- }
-
- public class VCTrigger {
- public readonly bool Pos;
- public readonly List<VCExpr/*!*/>/*!*/ Exprs;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Exprs != null);
- }
-
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCTrigger) {
- VCTrigger/*!*/ thatTrigger = (VCTrigger)that;
- return this.Pos == thatTrigger.Pos &&
- HelperFuns.SameElements(this.Exprs, thatTrigger.Exprs);
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return (Pos ? 913821 : 871334) +
- HelperFuns.PolyHash(123, 7, this.Exprs);
- }
-
- public VCTrigger(bool pos, List<VCExpr> exprs) {
- Contract.Requires(cce.NonNullElements(exprs));
- this.Pos = pos;
- this.Exprs = exprs;
- }
- }
-
- public class VCQuantifierInfos {
- public readonly string qid;
- public readonly int uniqueId;
- public readonly bool bvZ3Native;
- public QKeyValue attributes;
-
- public VCQuantifierInfos(string qid, int uniqueId, bool bvZ3Native, QKeyValue attributes) {
- this.qid = qid;
- this.uniqueId = uniqueId;
- this.bvZ3Native = bvZ3Native;
- this.attributes = attributes;
- }
- }
-
- public enum Quantifier {
- ALL,
- EX
- };
-
- public class VCExprQuantifier : VCExprBinder {
- public readonly Quantifier Quan;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Infos != null);
- Contract.Invariant(cce.NonNullElements(Triggers));
- }
-
-
- public readonly List<VCTrigger/*!*/>/*!*/ Triggers;
- public readonly VCQuantifierInfos Infos;
-
- // Equality is /not/ modulo bound renaming at this point
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprQuantifier) {
- VCExprQuantifier/*!*/ thatQuan = (VCExprQuantifier)that;
- return this.Quan == thatQuan.Quan &&
- HelperFuns.SameElements(this.Triggers, thatQuan.Triggers) &&
- HelperFuns.SameElements(this.TypeParameters, thatQuan.TypeParameters) &&
- HelperFuns.SameElements(this.BoundVars, thatQuan.BoundVars) &&
- this.Body.Equals(thatQuan.Body);
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return Quan.GetHashCode() +
- HelperFuns.PolyHash(973219, 7, TypeParameters) +
- HelperFuns.PolyHash(998431, 9, BoundVars) +
- HelperFuns.PolyHash(123, 11, Triggers);
- }
-
- internal VCExprQuantifier(Quantifier kind, List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ boundVars, List<VCTrigger/*!*/>/*!*/ triggers, VCQuantifierInfos infos, VCExpr body)
- : base(typeParams, boundVars, body) {
- Contract.Requires(body != null);
- Contract.Requires(infos != null);
- Contract.Requires(cce.NonNullElements(triggers));
- Contract.Requires(cce.NonNullElements(boundVars));
- Contract.Requires(cce.NonNullElements(typeParams));
-
- this.Quan = kind;
- this.Triggers = triggers;
- this.Infos = infos;
- }
- public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this, arg);
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
- // Let-Bindings
-
- public class VCExprLetBinding {
- public readonly VCExprVar V;
- public readonly VCExpr E;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(V != null);
- Contract.Invariant(E != null);
- }
-
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprLetBinding) {
- VCExprLetBinding/*!*/ thatB = (VCExprLetBinding)that;
- return this.V.Equals(thatB.V) && this.E.Equals(thatB.E);
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return V.GetHashCode() * 71261 + E.GetHashCode();
- }
-
- internal VCExprLetBinding(VCExprVar v, VCExpr e) {
- Contract.Requires(e != null);
- Contract.Requires(v != null);
- this.V = v;
- this.E = e;
- Contract.Assert(v.Type.Equals(e.Type));
- }
- }
-
- public class VCExprLet : VCExprBinder, IEnumerable<VCExprLetBinding/*!*/> {
- private readonly List<VCExprLetBinding/*!*/>/*!*/ Bindings;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(cce.NonNullElements(Bindings));
-
- }
-
-
- public int Length {
- get {
- return Bindings.Count;
- }
- }
- public VCExprLetBinding this[int index] {
- get {
- Contract.Ensures(Contract.Result<VCExprLetBinding>() != null);
- return Bindings[index];
- }
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- if (Object.ReferenceEquals(this, that))
- return true;
- if (that is VCExprLet) {
- VCExprLet/*!*/ thatLet = (VCExprLet)that;
- return this.Body.Equals(thatLet.Body) &&
- HelperFuns.SameElements(this, (VCExprLet)that);
- }
- return false;
- }
- [Pure]
- public override int GetHashCode() {
- return HelperFuns.PolyHash(Body.GetHashCode(), 9, Bindings);
- }
-
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- public IEnumerator<VCExprLetBinding/*!*/>/*!*/ GetEnumerator() {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerator<VCExprLetBinding>>()));
- return Bindings.GetEnumerator();
- }
- [Pure]
- [GlobalAccess(false)]
- [Escapes(true, false)]
- IEnumerator System.Collections.IEnumerable.GetEnumerator() {
- Contract.Ensures(Contract.Result<IEnumerator>() != null);
- return Bindings.GetEnumerator();
- }
-
- private static List<VCExprVar/*!*/>/*!*/ toSeq(List<VCExprLetBinding/*!*/>/*!*/ bindings) {
- Contract.Requires(cce.NonNullElements(bindings));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
- List<VCExprVar> res = new List<VCExprVar>();
- foreach (VCExprLetBinding/*!*/ b in bindings)
- res.Add(b.V);
- return res;
- }
-
- internal VCExprLet(List<VCExprLetBinding/*!*/>/*!*/ bindings, VCExpr/*!*/ body)
- : base(new List<TypeVariable/*!*/>(), toSeq(bindings), body) {
- Contract.Requires(cce.NonNullElements(bindings));
- Contract.Requires(body != null);
- this.Bindings = bindings;
- }
- public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
- //Contract.Requires(visitor != null);
- return visitor.Visit(this, arg);
- }
- }
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+
+// Prover-independent syntax trees for representing verification conditions
+// The language can be seen as a simple polymorphically typed first-order logic,
+// very similar to the expression language of Boogie
+
+namespace Microsoft.Boogie {
+ using Microsoft.Boogie.VCExprAST;
+
+ public class VCExpressionGenerator {
+ public static readonly VCExpr False = new VCExprLiteral(Type.Bool);
+ public static readonly VCExpr True = new VCExprLiteral(Type.Bool);
+
+ private Function ControlFlowFunction = null;
+ public VCExpr ControlFlowFunctionApplication(VCExpr e1, VCExpr e2) {
+ Contract.Requires(e1 != null);
+ Contract.Requires(e2 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ if (ControlFlowFunction == null) {
+ Formal/*!*/ first = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Int), true);
+ Formal/*!*/ second = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Int), true);
+ List<Variable> inputs = new List<Variable>();
+ inputs.Add(first);
+ inputs.Add(second);
+ Formal/*!*/ returnVar = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Int), false);
+ ControlFlowFunction = new Function(Token.NoToken, "ControlFlow", inputs, returnVar);
+ }
+ List<VCExpr/*!*/> args = new List<VCExpr/*!*/>();
+ args.Add(e1);
+ args.Add(e2);
+ return Function(BoogieFunctionOp(ControlFlowFunction), args);
+ }
+
+ public VCExpr/*!*/ Integer(BigNum x) {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return new VCExprIntLit(x);
+ }
+
+ public VCExpr/*!*/ Real(BigDec x) {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return new VCExprRealLit(x);
+ }
+
+ public VCExpr/*!*/ Function(VCExprOp/*!*/ op,
+ List<VCExpr/*!*/>/*!*/ arguments,
+ List<Type/*!*/>/*!*/ typeArguments) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(arguments));
+ Contract.Requires(cce.NonNullElements(typeArguments));
+ if (typeArguments.Count > 0)
+ return new VCExprMultiAry(op, arguments, typeArguments);
+
+ switch (arguments.Count) {
+ case 0:
+ return new VCExprNullary(op);
+ case 1:
+ return new VCExprUnary(op, arguments);
+ case 2:
+ return new VCExprBinary(op, arguments);
+ default:
+ return new VCExprMultiAry(op, arguments);
+ }
+ }
+
+ public VCExpr/*!*/ Function(VCExprOp/*!*/ op, List<VCExpr/*!*/>/*!*/ arguments) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(arguments));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return Function(op, arguments, VCExprNAry.EMPTY_TYPE_LIST);
+ }
+
+ public VCExpr/*!*/ Function(VCExprOp/*!*/ op, params VCExpr[]/*!*/ arguments) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(arguments));
+
+ return Function(op,
+ HelperFuns.ToNonNullList(arguments),
+ VCExprNAry.EMPTY_TYPE_LIST);
+ }
+
+ public VCExpr/*!*/ Function(VCExprOp/*!*/ op, VCExpr[]/*!*/ arguments, Type[]/*!*/ typeArguments) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(arguments));
+ Contract.Requires(cce.NonNullElements(typeArguments));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+
+ return Function(op,
+ HelperFuns.ToNonNullList(arguments),
+ HelperFuns.ToNonNullList(typeArguments));
+ }
+
+ public VCExpr/*!*/ Function(Function/*!*/ op, List<VCExpr/*!*/>/*!*/ arguments) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(arguments));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return Function(BoogieFunctionOp(op), arguments, VCExprNAry.EMPTY_TYPE_LIST);
+ }
+
+ public VCExpr/*!*/ Function(Function/*!*/ op, params VCExpr[]/*!*/ arguments) {
+ Contract.Requires(cce.NonNullElements(arguments));
+ Contract.Requires(op != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return Function(BoogieFunctionOp(op), arguments);
+ }
+
+
+ // The following method should really be called "ReduceLeft". It must
+ // only be used for the binary operators "and" and "or"
+ public VCExpr/*!*/ NAry(VCExprOp/*!*/ op, List<VCExpr/*!*/>/*!*/ args) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return NAry(op, args.ToArray());
+ }
+
+ public VCExpr/*!*/ NAry(VCExprOp/*!*/ op, params VCExpr[]/*!*/ args) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Requires(op == AndOp || op == OrOp);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ bool and = (op == AndOp);
+
+ VCExpr/*!*/ e = and ? True : False;
+ foreach (VCExpr a in args) {
+ e = and ? AndSimp(e, cce.NonNull(a)) : OrSimp(e, cce.NonNull(a));
+ }
+ return e;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ public static readonly VCExprOp NotOp = new VCExprNAryOp(1, Type.Bool);
+ public static readonly VCExprOp EqOp = new VCExprNAryOp(2, Type.Bool);
+ public static readonly VCExprOp NeqOp = new VCExprNAryOp(2, Type.Bool);
+ public static readonly VCExprOp AndOp = new VCExprNAryOp(2, Type.Bool);
+ public static readonly VCExprOp OrOp = new VCExprNAryOp(2, Type.Bool);
+ public static readonly VCExprOp ImpliesOp = new VCExprNAryOp(2, Type.Bool);
+
+ public VCExprDistinctOp DistinctOp(int arity) {
+ Contract.Ensures(Contract.Result<VCExprDistinctOp>() != null);
+
+ return new VCExprDistinctOp(arity);
+ }
+
+ public VCExpr/*!*/ Not(List<VCExpr/*!*/>/*!*/ args) {
+ Contract.Requires(args != null);
+ Contract.Requires(args.Count == 1);
+ Contract.Requires(args[0] != null);
+ return Function(NotOp, args);
+ }
+
+ public VCExpr/*!*/ Not(VCExpr/*!*/ e0) {
+ Contract.Requires(e0 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return Function(NotOp, e0);
+ }
+ public VCExpr/*!*/ Eq(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
+ return Function(EqOp, e0, e1);
+ }
+ public VCExpr/*!*/ Neq(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return Function(NeqOp, e0, e1);
+ }
+ public VCExpr/*!*/ And(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(AndOp, e0, e1);
+ }
+ public VCExpr/*!*/ Gt(VCExpr/*!*/ e0, VCExpr/*!*/ e1)
+ {
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ return Function(GtOp, e0, e1);
+ }
+ public VCExpr/*!*/ Add(VCExpr/*!*/ e0, VCExpr/*!*/ e1)
+ {
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ VCExprOp op = cce.NonNull(cce.NonNull(e0).Type).IsInt ? AddIOp : AddROp;
+ return Function(op, e0, e1);
+ }
+ public VCExpr/*!*/ Or(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(OrOp, e0, e1);
+ }
+ public VCExpr/*!*/ Implies(VCExpr/*!*/ e0, VCExpr/*!*/ e1) {
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(ImpliesOp, e0, e1);
+ }
+ public VCExpr/*!*/ Distinct(List<VCExpr/*!*/>/*!*/ args) {
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ if (args.Count <= 1)
+ // trivial case
+ return True;
+ return Function(DistinctOp(args.Count), args);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Versions of the propositional operators that automatically simplify in
+ // certain cases (for example, if one of the operators is True or False)
+
+ public VCExpr NotSimp(VCExpr e0) {
+ Contract.Requires(e0 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (e0.Equals(True))
+ return False;
+ if (e0.Equals(False))
+ return True;
+ return Not(e0);
+ }
+ public VCExpr AndSimp(VCExpr e0, VCExpr e1) {
+ Contract.Requires(e1 != null);
+ Contract.Requires(e0 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (e0.Equals(True))
+ return e1;
+ if (e1.Equals(True))
+ return e0;
+ if (e0.Equals(False) || e1.Equals(False))
+ return False;
+ return And(e0, e1);
+ }
+ public VCExpr OrSimp(VCExpr e0, VCExpr e1) {
+ Contract.Requires(e1 != null);
+ Contract.Requires(e0 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (e0.Equals(False))
+ return e1;
+ if (e1.Equals(False))
+ return e0;
+ if (e0.Equals(True) || e1.Equals(True))
+ return True;
+ return Or(e0, e1);
+ }
+ public VCExpr ImpliesSimp(VCExpr e0, VCExpr e1, bool aggressive = true) {
+ Contract.Requires(e1 != null);
+ Contract.Requires(e0 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (e0.Equals(True))
+ return e1;
+ if (e1.Equals(False))
+ return NotSimp(e0);
+ if (e0.Equals(False) || e1.Equals(True))
+ return True;
+ // attempt to save on the depth of expressions (to reduce chances of stack overflows)
+ while (aggressive && e1 is VCExprBinary) {
+ VCExprBinary n = (VCExprBinary)e1;
+ if (n.Op == ImpliesOp) {
+ if (AndSize(n[0]) <= AndSize(e0)) {
+ // combine the antecedents
+ e0 = And(e0, n[0]);
+ e1 = n[1];
+ continue;
+ }
+ }
+ break;
+ }
+ return Implies(e0, e1);
+ }
+
+ ///<summary>
+ /// Returns some measure of the number of conjuncts in e. This could be the total number of conjuncts in all
+ /// top-most layers of the expression, or it can simply be the length of the left-prong of this and-tree. The
+ /// important thing is that: AndSize(e0) >= AndSize(31) ==> AndSize(And(e0,e1)) > AndSize(e0).
+ ///</summary>
+ int AndSize(VCExpr e) {
+ Contract.Requires(e != null);
+ int n = 1;
+ while (true) {
+ VCExprNAry nary = e as VCExprNAry;
+ if (nary != null && nary.Op == AndOp && 2 <= nary.Arity) {
+ e = nary[0];
+ n++;
+ } else {
+ return n;
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Further operators
+
+ public static readonly VCExprOp AddIOp = new VCExprNAryOp(2, Type.Int);
+ public static readonly VCExprOp AddROp = new VCExprNAryOp(2, Type.Real);
+ public static readonly VCExprOp SubIOp = new VCExprNAryOp(2, Type.Int);
+ public static readonly VCExprOp SubROp = new VCExprNAryOp(2, Type.Real);
+ public static readonly VCExprOp MulIOp = new VCExprNAryOp(2, Type.Int);
+ public static readonly VCExprOp MulROp = new VCExprNAryOp(2, Type.Real);
+ public static readonly VCExprOp DivIOp = new VCExprNAryOp(2, Type.Int);
+ public static readonly VCExprOp DivROp = new VCExprNAryOp(2, Type.Real);
+ public static readonly VCExprOp ModOp = new VCExprNAryOp(2, Type.Int);
+ public static readonly VCExprOp PowOp = new VCExprNAryOp(2, Type.Real);
+ public static readonly VCExprOp LtOp = new VCExprNAryOp(2, Type.Bool);
+ public static readonly VCExprOp LeOp = new VCExprNAryOp(2, Type.Bool);
+ public static readonly VCExprOp GtOp = new VCExprNAryOp(2, Type.Bool);
+ public static readonly VCExprOp GeOp = new VCExprNAryOp(2, Type.Bool);
+ public static readonly VCExprOp SubtypeOp = new VCExprNAryOp(2, Type.Bool);
+ // ternary version of the subtype operator, the first argument of which gives
+ // the type of the compared terms
+ public static readonly VCExprOp Subtype3Op = new VCExprNAryOp(3, Type.Bool);
+ public static readonly VCExprOp IfThenElseOp = new VCExprIfThenElseOp();
+ public static readonly VCExprOp ToIntOp = new VCExprNAryOp(1, Type.Int);
+ public static readonly VCExprOp ToRealOp = new VCExprNAryOp(1, Type.Real);
+
+ public static readonly VCExprOp TickleBoolOp = new VCExprCustomOp("tickleBool", 1, Type.Bool);
+
+ public static readonly VCExprOp TimeoutDiagnosticsOp = new VCExprCustomOp("timeoutDiagnostics", 1, Type.Bool);
+
+ public VCExprOp BoogieFunctionOp(Function func) {
+ Contract.Requires(func != null);
+ Contract.Ensures(Contract.Result<VCExprOp>() != null);
+ return new VCExprBoogieFunctionOp(func);
+ }
+
+ // Bitvector nodes
+
+ public VCExpr Bitvector(BvConst bv) {
+ Contract.Requires(bv != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprBvOp(bv.Bits), Integer(bv.Value));
+ }
+
+ public VCExpr BvExtract(VCExpr bv, int bits, int start, int end) {
+ Contract.Requires(bv != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprBvExtractOp(start, end, bits), bv);
+ }
+
+ public VCExpr BvConcat(VCExpr bv1, VCExpr bv2) {
+ Contract.Requires(bv2 != null);
+ Contract.Requires(bv1 != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprBvConcatOp(bv1.Type.BvBits, bv2.Type.BvBits), bv1, bv2);
+ }
+
+ public VCExpr AtMost(VCExpr smaller, VCExpr greater) {
+ Contract.Requires(greater != null);
+ Contract.Requires(smaller != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(SubtypeOp, smaller, greater);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Dispatcher for the visitor
+
+ // the declared singleton operators
+ internal enum SingletonOp {
+ NotOp,
+ EqOp,
+ NeqOp,
+ AndOp,
+ OrOp,
+ ImpliesOp,
+ AddOp,
+ SubOp,
+ MulOp,
+ DivOp,
+ ModOp,
+ RealDivOp,
+ PowOp,
+ LtOp,
+ LeOp,
+ GtOp,
+ GeOp,
+ SubtypeOp,
+ Subtype3Op,
+ BvConcatOp,
+ ToIntOp,
+ ToRealOp
+ };
+ internal static Dictionary<VCExprOp/*!*/, SingletonOp>/*!*/ SingletonOpDict;
+ [ContractInvariantMethod]
+ void MiscInvariant() {
+ Contract.Invariant(SingletonOpDict != null);
+ }
+
+
+ static VCExpressionGenerator() {
+ SingletonOpDict = new Dictionary<VCExprOp/*!*/, SingletonOp>();
+ SingletonOpDict.Add(NotOp, SingletonOp.NotOp);
+ SingletonOpDict.Add(EqOp, SingletonOp.EqOp);
+ SingletonOpDict.Add(NeqOp, SingletonOp.NeqOp);
+ SingletonOpDict.Add(AndOp, SingletonOp.AndOp);
+ SingletonOpDict.Add(OrOp, SingletonOp.OrOp);
+ SingletonOpDict.Add(ImpliesOp, SingletonOp.ImpliesOp);
+ SingletonOpDict.Add(AddIOp, SingletonOp.AddOp);
+ SingletonOpDict.Add(AddROp, SingletonOp.AddOp);
+ SingletonOpDict.Add(SubIOp, SingletonOp.SubOp);
+ SingletonOpDict.Add(SubROp, SingletonOp.SubOp);
+ SingletonOpDict.Add(MulIOp, SingletonOp.MulOp);
+ SingletonOpDict.Add(MulROp, SingletonOp.MulOp);
+ SingletonOpDict.Add(DivIOp, SingletonOp.DivOp);
+ SingletonOpDict.Add(DivROp, SingletonOp.RealDivOp);
+ SingletonOpDict.Add(ModOp, SingletonOp.ModOp);
+ SingletonOpDict.Add(PowOp, SingletonOp.PowOp);
+ SingletonOpDict.Add(LtOp, SingletonOp.LtOp);
+ SingletonOpDict.Add(LeOp, SingletonOp.LeOp);
+ SingletonOpDict.Add(GtOp, SingletonOp.GtOp);
+ SingletonOpDict.Add(GeOp, SingletonOp.GeOp);
+ SingletonOpDict.Add(SubtypeOp, SingletonOp.SubtypeOp);
+ SingletonOpDict.Add(Subtype3Op, SingletonOp.Subtype3Op);
+ SingletonOpDict.Add(ToIntOp, SingletonOp.ToIntOp);
+ SingletonOpDict.Add(ToRealOp, SingletonOp.ToRealOp);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ // Let-bindings
+
+ public VCExprLetBinding LetBinding(VCExprVar v, VCExpr e) {
+ Contract.Requires(e != null);
+ Contract.Requires(v != null);
+ Contract.Ensures(Contract.Result<VCExprLetBinding>() != null);
+ return new VCExprLetBinding(v, e);
+ }
+
+ // A "real" let expression. All let-bindings happen simultaneously, i.e.,
+ // at this level the order of the bindings does not matter. It is possible to
+ // create expressions like "let x = y, y = 5 in ...". All bound variables are
+ // bound in all bound terms/formulas and can occur there, but the dependencies
+ // have to be acyclic
+ public VCExpr Let(List<VCExprLetBinding> bindings, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(cce.NonNullElements(bindings));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (bindings.Count == 0)
+ // no empty let-bindings
+ return body;
+ return new VCExprLet(bindings, body);
+ }
+
+ public VCExpr Let(VCExpr body, params VCExprLetBinding[] bindings) {
+ Contract.Requires(body != null);
+ Contract.Requires((cce.NonNullElements(bindings)));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Let(HelperFuns.ToNonNullList(bindings), body);
+ }
+
+
+ /// <summary>
+ /// In contrast to the previous method, the following methods are not a general LET.
+ /// Instead, it
+ /// is a boolean "LET b = P in Q", where P and Q are predicates, that is allowed to be
+ /// encoded as "(b == P) ==> Q" or even as "(P ==> b) ==> Q"
+ /// (or "(P ==> b) and Q" in negative positions).
+ /// The method assumes that the variables in the bindings are unique in the entire formula
+ /// to be produced, which allows the implementation to ignore scope issues in the event that
+ /// it needs to generate an alternate expression for LET.
+ /// </summary>
+
+
+ // Turn let-bindings let v = E in ... into implications E ==> v
+ public VCExpr AsImplications(List<VCExprLetBinding> bindings) {
+ Contract.Requires(cce.NonNullElements(bindings));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr/*!*/ antecedents = True;
+ foreach (VCExprLetBinding b in bindings)
+ // turn "LET_binding v = E" into "v <== E"
+ antecedents = AndSimp(antecedents, Implies(b.E, b.V));
+ return antecedents;
+ }
+
+ // Turn let-bindings let v = E in ... into equations v == E
+ public VCExpr AsEquations(List<VCExprLetBinding> bindings) {
+ Contract.Requires(cce.NonNullElements(bindings));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr/*!*/ antecedents = True;
+ foreach (VCExprLetBinding b in bindings)
+ // turn "LET_binding v = E" into "v <== E"
+ antecedents = AndSimp(antecedents, Eq(b.E, b.V));
+ return antecedents;
+ }
+
+
+
+ // Maps
+
+ public VCExpr Select(params VCExpr[] allArgs) {
+ Contract.Requires(allArgs != null);
+ Contract.Requires((cce.NonNullElements(allArgs)));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprSelectOp(allArgs.Length - 1, 0),
+ HelperFuns.ToNonNullList(allArgs),
+ VCExprNAry.EMPTY_TYPE_LIST);
+ }
+
+ public VCExpr Select(VCExpr[] allArgs, Type[] typeArgs) {
+ Contract.Requires(1 <= allArgs.Length);
+ Contract.Requires(cce.NonNullElements(allArgs));
+ Contract.Requires(cce.NonNullElements(typeArgs));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprSelectOp(allArgs.Length - 1, typeArgs.Length),
+ allArgs, typeArgs);
+ }
+
+ public VCExpr Select(List<VCExpr> allArgs, List<Type> typeArgs) {
+ Contract.Requires(cce.NonNullElements(typeArgs));
+ Contract.Requires(cce.NonNullElements(allArgs));
+ Contract.Requires((1 <= allArgs.Count));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprSelectOp(allArgs.Count - 1, typeArgs.Count),
+ allArgs, typeArgs);
+ }
+
+ public VCExpr Store(params VCExpr[] allArgs) {
+ Contract.Requires(allArgs != null);
+ Contract.Requires(cce.NonNullElements(allArgs));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprStoreOp(allArgs.Length - 2, 0),
+ HelperFuns.ToNonNullList(allArgs),
+ VCExprNAry.EMPTY_TYPE_LIST);
+ }
+
+ public VCExpr Store(VCExpr[] allArgs, Type[] typeArgs) {
+ Contract.Requires(typeArgs != null);
+ Contract.Requires(allArgs != null);
+ Contract.Requires((2 <= allArgs.Length));
+ Contract.Requires(cce.NonNullElements(allArgs));
+ Contract.Requires(cce.NonNullElements(typeArgs));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprStoreOp(allArgs.Length - 2, typeArgs.Length),
+ allArgs, typeArgs);
+ }
+
+ public VCExpr Store(List<VCExpr> allArgs, List<Type/*!*/>/*!*/ typeArgs) {
+ Contract.Requires(cce.NonNullElements(typeArgs));
+ Contract.Requires(cce.NonNullElements(allArgs));
+ Contract.Requires((2 <= allArgs.Count));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(new VCExprStoreOp(allArgs.Count - 2, typeArgs.Count),
+ allArgs, typeArgs);
+ }
+
+
+ // Labels
+
+ public VCExprLabelOp LabelOp(bool pos, string l) {
+ Contract.Requires(l != null);
+ Contract.Ensures(Contract.Result<VCExprLabelOp>() != null);
+ return new VCExprLabelOp(pos, l);
+ }
+
+ public VCExpr LabelNeg(string label, VCExpr e) {
+ Contract.Requires(e != null);
+ Contract.Requires(label != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ if (e.Equals(True)) {
+ return e; // don't bother putting negative labels around True (which will expose the True to further peephole optimizations)
+ }
+ return Function(LabelOp(false, label), e);
+ }
+ public VCExpr LabelPos(string label, VCExpr e) {
+ Contract.Requires(e != null);
+ Contract.Requires(label != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Function(LabelOp(true, label), e);
+ }
+
+ // Quantifiers
+
+ public VCExpr Quantify(Quantifier quan, List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCQuantifierInfos infos, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(infos != null);
+ Contract.Requires(cce.NonNullElements(triggers));
+ Contract.Requires(cce.NonNullElements(vars));
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return new VCExprQuantifier(quan, typeParams, vars, triggers, infos, body);
+ }
+
+ public VCExpr Forall(List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCQuantifierInfos infos, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(infos != null);
+ Contract.Requires(cce.NonNullElements(triggers));
+ Contract.Requires(cce.NonNullElements(vars));
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Quantify(Quantifier.ALL, typeParams, vars, triggers, infos, body);
+ }
+ public VCExpr Forall(List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, string qid, int weight, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(qid != null);
+ Contract.Requires(cce.NonNullElements(triggers));
+ Contract.Requires(cce.NonNullElements(vars));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ QKeyValue kv = null;
+ if (0 <= weight) {
+ kv = new QKeyValue(Token.NoToken, "weight", new List<object>() { new LiteralExpr(Token.NoToken, BigNum.FromInt(0)) }, null);
+ }
+ return Quantify(Quantifier.ALL, new List<TypeVariable/*!*/>(), vars,
+ triggers, new VCQuantifierInfos(qid, -1, false, kv), body);
+ }
+ public VCExpr Forall(List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(cce.NonNullElements(triggers));
+ Contract.Requires(cce.NonNullElements(vars));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Quantify(Quantifier.ALL, new List<TypeVariable/*!*/>(), vars,
+ triggers, new VCQuantifierInfos(null, -1, false, null), body);
+ }
+ public VCExpr Forall(VCExprVar var, VCTrigger trigger, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(trigger != null);
+ Contract.Requires(var != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Forall(HelperFuns.ToNonNullList(var), HelperFuns.ToNonNullList(trigger), body);
+ }
+ public VCExpr Exists(List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCQuantifierInfos infos, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(infos != null);
+ Contract.Requires(cce.NonNullElements(triggers));
+ Contract.Requires(cce.NonNullElements(vars));
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Quantify(Quantifier.EX, typeParams, vars, triggers, infos, body);
+ }
+ public VCExpr Exists(List<VCExprVar/*!*/>/*!*/ vars, List<VCTrigger/*!*/>/*!*/ triggers, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(cce.NonNullElements(triggers));
+ Contract.Requires(cce.NonNullElements(vars));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Quantify(Quantifier.EX, new List<TypeVariable/*!*/>(), vars,
+ triggers, new VCQuantifierInfos(null, -1, false, null), body);
+ }
+ public VCExpr Exists(VCExprVar var, VCTrigger trigger, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(trigger != null);
+ Contract.Requires(var != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return Exists(HelperFuns.ToNonNullList(var), HelperFuns.ToNonNullList(trigger), body);
+ }
+
+ public VCTrigger Trigger(bool pos, List<VCExpr> exprs) {
+ Contract.Requires(cce.NonNullElements(exprs));
+ Contract.Ensures(Contract.Result<VCTrigger>() != null);
+ return new VCTrigger(pos, exprs);
+ }
+
+ public VCTrigger Trigger(bool pos, params VCExpr[] exprs) {
+ Contract.Requires(exprs != null);
+ Contract.Requires((Contract.ForAll(0, exprs.Length, i => exprs[i] != null)));
+ Contract.Ensures(Contract.Result<VCTrigger>() != null);
+ return Trigger(pos, HelperFuns.ToNonNullList(exprs));
+ }
+
+ // Reference to a bound or free variable
+
+ public VCExprVar Variable(string name, Type type) {
+ Contract.Requires(type != null);
+ Contract.Requires(name != null);
+ Contract.Ensures(Contract.Result<VCExprVar>() != null);
+ return new VCExprVar(name, type);
+ }
+ }
+}
+
+namespace Microsoft.Boogie.VCExprAST {
+
+ public class HelperFuns {
+ public static bool SameElements(IEnumerable a, IEnumerable b) {
+ Contract.Requires(b != null);
+ Contract.Requires(a != null);
+ IEnumerator ia = a.GetEnumerator();
+ IEnumerator ib = b.GetEnumerator();
+ while (true) {
+ if (ia.MoveNext()) {
+ if (ib.MoveNext()) {
+ if (!cce.NonNull(ia.Current).Equals(ib.Current))
+ return false;
+ } else {
+ return false;
+ }
+ } else {
+ return !ib.MoveNext();
+ }
+ }
+ }
+
+ public static int PolyHash(int init, int factor, IEnumerable a) {
+ Contract.Requires(a != null);
+ int res = init;
+ foreach (object x in a)
+ res = res * factor + (cce.NonNull(x)).GetHashCode();
+ return res;
+ }
+
+ public static List<T> ToList<T>(IEnumerable<T> l) {
+ Contract.Requires(l != null);
+ Contract.Ensures(Contract.Result<List<T>>() != null);
+ List<T>/*!*/ res = new List<T>();
+ foreach (T x in l)
+ res.Add(x);
+ return res;
+ }
+
+ public static List<Type> ToTypeSeq(VCExpr[] exprs, int startIndex) {
+ Contract.Requires(exprs != null);
+ Contract.Requires((Contract.ForAll(0, exprs.Length, i => exprs[i] != null)));
+ Contract.Ensures(Contract.Result<List<Type>>() != null);
+ List<Type>/*!*/ res = new List<Type>();
+ for (int i = startIndex; i < exprs.Length; ++i)
+ res.Add(cce.NonNull(exprs[i]).Type);
+ return res;
+ }
+
+ public static List<T/*!*/>/*!*/ ToNonNullList<T>(params T[] args) where T : class {
+ Contract.Requires(args != null);
+ List<T/*!*/>/*!*/ res = new List<T>(args.Length);
+ foreach (T t in args)
+ res.Add(cce.NonNull(t));
+ return res;
+ }
+
+ public static IDictionary<A, B> Clone<A, B>(IDictionary<A, B> dict) {
+ Contract.Requires(dict != null);
+ Contract.Ensures(Contract.Result<IDictionary<A, B>>() != null);
+ IDictionary<A, B> res = new Dictionary<A, B>(dict.Count);
+ foreach (KeyValuePair<A, B> pair in dict)
+ res.Add(pair);
+ return res;
+ }
+ }
+
+ [ContractClassFor(typeof(VCExpr))]
+ public abstract class VCExprContracts : VCExpr {
+ public override Type Type {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ throw new NotImplementedException();
+ }
+
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
+ Contract.Requires(visitor != null);
+ throw new NotImplementedException();
+ }
+ }
+
+ [ContractClass(typeof(VCExprContracts))]
+ public abstract class VCExpr {
+ public abstract Type Type {
+ get;
+ }
+
+ public abstract Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg);
+
+ [Pure]
+ public override string ToString() {
+ Contract.Ensures(Contract.Result<string>() != null);
+ StringWriter sw = new StringWriter();
+ VCExprPrinter printer = new VCExprPrinter();
+ printer.Print(this, sw);
+ return cce.NonNull(sw.ToString());
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Literal expressions
+
+ public class VCExprLiteral : VCExpr {
+ private readonly Type LitType;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(LitType != null);
+ }
+
+ public override Type Type {
+ get {
+ return LitType;
+ }
+ }
+ internal VCExprLiteral(Type type) {
+ Contract.Requires(type != null);
+ this.LitType = type;
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this, arg);
+ }
+ }
+
+ public class VCExprIntLit : VCExprLiteral {
+ public readonly BigNum Val;
+ internal VCExprIntLit(BigNum val)
+ : base(Type.Int) {
+ this.Val = val;
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprIntLit)
+ return Val == ((VCExprIntLit)that).Val;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Val.GetHashCode() * 72321;
+ }
+ }
+
+ public class VCExprRealLit : VCExprLiteral {
+ public readonly BigDec Val;
+ internal VCExprRealLit(BigDec val)
+ : base(Type.Real) {
+ this.Val = val;
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprRealLit)
+ return Val == ((VCExprRealLit)that).Val;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Val.GetHashCode() * 72321;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Operator expressions with fixed arity
+ [ContractClassFor(typeof(VCExprNAry))]
+ public abstract class VCExprNAryContracts : VCExprNAry {
+ public VCExprNAryContracts()
+ : base(null) {
+ }
+ public override VCExpr this[int index] {
+ get {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ throw new NotImplementedException();
+ }
+ }
+ }
+
+ [ContractClass(typeof(VCExprNAryContracts))]
+ public abstract class VCExprNAry : VCExpr, IEnumerable<VCExpr/*!*/> {
+ public readonly VCExprOp Op;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Op != null);
+ Contract.Invariant(cce.NonNullElements(EMPTY_TYPE_LIST));
+ Contract.Invariant(cce.NonNullElements(EMPTY_VCEXPR_LIST));
+ }
+
+ public int Arity {
+ get {
+ return Op.Arity;
+ }
+ }
+ public int TypeParamArity {
+ get {
+ return Op.TypeParamArity;
+ }
+ }
+ public int Length {
+ get {
+ return Arity;
+ }
+ }
+ // the sub-expressions of the expression
+ public abstract VCExpr/*!*/ this[int index] {
+ get;
+ }
+
+ // the type arguments
+ public abstract List<Type/*!*/>/*!*/ TypeArguments {
+ get;
+ }
+
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ public IEnumerator<VCExpr/*!*/>/*!*/ GetEnumerator() {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerator<VCExpr>>()));
+ for (int i = 0; i < Arity; ++i)
+ yield return this[i];
+ }
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ Contract.Ensures(Contract.Result<IEnumerator>() != null);
+ for (int i = 0; i < Arity; ++i)
+ yield return this[i];
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprNAry) {
+ // we compare the subterms iteratively (not recursively)
+ // to avoid stack overflows
+
+ VCExprNAryEnumerator enum0 = new VCExprNAryEnumerator(this);
+ VCExprNAryEnumerator enum1 = new VCExprNAryEnumerator((VCExprNAry)that);
+
+ while (true) {
+ bool next0 = enum0.MoveNext();
+ bool next1 = enum1.MoveNext();
+ if (next0 != next1)
+ return false;
+ if (!next0)
+ return true;
+
+ VCExprNAry nextExprNAry0 = enum0.Current as VCExprNAry;
+ VCExprNAry nextExprNAry1 = enum1.Current as VCExprNAry;
+
+ if ((nextExprNAry0 == null) != (nextExprNAry1 == null))
+ return false;
+ if (nextExprNAry0 != null && nextExprNAry1 != null) {
+ if (!nextExprNAry0.Op.Equals(nextExprNAry1.Op))
+ return false;
+ } else {
+ if (!cce.NonNull(enum0.Current).Equals(enum1.Current))
+ return false;
+ }
+ }
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return HelperFuns.PolyHash(Op.GetHashCode() * 123 + Arity * 61521,
+ 3, this);
+ }
+
+ internal VCExprNAry(VCExprOp op) {
+ Contract.Requires(op != null);
+ this.Op = op;
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this, arg);
+ }
+ public Result Accept<Result, Arg>(IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ Contract.Requires(visitor != null);
+ return Op.Accept(this, visitor, arg);
+ }
+
+ internal static readonly List<Type/*!*/>/*!*/ EMPTY_TYPE_LIST = new List<Type/*!*/>();
+ internal static readonly List<VCExpr/*!*/>/*!*/ EMPTY_VCEXPR_LIST = new List<VCExpr/*!*/>();
+
+ public IEnumerable<VCExpr> UniformArguments
+ {
+ get
+ {
+ var enumerator = new VCExprNAryUniformOpEnumerator(this);
+ while (enumerator.MoveNext()) {
+ VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
+ if (naryExpr == null || !naryExpr.Op.Equals(this.Op)) {
+ yield return (VCExpr)enumerator.Current;
+ }
+ }
+ }
+ }
+ }
+
+ // We give specialised implementations for nullary, unary and binary expressions
+
+ internal class VCExprNullary : VCExprNAry {
+ private readonly Type ExprType;
+ [ContractInvariantMethod]
+ void loneinvariant() {
+ Contract.Invariant(ExprType != null);
+ }
+
+ public override Type Type {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return ExprType;
+ }
+ }
+ public override VCExpr this[int index] {
+ get {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ Contract.Assert(false);
+ throw new cce.UnreachableException(); // no arguments
+ }
+ }
+
+ // the type arguments
+ public override List<Type/*!*/>/*!*/ TypeArguments {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
+ return EMPTY_TYPE_LIST;
+ }
+ }
+
+ internal VCExprNullary(VCExprOp op)
+ : base(op) {
+ Contract.Requires(op != null);
+ Contract.Requires(op.Arity == 0 && op.TypeParamArity == 0);
+ this.ExprType = op.InferType(EMPTY_VCEXPR_LIST, EMPTY_TYPE_LIST);
+ }
+ }
+
+ internal class VCExprUnary : VCExprNAry {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Argument != null);
+ Contract.Invariant(ExprType != null);
+
+ }
+
+ private readonly VCExpr/*!*/ Argument;
+ private readonly Type/*!*/ ExprType;
+ public override Type/*!*/ Type {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return ExprType;
+ }
+ }
+ public override VCExpr/*!*/ this[int index] {
+ get {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ Contract.Assume(index == 0);
+ return Argument;
+ }
+ }
+
+ // the type arguments
+ public override List<Type/*!*/>/*!*/ TypeArguments {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
+ return EMPTY_TYPE_LIST;
+ }
+ }
+
+ internal VCExprUnary(VCExprOp op, List<VCExpr> arguments)
+ : base(op) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(arguments));
+ Contract.Requires(op.Arity == 1 && op.TypeParamArity == 0 && arguments.Count == 1);
+
+ this.Argument = arguments[0];
+ this.ExprType =
+ op.InferType(arguments, EMPTY_TYPE_LIST);
+ }
+
+ internal VCExprUnary(VCExprOp op, VCExpr argument)
+ : base(op) {
+ Contract.Requires(argument != null);
+ Contract.Requires(op != null);
+ Contract.Requires(op.Arity == 1 && op.TypeParamArity == 0);
+
+ this.Argument = argument;
+ // PR: could be optimised so that the argument does
+ // not have to be boxed in an array each time
+ this.ExprType =
+ op.InferType(HelperFuns.ToNonNullList(argument), EMPTY_TYPE_LIST);
+ }
+ }
+
+ internal class VCExprBinary : VCExprNAry {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Argument0 != null);
+ Contract.Invariant(Argument1 != null);
+ Contract.Invariant(ExprType != null);
+ }
+
+ private readonly VCExpr Argument0;
+ private readonly VCExpr Argument1;
+ private readonly Type ExprType;
+ public override Type Type {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return ExprType;
+ }
+ }
+ public override VCExpr this[int index] {
+ get {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ switch (index) {
+ case 0:
+ return Argument0;
+ case 1:
+ return Argument1;
+ default: {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ }
+ }
+ }
+
+ // the type arguments
+ public override List<Type/*!*/>/*!*/ TypeArguments {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
+ return EMPTY_TYPE_LIST;
+ }
+ }
+
+ internal VCExprBinary(VCExprOp op, List<VCExpr> arguments)
+ : base(op) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(arguments));
+ Contract.Requires(op.Arity == 2 && op.TypeParamArity == 0 && arguments.Count == 2);
+
+ this.Argument0 = arguments[0];
+ this.Argument1 = arguments[1];
+ this.ExprType = op.InferType(arguments, EMPTY_TYPE_LIST);
+ }
+
+ internal VCExprBinary(VCExprOp op, VCExpr argument0, VCExpr argument1)
+ : base(op) {
+ Contract.Requires(argument1 != null);
+ Contract.Requires(argument0 != null);
+ Contract.Requires(op != null);
+ Contract.Requires(op.Arity == 2 && op.TypeParamArity == 0);
+ this.Argument0 = argument0;
+ this.Argument1 = argument1;
+ // PR: could be optimised so that the arguments do
+ // not have to be boxed in an array each time
+ this.ExprType =
+ op.InferType(HelperFuns.ToNonNullList(argument0, argument1),
+ EMPTY_TYPE_LIST);
+ }
+ }
+
+ internal class VCExprMultiAry : VCExprNAry {
+ private readonly List<VCExpr/*!*/>/*!*/ Arguments;
+ private readonly List<Type/*!*/>/*!*/ TypeArgumentsAttr;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(Arguments));
+ Contract.Invariant(cce.NonNullElements(TypeArgumentsAttr));
+ Contract.Invariant(ExprType != null);
+ }
+
+
+ private readonly Type/*!*/ ExprType;
+ public override Type/*!*/ Type {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return ExprType;
+ }
+ }
+ public override VCExpr/*!*/ this[int index] {
+ get {
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ Contract.Assume(index >= 0 && index < Arity);
+ return cce.NonNull(Arguments)[index];
+ }
+ }
+
+ // the type arguments
+ public override List<Type/*!*/>/*!*/ TypeArguments {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<Type>>()));
+ return TypeArgumentsAttr;
+ }
+ }
+
+ internal VCExprMultiAry(VCExprOp op, List<VCExpr> arguments)
+ : base(op) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(arguments));
+ this.Arguments = arguments;
+ this.TypeArgumentsAttr = EMPTY_TYPE_LIST;
+ this.ExprType = op.InferType(arguments, TypeArgumentsAttr);
+ }
+ internal VCExprMultiAry(VCExprOp op, List<VCExpr> arguments, List<Type/*!*/>/*!*/ typeArguments)
+ : base(op) {
+ Contract.Requires(op != null);
+ Contract.Requires(cce.NonNullElements(typeArguments));
+ Contract.Requires(cce.NonNullElements(arguments));
+ Contract.Requires(arguments.Count > 2 || typeArguments.Count > 0);
+ Contract.Requires(op.Arity == arguments.Count);
+ Contract.Requires(op.TypeParamArity == typeArguments.Count);
+ this.Arguments = arguments;
+ this.TypeArgumentsAttr = typeArguments;
+ this.ExprType = op.InferType(arguments, typeArguments);
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // The various operators available
+ [ContractClass(typeof(VCExprOpContracts))]
+ public abstract class VCExprOp {
+ // the number of value parameters
+ public abstract int Arity {
+ get;
+ }
+ // the number of type parameters
+ public abstract int TypeParamArity {
+ get;
+ }
+
+ public abstract Type/*!*/ InferType(List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs);
+
+ public virtual Result Accept<Result, Arg>(VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ Contract.Requires(visitor != null);
+ Contract.Requires(expr != null);
+ VCExpressionGenerator.SingletonOp op;
+ if (VCExpressionGenerator.SingletonOpDict.TryGetValue(this, out op)) {
+ switch (op) {
+ case VCExpressionGenerator.SingletonOp.NotOp:
+ return visitor.VisitNotOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.EqOp:
+ return visitor.VisitEqOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.NeqOp:
+ return visitor.VisitNeqOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.AndOp:
+ return visitor.VisitAndOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.OrOp:
+ return visitor.VisitOrOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.ImpliesOp:
+ return visitor.VisitImpliesOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.AddOp:
+ return visitor.VisitAddOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.SubOp:
+ return visitor.VisitSubOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.MulOp:
+ return visitor.VisitMulOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.DivOp:
+ return visitor.VisitDivOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.ModOp:
+ return visitor.VisitModOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.RealDivOp:
+ return visitor.VisitRealDivOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.PowOp:
+ return visitor.VisitPowOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.LtOp:
+ return visitor.VisitLtOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.LeOp:
+ return visitor.VisitLeOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.GtOp:
+ return visitor.VisitGtOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.GeOp:
+ return visitor.VisitGeOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.SubtypeOp:
+ return visitor.VisitSubtypeOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.Subtype3Op:
+ return visitor.VisitSubtype3Op(expr, arg);
+ case VCExpressionGenerator.SingletonOp.BvConcatOp:
+ return visitor.VisitBvConcatOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.ToIntOp:
+ return visitor.VisitToIntOp(expr, arg);
+ case VCExpressionGenerator.SingletonOp.ToRealOp:
+ return visitor.VisitToRealOp(expr, arg);
+ default:
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ } else {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ }
+ }
+ [ContractClassFor(typeof(VCExprOp))]
+ abstract class VCExprOpContracts : VCExprOp {
+ public override Type InferType(List<VCExpr> args, List<Type> typeArgs) {
+ Contract.Requires(cce.NonNullElements(args));
+ Contract.Requires(cce.NonNullElements(typeArgs));
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ throw new NotImplementedException();
+ }
+ }
+
+ public class VCExprNAryOp : VCExprOp {
+ private readonly Type OpType;
+ private readonly int OpArity;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(OpType != null);
+ }
+
+ public override int Arity {
+ get {
+ return OpArity;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return 0;
+ }
+ }
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return OpType;
+ }
+
+ internal VCExprNAryOp(int arity, Type type) {
+ Contract.Requires(type != null);
+ this.OpArity = arity;
+ this.OpType = type;
+ }
+ }
+
+ public class VCExprDistinctOp : VCExprNAryOp {
+ internal VCExprDistinctOp(int arity)
+ : base(arity, Type.Bool) {
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprDistinctOp)
+ return Arity == ((VCExprDistinctOp)that).Arity;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Arity * 917632481;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitDistinctOp(expr, arg);
+ }
+ }
+
+ public class VCExprLabelOp : VCExprOp {
+ public override int Arity {
+ get {
+ return 1;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return 0;
+ }
+ }
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return args[0].Type;
+ }
+
+ public readonly bool pos;
+ public readonly string label;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(label != null);
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprLabelOp) {
+ VCExprLabelOp/*!*/ thatOp = (VCExprLabelOp)that;
+ return this.pos == thatOp.pos && this.label.Equals(thatOp.label);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return (pos ? 9817231 : 7198639) + label.GetHashCode();
+ }
+
+ internal VCExprLabelOp(bool pos, string l) {
+ Contract.Requires(l != null);
+ this.pos = pos;
+ this.label = pos ? "+" + l : "@" + l;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitLabelOp(expr, arg);
+ }
+ }
+
+ public class VCExprSelectOp : VCExprOp {
+ private readonly int MapArity;
+ private readonly int MapTypeParamArity;
+ public override int Arity {
+ get {
+ return MapArity + 1;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return MapTypeParamArity;
+ }
+ }
+
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ MapType/*!*/ mapType = args[0].Type.AsMap;
+ Contract.Assert(TypeParamArity == mapType.TypeParameters.Count);
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
+ for (int i = 0; i < TypeParamArity; ++i)
+ subst.Add(mapType.TypeParameters[i], typeArgs[i]);
+ return mapType.Result.Substitute(subst);
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprSelectOp)
+ return Arity == ((VCExprSelectOp)that).Arity &&
+ TypeParamArity == ((VCExprSelectOp)that).TypeParamArity;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Arity * 1212481 + TypeParamArity * 298741;
+ }
+
+ internal VCExprSelectOp(int arity, int typeParamArity) {
+ Contract.Requires(0 <= arity && 0 <= typeParamArity);
+ this.MapArity = arity;
+ this.MapTypeParamArity = typeParamArity;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitSelectOp(expr, arg);
+ }
+ }
+
+ public class VCExprStoreOp : VCExprOp {
+ private readonly int MapArity;
+ private readonly int MapTypeParamArity;
+ public override int Arity {
+ get {
+ return MapArity + 2;
+ }
+ }
+ // stores never need explicit type parameters, because also the
+ // rhs is a value argument
+ public override int TypeParamArity {
+ get {
+ return MapTypeParamArity;
+ }
+ }
+
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return args[0].Type;
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprStoreOp)
+ return Arity == ((VCExprStoreOp)that).Arity;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Arity * 91361821;
+ }
+
+ internal VCExprStoreOp(int arity, int typeParamArity) {
+ Contract.Requires(0 <= arity && 0 <= typeParamArity);
+ this.MapArity = arity;
+ this.MapTypeParamArity = typeParamArity;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitStoreOp(expr, arg);
+ }
+ }
+
+ public class VCExprIfThenElseOp : VCExprOp {
+ public override int Arity {
+ get {
+ return 3;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return 0;
+ }
+ }
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return args[1].Type;
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprIfThenElseOp)
+ return true;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return 1;
+ }
+
+ internal VCExprIfThenElseOp() {
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitIfThenElseOp(expr, arg);
+ }
+ }
+
+ public class VCExprCustomOp : VCExprOp {
+ public readonly string/*!*/ Name;
+ int arity;
+ public readonly Type/*!*/ Type;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Name != null);
+ Contract.Invariant(Type != null);
+ }
+
+ public VCExprCustomOp(string/*!*/ name, int arity, Type/*!*/ type) {
+ Contract.Requires(name != null);
+ Contract.Requires(type != null);
+ this.Name = name;
+ this.arity = arity;
+ this.Type = type;
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ VCExprCustomOp t = that as VCExprCustomOp;
+ if (t == null)
+ return false;
+ return this.Name == t.Name && this.arity == t.arity && this.Type == t.Type;
+ }
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override int GetHashCode() {
+ int h = Name.GetHashCode();
+ h = 7823 * h + arity;
+ h = 7823 * h + Type.GetHashCode();
+ return h;
+ }
+ public override int Arity {
+ get {
+ return arity;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return 0;
+ }
+ }
+ public override Type/*!*/ InferType(List<VCExpr/*!*/>/*!*/ args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires((cce.NonNullElements(args)));
+ //Contract.Requires((cce.NonNullElements(typeArgs)));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return Type;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry/*!*/ expr, IVCExprOpVisitor<Result, Arg>/*!*/ visitor, Arg arg) {
+ //Contract.Requires(expr != null);
+ //Contract.Requires(visitor != null);
+ return visitor.VisitCustomOp(expr, arg);
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Bitvector operators
+
+ public class VCExprBvOp : VCExprOp {
+ public readonly int Bits;
+
+ public override int Arity {
+ get {
+ return 1;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return 0;
+ }
+ }
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return Type.GetBvType(Bits);
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprBvOp)
+ return this.Bits == ((VCExprBvOp)that).Bits;
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Bits * 81748912;
+ }
+
+ internal VCExprBvOp(int bits) {
+ this.Bits = bits;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitBvOp(expr, arg);
+ }
+ }
+
+ public class VCExprBvExtractOp : VCExprOp {
+ public readonly int Start;
+ public readonly int End;
+ public readonly int Total; // the number of bits from which the End-Start bits are extracted
+
+ public override int Arity {
+ get {
+ return 1;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return 0;
+ }
+ }
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return Type.GetBvType(End - Start);
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprBvExtractOp) {
+ VCExprBvExtractOp/*!*/ thatExtract = (VCExprBvExtractOp)that;
+ return this.Start == thatExtract.Start && this.End == thatExtract.End && this.Total == thatExtract.Total;
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Start * 81912 + End * 978132 + Total * 571289;
+ }
+
+ internal VCExprBvExtractOp(int start, int end, int total) {
+ Contract.Requires(0 <= start && start <= end && end <= total);
+ this.Start = start;
+ this.End = end;
+ this.Total = total;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitBvExtractOp(expr, arg);
+ }
+ }
+
+ public class VCExprBvConcatOp : VCExprOp {
+ public readonly int LeftSize;
+ public readonly int RightSize;
+
+ public override int Arity {
+ get {
+ return 2;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return 0;
+ }
+ }
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return Type.GetBvType(args[0].Type.BvBits + args[1].Type.BvBits);
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprBvConcatOp) {
+ VCExprBvConcatOp thatConcat = (VCExprBvConcatOp)that;
+ return this.LeftSize == thatConcat.LeftSize && this.RightSize == thatConcat.RightSize;
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return LeftSize * 81912 + RightSize * 978132;
+ }
+
+ internal VCExprBvConcatOp(int leftSize, int rightSize) {
+ Contract.Requires(0 <= leftSize && 0 <= rightSize);
+ this.LeftSize = leftSize;
+ this.RightSize = rightSize;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitBvConcatOp(expr, arg);
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // References to user-defined Boogie functions
+
+ public class VCExprBoogieFunctionOp : VCExprOp {
+ public readonly Function Func;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Func != null);
+ }
+
+
+ public override int Arity {
+ get {
+ return Func.InParams.Count;
+ }
+ }
+ public override int TypeParamArity {
+ get {
+ return Func.TypeParameters.Count;
+ }
+ }
+ public override Type InferType(List<VCExpr> args, List<Type/*!*/>/*!*/ typeArgs) {
+ //Contract.Requires(cce.NonNullElements(typeArgs));
+ //Contract.Requires(cce.NonNullElements(args));
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Contract.Assert(TypeParamArity == Func.TypeParameters.Count);
+ if (TypeParamArity == 0)
+ return cce.NonNull(Func.OutParams[0]).TypedIdent.Type;
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ subst = new Dictionary<TypeVariable/*!*/, Type/*!*/>(TypeParamArity);
+ for (int i = 0; i < TypeParamArity; ++i)
+ subst.Add(Func.TypeParameters[i], typeArgs[i]);
+ return cce.NonNull(Func.OutParams[0]).TypedIdent.Type.Substitute(subst);
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprBoogieFunctionOp)
+ return this.Func.Equals(((VCExprBoogieFunctionOp)that).Func);
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Func.GetHashCode() + 18731;
+ }
+
+ // we require that the result type of the expression is specified, because we
+ // do not want to perform full type inference at this point
+ internal VCExprBoogieFunctionOp(Function func) {
+ Contract.Requires(func != null);
+ this.Func = func;
+ }
+ public override Result Accept<Result, Arg>
+ (VCExprNAry expr, IVCExprOpVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ //Contract.Requires(expr != null);
+ return visitor.VisitBoogieFunctionOp(expr, arg);
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Binders (quantifiers and let-expressions). We introduce our own class for
+ // term variables, but use the Boogie-AST class for type variables
+
+ public class VCExprVar : VCExpr {
+ // the name of the variable. Note that the name is not used for comparison,
+ // i.e., there can be two distinct variables with the same name
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Name != null);
+ Contract.Invariant(VarType != null);
+ }
+
+ public readonly string/*!*/ Name;
+ private readonly Type/*!*/ VarType;
+ public override Type/*!*/ Type {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ return VarType;
+ }
+ }
+
+ internal VCExprVar(string name, Type type) {
+ Contract.Requires(type != null);
+ Contract.Requires(name != null);
+ this.Name = name;
+ this.VarType = type;
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this, arg);
+ }
+ }
+
+ public class VCExprConstant : VCExprVar
+ {
+ internal VCExprConstant(string name, Type type) : base(name,type) {
+ Contract.Requires(type != null);
+ Contract.Requires(name != null);
+ }
+ }
+
+ public abstract class VCExprBinder : VCExpr {
+ public readonly VCExpr/*!*/ Body;
+ public readonly List<TypeVariable/*!*/>/*!*/ TypeParameters;
+ public readonly List<VCExprVar/*!*/>/*!*/ BoundVars;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Body != null);
+ Contract.Invariant(cce.NonNullElements(TypeParameters));
+ Contract.Invariant(cce.NonNullElements(BoundVars));
+ }
+
+
+ public override Type/*!*/ Type {
+ get {
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ return Body.Type;
+ }
+ }
+
+ internal VCExprBinder(List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ boundVars, VCExpr body) {
+ Contract.Requires(body != null);
+ Contract.Requires(cce.NonNullElements(boundVars));
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Requires(boundVars.Count + typeParams.Count > 0); // only nontrivial binders ...
+ this.TypeParameters = typeParams;
+ this.BoundVars = boundVars;
+ this.Body = body;
+ }
+ }
+
+ public class VCTrigger {
+ public readonly bool Pos;
+ public readonly List<VCExpr/*!*/>/*!*/ Exprs;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Exprs != null);
+ }
+
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCTrigger) {
+ VCTrigger/*!*/ thatTrigger = (VCTrigger)that;
+ return this.Pos == thatTrigger.Pos &&
+ HelperFuns.SameElements(this.Exprs, thatTrigger.Exprs);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return (Pos ? 913821 : 871334) +
+ HelperFuns.PolyHash(123, 7, this.Exprs);
+ }
+
+ public VCTrigger(bool pos, List<VCExpr> exprs) {
+ Contract.Requires(cce.NonNullElements(exprs));
+ this.Pos = pos;
+ this.Exprs = exprs;
+ }
+ }
+
+ public class VCQuantifierInfos {
+ public readonly string qid;
+ public readonly int uniqueId;
+ public readonly bool bvZ3Native;
+ public QKeyValue attributes;
+
+ public VCQuantifierInfos(string qid, int uniqueId, bool bvZ3Native, QKeyValue attributes) {
+ this.qid = qid;
+ this.uniqueId = uniqueId;
+ this.bvZ3Native = bvZ3Native;
+ this.attributes = attributes;
+ }
+ }
+
+ public enum Quantifier {
+ ALL,
+ EX
+ };
+
+ public class VCExprQuantifier : VCExprBinder {
+ public readonly Quantifier Quan;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Infos != null);
+ Contract.Invariant(cce.NonNullElements(Triggers));
+ }
+
+
+ public readonly List<VCTrigger/*!*/>/*!*/ Triggers;
+ public readonly VCQuantifierInfos Infos;
+
+ // Equality is /not/ modulo bound renaming at this point
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprQuantifier) {
+ VCExprQuantifier/*!*/ thatQuan = (VCExprQuantifier)that;
+ return this.Quan == thatQuan.Quan &&
+ HelperFuns.SameElements(this.Triggers, thatQuan.Triggers) &&
+ HelperFuns.SameElements(this.TypeParameters, thatQuan.TypeParameters) &&
+ HelperFuns.SameElements(this.BoundVars, thatQuan.BoundVars) &&
+ this.Body.Equals(thatQuan.Body);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return Quan.GetHashCode() +
+ HelperFuns.PolyHash(973219, 7, TypeParameters) +
+ HelperFuns.PolyHash(998431, 9, BoundVars) +
+ HelperFuns.PolyHash(123, 11, Triggers);
+ }
+
+ internal VCExprQuantifier(Quantifier kind, List<TypeVariable/*!*/>/*!*/ typeParams, List<VCExprVar/*!*/>/*!*/ boundVars, List<VCTrigger/*!*/>/*!*/ triggers, VCQuantifierInfos infos, VCExpr body)
+ : base(typeParams, boundVars, body) {
+ Contract.Requires(body != null);
+ Contract.Requires(infos != null);
+ Contract.Requires(cce.NonNullElements(triggers));
+ Contract.Requires(cce.NonNullElements(boundVars));
+ Contract.Requires(cce.NonNullElements(typeParams));
+
+ this.Quan = kind;
+ this.Triggers = triggers;
+ this.Infos = infos;
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this, arg);
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Let-Bindings
+
+ public class VCExprLetBinding {
+ public readonly VCExprVar V;
+ public readonly VCExpr E;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(V != null);
+ Contract.Invariant(E != null);
+ }
+
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprLetBinding) {
+ VCExprLetBinding/*!*/ thatB = (VCExprLetBinding)that;
+ return this.V.Equals(thatB.V) && this.E.Equals(thatB.E);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return V.GetHashCode() * 71261 + E.GetHashCode();
+ }
+
+ internal VCExprLetBinding(VCExprVar v, VCExpr e) {
+ Contract.Requires(e != null);
+ Contract.Requires(v != null);
+ this.V = v;
+ this.E = e;
+ Contract.Assert(v.Type.Equals(e.Type));
+ }
+ }
+
+ public class VCExprLet : VCExprBinder, IEnumerable<VCExprLetBinding/*!*/> {
+ private readonly List<VCExprLetBinding/*!*/>/*!*/ Bindings;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(cce.NonNullElements(Bindings));
+
+ }
+
+
+ public int Length {
+ get {
+ return Bindings.Count;
+ }
+ }
+ public VCExprLetBinding this[int index] {
+ get {
+ Contract.Ensures(Contract.Result<VCExprLetBinding>() != null);
+ return Bindings[index];
+ }
+ }
+
+ [Pure]
+ [Reads(ReadsAttribute.Reads.Nothing)]
+ public override bool Equals(object that) {
+ if (Object.ReferenceEquals(this, that))
+ return true;
+ if (that is VCExprLet) {
+ VCExprLet/*!*/ thatLet = (VCExprLet)that;
+ return this.Body.Equals(thatLet.Body) &&
+ HelperFuns.SameElements(this, (VCExprLet)that);
+ }
+ return false;
+ }
+ [Pure]
+ public override int GetHashCode() {
+ return HelperFuns.PolyHash(Body.GetHashCode(), 9, Bindings);
+ }
+
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ public IEnumerator<VCExprLetBinding/*!*/>/*!*/ GetEnumerator() {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerator<VCExprLetBinding>>()));
+ return Bindings.GetEnumerator();
+ }
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ Contract.Ensures(Contract.Result<IEnumerator>() != null);
+ return Bindings.GetEnumerator();
+ }
+
+ private static List<VCExprVar/*!*/>/*!*/ toSeq(List<VCExprLetBinding/*!*/>/*!*/ bindings) {
+ Contract.Requires(cce.NonNullElements(bindings));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+ List<VCExprVar> res = new List<VCExprVar>();
+ foreach (VCExprLetBinding/*!*/ b in bindings)
+ res.Add(b.V);
+ return res;
+ }
+
+ internal VCExprLet(List<VCExprLetBinding/*!*/>/*!*/ bindings, VCExpr/*!*/ body)
+ : base(new List<TypeVariable/*!*/>(), toSeq(bindings), body) {
+ Contract.Requires(cce.NonNullElements(bindings));
+ Contract.Requires(body != null);
+ this.Bindings = bindings;
+ }
+ public override Result Accept<Result, Arg>(IVCExprVisitor<Result, Arg> visitor, Arg arg) {
+ //Contract.Requires(visitor != null);
+ return visitor.Visit(this, arg);
+ }
+ }
+}
diff --git a/Source/VCExpr/VCExprASTPrinter.cs b/Source/VCExpr/VCExprASTPrinter.cs
index 00e6fb9c..2af4708d 100644
--- a/Source/VCExpr/VCExprASTPrinter.cs
+++ b/Source/VCExpr/VCExprASTPrinter.cs
@@ -1,360 +1,360 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using Microsoft.Basetypes;
-
-// A simple visitor for turning a VCExpr into a human-readable string
-// (S-expr syntax)
-
-namespace Microsoft.Boogie.VCExprAST {
-
- public class VCExprPrinter : IVCExprVisitor<bool, TextWriter/*!*/> {
- private VCExprOpPrinter OpPrinterVar = null;
- private VCExprOpPrinter/*!*/ OpPrinter {
- get {
- Contract.Ensures(Contract.Result<VCExprOpPrinter>() != null);
-
- if (OpPrinterVar == null)
- OpPrinterVar = new VCExprOpPrinter(this);
- return OpPrinterVar;
- }
- }
-
- public void Print(VCExpr expr, TextWriter wr) {
- Contract.Requires(wr != null);
- Contract.Requires(expr != null);
- expr.Accept<bool, TextWriter/*!*/>(this, wr);
- }
-
- public bool Visit(VCExprLiteral node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- if (node == VCExpressionGenerator.True) {
- wr.Write("true");
- } else if (node == VCExpressionGenerator.False) {
- wr.Write("false");
- } else if (node is VCExprIntLit) {
- wr.Write(((VCExprIntLit)node).Val);
- } else {
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- return true;
- }
- public bool Visit(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- VCExprOp/*!*/ op = node.Op;
- Contract.Assert(op != null);
-
- if (op.Equals(VCExpressionGenerator.AndOp) ||
- op.Equals(VCExpressionGenerator.OrOp)) {
- // handle these operators without recursion
-
- wr.Write("({0}",
- op.Equals(VCExpressionGenerator.AndOp) ? "And" : "Or");
- IEnumerator/*!*/ enumerator = new VCExprNAryUniformOpEnumerator(node);
- Contract.Assert(enumerator != null);
- while (enumerator.MoveNext()) {
- VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
- if (naryExpr == null || !naryExpr.Op.Equals(op)) {
- wr.Write(" ");
- Print(cce.NonNull((VCExpr/*!*/)enumerator.Current), wr);
- }
- }
-
- wr.Write(")");
-
- return true;
- }
-
- return node.Accept<bool, TextWriter/*!*/>(OpPrinter, wr);
- }
- public bool Visit(VCExprVar node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- wr.Write(node.Name);
- return true;
- }
- public bool Visit(VCExprQuantifier node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- string/*!*/ quan = node.Quan == Quantifier.ALL ? "Forall" : "Exists";
- Contract.Assert(quan != null);
-
- wr.Write("({0} ", quan);
-
- if (node.TypeParameters.Count > 0) {
- wr.Write("<");
- string/*!*/ sep = "";
- foreach (TypeVariable/*!*/ v in node.TypeParameters) {
- Contract.Assert(v != null);
- wr.Write(sep);
- sep = ", ";
- wr.Write("{0}", v.Name);
- }
- wr.Write("> ");
- }
-
- if (node.BoundVars.Count > 0) {
- string/*!*/ sep = "";
- foreach (VCExprVar/*!*/ v in node.BoundVars) {
- Contract.Assert(v != null);
- wr.Write(sep);
- sep = ", ";
- Print(v, wr);
- }
- wr.Write(" ");
- }
-
- wr.Write(":: ");
-
- if (node.Triggers.Count > 0) {
- wr.Write("{0} ", "{");
- string/*!*/ sep = "";
- foreach (VCTrigger/*!*/ t in node.Triggers) {
- Contract.Assert(t != null);
- wr.Write(sep);
- sep = ", ";
- string/*!*/ sep2 = "";
- foreach (VCExpr/*!*/ e in t.Exprs) {
- Contract.Assert(e != null);
- wr.Write(sep2);
- sep2 = "+";
- Print(e, wr);
- }
- }
- wr.Write(" {0} ", "}");
- }
-
- Print(node.Body, wr);
- wr.Write(")");
- return true;
- }
- public bool Visit(VCExprLet node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- wr.Write("(Let ");
-
- string/*!*/ sep = "";
- foreach (VCExprLetBinding/*!*/ b in node) {
- Contract.Assert(b != null);
- wr.Write(sep);
- sep = ", ";
- Print(b.V, wr);
- wr.Write(" = ");
- Print(b.E, wr);
- }
- wr.Write(" ");
-
- Print(node.Body, wr);
- wr.Write(")");
- return true;
- }
- }
-
- public class VCExprOpPrinter : IVCExprOpVisitor<bool, TextWriter/*!*/> {
- private VCExprPrinter/*!*/ ExprPrinter;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(ExprPrinter != null);
- }
-
-
- public VCExprOpPrinter(VCExprPrinter exprPrinter) {
- Contract.Requires(exprPrinter != null);
- this.ExprPrinter = exprPrinter;
- }
-
- private bool PrintNAry(string op, VCExprNAry node, TextWriter wr) {
- Contract.Requires(wr != null);
- Contract.Requires(node != null);
- Contract.Requires(op != null);
- wr.Write("({0}", op);
- foreach (VCExpr/*!*/ arg in node) {
- Contract.Assert(arg != null);
- wr.Write(" ");
- ExprPrinter.Print(arg, wr);
- }
- wr.Write(")");
- return true;
- }
-
- public bool VisitNotOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("!", node, wr);
- }
- public bool VisitEqOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("==", node, wr);
- }
- public bool VisitNeqOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("!=", node, wr);
- }
- public bool VisitAndOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public bool VisitOrOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
- public bool VisitImpliesOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("Implies", node, wr);
- }
- public bool VisitDistinctOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("Distinct", node, wr);
- }
- public bool VisitLabelOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- VCExprLabelOp/*!*/ op = (VCExprLabelOp)node.Op;
- Contract.Assert(op != null);
- return PrintNAry("Label " + op.label, node, wr);
- }
- public bool VisitSelectOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("Select", node, wr);
- }
- public bool VisitStoreOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("Store", node, wr);
- }
- public bool VisitBvOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("Bv", node, wr);
- }
- public bool VisitBvExtractOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("BvExtract", node, wr);
- }
- public bool VisitBvConcatOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("BvConcat", node, wr);
- }
- public bool VisitIfThenElseOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("if-then-else", node, wr);
- }
- public bool VisitCustomOp(VCExprNAry/*!*/ node, TextWriter/*!*/ wr) {
- //Contract.Requires(node!=null);
- //Contract.Requires(wr != null);
- VCExprCustomOp op = (VCExprCustomOp)node.Op;
- return PrintNAry(op.Name, node, wr);
- }
- public bool VisitAddOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- if (CommandLineOptions.Clo.ReflectAdd) {
- return PrintNAry("Reflect$Add", node, wr);
- } else {
- return PrintNAry("+", node, wr);
- }
- }
- public bool VisitSubOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("-", node, wr);
- }
- public bool VisitMulOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("*", node, wr);
- }
- public bool VisitDivOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("div", node, wr);
- }
- public bool VisitModOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("mod", node, wr);
- }
- public bool VisitRealDivOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("/", node, wr);
- }
- public bool VisitPowOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("**", node, wr);
- }
- public bool VisitLtOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("<", node, wr);
- }
- public bool VisitLeOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("<=", node, wr);
- }
- public bool VisitGtOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry(">", node, wr);
- }
- public bool VisitGeOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry(">=", node, wr);
- }
- public bool VisitSubtypeOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("<:", node, wr);
- }
- public bool VisitSubtype3Op(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("<::", node, wr);
- }
- public bool VisitToIntOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("int", node, wr);
- }
- public bool VisitToRealOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- return PrintNAry("real", node, wr);
- }
- public bool VisitBoogieFunctionOp(VCExprNAry node, TextWriter wr) {
- //Contract.Requires(wr != null);
- //Contract.Requires(node != null);
- VCExprBoogieFunctionOp/*!*/ op = (VCExprBoogieFunctionOp)node.Op;
- Contract.Assert(op != null);
- return PrintNAry(op.Func.Name, node, wr);
- }
- }
-
-
-}
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Microsoft.Basetypes;
+
+// A simple visitor for turning a VCExpr into a human-readable string
+// (S-expr syntax)
+
+namespace Microsoft.Boogie.VCExprAST {
+
+ public class VCExprPrinter : IVCExprVisitor<bool, TextWriter/*!*/> {
+ private VCExprOpPrinter OpPrinterVar = null;
+ private VCExprOpPrinter/*!*/ OpPrinter {
+ get {
+ Contract.Ensures(Contract.Result<VCExprOpPrinter>() != null);
+
+ if (OpPrinterVar == null)
+ OpPrinterVar = new VCExprOpPrinter(this);
+ return OpPrinterVar;
+ }
+ }
+
+ public void Print(VCExpr expr, TextWriter wr) {
+ Contract.Requires(wr != null);
+ Contract.Requires(expr != null);
+ expr.Accept<bool, TextWriter/*!*/>(this, wr);
+ }
+
+ public bool Visit(VCExprLiteral node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ if (node == VCExpressionGenerator.True) {
+ wr.Write("true");
+ } else if (node == VCExpressionGenerator.False) {
+ wr.Write("false");
+ } else if (node is VCExprIntLit) {
+ wr.Write(((VCExprIntLit)node).Val);
+ } else {
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ return true;
+ }
+ public bool Visit(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ VCExprOp/*!*/ op = node.Op;
+ Contract.Assert(op != null);
+
+ if (op.Equals(VCExpressionGenerator.AndOp) ||
+ op.Equals(VCExpressionGenerator.OrOp)) {
+ // handle these operators without recursion
+
+ wr.Write("({0}",
+ op.Equals(VCExpressionGenerator.AndOp) ? "And" : "Or");
+ IEnumerator/*!*/ enumerator = new VCExprNAryUniformOpEnumerator(node);
+ Contract.Assert(enumerator != null);
+ while (enumerator.MoveNext()) {
+ VCExprNAry naryExpr = enumerator.Current as VCExprNAry;
+ if (naryExpr == null || !naryExpr.Op.Equals(op)) {
+ wr.Write(" ");
+ Print(cce.NonNull((VCExpr/*!*/)enumerator.Current), wr);
+ }
+ }
+
+ wr.Write(")");
+
+ return true;
+ }
+
+ return node.Accept<bool, TextWriter/*!*/>(OpPrinter, wr);
+ }
+ public bool Visit(VCExprVar node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ wr.Write(node.Name);
+ return true;
+ }
+ public bool Visit(VCExprQuantifier node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ string/*!*/ quan = node.Quan == Quantifier.ALL ? "Forall" : "Exists";
+ Contract.Assert(quan != null);
+
+ wr.Write("({0} ", quan);
+
+ if (node.TypeParameters.Count > 0) {
+ wr.Write("<");
+ string/*!*/ sep = "";
+ foreach (TypeVariable/*!*/ v in node.TypeParameters) {
+ Contract.Assert(v != null);
+ wr.Write(sep);
+ sep = ", ";
+ wr.Write("{0}", v.Name);
+ }
+ wr.Write("> ");
+ }
+
+ if (node.BoundVars.Count > 0) {
+ string/*!*/ sep = "";
+ foreach (VCExprVar/*!*/ v in node.BoundVars) {
+ Contract.Assert(v != null);
+ wr.Write(sep);
+ sep = ", ";
+ Print(v, wr);
+ }
+ wr.Write(" ");
+ }
+
+ wr.Write(":: ");
+
+ if (node.Triggers.Count > 0) {
+ wr.Write("{0} ", "{");
+ string/*!*/ sep = "";
+ foreach (VCTrigger/*!*/ t in node.Triggers) {
+ Contract.Assert(t != null);
+ wr.Write(sep);
+ sep = ", ";
+ string/*!*/ sep2 = "";
+ foreach (VCExpr/*!*/ e in t.Exprs) {
+ Contract.Assert(e != null);
+ wr.Write(sep2);
+ sep2 = "+";
+ Print(e, wr);
+ }
+ }
+ wr.Write(" {0} ", "}");
+ }
+
+ Print(node.Body, wr);
+ wr.Write(")");
+ return true;
+ }
+ public bool Visit(VCExprLet node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ wr.Write("(Let ");
+
+ string/*!*/ sep = "";
+ foreach (VCExprLetBinding/*!*/ b in node) {
+ Contract.Assert(b != null);
+ wr.Write(sep);
+ sep = ", ";
+ Print(b.V, wr);
+ wr.Write(" = ");
+ Print(b.E, wr);
+ }
+ wr.Write(" ");
+
+ Print(node.Body, wr);
+ wr.Write(")");
+ return true;
+ }
+ }
+
+ public class VCExprOpPrinter : IVCExprOpVisitor<bool, TextWriter/*!*/> {
+ private VCExprPrinter/*!*/ ExprPrinter;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(ExprPrinter != null);
+ }
+
+
+ public VCExprOpPrinter(VCExprPrinter exprPrinter) {
+ Contract.Requires(exprPrinter != null);
+ this.ExprPrinter = exprPrinter;
+ }
+
+ private bool PrintNAry(string op, VCExprNAry node, TextWriter wr) {
+ Contract.Requires(wr != null);
+ Contract.Requires(node != null);
+ Contract.Requires(op != null);
+ wr.Write("({0}", op);
+ foreach (VCExpr/*!*/ arg in node) {
+ Contract.Assert(arg != null);
+ wr.Write(" ");
+ ExprPrinter.Print(arg, wr);
+ }
+ wr.Write(")");
+ return true;
+ }
+
+ public bool VisitNotOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("!", node, wr);
+ }
+ public bool VisitEqOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("==", node, wr);
+ }
+ public bool VisitNeqOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("!=", node, wr);
+ }
+ public bool VisitAndOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public bool VisitOrOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ Contract.Assert(false);
+ throw new cce.UnreachableException();
+ }
+ public bool VisitImpliesOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("Implies", node, wr);
+ }
+ public bool VisitDistinctOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("Distinct", node, wr);
+ }
+ public bool VisitLabelOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ VCExprLabelOp/*!*/ op = (VCExprLabelOp)node.Op;
+ Contract.Assert(op != null);
+ return PrintNAry("Label " + op.label, node, wr);
+ }
+ public bool VisitSelectOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("Select", node, wr);
+ }
+ public bool VisitStoreOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("Store", node, wr);
+ }
+ public bool VisitBvOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("Bv", node, wr);
+ }
+ public bool VisitBvExtractOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("BvExtract", node, wr);
+ }
+ public bool VisitBvConcatOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("BvConcat", node, wr);
+ }
+ public bool VisitIfThenElseOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("if-then-else", node, wr);
+ }
+ public bool VisitCustomOp(VCExprNAry/*!*/ node, TextWriter/*!*/ wr) {
+ //Contract.Requires(node!=null);
+ //Contract.Requires(wr != null);
+ VCExprCustomOp op = (VCExprCustomOp)node.Op;
+ return PrintNAry(op.Name, node, wr);
+ }
+ public bool VisitAddOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ if (CommandLineOptions.Clo.ReflectAdd) {
+ return PrintNAry("Reflect$Add", node, wr);
+ } else {
+ return PrintNAry("+", node, wr);
+ }
+ }
+ public bool VisitSubOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("-", node, wr);
+ }
+ public bool VisitMulOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("*", node, wr);
+ }
+ public bool VisitDivOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("div", node, wr);
+ }
+ public bool VisitModOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("mod", node, wr);
+ }
+ public bool VisitRealDivOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("/", node, wr);
+ }
+ public bool VisitPowOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("**", node, wr);
+ }
+ public bool VisitLtOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("<", node, wr);
+ }
+ public bool VisitLeOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("<=", node, wr);
+ }
+ public bool VisitGtOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry(">", node, wr);
+ }
+ public bool VisitGeOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry(">=", node, wr);
+ }
+ public bool VisitSubtypeOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("<:", node, wr);
+ }
+ public bool VisitSubtype3Op(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("<::", node, wr);
+ }
+ public bool VisitToIntOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("int", node, wr);
+ }
+ public bool VisitToRealOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ return PrintNAry("real", node, wr);
+ }
+ public bool VisitBoogieFunctionOp(VCExprNAry node, TextWriter wr) {
+ //Contract.Requires(wr != null);
+ //Contract.Requires(node != null);
+ VCExprBoogieFunctionOp/*!*/ op = (VCExprBoogieFunctionOp)node.Op;
+ Contract.Assert(op != null);
+ return PrintNAry(op.Func.Name, node, wr);
+ }
+ }
+
+
+}
diff --git a/Source/VCExpr/VCExprASTVisitors.cs b/Source/VCExpr/VCExprASTVisitors.cs
index ad0c270d..fc1bdd65 100644
--- a/Source/VCExpr/VCExprASTVisitors.cs
+++ b/Source/VCExpr/VCExprASTVisitors.cs
@@ -1,1527 +1,1527 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Linq;
-using Microsoft.Basetypes;
-
-// Some visitor skeletons for the VCExpression AST
-
-namespace Microsoft.Boogie.VCExprAST {
- using Microsoft.Boogie;
-
- [ContractClass(typeof(IVCExprVisitorContracts<,>))]
- public interface IVCExprVisitor<Result, Arg> {
- Result Visit(VCExprLiteral/*!*/ node, Arg arg);
- Result Visit(VCExprNAry/*!*/ node, Arg arg);
- Result Visit(VCExprVar/*!*/ node, Arg arg);
- Result Visit(VCExprQuantifier/*!*/ node, Arg arg);
- Result Visit(VCExprLet/*!*/ node, Arg arg);
- }
- [ContractClassFor(typeof(IVCExprVisitor<,>))]
- public abstract class IVCExprVisitorContracts<Result, Arg> : IVCExprVisitor<Result, Arg> {
- #region IVCExprVisitor Members
-
- public Result Visit(VCExprLiteral node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result Visit(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result Visit(VCExprVar node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result Visit(VCExprQuantifier node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result Visit(VCExprLet node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- #endregion
- }
- [ContractClass(typeof(IVCExprOpVisitorContracts<,>))]
- public interface IVCExprOpVisitor<Result, Arg> {
- Result VisitNotOp(VCExprNAry node, Arg arg);
- Result VisitEqOp(VCExprNAry node, Arg arg);
- Result VisitNeqOp(VCExprNAry node, Arg arg);
- Result VisitAndOp(VCExprNAry node, Arg arg);
- Result VisitOrOp(VCExprNAry node, Arg arg);
- Result VisitImpliesOp(VCExprNAry node, Arg arg);
- Result VisitDistinctOp(VCExprNAry node, Arg arg);
- Result VisitLabelOp(VCExprNAry node, Arg arg);
- Result VisitSelectOp(VCExprNAry node, Arg arg);
- Result VisitStoreOp(VCExprNAry node, Arg arg);
- Result VisitBvOp(VCExprNAry node, Arg arg);
- Result VisitBvExtractOp(VCExprNAry node, Arg arg);
- Result VisitBvConcatOp(VCExprNAry node, Arg arg);
- Result VisitAddOp(VCExprNAry node, Arg arg);
- Result VisitSubOp(VCExprNAry node, Arg arg);
- Result VisitMulOp(VCExprNAry node, Arg arg);
- Result VisitDivOp(VCExprNAry node, Arg arg);
- Result VisitModOp(VCExprNAry node, Arg arg);
- Result VisitRealDivOp(VCExprNAry node, Arg arg);
- Result VisitPowOp(VCExprNAry node, Arg arg);
- Result VisitLtOp(VCExprNAry node, Arg arg);
- Result VisitLeOp(VCExprNAry node, Arg arg);
- Result VisitGtOp(VCExprNAry node, Arg arg);
- Result VisitGeOp(VCExprNAry node, Arg arg);
- Result VisitSubtypeOp(VCExprNAry node, Arg arg);
- Result VisitSubtype3Op(VCExprNAry node, Arg arg);
- Result VisitToIntOp(VCExprNAry node, Arg arg);
- Result VisitToRealOp(VCExprNAry node, Arg arg);
- Result VisitBoogieFunctionOp(VCExprNAry node, Arg arg);
- Result VisitIfThenElseOp(VCExprNAry node, Arg arg);
- Result VisitCustomOp(VCExprNAry node, Arg arg);
- }
- [ContractClassFor(typeof(IVCExprOpVisitor<,>))]
- public abstract class IVCExprOpVisitorContracts<Result, Arg> : IVCExprOpVisitor<Result, Arg> {
- #region IVCExprOpVisitor<Result,Arg> Members
-
- public Result VisitNotOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitEqOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitNeqOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitAndOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitOrOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitImpliesOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitDistinctOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitLabelOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitSelectOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitStoreOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitBvOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitBvExtractOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitBvConcatOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitAddOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitSubOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitMulOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitDivOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitModOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitRealDivOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitPowOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitLtOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitLeOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitGtOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitGeOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitSubtypeOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitSubtype3Op(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitToIntOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitToRealOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitBoogieFunctionOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitIfThenElseOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- public Result VisitCustomOp(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
-
- #endregion
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // Standard implementations that make it easier to create own visitors
-
- // Simple traversal of VCExprs. The Visit implementations work
- // recursively, apart from the implementation for VCExprNAry that
- // uses a stack when applied to nested nodes with the same
- // operator, e.g., (AND (AND (AND ...) ...) ...). This is necessary
- // to avoid stack overflows
-
-
- [ContractClass(typeof(TraversingVCExprVisitorContracts<,>))]
- public abstract class TraversingVCExprVisitor<Result, Arg>
- : IVCExprVisitor<Result, Arg> {
- protected abstract Result StandardResult(VCExpr/*!*/ node, Arg arg);
-
- public Result Traverse(VCExpr node, Arg arg) {
- Contract.Requires(node != null);
- return node.Accept(this, arg);
- }
-
- public virtual Result Visit(VCExprLiteral node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
-
- public virtual Result Visit(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- Result res = StandardResult(node, arg);
-
-
- if (node.TypeParamArity == 0 &&
- (node.Op == VCExpressionGenerator.AndOp ||
- node.Op == VCExpressionGenerator.OrOp ||
- node.Op == VCExpressionGenerator.ImpliesOp)) {
- Contract.Assert(node.Op != null);
- VCExprOp op = node.Op;
- HashSet<VCExprOp> ops = new HashSet<VCExprOp>();
- ops.Add(VCExpressionGenerator.AndOp);
- ops.Add(VCExpressionGenerator.OrOp);
- ops.Add(VCExpressionGenerator.ImpliesOp);
- IEnumerator enumerator = new VCExprNAryMultiUniformOpEnumerator(node, ops);
- while (enumerator.MoveNext()) {
- VCExpr expr = cce.NonNull((VCExpr)enumerator.Current);
- VCExprNAry naryExpr = expr as VCExprNAry;
- if (naryExpr == null || !ops.Contains(naryExpr.Op)) {
- expr.Accept(this, arg);
- } else {
- StandardResult(expr, arg);
- }
- }
- } else {
- foreach (VCExpr e in node) {
- Contract.Assert(e != null);
- e.Accept(this, arg);
- }
- }
-
- return res;
- }
-
- public virtual Result Visit(VCExprVar node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result Visit(VCExprQuantifier node, Arg arg) {
- //Contract.Requires(node != null);
- Result res = StandardResult(node, arg);
- foreach (VCTrigger/*!*/ trigger in node.Triggers) {
- Contract.Assert(trigger != null);
- foreach (VCExpr/*!*/ expr in trigger.Exprs) {
- Contract.Assert(expr != null);
- expr.Accept(this, arg);
- }
- }
- node.Body.Accept(this, arg);
- return res;
- }
- public virtual Result Visit(VCExprLet node, Arg arg) {
- //Contract.Requires(node != null);
- Result res = StandardResult(node, arg);
- // visit the bound expressions first
- foreach (VCExprLetBinding/*!*/ binding in node) {
- Contract.Assert(binding != null);
- binding.E.Accept(this, arg);
- }
- node.Body.Accept(this, arg);
- return res;
- }
- }
- [ContractClassFor(typeof(TraversingVCExprVisitor<,>))]
- public abstract class TraversingVCExprVisitorContracts<Result, Arg> : TraversingVCExprVisitor<Result, Arg> {
- protected override Result StandardResult(VCExpr node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- // Class to iterate over the nodes of a tree of VCExprNAry. This is
- // used to avoid handling such VCExpr recursively, which can easily
- // lead to stack overflows
-
- public class VCExprNAryEnumerator : IEnumerator {
-
- private readonly VCExprNAry/*!*/ CompleteExpr;
- private VCExpr CurrentExpr = null;
- private readonly Stack<VCExpr/*!*/>/*!*/ ExprTodo = new Stack<VCExpr/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(CompleteExpr != null);
- Contract.Invariant(cce.NonNullElements(ExprTodo));
- }
-
- public VCExprNAryEnumerator(VCExprNAry completeExpr) {
- Contract.Requires(completeExpr != null);
- this.CompleteExpr = completeExpr;
- Stack<VCExpr/*!*/>/*!*/ exprTodo = new Stack<VCExpr/*!*/>();
- exprTodo.Push(completeExpr);
- ExprTodo = exprTodo;
- }
-
- // Method using which a subclass can decide whether the
- // subexpressions of an expression should be enumerated as well
- // The default is to enumerate all nodes
- protected virtual bool Descend(VCExprNAry expr) {
- Contract.Requires(expr != null);
- return true;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public bool MoveNext() {
- if (ExprTodo.Count == 0)
- return false;
-
- CurrentExpr = ExprTodo.Pop();
- VCExprNAry currentNAry = CurrentExpr as VCExprNAry;
- if (currentNAry != null && Descend(currentNAry)) {
- for (int i = currentNAry.Arity - 1; i >= 0; --i)
- ExprTodo.Push(currentNAry[i]);
- }
-
- return true;
- }
-
- public object Current {
- get {
- return cce.NonNull(CurrentExpr);
- }
- }
-
- public void Reset() {
- ExprTodo.Clear();
- CurrentExpr = null;
- ExprTodo.Push(CompleteExpr);
- }
- }
-
-
- //////////////////////////////////////////////////////////////////////////////
-
- public class VCExprNAryUniformOpEnumerator : VCExprNAryEnumerator {
- private readonly VCExprOp/*!*/ Op;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Op != null);
- }
-
- public VCExprNAryUniformOpEnumerator(VCExprNAry completeExpr)
- : base(completeExpr) {
- Contract.Requires(completeExpr != null);
-
- this.Op = completeExpr.Op;
- }
- protected override bool Descend(VCExprNAry expr) {
- //Contract.Requires(expr != null);
- return expr.Op.Equals(Op) &&
- // we never skip nodes with type parameters
- // (those are too interesting ...)
- expr.TypeParamArity == 0;
- }
- }
-
- public class VCExprNAryMultiUniformOpEnumerator : VCExprNAryEnumerator
- {
- private readonly HashSet<VCExprOp> Ops;
- [ContractInvariantMethod]
- void ObjectInvariant()
- {
- Contract.Invariant(Ops != null);
- }
-
- public VCExprNAryMultiUniformOpEnumerator(VCExprNAry completeExpr, HashSet<VCExprOp> ops)
- : base(completeExpr)
- {
- Contract.Requires(completeExpr != null);
-
- this.Ops = ops;
- }
- protected override bool Descend(VCExprNAry expr)
- {
- return Ops.Contains(expr.Op) && expr.TypeParamArity == 0;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // Visitor that knows about the variables bound at each location in a VCExpr
-
- public abstract class BoundVarTraversingVCExprVisitor<Result, Arg>
- : TraversingVCExprVisitor<Result, Arg> {
- // Maps with all variables bound above a certain location in the VCExpression.
- // The value of the map tells how often a particular symbol was bound
- private readonly IDictionary<VCExprVar/*!*/, int>/*!*/ BoundTermVarsDict =
- new Dictionary<VCExprVar/*!*/, int>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(BoundTermVarsDict != null);
- Contract.Invariant(BoundTypeVarsDict != null);
- }
-
- private readonly IDictionary<TypeVariable/*!*/, int>/*!*/ BoundTypeVarsDict =
- new Dictionary<TypeVariable/*!*/, int>();
-
- protected ICollection<VCExprVar/*!*/>/*!*/ BoundTermVars {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<VCExprVar>>()));
- return BoundTermVarsDict.Keys;
- }
- }
- protected ICollection<TypeVariable/*!*/>/*!*/ BoundTypeVars {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<TypeVariable>>()));
- return BoundTypeVarsDict.Keys;
- }
- }
-
- private void AddBoundVar<T>(IDictionary<T, int> dict, T sym) {
- Contract.Requires(sym != null);
- Contract.Requires(dict != null);
- int n;
- if (dict.TryGetValue(sym, out n))
- dict[sym] = n + 1;
- else
- dict[sym] = 1;
- }
-
- private void RemoveBoundVar<T>(IDictionary<T/*!*/, int/*!*/>/*!*/ dict, T sym) {
- Contract.Requires(sym != null);
- Contract.Requires(dict != null);
- int n;
- bool b = dict.TryGetValue(sym, out n);
- Contract.Assert(b && n > 0);
- if (n == 1)
- dict.Remove(sym);
- else
- dict[sym] = n - 1;
- }
-
- public override Result Visit(VCExprQuantifier node, Arg arg) {
- Contract.Requires(node != null);
- // we temporarily add bound (term and type) variables to the
- // corresponding lists
- foreach (VCExprVar/*!*/ v in node.BoundVars) {
- Contract.Assert(v != null);
- AddBoundVar<VCExprVar>(BoundTermVarsDict, v);
- }
- foreach (TypeVariable/*!*/ v in node.TypeParameters) {
- Contract.Assert(v != null);
- AddBoundVar<TypeVariable>(BoundTypeVarsDict, v);
- }
-
- Result res;
- try {
- res = VisitAfterBinding(node, arg);
- } finally {
- foreach (VCExprVar/*!*/ v in node.BoundVars) {
- Contract.Assert(v != null);
- RemoveBoundVar<VCExprVar>(BoundTermVarsDict, v);
- }
- foreach (TypeVariable/*!*/ v in node.TypeParameters) {
- Contract.Assert(v != null);
- RemoveBoundVar<TypeVariable>(BoundTypeVarsDict, v);
- }
- }
- return res;
- }
- public override Result Visit(VCExprLet node, Arg arg) {
- Contract.Requires(node != null);
- // we temporarily add bound term variables to the
- // corresponding lists
- foreach (VCExprVar/*!*/ v in node.BoundVars) {
- Contract.Assert(v != null);
- AddBoundVar<VCExprVar>(BoundTermVarsDict, v);
- }
-
- Result res;
- try {
- res = VisitAfterBinding(node, arg);
- } finally {
- foreach (VCExprVar/*!*/ v in node.BoundVars) {
- Contract.Assert(v != null);
- RemoveBoundVar<VCExprVar>(BoundTermVarsDict, v);
- }
- }
- return res;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // The possibility is provided to look at a (quantifier or let) node
- // after its bound variables have been registered
- // (when overriding the normal visit-methods, the node will be visited
- // before the binding happens)
-
- protected virtual Result VisitAfterBinding(VCExprQuantifier node, Arg arg) {
- Contract.Requires(node != null);
- return base.Visit(node, arg);
- }
-
- protected virtual Result VisitAfterBinding(VCExprLet node, Arg arg) {
- Contract.Requires(node != null);
- return base.Visit(node, arg);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // General visitor for recursively collecting information in a VCExpr.
- // As the visitor is not used anywhere for the time being, it maybe should
- // be removed
-
- [ContractClass(typeof(CollectingVCExprVisitorContracts<,>))]
- public abstract class CollectingVCExprVisitor<Result, Arg>
- : IVCExprVisitor<Result, Arg> {
- protected abstract Result CombineResults(List<Result>/*!*/ results, Arg arg);
-
- public Result Collect(VCExpr node, Arg arg) {
- Contract.Requires(node != null);
- return node.Accept(this, arg);
- }
-
- public virtual Result Visit(VCExprLiteral node, Arg arg) {
- //Contract.Requires(node != null);
- return CombineResults(new List<Result>(), arg);
- }
- public virtual Result Visit(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- List<Result>/*!*/ results = new List<Result>();
- foreach (VCExpr/*!*/ subnode in node) {
- Contract.Assert(subnode != null);
- results.Add(subnode.Accept(this, arg));
- }
- return CombineResults(results, arg);
- }
- public virtual Result Visit(VCExprVar node, Arg arg) {
- //Contract.Requires(node != null);
- return CombineResults(new List<Result>(), arg);
- }
- public virtual Result Visit(VCExprQuantifier node, Arg arg) {
- //Contract.Requires(node != null);
- List<Result>/*!*/ result = new List<Result>();
- result.Add(node.Body.Accept(this, arg));
- foreach (VCTrigger/*!*/ trigger in node.Triggers) {
- Contract.Assert(trigger != null);
- foreach (VCExpr/*!*/ expr in trigger.Exprs) {
- Contract.Assert(expr != null);
- result.Add(expr.Accept(this, arg));
- }
- }
- return CombineResults(result, arg);
- }
- public virtual Result Visit(VCExprLet node, Arg arg) {
- //Contract.Requires(node != null);
- List<Result>/*!*/ results = new List<Result>();
- // visit the bound expressions first
- foreach (VCExprLetBinding/*!*/ binding in node) {
- Contract.Assert(binding != null);
- results.Add(binding.E.Accept(this, arg));
- }
- results.Add(node.Body.Accept(this, arg));
- return CombineResults(results, arg);
- }
- }
- [ContractClassFor(typeof(CollectingVCExprVisitor<,>))]
- public abstract class CollectingVCExprVisitorContracts<Result, Arg> : CollectingVCExprVisitor<Result, Arg> {
- protected override Result CombineResults(List<Result> results, Arg arg) {
- Contract.Requires(results != null);
- throw new NotImplementedException();
- }
- }
- ////////////////////////////////////////////////////////////////////////////
-
- public class SizeComputingVisitor : TraversingVCExprVisitor<bool, bool> {
-
- private int Size = 0;
-
- public static int ComputeSize(VCExpr expr) {
- Contract.Requires(expr != null);
- SizeComputingVisitor/*!*/ visitor = new SizeComputingVisitor();
- visitor.Traverse(expr, true);
- return visitor.Size;
- }
-
- protected override bool StandardResult(VCExpr node, bool arg) {
- //Contract.Requires(node != null);
- Size = Size + 1;
- return true;
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // Collect all free term and type variables in a VCExpr. Type variables
- // can occur free either in the types of bound variables, or in the type
- // parameters of VCExprNAry.
-
- // the result and argument (of type bool) are not used currently
- public class FreeVariableCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
- public readonly Dictionary<VCExprVar/*!*/, object>/*!*/ FreeTermVars = new Dictionary<VCExprVar/*!*/, object>();
- public readonly List<TypeVariable/*!*/>/*!*/ FreeTypeVars = new List<TypeVariable/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(FreeTermVars != null && Contract.ForAll(FreeTermVars, entry => entry.Key != null));
- Contract.Invariant(cce.NonNullElements(FreeTypeVars));
- }
-
-
- // not used
- protected override bool StandardResult(VCExpr node, bool arg) {
- //Contract.Requires(node != null);
- return true;
- }
-
- public static Dictionary<VCExprVar/*!*/, object>/*!*/ FreeTermVariables(VCExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<Dictionary<VCExprVar, object>>() != null);
- Contract.Ensures(Contract.ForAll(Contract.Result<Dictionary<VCExprVar, object>>(), ftv => ftv.Key != null));
- FreeVariableCollector collector = new FreeVariableCollector();
- collector.Traverse(node, true);
- return collector.FreeTermVars;
- }
-
- public static List<TypeVariable/*!*/>/*!*/ FreeTypeVariables(VCExpr node) {
- Contract.Requires(node != null);
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeVariable>>()));
- FreeVariableCollector collector = new FreeVariableCollector();
- collector.Traverse(node, true);
- return collector.FreeTypeVars;
- }
-
- public void Reset() {
- FreeTermVars.Clear();
- FreeTypeVars.Clear();
- }
-
- public void Collect(VCExpr node) {
- Contract.Requires(node != null);
- Traverse(node, true);
- }
-
- public void Collect(Type type) {
- Contract.Requires(type != null);
- AddTypeVariables(type.FreeVariables.ToList());
- }
-
- /////////////////////////////////////////////////////////////////////////
-
- private void CollectTypeVariables(IEnumerable<VCExprVar/*!*/>/*!*/ boundVars) {
- Contract.Requires(cce.NonNullElements(boundVars));
- foreach (VCExprVar/*!*/ var in boundVars) {
- Contract.Assert(var != null);
- Collect(var.Type);
- }
- }
-
- private void AddTypeVariables(IEnumerable<TypeVariable/*!*/>/*!*/ typeVars) {
- Contract.Requires(cce.NonNullElements(typeVars));
- foreach (TypeVariable/*!*/ tvar in typeVars) {
- Contract.Assert(tvar != null);
- if (!BoundTypeVars.Contains(tvar) && !FreeTypeVars.Contains(tvar))
- FreeTypeVars.Add(tvar);
- }
- }
-
- public override bool Visit(VCExprVar node, bool arg) {
- Contract.Requires(node != null);
- if (!BoundTermVars.Contains(node) && !FreeTermVars.ContainsKey(node)) {
- FreeTermVars.Add(node, null);
- Collect(node.Type);
- }
- return true;
- }
-
- public override bool Visit(VCExprNAry node, bool arg) {
- Contract.Requires(node != null);
- foreach (Type/*!*/ t in node.TypeArguments) {
- Contract.Assert(t != null);
- Collect(t);
- }
- return base.Visit(node, arg);
- }
-
- protected override bool VisitAfterBinding(VCExprQuantifier node, bool arg) {
- //Contract.Requires(node != null);
- CollectTypeVariables(node.BoundVars);
- return base.VisitAfterBinding(node, arg);
- }
-
- protected override bool VisitAfterBinding(VCExprLet node, bool arg) {
- //Contract.Requires(node != null);
- CollectTypeVariables(node.BoundVars);
- return base.VisitAfterBinding(node, arg);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Framework for mutating VCExprs
-
- // The Visit implementations in the following visitor work
- // recursively, apart from the implementation for VCExprNAry that
- // uses its own stack when applied to nested nodes with the same
- // operator, e.g., (AND (AND (AND ...) ...) ...). This is necessary
- // to avoid stack overflows (like in TraversingVCExprVisitor)
-
- public abstract class MutatingVCExprVisitor<Arg>
- : IVCExprVisitor<VCExpr/*!*/, Arg> {
- protected readonly VCExpressionGenerator/*!*/ Gen;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Gen != null);
- }
-
-
- public MutatingVCExprVisitor(VCExpressionGenerator gen) {
- Contract.Requires(gen != null);
- this.Gen = gen;
- }
-
- public VCExpr Mutate(VCExpr expr, Arg arg) {
- Contract.Requires(expr != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return expr.Accept(this, arg);
- }
-
- public List<VCExpr/*!*/>/*!*/ MutateSeq(IEnumerable<VCExpr/*!*/>/*!*/ exprs, Arg arg) {
- Contract.Requires(cce.NonNullElements(exprs));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
- List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>();
- foreach (VCExpr/*!*/ expr in exprs) {
- Contract.Assert(expr != null);
- res.Add(expr.Accept(this, arg));
- }
- return res;
- }
-
- private List<VCExpr/*!*/>/*!*/ MutateList(List<VCExpr/*!*/>/*!*/ exprs, Arg arg) {
- Contract.Requires(cce.NonNullElements(exprs));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
- bool changed = false;
- List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>();
- foreach (VCExpr/*!*/ expr in exprs) {
- Contract.Assert(expr != null);
- VCExpr/*!*/ newExpr = expr.Accept(this, arg);
- if (!Object.ReferenceEquals(expr, newExpr))
- changed = true;
- res.Add(newExpr);
- }
- if (!changed)
- return exprs;
- return res;
- }
-
- public virtual VCExpr Visit(VCExprLiteral node, Arg arg) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return node;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- // Special element used to mark the positions in the todo-stack where
- // results have to be popped from the result-stack.
- private static readonly VCExpr/*!*/ CombineResultsMarker = new VCExprLiteral(Type.Bool);
-
- // The todo-stack contains records of the shape
- //
- // arg0
- // arg1
- // arg2
- // ...
- // CombineResultsMarker
- // f(arg0, arg1, arg2, ...) (the original expression)
-
- private readonly Stack<VCExpr/*!*/>/*!*/ NAryExprTodoStack = new Stack<VCExpr/*!*/>();
- private readonly Stack<VCExpr/*!*/>/*!*/ NAryExprResultStack = new Stack<VCExpr/*!*/>();
- [ContractInvariantMethod]
- void ObjectInvarianta() {
- Contract.Invariant(cce.NonNullElements(NAryExprResultStack));
- Contract.Invariant(cce.NonNullElements(NAryExprTodoStack));
- }
-
-
- private void PushTodo(VCExprNAry exprTodo) {
- Contract.Requires(exprTodo != null);
- NAryExprTodoStack.Push(exprTodo);
- NAryExprTodoStack.Push(CombineResultsMarker);
- for (int i = exprTodo.Arity - 1; i >= 0; --i)
- NAryExprTodoStack.Push(exprTodo[i]);
- }
-
- public virtual bool AvoidVisit(VCExprNAry node, Arg arg)
- {
- return true;
- }
-
- public virtual VCExpr Visit(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- int initialStackSize = NAryExprTodoStack.Count;
- int initialResultStackSize = NAryExprResultStack.Count;
-
- PushTodo(node);
-
- while (NAryExprTodoStack.Count > initialStackSize) {
- VCExpr/*!*/ subExpr = NAryExprTodoStack.Pop();
- Contract.Assert(subExpr != null);
-
- if (Object.ReferenceEquals(subExpr, CombineResultsMarker)) {
- // assemble a result
- VCExprNAry/*!*/ originalExpr = (VCExprNAry)NAryExprTodoStack.Pop();
- Contract.Assert(originalExpr != null);
- VCExprOp/*!*/ op = originalExpr.Op;
- bool changed = false;
- List<VCExpr/*!*/>/*!*/ newSubExprs = new List<VCExpr/*!*/>();
-
- for (int i = op.Arity - 1; i >= 0; --i) {
- VCExpr/*!*/ nextSubExpr = NAryExprResultStack.Pop();
- Contract.Assert(nextSubExpr != null);
- if (!Object.ReferenceEquals(nextSubExpr, originalExpr[i]))
- changed = true;
- newSubExprs.Insert(0, nextSubExpr);
- }
-
- NAryExprResultStack.Push(UpdateModifiedNode(originalExpr, newSubExprs, changed, arg));
- //
- } else {
- //
- VCExprNAry narySubExpr = subExpr as VCExprNAry;
- if (narySubExpr != null && this.AvoidVisit(narySubExpr, arg) &&
- // as in VCExprNAryUniformOpEnumerator, all expressions with
- // type parameters are allowed to be inspected more closely
- narySubExpr.TypeParamArity == 0) {
- PushTodo(narySubExpr);
- } else {
- NAryExprResultStack.Push(subExpr.Accept(this, arg));
- }
- //
- }
- }
-
- Contract.Assert(NAryExprTodoStack.Count == initialStackSize && NAryExprResultStack.Count == initialResultStackSize + 1);
- return NAryExprResultStack.Pop();
- }
-
- protected virtual VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode, List<VCExpr/*!*/>/*!*/ newSubExprs, // has any of the subexpressions changed?
- bool changed,
- Arg arg) {
- Contract.Requires(cce.NonNullElements(newSubExprs));
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- if (changed)
- return Gen.Function(originalNode.Op,
- newSubExprs, originalNode.TypeArguments);
- else
- return originalNode;
- }
-
- ////////////////////////////////////////////////////////////////////////////
-
- public virtual VCExpr Visit(VCExprVar node, Arg arg) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- return node;
- }
-
- protected List<VCTrigger/*!*/>/*!*/ MutateTriggers(List<VCTrigger/*!*/>/*!*/ triggers, Arg arg) {
- Contract.Requires(cce.NonNullElements(triggers));
- Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCTrigger>>()));
- List<VCTrigger/*!*/>/*!*/ newTriggers = new List<VCTrigger/*!*/>();
- bool changed = false;
- foreach (VCTrigger/*!*/ trigger in triggers) {
- Contract.Assert(trigger != null);
- List<VCExpr/*!*/>/*!*/ exprs = trigger.Exprs;
- List<VCExpr/*!*/>/*!*/ newExprs = MutateList(exprs, arg);
-
- if (Object.ReferenceEquals(exprs, newExprs)) {
- newTriggers.Add(trigger);
- } else {
- newTriggers.Add(Gen.Trigger(trigger.Pos, newExprs));
- changed = true;
- }
- }
- if (!changed)
- return triggers;
- return newTriggers;
- }
-
- public virtual VCExpr Visit(VCExprQuantifier node, Arg arg) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- bool changed = false;
-
- VCExpr/*!*/ body = node.Body;
- Contract.Assert(body != null);
- VCExpr/*!*/ newbody = body.Accept(this, arg);
- Contract.Assert(newbody != null);
- if (!Object.ReferenceEquals(body, newbody))
- changed = true;
-
- // visit the trigger expressions as well
- List<VCTrigger/*!*/>/*!*/ triggers = node.Triggers;
- Contract.Assert(cce.NonNullElements(triggers));
- List<VCTrigger/*!*/>/*!*/ newTriggers = MutateTriggers(triggers, arg);
- Contract.Assert(cce.NonNullElements(newTriggers));
- if (!Object.ReferenceEquals(triggers, newTriggers))
- changed = true;
-
- if (!changed)
- return node;
- return Gen.Quantify(node.Quan, node.TypeParameters, node.BoundVars,
- newTriggers, node.Infos, newbody);
- }
-
- public virtual VCExpr Visit(VCExprLet node, Arg arg) {
- //Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- bool changed = false;
-
- VCExpr/*!*/ body = node.Body;
- VCExpr/*!*/ newbody = body.Accept(this, arg);
- if (!Object.ReferenceEquals(body, newbody))
- changed = true;
-
- List<VCExprLetBinding/*!*/>/*!*/ newbindings = new List<VCExprLetBinding/*!*/>();
- for (int i = 0; i < node.Length; ++i) {
- VCExprLetBinding/*!*/ binding = node[i];
- Contract.Assert(binding != null);
- VCExpr/*!*/ e = binding.E;
- VCExpr/*!*/ newE = e.Accept(this, arg);
- if (Object.ReferenceEquals(e, newE)) {
- newbindings.Add(binding);
- } else {
- changed = true;
- newbindings.Add(Gen.LetBinding(binding.V, newE));
- }
- }
-
- if (!changed)
- return node;
- return Gen.Let(newbindings, newbody);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Substitutions and a visitor for applying substitutions. A substitution can
- // substitute both type variables and term variables
-
- public class VCExprSubstitution {
- private readonly List<IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/>/*!*/ TermSubsts;
- [ContractInvariantMethod]
- void TermSubstsInvariantMethod() {
- Contract.Invariant(TermSubsts != null && Contract.ForAll(TermSubsts, i => cce.NonNullDictionaryAndValues(i)));
- }
- private readonly List<IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/>/*!*/ TypeSubsts;
- [ContractInvariantMethod]
- void TypeSubstsInvariantMethod() {
- Contract.Invariant(TermSubsts != null && Contract.ForAll(TypeSubsts, i => cce.NonNullDictionaryAndValues(i)));
- }
-
- public VCExprSubstitution(IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/ termSubst, IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ typeSubst) {
- Contract.Requires(cce.NonNullDictionaryAndValues(termSubst));
- Contract.Requires(cce.NonNullDictionaryAndValues(typeSubst));
- List<IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/>/*!*/ termSubsts =
- new List<IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/>();
- termSubsts.Add(termSubst);
- List<IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/>/*!*/ typeSubsts =
- new List<IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/>();
- typeSubsts.Add(typeSubst);
- this.TermSubsts = termSubsts;
- this.TypeSubsts = typeSubsts;
- }
-
- public VCExprSubstitution()
- : this(new Dictionary<VCExprVar/*!*/, VCExpr/*!*/>(), new Dictionary<TypeVariable/*!*/, Type/*!*/>()) {
-
- }
-
- public void PushScope() {
- TermSubsts.Add(new Dictionary<VCExprVar/*!*/, VCExpr/*!*/>());
- TypeSubsts.Add(new Dictionary<TypeVariable/*!*/, Type/*!*/>());
- }
-
- public void PopScope() {
- TermSubsts.RemoveAt(TermSubsts.Count - 1);
- TypeSubsts.RemoveAt(TypeSubsts.Count - 1);
- }
-
- public VCExpr this[VCExprVar/*!*/ var] {
- get {
- Contract.Requires(var != null);
- VCExpr res;
- for (int i = TermSubsts.Count - 1; i >= 0; --i) {
- if (TermSubsts[i].TryGetValue(var, out res))
- return res;
- }
- return null;
- }
- set {
- TermSubsts[TermSubsts.Count - 1][var] = cce.NonNull(value);
- }
- }
-
- public Type this[TypeVariable/*!*/ var] {
- get {
- Contract.Requires(var != null);
- Type res;
- for (int i = TypeSubsts.Count - 1; i >= 0; --i) {
- if (TypeSubsts[i].TryGetValue(var, out res))
- return res;
- }
- return null;
- }
- set {
- TypeSubsts[TypeSubsts.Count - 1][var] = cce.NonNull(value);
- }
- }
-
- public bool ContainsKey(VCExprVar var) {
- Contract.Requires(var != null);
- return this[var] != null;
- }
-
- public bool ContainsKey(TypeVariable var) {
- Contract.Requires(var != null);
- return this[var] != null;
- }
-
- public bool TermSubstIsEmpty {
- get {
- return TermSubsts.All(dict => !dict.Any());
- }
- }
-
- public bool TypeSubstIsEmpty {
- get {
- return TypeSubsts.All(dict => !dict.Any());
- }
- }
-
- public IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ ToTypeSubst {
- get {
- Contract.Ensures(cce.NonNullDictionaryAndValues(Contract.Result<IDictionary<TypeVariable, Type>>()));
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ res = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
- foreach (IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ dict in TypeSubsts) {
- foreach (KeyValuePair<TypeVariable/*!*/, Type/*!*/> pair in dict) {
- Contract.Assert(cce.NonNullElements(pair));
- // later ones overwrite earlier ones
- res[pair.Key] = pair.Value;
- }
- }
- return res;
- }
- }
-
- // the variables that are not mapped to themselves
- public IEnumerable<VCExprVar/*!*/>/*!*/ TermDomain {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<VCExprVar>>()));
- HashSet<VCExprVar/*!*/>/*!*/ domain = new HashSet<VCExprVar/*!*/>();
- foreach (IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/ dict in TermSubsts) {
- Contract.Assert(dict != null);
- foreach (VCExprVar/*!*/ var in dict.Keys) {
- Contract.Assert(var != null);
- if (!var.Equals(this[var]))
- domain.Add(var);
- }
- }
- return domain;
- }
- }
-
- // the variables that are not mapped to themselves
- public IEnumerable<TypeVariable/*!*/>/*!*/ TypeDomain {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<TypeVariable>>()));
- HashSet<TypeVariable/*!*/>/*!*/ domain = new HashSet<TypeVariable/*!*/>();
- foreach (IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ dict in TypeSubsts) {
- Contract.Assert(dict != null);
- foreach (TypeVariable/*!*/ var in dict.Keys) {
- Contract.Assert(var != null);
- if (!var.Equals(this[var]))
- domain.Add(var);
- }
- }
- return domain;
- }
- }
-
- public FreeVariableCollector/*!*/ Codomains {
- get {
- Contract.Ensures(Contract.Result<FreeVariableCollector>() != null);
-
- FreeVariableCollector/*!*/ coll = new FreeVariableCollector();
- foreach (VCExprVar/*!*/ var in TermDomain)
- coll.Collect(cce.NonNull(this)[var]);
- foreach (TypeVariable/*!*/ var in TypeDomain)
- coll.Collect(cce.NonNull(this)[var]);
- return coll;
- }
- }
-
- public VCExprSubstitution Clone() {
- Contract.Ensures(Contract.Result<VCExprSubstitution>() != null);
- VCExprSubstitution/*!*/ res = new VCExprSubstitution();
- foreach (IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/ dict in TermSubsts)
- res.TermSubsts.Add(HelperFuns.Clone(dict));
- foreach (IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ dict in TypeSubsts)
- res.TypeSubsts.Add(HelperFuns.Clone(dict));
- return res;
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////////
-
- public class SubstitutingVCExprVisitor
- : MutatingVCExprVisitor<VCExprSubstitution/*!*/> {
- public SubstitutingVCExprVisitor(VCExpressionGenerator gen)
- : base(gen) {
- Contract.Requires(gen != null);
-
- }
-
- // when descending across a binder, we have to check that no collisions
- // or variable capture can occur. if this might happen, we replace the
- // term and type variables bound by the binder with fresh variables
- private bool CollisionPossible(IEnumerable<TypeVariable/*!*/>/*!*/ typeParams, IEnumerable<VCExprVar/*!*/>/*!*/ boundVars, VCExprSubstitution/*!*/ substitution) {
- Contract.Requires(cce.NonNullElements(typeParams));
- Contract.Requires(cce.NonNullElements(boundVars));
- Contract.Requires(substitution != null);
- // variables can be shadowed by a binder
- if (typeParams.Any(var => substitution.ContainsKey(var)) ||
- boundVars.Any(var => substitution.ContainsKey(var)))
- return true;
- // compute the codomain of the substitution
- FreeVariableCollector coll = substitution.Codomains;
- Contract.Assert(coll != null);
- // variables could be captured when applying the substitution
- return typeParams.Any(var => coll.FreeTypeVars.Contains(var)) ||
- boundVars.Any(var => coll.FreeTermVars.ContainsKey(var));
- }
-
- // can be overwritten if names of bound variables are to be changed
- protected virtual string ChooseNewVariableName(string oldName) {
- Contract.Requires(oldName != null);
- Contract.Ensures(Contract.Result<string>() != null);
- return oldName;
- }
-
- // handle type parameters in VCExprNAry
- protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode, List<VCExpr/*!*/>/*!*/ newSubExprs, bool changed, VCExprSubstitution/*!*/ substitution) {
- //Contract.Requires(originalNode != null);
- //Contract.Requires(cce.NonNullElements(newSubExprs));
- //Contract.Requires(substitution != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- List<Type/*!*/>/*!*/ typeParams = new List<Type/*!*/>();
- foreach (Type/*!*/ t in originalNode.TypeArguments) {
- Contract.Assert(t != null);
- Type/*!*/ newType = t.Substitute(substitution.ToTypeSubst);
- Contract.Assert(newType != null);
- if (!ReferenceEquals(t, newType))
- changed = true;
- typeParams.Add(newType);
- }
- if (changed)
- return Gen.Function(originalNode.Op, newSubExprs, typeParams);
- else
- return originalNode;
- }
-
- public override VCExpr/*!*/ Visit(VCExprQuantifier/*!*/ node, VCExprSubstitution/*!*/ substitution) {
- Contract.Requires(node != null);
- Contract.Requires(substitution != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- // the default is to refresh bound variables only if necessary
- // because of collisions
- return Visit(node, substitution, false);
- }
-
- public VCExpr/*!*/ Visit(VCExprQuantifier/*!*/ node, VCExprSubstitution/*!*/ substitution, bool refreshBoundVariables) {
- Contract.Requires(node != null);
- Contract.Requires(substitution != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
-
- substitution.PushScope();
- try {
-
- List<TypeVariable/*!*/>/*!*/ typeParams = node.TypeParameters;
- Contract.Assert(cce.NonNullElements(typeParams));
- bool refreshAllVariables = refreshBoundVariables ||
- CollisionPossible(node.TypeParameters, node.BoundVars, substitution);
- if (refreshAllVariables) {
- // we introduce fresh type variables to ensure that none gets captured
- typeParams = new List<TypeVariable/*!*/>();
- foreach (TypeVariable/*!*/ var in node.TypeParameters) {
- Contract.Assert(var != null);
- TypeVariable/*!*/ freshVar =
- new TypeVariable(Token.NoToken, ChooseNewVariableName(var.Name));
- Contract.Assert(freshVar != null);
- typeParams.Add(freshVar);
- substitution[var] = freshVar;
- // this might overwrite other elements of the substitution, deliberately
- }
- }
-
- List<VCExprVar/*!*/>/*!*/ boundVars = node.BoundVars;
- Contract.Assert(cce.NonNullElements(boundVars));
- if (refreshAllVariables || !substitution.TypeSubstIsEmpty) {
- // collisions are possible, or we also substitute type variables. in this case
- // the bound term variables have to be replaced with fresh variables with the
- // right types
- boundVars = new List<VCExprVar/*!*/>();
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ typeSubst = substitution.ToTypeSubst;
- Contract.Assert(cce.NonNullDictionaryAndValues(typeSubst));
- foreach (VCExprVar/*!*/ var in node.BoundVars) {
- Contract.Assert(var != null);
- VCExprVar/*!*/ freshVar =
- Gen.Variable(ChooseNewVariableName(var.Name),
- var.Type.Substitute(typeSubst));
- Contract.Assert(freshVar != null);
- boundVars.Add(freshVar);
- substitution[var] = freshVar;
- // this might overwrite other elements of the substitution, deliberately
- }
- }
-
- List<VCTrigger/*!*/>/*!*/ newTriggers = new List<VCTrigger/*!*/>();
- foreach (VCTrigger/*!*/ trigger in node.Triggers) {
- Contract.Assert(trigger != null);
- newTriggers.Add(Gen.Trigger(trigger.Pos, MutateSeq(trigger.Exprs, substitution)));
- }
-
- VCExpr/*!*/ newBody = Mutate(node.Body, substitution);
- Contract.Assert(newBody != null);
-
- return Gen.Quantify(node.Quan, typeParams, boundVars,
- newTriggers, node.Infos, newBody);
-
- } finally {
- substitution.PopScope();
- }
- }
-
- public override VCExpr Visit(VCExprVar node, VCExprSubstitution substitution) {
- Contract.Requires(substitution != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- VCExpr res = substitution[node];
- if (res != null)
- return res;
- return node;
- }
-
- public override VCExpr Visit(VCExprLet node, VCExprSubstitution substitution) {
- Contract.Requires(substitution != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- // the default is to refresh bound variables only if necessary
- // because of collisions
- return Visit(node, substitution, false);
- }
-
- public VCExpr Visit(VCExprLet node, VCExprSubstitution substitution, bool refreshBoundVariables) {
- Contract.Requires(substitution != null);
- Contract.Requires(node != null);
- Contract.Ensures(Contract.Result<VCExpr>() != null);
- // let-expressions do not have type parameters (fortunately ...)
- substitution.PushScope();
- try {
-
- bool refreshAllVariables =
- refreshBoundVariables ||
- !substitution.TypeSubstIsEmpty ||
- CollisionPossible(new List<TypeVariable/*!*/>(), node.BoundVars, substitution);
-
- List<VCExprVar/*!*/>/*!*/ newBoundVars = node.BoundVars;
- Contract.Assert(cce.NonNullElements(newBoundVars));
- if (refreshAllVariables) {
- // collisions are possible, or we also substitute type variables. in this case
- // the bound term variables have to be replaced with fresh variables with the
- // right types
- newBoundVars = new List<VCExprVar/*!*/>();
- IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ typeSubst = substitution.ToTypeSubst;
- Contract.Assert(cce.NonNullDictionaryAndValues(typeSubst));
- foreach (VCExprVar/*!*/ var in node.BoundVars) {
- Contract.Assert(var != null);
- VCExprVar/*!*/ freshVar =
- Gen.Variable(ChooseNewVariableName(var.Name),
- var.Type.Substitute(typeSubst));
- Contract.Assert(freshVar != null);
- newBoundVars.Add(freshVar);
- substitution[var] = freshVar;
- // this might overwrite other elements of the substitution, deliberately
- }
- }
-
- List<VCExprLetBinding/*!*/>/*!*/ newbindings = new List<VCExprLetBinding/*!*/>();
- for (int i = 0; i < node.Length; ++i) {
- VCExprLetBinding/*!*/ binding = node[i];
- Contract.Assert(binding != null);
- newbindings.Add(Gen.LetBinding(newBoundVars[i], Mutate(binding.E, substitution)));
- }
-
- VCExpr/*!*/ newBody = Mutate(node.Body, substitution);
- Contract.Assert(newBody != null);
- return Gen.Let(newbindings, newBody);
-
- } finally {
- substitution.PopScope();
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- [ContractClassFor(typeof(StandardVCExprOpVisitor<,>))]
- public abstract class StandardVCExprOpVisitorContracts<Result, Arg> : StandardVCExprOpVisitor<Result, Arg> {
- protected override Result StandardResult(VCExprNAry node, Arg arg) {
- Contract.Requires(node != null);
- throw new NotImplementedException();
- }
- }
-
-
- [ContractClass(typeof(StandardVCExprOpVisitorContracts<,>))]
- public abstract class StandardVCExprOpVisitor<Result, Arg>
- : IVCExprOpVisitor<Result, Arg> {
- protected abstract Result StandardResult(VCExprNAry/*!*/ node, Arg arg);
-
- public virtual Result VisitNotOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitEqOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitNeqOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitAndOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitOrOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitImpliesOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitDistinctOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitLabelOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitSelectOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitStoreOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitBvOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitBvExtractOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitBvConcatOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitIfThenElseOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitCustomOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitAddOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitSubOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitMulOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitDivOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitModOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitRealDivOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitPowOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitLtOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitLeOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitGtOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitGeOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitSubtypeOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitSubtype3Op(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitToIntOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitToRealOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- public virtual Result VisitBoogieFunctionOp(VCExprNAry node, Arg arg) {
- //Contract.Requires(node != null);
- return StandardResult(node, arg);
- }
- }
-
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Linq;
+using Microsoft.Basetypes;
+
+// Some visitor skeletons for the VCExpression AST
+
+namespace Microsoft.Boogie.VCExprAST {
+ using Microsoft.Boogie;
+
+ [ContractClass(typeof(IVCExprVisitorContracts<,>))]
+ public interface IVCExprVisitor<Result, Arg> {
+ Result Visit(VCExprLiteral/*!*/ node, Arg arg);
+ Result Visit(VCExprNAry/*!*/ node, Arg arg);
+ Result Visit(VCExprVar/*!*/ node, Arg arg);
+ Result Visit(VCExprQuantifier/*!*/ node, Arg arg);
+ Result Visit(VCExprLet/*!*/ node, Arg arg);
+ }
+ [ContractClassFor(typeof(IVCExprVisitor<,>))]
+ public abstract class IVCExprVisitorContracts<Result, Arg> : IVCExprVisitor<Result, Arg> {
+ #region IVCExprVisitor Members
+
+ public Result Visit(VCExprLiteral node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result Visit(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result Visit(VCExprVar node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result Visit(VCExprQuantifier node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result Visit(VCExprLet node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+ [ContractClass(typeof(IVCExprOpVisitorContracts<,>))]
+ public interface IVCExprOpVisitor<Result, Arg> {
+ Result VisitNotOp(VCExprNAry node, Arg arg);
+ Result VisitEqOp(VCExprNAry node, Arg arg);
+ Result VisitNeqOp(VCExprNAry node, Arg arg);
+ Result VisitAndOp(VCExprNAry node, Arg arg);
+ Result VisitOrOp(VCExprNAry node, Arg arg);
+ Result VisitImpliesOp(VCExprNAry node, Arg arg);
+ Result VisitDistinctOp(VCExprNAry node, Arg arg);
+ Result VisitLabelOp(VCExprNAry node, Arg arg);
+ Result VisitSelectOp(VCExprNAry node, Arg arg);
+ Result VisitStoreOp(VCExprNAry node, Arg arg);
+ Result VisitBvOp(VCExprNAry node, Arg arg);
+ Result VisitBvExtractOp(VCExprNAry node, Arg arg);
+ Result VisitBvConcatOp(VCExprNAry node, Arg arg);
+ Result VisitAddOp(VCExprNAry node, Arg arg);
+ Result VisitSubOp(VCExprNAry node, Arg arg);
+ Result VisitMulOp(VCExprNAry node, Arg arg);
+ Result VisitDivOp(VCExprNAry node, Arg arg);
+ Result VisitModOp(VCExprNAry node, Arg arg);
+ Result VisitRealDivOp(VCExprNAry node, Arg arg);
+ Result VisitPowOp(VCExprNAry node, Arg arg);
+ Result VisitLtOp(VCExprNAry node, Arg arg);
+ Result VisitLeOp(VCExprNAry node, Arg arg);
+ Result VisitGtOp(VCExprNAry node, Arg arg);
+ Result VisitGeOp(VCExprNAry node, Arg arg);
+ Result VisitSubtypeOp(VCExprNAry node, Arg arg);
+ Result VisitSubtype3Op(VCExprNAry node, Arg arg);
+ Result VisitToIntOp(VCExprNAry node, Arg arg);
+ Result VisitToRealOp(VCExprNAry node, Arg arg);
+ Result VisitBoogieFunctionOp(VCExprNAry node, Arg arg);
+ Result VisitIfThenElseOp(VCExprNAry node, Arg arg);
+ Result VisitCustomOp(VCExprNAry node, Arg arg);
+ }
+ [ContractClassFor(typeof(IVCExprOpVisitor<,>))]
+ public abstract class IVCExprOpVisitorContracts<Result, Arg> : IVCExprOpVisitor<Result, Arg> {
+ #region IVCExprOpVisitor<Result,Arg> Members
+
+ public Result VisitNotOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitEqOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitNeqOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitAndOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitOrOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitImpliesOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitDistinctOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitLabelOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitSelectOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitStoreOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitBvOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitBvExtractOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitBvConcatOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitAddOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitSubOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitMulOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitDivOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitModOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitRealDivOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitPowOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitLtOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitLeOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitGtOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitGeOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitSubtypeOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitSubtype3Op(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitToIntOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitToRealOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitBoogieFunctionOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitIfThenElseOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ public Result VisitCustomOp(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Standard implementations that make it easier to create own visitors
+
+ // Simple traversal of VCExprs. The Visit implementations work
+ // recursively, apart from the implementation for VCExprNAry that
+ // uses a stack when applied to nested nodes with the same
+ // operator, e.g., (AND (AND (AND ...) ...) ...). This is necessary
+ // to avoid stack overflows
+
+
+ [ContractClass(typeof(TraversingVCExprVisitorContracts<,>))]
+ public abstract class TraversingVCExprVisitor<Result, Arg>
+ : IVCExprVisitor<Result, Arg> {
+ protected abstract Result StandardResult(VCExpr/*!*/ node, Arg arg);
+
+ public Result Traverse(VCExpr node, Arg arg) {
+ Contract.Requires(node != null);
+ return node.Accept(this, arg);
+ }
+
+ public virtual Result Visit(VCExprLiteral node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+
+ public virtual Result Visit(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ Result res = StandardResult(node, arg);
+
+
+ if (node.TypeParamArity == 0 &&
+ (node.Op == VCExpressionGenerator.AndOp ||
+ node.Op == VCExpressionGenerator.OrOp ||
+ node.Op == VCExpressionGenerator.ImpliesOp)) {
+ Contract.Assert(node.Op != null);
+ VCExprOp op = node.Op;
+ HashSet<VCExprOp> ops = new HashSet<VCExprOp>();
+ ops.Add(VCExpressionGenerator.AndOp);
+ ops.Add(VCExpressionGenerator.OrOp);
+ ops.Add(VCExpressionGenerator.ImpliesOp);
+ IEnumerator enumerator = new VCExprNAryMultiUniformOpEnumerator(node, ops);
+ while (enumerator.MoveNext()) {
+ VCExpr expr = cce.NonNull((VCExpr)enumerator.Current);
+ VCExprNAry naryExpr = expr as VCExprNAry;
+ if (naryExpr == null || !ops.Contains(naryExpr.Op)) {
+ expr.Accept(this, arg);
+ } else {
+ StandardResult(expr, arg);
+ }
+ }
+ } else {
+ foreach (VCExpr e in node) {
+ Contract.Assert(e != null);
+ e.Accept(this, arg);
+ }
+ }
+
+ return res;
+ }
+
+ public virtual Result Visit(VCExprVar node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result Visit(VCExprQuantifier node, Arg arg) {
+ //Contract.Requires(node != null);
+ Result res = StandardResult(node, arg);
+ foreach (VCTrigger/*!*/ trigger in node.Triggers) {
+ Contract.Assert(trigger != null);
+ foreach (VCExpr/*!*/ expr in trigger.Exprs) {
+ Contract.Assert(expr != null);
+ expr.Accept(this, arg);
+ }
+ }
+ node.Body.Accept(this, arg);
+ return res;
+ }
+ public virtual Result Visit(VCExprLet node, Arg arg) {
+ //Contract.Requires(node != null);
+ Result res = StandardResult(node, arg);
+ // visit the bound expressions first
+ foreach (VCExprLetBinding/*!*/ binding in node) {
+ Contract.Assert(binding != null);
+ binding.E.Accept(this, arg);
+ }
+ node.Body.Accept(this, arg);
+ return res;
+ }
+ }
+ [ContractClassFor(typeof(TraversingVCExprVisitor<,>))]
+ public abstract class TraversingVCExprVisitorContracts<Result, Arg> : TraversingVCExprVisitor<Result, Arg> {
+ protected override Result StandardResult(VCExpr node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+ }
+ //////////////////////////////////////////////////////////////////////////////
+ // Class to iterate over the nodes of a tree of VCExprNAry. This is
+ // used to avoid handling such VCExpr recursively, which can easily
+ // lead to stack overflows
+
+ public class VCExprNAryEnumerator : IEnumerator {
+
+ private readonly VCExprNAry/*!*/ CompleteExpr;
+ private VCExpr CurrentExpr = null;
+ private readonly Stack<VCExpr/*!*/>/*!*/ ExprTodo = new Stack<VCExpr/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(CompleteExpr != null);
+ Contract.Invariant(cce.NonNullElements(ExprTodo));
+ }
+
+ public VCExprNAryEnumerator(VCExprNAry completeExpr) {
+ Contract.Requires(completeExpr != null);
+ this.CompleteExpr = completeExpr;
+ Stack<VCExpr/*!*/>/*!*/ exprTodo = new Stack<VCExpr/*!*/>();
+ exprTodo.Push(completeExpr);
+ ExprTodo = exprTodo;
+ }
+
+ // Method using which a subclass can decide whether the
+ // subexpressions of an expression should be enumerated as well
+ // The default is to enumerate all nodes
+ protected virtual bool Descend(VCExprNAry expr) {
+ Contract.Requires(expr != null);
+ return true;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public bool MoveNext() {
+ if (ExprTodo.Count == 0)
+ return false;
+
+ CurrentExpr = ExprTodo.Pop();
+ VCExprNAry currentNAry = CurrentExpr as VCExprNAry;
+ if (currentNAry != null && Descend(currentNAry)) {
+ for (int i = currentNAry.Arity - 1; i >= 0; --i)
+ ExprTodo.Push(currentNAry[i]);
+ }
+
+ return true;
+ }
+
+ public object Current {
+ get {
+ return cce.NonNull(CurrentExpr);
+ }
+ }
+
+ public void Reset() {
+ ExprTodo.Clear();
+ CurrentExpr = null;
+ ExprTodo.Push(CompleteExpr);
+ }
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ public class VCExprNAryUniformOpEnumerator : VCExprNAryEnumerator {
+ private readonly VCExprOp/*!*/ Op;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Op != null);
+ }
+
+ public VCExprNAryUniformOpEnumerator(VCExprNAry completeExpr)
+ : base(completeExpr) {
+ Contract.Requires(completeExpr != null);
+
+ this.Op = completeExpr.Op;
+ }
+ protected override bool Descend(VCExprNAry expr) {
+ //Contract.Requires(expr != null);
+ return expr.Op.Equals(Op) &&
+ // we never skip nodes with type parameters
+ // (those are too interesting ...)
+ expr.TypeParamArity == 0;
+ }
+ }
+
+ public class VCExprNAryMultiUniformOpEnumerator : VCExprNAryEnumerator
+ {
+ private readonly HashSet<VCExprOp> Ops;
+ [ContractInvariantMethod]
+ void ObjectInvariant()
+ {
+ Contract.Invariant(Ops != null);
+ }
+
+ public VCExprNAryMultiUniformOpEnumerator(VCExprNAry completeExpr, HashSet<VCExprOp> ops)
+ : base(completeExpr)
+ {
+ Contract.Requires(completeExpr != null);
+
+ this.Ops = ops;
+ }
+ protected override bool Descend(VCExprNAry expr)
+ {
+ return Ops.Contains(expr.Op) && expr.TypeParamArity == 0;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Visitor that knows about the variables bound at each location in a VCExpr
+
+ public abstract class BoundVarTraversingVCExprVisitor<Result, Arg>
+ : TraversingVCExprVisitor<Result, Arg> {
+ // Maps with all variables bound above a certain location in the VCExpression.
+ // The value of the map tells how often a particular symbol was bound
+ private readonly IDictionary<VCExprVar/*!*/, int>/*!*/ BoundTermVarsDict =
+ new Dictionary<VCExprVar/*!*/, int>();
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(BoundTermVarsDict != null);
+ Contract.Invariant(BoundTypeVarsDict != null);
+ }
+
+ private readonly IDictionary<TypeVariable/*!*/, int>/*!*/ BoundTypeVarsDict =
+ new Dictionary<TypeVariable/*!*/, int>();
+
+ protected ICollection<VCExprVar/*!*/>/*!*/ BoundTermVars {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<VCExprVar>>()));
+ return BoundTermVarsDict.Keys;
+ }
+ }
+ protected ICollection<TypeVariable/*!*/>/*!*/ BoundTypeVars {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<TypeVariable>>()));
+ return BoundTypeVarsDict.Keys;
+ }
+ }
+
+ private void AddBoundVar<T>(IDictionary<T, int> dict, T sym) {
+ Contract.Requires(sym != null);
+ Contract.Requires(dict != null);
+ int n;
+ if (dict.TryGetValue(sym, out n))
+ dict[sym] = n + 1;
+ else
+ dict[sym] = 1;
+ }
+
+ private void RemoveBoundVar<T>(IDictionary<T/*!*/, int/*!*/>/*!*/ dict, T sym) {
+ Contract.Requires(sym != null);
+ Contract.Requires(dict != null);
+ int n;
+ bool b = dict.TryGetValue(sym, out n);
+ Contract.Assert(b && n > 0);
+ if (n == 1)
+ dict.Remove(sym);
+ else
+ dict[sym] = n - 1;
+ }
+
+ public override Result Visit(VCExprQuantifier node, Arg arg) {
+ Contract.Requires(node != null);
+ // we temporarily add bound (term and type) variables to the
+ // corresponding lists
+ foreach (VCExprVar/*!*/ v in node.BoundVars) {
+ Contract.Assert(v != null);
+ AddBoundVar<VCExprVar>(BoundTermVarsDict, v);
+ }
+ foreach (TypeVariable/*!*/ v in node.TypeParameters) {
+ Contract.Assert(v != null);
+ AddBoundVar<TypeVariable>(BoundTypeVarsDict, v);
+ }
+
+ Result res;
+ try {
+ res = VisitAfterBinding(node, arg);
+ } finally {
+ foreach (VCExprVar/*!*/ v in node.BoundVars) {
+ Contract.Assert(v != null);
+ RemoveBoundVar<VCExprVar>(BoundTermVarsDict, v);
+ }
+ foreach (TypeVariable/*!*/ v in node.TypeParameters) {
+ Contract.Assert(v != null);
+ RemoveBoundVar<TypeVariable>(BoundTypeVarsDict, v);
+ }
+ }
+ return res;
+ }
+ public override Result Visit(VCExprLet node, Arg arg) {
+ Contract.Requires(node != null);
+ // we temporarily add bound term variables to the
+ // corresponding lists
+ foreach (VCExprVar/*!*/ v in node.BoundVars) {
+ Contract.Assert(v != null);
+ AddBoundVar<VCExprVar>(BoundTermVarsDict, v);
+ }
+
+ Result res;
+ try {
+ res = VisitAfterBinding(node, arg);
+ } finally {
+ foreach (VCExprVar/*!*/ v in node.BoundVars) {
+ Contract.Assert(v != null);
+ RemoveBoundVar<VCExprVar>(BoundTermVarsDict, v);
+ }
+ }
+ return res;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // The possibility is provided to look at a (quantifier or let) node
+ // after its bound variables have been registered
+ // (when overriding the normal visit-methods, the node will be visited
+ // before the binding happens)
+
+ protected virtual Result VisitAfterBinding(VCExprQuantifier node, Arg arg) {
+ Contract.Requires(node != null);
+ return base.Visit(node, arg);
+ }
+
+ protected virtual Result VisitAfterBinding(VCExprLet node, Arg arg) {
+ Contract.Requires(node != null);
+ return base.Visit(node, arg);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // General visitor for recursively collecting information in a VCExpr.
+ // As the visitor is not used anywhere for the time being, it maybe should
+ // be removed
+
+ [ContractClass(typeof(CollectingVCExprVisitorContracts<,>))]
+ public abstract class CollectingVCExprVisitor<Result, Arg>
+ : IVCExprVisitor<Result, Arg> {
+ protected abstract Result CombineResults(List<Result>/*!*/ results, Arg arg);
+
+ public Result Collect(VCExpr node, Arg arg) {
+ Contract.Requires(node != null);
+ return node.Accept(this, arg);
+ }
+
+ public virtual Result Visit(VCExprLiteral node, Arg arg) {
+ //Contract.Requires(node != null);
+ return CombineResults(new List<Result>(), arg);
+ }
+ public virtual Result Visit(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ List<Result>/*!*/ results = new List<Result>();
+ foreach (VCExpr/*!*/ subnode in node) {
+ Contract.Assert(subnode != null);
+ results.Add(subnode.Accept(this, arg));
+ }
+ return CombineResults(results, arg);
+ }
+ public virtual Result Visit(VCExprVar node, Arg arg) {
+ //Contract.Requires(node != null);
+ return CombineResults(new List<Result>(), arg);
+ }
+ public virtual Result Visit(VCExprQuantifier node, Arg arg) {
+ //Contract.Requires(node != null);
+ List<Result>/*!*/ result = new List<Result>();
+ result.Add(node.Body.Accept(this, arg));
+ foreach (VCTrigger/*!*/ trigger in node.Triggers) {
+ Contract.Assert(trigger != null);
+ foreach (VCExpr/*!*/ expr in trigger.Exprs) {
+ Contract.Assert(expr != null);
+ result.Add(expr.Accept(this, arg));
+ }
+ }
+ return CombineResults(result, arg);
+ }
+ public virtual Result Visit(VCExprLet node, Arg arg) {
+ //Contract.Requires(node != null);
+ List<Result>/*!*/ results = new List<Result>();
+ // visit the bound expressions first
+ foreach (VCExprLetBinding/*!*/ binding in node) {
+ Contract.Assert(binding != null);
+ results.Add(binding.E.Accept(this, arg));
+ }
+ results.Add(node.Body.Accept(this, arg));
+ return CombineResults(results, arg);
+ }
+ }
+ [ContractClassFor(typeof(CollectingVCExprVisitor<,>))]
+ public abstract class CollectingVCExprVisitorContracts<Result, Arg> : CollectingVCExprVisitor<Result, Arg> {
+ protected override Result CombineResults(List<Result> results, Arg arg) {
+ Contract.Requires(results != null);
+ throw new NotImplementedException();
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+
+ public class SizeComputingVisitor : TraversingVCExprVisitor<bool, bool> {
+
+ private int Size = 0;
+
+ public static int ComputeSize(VCExpr expr) {
+ Contract.Requires(expr != null);
+ SizeComputingVisitor/*!*/ visitor = new SizeComputingVisitor();
+ visitor.Traverse(expr, true);
+ return visitor.Size;
+ }
+
+ protected override bool StandardResult(VCExpr node, bool arg) {
+ //Contract.Requires(node != null);
+ Size = Size + 1;
+ return true;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Collect all free term and type variables in a VCExpr. Type variables
+ // can occur free either in the types of bound variables, or in the type
+ // parameters of VCExprNAry.
+
+ // the result and argument (of type bool) are not used currently
+ public class FreeVariableCollector : BoundVarTraversingVCExprVisitor<bool, bool> {
+ public readonly Dictionary<VCExprVar/*!*/, object>/*!*/ FreeTermVars = new Dictionary<VCExprVar/*!*/, object>();
+ public readonly List<TypeVariable/*!*/>/*!*/ FreeTypeVars = new List<TypeVariable/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(FreeTermVars != null && Contract.ForAll(FreeTermVars, entry => entry.Key != null));
+ Contract.Invariant(cce.NonNullElements(FreeTypeVars));
+ }
+
+
+ // not used
+ protected override bool StandardResult(VCExpr node, bool arg) {
+ //Contract.Requires(node != null);
+ return true;
+ }
+
+ public static Dictionary<VCExprVar/*!*/, object>/*!*/ FreeTermVariables(VCExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<Dictionary<VCExprVar, object>>() != null);
+ Contract.Ensures(Contract.ForAll(Contract.Result<Dictionary<VCExprVar, object>>(), ftv => ftv.Key != null));
+ FreeVariableCollector collector = new FreeVariableCollector();
+ collector.Traverse(node, true);
+ return collector.FreeTermVars;
+ }
+
+ public static List<TypeVariable/*!*/>/*!*/ FreeTypeVariables(VCExpr node) {
+ Contract.Requires(node != null);
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<TypeVariable>>()));
+ FreeVariableCollector collector = new FreeVariableCollector();
+ collector.Traverse(node, true);
+ return collector.FreeTypeVars;
+ }
+
+ public void Reset() {
+ FreeTermVars.Clear();
+ FreeTypeVars.Clear();
+ }
+
+ public void Collect(VCExpr node) {
+ Contract.Requires(node != null);
+ Traverse(node, true);
+ }
+
+ public void Collect(Type type) {
+ Contract.Requires(type != null);
+ AddTypeVariables(type.FreeVariables.ToList());
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ private void CollectTypeVariables(IEnumerable<VCExprVar/*!*/>/*!*/ boundVars) {
+ Contract.Requires(cce.NonNullElements(boundVars));
+ foreach (VCExprVar/*!*/ var in boundVars) {
+ Contract.Assert(var != null);
+ Collect(var.Type);
+ }
+ }
+
+ private void AddTypeVariables(IEnumerable<TypeVariable/*!*/>/*!*/ typeVars) {
+ Contract.Requires(cce.NonNullElements(typeVars));
+ foreach (TypeVariable/*!*/ tvar in typeVars) {
+ Contract.Assert(tvar != null);
+ if (!BoundTypeVars.Contains(tvar) && !FreeTypeVars.Contains(tvar))
+ FreeTypeVars.Add(tvar);
+ }
+ }
+
+ public override bool Visit(VCExprVar node, bool arg) {
+ Contract.Requires(node != null);
+ if (!BoundTermVars.Contains(node) && !FreeTermVars.ContainsKey(node)) {
+ FreeTermVars.Add(node, null);
+ Collect(node.Type);
+ }
+ return true;
+ }
+
+ public override bool Visit(VCExprNAry node, bool arg) {
+ Contract.Requires(node != null);
+ foreach (Type/*!*/ t in node.TypeArguments) {
+ Contract.Assert(t != null);
+ Collect(t);
+ }
+ return base.Visit(node, arg);
+ }
+
+ protected override bool VisitAfterBinding(VCExprQuantifier node, bool arg) {
+ //Contract.Requires(node != null);
+ CollectTypeVariables(node.BoundVars);
+ return base.VisitAfterBinding(node, arg);
+ }
+
+ protected override bool VisitAfterBinding(VCExprLet node, bool arg) {
+ //Contract.Requires(node != null);
+ CollectTypeVariables(node.BoundVars);
+ return base.VisitAfterBinding(node, arg);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Framework for mutating VCExprs
+
+ // The Visit implementations in the following visitor work
+ // recursively, apart from the implementation for VCExprNAry that
+ // uses its own stack when applied to nested nodes with the same
+ // operator, e.g., (AND (AND (AND ...) ...) ...). This is necessary
+ // to avoid stack overflows (like in TraversingVCExprVisitor)
+
+ public abstract class MutatingVCExprVisitor<Arg>
+ : IVCExprVisitor<VCExpr/*!*/, Arg> {
+ protected readonly VCExpressionGenerator/*!*/ Gen;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(Gen != null);
+ }
+
+
+ public MutatingVCExprVisitor(VCExpressionGenerator gen) {
+ Contract.Requires(gen != null);
+ this.Gen = gen;
+ }
+
+ public VCExpr Mutate(VCExpr expr, Arg arg) {
+ Contract.Requires(expr != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return expr.Accept(this, arg);
+ }
+
+ public List<VCExpr/*!*/>/*!*/ MutateSeq(IEnumerable<VCExpr/*!*/>/*!*/ exprs, Arg arg) {
+ Contract.Requires(cce.NonNullElements(exprs));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
+ List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>();
+ foreach (VCExpr/*!*/ expr in exprs) {
+ Contract.Assert(expr != null);
+ res.Add(expr.Accept(this, arg));
+ }
+ return res;
+ }
+
+ private List<VCExpr/*!*/>/*!*/ MutateList(List<VCExpr/*!*/>/*!*/ exprs, Arg arg) {
+ Contract.Requires(cce.NonNullElements(exprs));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExpr>>()));
+ bool changed = false;
+ List<VCExpr/*!*/>/*!*/ res = new List<VCExpr/*!*/>();
+ foreach (VCExpr/*!*/ expr in exprs) {
+ Contract.Assert(expr != null);
+ VCExpr/*!*/ newExpr = expr.Accept(this, arg);
+ if (!Object.ReferenceEquals(expr, newExpr))
+ changed = true;
+ res.Add(newExpr);
+ }
+ if (!changed)
+ return exprs;
+ return res;
+ }
+
+ public virtual VCExpr Visit(VCExprLiteral node, Arg arg) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return node;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Special element used to mark the positions in the todo-stack where
+ // results have to be popped from the result-stack.
+ private static readonly VCExpr/*!*/ CombineResultsMarker = new VCExprLiteral(Type.Bool);
+
+ // The todo-stack contains records of the shape
+ //
+ // arg0
+ // arg1
+ // arg2
+ // ...
+ // CombineResultsMarker
+ // f(arg0, arg1, arg2, ...) (the original expression)
+
+ private readonly Stack<VCExpr/*!*/>/*!*/ NAryExprTodoStack = new Stack<VCExpr/*!*/>();
+ private readonly Stack<VCExpr/*!*/>/*!*/ NAryExprResultStack = new Stack<VCExpr/*!*/>();
+ [ContractInvariantMethod]
+ void ObjectInvarianta() {
+ Contract.Invariant(cce.NonNullElements(NAryExprResultStack));
+ Contract.Invariant(cce.NonNullElements(NAryExprTodoStack));
+ }
+
+
+ private void PushTodo(VCExprNAry exprTodo) {
+ Contract.Requires(exprTodo != null);
+ NAryExprTodoStack.Push(exprTodo);
+ NAryExprTodoStack.Push(CombineResultsMarker);
+ for (int i = exprTodo.Arity - 1; i >= 0; --i)
+ NAryExprTodoStack.Push(exprTodo[i]);
+ }
+
+ public virtual bool AvoidVisit(VCExprNAry node, Arg arg)
+ {
+ return true;
+ }
+
+ public virtual VCExpr Visit(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ int initialStackSize = NAryExprTodoStack.Count;
+ int initialResultStackSize = NAryExprResultStack.Count;
+
+ PushTodo(node);
+
+ while (NAryExprTodoStack.Count > initialStackSize) {
+ VCExpr/*!*/ subExpr = NAryExprTodoStack.Pop();
+ Contract.Assert(subExpr != null);
+
+ if (Object.ReferenceEquals(subExpr, CombineResultsMarker)) {
+ // assemble a result
+ VCExprNAry/*!*/ originalExpr = (VCExprNAry)NAryExprTodoStack.Pop();
+ Contract.Assert(originalExpr != null);
+ VCExprOp/*!*/ op = originalExpr.Op;
+ bool changed = false;
+ List<VCExpr/*!*/>/*!*/ newSubExprs = new List<VCExpr/*!*/>();
+
+ for (int i = op.Arity - 1; i >= 0; --i) {
+ VCExpr/*!*/ nextSubExpr = NAryExprResultStack.Pop();
+ Contract.Assert(nextSubExpr != null);
+ if (!Object.ReferenceEquals(nextSubExpr, originalExpr[i]))
+ changed = true;
+ newSubExprs.Insert(0, nextSubExpr);
+ }
+
+ NAryExprResultStack.Push(UpdateModifiedNode(originalExpr, newSubExprs, changed, arg));
+ //
+ } else {
+ //
+ VCExprNAry narySubExpr = subExpr as VCExprNAry;
+ if (narySubExpr != null && this.AvoidVisit(narySubExpr, arg) &&
+ // as in VCExprNAryUniformOpEnumerator, all expressions with
+ // type parameters are allowed to be inspected more closely
+ narySubExpr.TypeParamArity == 0) {
+ PushTodo(narySubExpr);
+ } else {
+ NAryExprResultStack.Push(subExpr.Accept(this, arg));
+ }
+ //
+ }
+ }
+
+ Contract.Assert(NAryExprTodoStack.Count == initialStackSize && NAryExprResultStack.Count == initialResultStackSize + 1);
+ return NAryExprResultStack.Pop();
+ }
+
+ protected virtual VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode, List<VCExpr/*!*/>/*!*/ newSubExprs, // has any of the subexpressions changed?
+ bool changed,
+ Arg arg) {
+ Contract.Requires(cce.NonNullElements(newSubExprs));
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ if (changed)
+ return Gen.Function(originalNode.Op,
+ newSubExprs, originalNode.TypeArguments);
+ else
+ return originalNode;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ public virtual VCExpr Visit(VCExprVar node, Arg arg) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ return node;
+ }
+
+ protected List<VCTrigger/*!*/>/*!*/ MutateTriggers(List<VCTrigger/*!*/>/*!*/ triggers, Arg arg) {
+ Contract.Requires(cce.NonNullElements(triggers));
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCTrigger>>()));
+ List<VCTrigger/*!*/>/*!*/ newTriggers = new List<VCTrigger/*!*/>();
+ bool changed = false;
+ foreach (VCTrigger/*!*/ trigger in triggers) {
+ Contract.Assert(trigger != null);
+ List<VCExpr/*!*/>/*!*/ exprs = trigger.Exprs;
+ List<VCExpr/*!*/>/*!*/ newExprs = MutateList(exprs, arg);
+
+ if (Object.ReferenceEquals(exprs, newExprs)) {
+ newTriggers.Add(trigger);
+ } else {
+ newTriggers.Add(Gen.Trigger(trigger.Pos, newExprs));
+ changed = true;
+ }
+ }
+ if (!changed)
+ return triggers;
+ return newTriggers;
+ }
+
+ public virtual VCExpr Visit(VCExprQuantifier node, Arg arg) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ bool changed = false;
+
+ VCExpr/*!*/ body = node.Body;
+ Contract.Assert(body != null);
+ VCExpr/*!*/ newbody = body.Accept(this, arg);
+ Contract.Assert(newbody != null);
+ if (!Object.ReferenceEquals(body, newbody))
+ changed = true;
+
+ // visit the trigger expressions as well
+ List<VCTrigger/*!*/>/*!*/ triggers = node.Triggers;
+ Contract.Assert(cce.NonNullElements(triggers));
+ List<VCTrigger/*!*/>/*!*/ newTriggers = MutateTriggers(triggers, arg);
+ Contract.Assert(cce.NonNullElements(newTriggers));
+ if (!Object.ReferenceEquals(triggers, newTriggers))
+ changed = true;
+
+ if (!changed)
+ return node;
+ return Gen.Quantify(node.Quan, node.TypeParameters, node.BoundVars,
+ newTriggers, node.Infos, newbody);
+ }
+
+ public virtual VCExpr Visit(VCExprLet node, Arg arg) {
+ //Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ bool changed = false;
+
+ VCExpr/*!*/ body = node.Body;
+ VCExpr/*!*/ newbody = body.Accept(this, arg);
+ if (!Object.ReferenceEquals(body, newbody))
+ changed = true;
+
+ List<VCExprLetBinding/*!*/>/*!*/ newbindings = new List<VCExprLetBinding/*!*/>();
+ for (int i = 0; i < node.Length; ++i) {
+ VCExprLetBinding/*!*/ binding = node[i];
+ Contract.Assert(binding != null);
+ VCExpr/*!*/ e = binding.E;
+ VCExpr/*!*/ newE = e.Accept(this, arg);
+ if (Object.ReferenceEquals(e, newE)) {
+ newbindings.Add(binding);
+ } else {
+ changed = true;
+ newbindings.Add(Gen.LetBinding(binding.V, newE));
+ }
+ }
+
+ if (!changed)
+ return node;
+ return Gen.Let(newbindings, newbody);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Substitutions and a visitor for applying substitutions. A substitution can
+ // substitute both type variables and term variables
+
+ public class VCExprSubstitution {
+ private readonly List<IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/>/*!*/ TermSubsts;
+ [ContractInvariantMethod]
+ void TermSubstsInvariantMethod() {
+ Contract.Invariant(TermSubsts != null && Contract.ForAll(TermSubsts, i => cce.NonNullDictionaryAndValues(i)));
+ }
+ private readonly List<IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/>/*!*/ TypeSubsts;
+ [ContractInvariantMethod]
+ void TypeSubstsInvariantMethod() {
+ Contract.Invariant(TermSubsts != null && Contract.ForAll(TypeSubsts, i => cce.NonNullDictionaryAndValues(i)));
+ }
+
+ public VCExprSubstitution(IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/ termSubst, IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ typeSubst) {
+ Contract.Requires(cce.NonNullDictionaryAndValues(termSubst));
+ Contract.Requires(cce.NonNullDictionaryAndValues(typeSubst));
+ List<IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/>/*!*/ termSubsts =
+ new List<IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/>();
+ termSubsts.Add(termSubst);
+ List<IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/>/*!*/ typeSubsts =
+ new List<IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/>();
+ typeSubsts.Add(typeSubst);
+ this.TermSubsts = termSubsts;
+ this.TypeSubsts = typeSubsts;
+ }
+
+ public VCExprSubstitution()
+ : this(new Dictionary<VCExprVar/*!*/, VCExpr/*!*/>(), new Dictionary<TypeVariable/*!*/, Type/*!*/>()) {
+
+ }
+
+ public void PushScope() {
+ TermSubsts.Add(new Dictionary<VCExprVar/*!*/, VCExpr/*!*/>());
+ TypeSubsts.Add(new Dictionary<TypeVariable/*!*/, Type/*!*/>());
+ }
+
+ public void PopScope() {
+ TermSubsts.RemoveAt(TermSubsts.Count - 1);
+ TypeSubsts.RemoveAt(TypeSubsts.Count - 1);
+ }
+
+ public VCExpr this[VCExprVar/*!*/ var] {
+ get {
+ Contract.Requires(var != null);
+ VCExpr res;
+ for (int i = TermSubsts.Count - 1; i >= 0; --i) {
+ if (TermSubsts[i].TryGetValue(var, out res))
+ return res;
+ }
+ return null;
+ }
+ set {
+ TermSubsts[TermSubsts.Count - 1][var] = cce.NonNull(value);
+ }
+ }
+
+ public Type this[TypeVariable/*!*/ var] {
+ get {
+ Contract.Requires(var != null);
+ Type res;
+ for (int i = TypeSubsts.Count - 1; i >= 0; --i) {
+ if (TypeSubsts[i].TryGetValue(var, out res))
+ return res;
+ }
+ return null;
+ }
+ set {
+ TypeSubsts[TypeSubsts.Count - 1][var] = cce.NonNull(value);
+ }
+ }
+
+ public bool ContainsKey(VCExprVar var) {
+ Contract.Requires(var != null);
+ return this[var] != null;
+ }
+
+ public bool ContainsKey(TypeVariable var) {
+ Contract.Requires(var != null);
+ return this[var] != null;
+ }
+
+ public bool TermSubstIsEmpty {
+ get {
+ return TermSubsts.All(dict => !dict.Any());
+ }
+ }
+
+ public bool TypeSubstIsEmpty {
+ get {
+ return TypeSubsts.All(dict => !dict.Any());
+ }
+ }
+
+ public IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ ToTypeSubst {
+ get {
+ Contract.Ensures(cce.NonNullDictionaryAndValues(Contract.Result<IDictionary<TypeVariable, Type>>()));
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ res = new Dictionary<TypeVariable/*!*/, Type/*!*/>();
+ foreach (IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ dict in TypeSubsts) {
+ foreach (KeyValuePair<TypeVariable/*!*/, Type/*!*/> pair in dict) {
+ Contract.Assert(cce.NonNullElements(pair));
+ // later ones overwrite earlier ones
+ res[pair.Key] = pair.Value;
+ }
+ }
+ return res;
+ }
+ }
+
+ // the variables that are not mapped to themselves
+ public IEnumerable<VCExprVar/*!*/>/*!*/ TermDomain {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<VCExprVar>>()));
+ HashSet<VCExprVar/*!*/>/*!*/ domain = new HashSet<VCExprVar/*!*/>();
+ foreach (IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/ dict in TermSubsts) {
+ Contract.Assert(dict != null);
+ foreach (VCExprVar/*!*/ var in dict.Keys) {
+ Contract.Assert(var != null);
+ if (!var.Equals(this[var]))
+ domain.Add(var);
+ }
+ }
+ return domain;
+ }
+ }
+
+ // the variables that are not mapped to themselves
+ public IEnumerable<TypeVariable/*!*/>/*!*/ TypeDomain {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<TypeVariable>>()));
+ HashSet<TypeVariable/*!*/>/*!*/ domain = new HashSet<TypeVariable/*!*/>();
+ foreach (IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ dict in TypeSubsts) {
+ Contract.Assert(dict != null);
+ foreach (TypeVariable/*!*/ var in dict.Keys) {
+ Contract.Assert(var != null);
+ if (!var.Equals(this[var]))
+ domain.Add(var);
+ }
+ }
+ return domain;
+ }
+ }
+
+ public FreeVariableCollector/*!*/ Codomains {
+ get {
+ Contract.Ensures(Contract.Result<FreeVariableCollector>() != null);
+
+ FreeVariableCollector/*!*/ coll = new FreeVariableCollector();
+ foreach (VCExprVar/*!*/ var in TermDomain)
+ coll.Collect(cce.NonNull(this)[var]);
+ foreach (TypeVariable/*!*/ var in TypeDomain)
+ coll.Collect(cce.NonNull(this)[var]);
+ return coll;
+ }
+ }
+
+ public VCExprSubstitution Clone() {
+ Contract.Ensures(Contract.Result<VCExprSubstitution>() != null);
+ VCExprSubstitution/*!*/ res = new VCExprSubstitution();
+ foreach (IDictionary<VCExprVar/*!*/, VCExpr/*!*/>/*!*/ dict in TermSubsts)
+ res.TermSubsts.Add(HelperFuns.Clone(dict));
+ foreach (IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ dict in TypeSubsts)
+ res.TypeSubsts.Add(HelperFuns.Clone(dict));
+ return res;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+
+ public class SubstitutingVCExprVisitor
+ : MutatingVCExprVisitor<VCExprSubstitution/*!*/> {
+ public SubstitutingVCExprVisitor(VCExpressionGenerator gen)
+ : base(gen) {
+ Contract.Requires(gen != null);
+
+ }
+
+ // when descending across a binder, we have to check that no collisions
+ // or variable capture can occur. if this might happen, we replace the
+ // term and type variables bound by the binder with fresh variables
+ private bool CollisionPossible(IEnumerable<TypeVariable/*!*/>/*!*/ typeParams, IEnumerable<VCExprVar/*!*/>/*!*/ boundVars, VCExprSubstitution/*!*/ substitution) {
+ Contract.Requires(cce.NonNullElements(typeParams));
+ Contract.Requires(cce.NonNullElements(boundVars));
+ Contract.Requires(substitution != null);
+ // variables can be shadowed by a binder
+ if (typeParams.Any(var => substitution.ContainsKey(var)) ||
+ boundVars.Any(var => substitution.ContainsKey(var)))
+ return true;
+ // compute the codomain of the substitution
+ FreeVariableCollector coll = substitution.Codomains;
+ Contract.Assert(coll != null);
+ // variables could be captured when applying the substitution
+ return typeParams.Any(var => coll.FreeTypeVars.Contains(var)) ||
+ boundVars.Any(var => coll.FreeTermVars.ContainsKey(var));
+ }
+
+ // can be overwritten if names of bound variables are to be changed
+ protected virtual string ChooseNewVariableName(string oldName) {
+ Contract.Requires(oldName != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+ return oldName;
+ }
+
+ // handle type parameters in VCExprNAry
+ protected override VCExpr/*!*/ UpdateModifiedNode(VCExprNAry/*!*/ originalNode, List<VCExpr/*!*/>/*!*/ newSubExprs, bool changed, VCExprSubstitution/*!*/ substitution) {
+ //Contract.Requires(originalNode != null);
+ //Contract.Requires(cce.NonNullElements(newSubExprs));
+ //Contract.Requires(substitution != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ List<Type/*!*/>/*!*/ typeParams = new List<Type/*!*/>();
+ foreach (Type/*!*/ t in originalNode.TypeArguments) {
+ Contract.Assert(t != null);
+ Type/*!*/ newType = t.Substitute(substitution.ToTypeSubst);
+ Contract.Assert(newType != null);
+ if (!ReferenceEquals(t, newType))
+ changed = true;
+ typeParams.Add(newType);
+ }
+ if (changed)
+ return Gen.Function(originalNode.Op, newSubExprs, typeParams);
+ else
+ return originalNode;
+ }
+
+ public override VCExpr/*!*/ Visit(VCExprQuantifier/*!*/ node, VCExprSubstitution/*!*/ substitution) {
+ Contract.Requires(node != null);
+ Contract.Requires(substitution != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ // the default is to refresh bound variables only if necessary
+ // because of collisions
+ return Visit(node, substitution, false);
+ }
+
+ public VCExpr/*!*/ Visit(VCExprQuantifier/*!*/ node, VCExprSubstitution/*!*/ substitution, bool refreshBoundVariables) {
+ Contract.Requires(node != null);
+ Contract.Requires(substitution != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+
+ substitution.PushScope();
+ try {
+
+ List<TypeVariable/*!*/>/*!*/ typeParams = node.TypeParameters;
+ Contract.Assert(cce.NonNullElements(typeParams));
+ bool refreshAllVariables = refreshBoundVariables ||
+ CollisionPossible(node.TypeParameters, node.BoundVars, substitution);
+ if (refreshAllVariables) {
+ // we introduce fresh type variables to ensure that none gets captured
+ typeParams = new List<TypeVariable/*!*/>();
+ foreach (TypeVariable/*!*/ var in node.TypeParameters) {
+ Contract.Assert(var != null);
+ TypeVariable/*!*/ freshVar =
+ new TypeVariable(Token.NoToken, ChooseNewVariableName(var.Name));
+ Contract.Assert(freshVar != null);
+ typeParams.Add(freshVar);
+ substitution[var] = freshVar;
+ // this might overwrite other elements of the substitution, deliberately
+ }
+ }
+
+ List<VCExprVar/*!*/>/*!*/ boundVars = node.BoundVars;
+ Contract.Assert(cce.NonNullElements(boundVars));
+ if (refreshAllVariables || !substitution.TypeSubstIsEmpty) {
+ // collisions are possible, or we also substitute type variables. in this case
+ // the bound term variables have to be replaced with fresh variables with the
+ // right types
+ boundVars = new List<VCExprVar/*!*/>();
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ typeSubst = substitution.ToTypeSubst;
+ Contract.Assert(cce.NonNullDictionaryAndValues(typeSubst));
+ foreach (VCExprVar/*!*/ var in node.BoundVars) {
+ Contract.Assert(var != null);
+ VCExprVar/*!*/ freshVar =
+ Gen.Variable(ChooseNewVariableName(var.Name),
+ var.Type.Substitute(typeSubst));
+ Contract.Assert(freshVar != null);
+ boundVars.Add(freshVar);
+ substitution[var] = freshVar;
+ // this might overwrite other elements of the substitution, deliberately
+ }
+ }
+
+ List<VCTrigger/*!*/>/*!*/ newTriggers = new List<VCTrigger/*!*/>();
+ foreach (VCTrigger/*!*/ trigger in node.Triggers) {
+ Contract.Assert(trigger != null);
+ newTriggers.Add(Gen.Trigger(trigger.Pos, MutateSeq(trigger.Exprs, substitution)));
+ }
+
+ VCExpr/*!*/ newBody = Mutate(node.Body, substitution);
+ Contract.Assert(newBody != null);
+
+ return Gen.Quantify(node.Quan, typeParams, boundVars,
+ newTriggers, node.Infos, newBody);
+
+ } finally {
+ substitution.PopScope();
+ }
+ }
+
+ public override VCExpr Visit(VCExprVar node, VCExprSubstitution substitution) {
+ Contract.Requires(substitution != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ VCExpr res = substitution[node];
+ if (res != null)
+ return res;
+ return node;
+ }
+
+ public override VCExpr Visit(VCExprLet node, VCExprSubstitution substitution) {
+ Contract.Requires(substitution != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // the default is to refresh bound variables only if necessary
+ // because of collisions
+ return Visit(node, substitution, false);
+ }
+
+ public VCExpr Visit(VCExprLet node, VCExprSubstitution substitution, bool refreshBoundVariables) {
+ Contract.Requires(substitution != null);
+ Contract.Requires(node != null);
+ Contract.Ensures(Contract.Result<VCExpr>() != null);
+ // let-expressions do not have type parameters (fortunately ...)
+ substitution.PushScope();
+ try {
+
+ bool refreshAllVariables =
+ refreshBoundVariables ||
+ !substitution.TypeSubstIsEmpty ||
+ CollisionPossible(new List<TypeVariable/*!*/>(), node.BoundVars, substitution);
+
+ List<VCExprVar/*!*/>/*!*/ newBoundVars = node.BoundVars;
+ Contract.Assert(cce.NonNullElements(newBoundVars));
+ if (refreshAllVariables) {
+ // collisions are possible, or we also substitute type variables. in this case
+ // the bound term variables have to be replaced with fresh variables with the
+ // right types
+ newBoundVars = new List<VCExprVar/*!*/>();
+ IDictionary<TypeVariable/*!*/, Type/*!*/>/*!*/ typeSubst = substitution.ToTypeSubst;
+ Contract.Assert(cce.NonNullDictionaryAndValues(typeSubst));
+ foreach (VCExprVar/*!*/ var in node.BoundVars) {
+ Contract.Assert(var != null);
+ VCExprVar/*!*/ freshVar =
+ Gen.Variable(ChooseNewVariableName(var.Name),
+ var.Type.Substitute(typeSubst));
+ Contract.Assert(freshVar != null);
+ newBoundVars.Add(freshVar);
+ substitution[var] = freshVar;
+ // this might overwrite other elements of the substitution, deliberately
+ }
+ }
+
+ List<VCExprLetBinding/*!*/>/*!*/ newbindings = new List<VCExprLetBinding/*!*/>();
+ for (int i = 0; i < node.Length; ++i) {
+ VCExprLetBinding/*!*/ binding = node[i];
+ Contract.Assert(binding != null);
+ newbindings.Add(Gen.LetBinding(newBoundVars[i], Mutate(binding.E, substitution)));
+ }
+
+ VCExpr/*!*/ newBody = Mutate(node.Body, substitution);
+ Contract.Assert(newBody != null);
+ return Gen.Let(newbindings, newBody);
+
+ } finally {
+ substitution.PopScope();
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ [ContractClassFor(typeof(StandardVCExprOpVisitor<,>))]
+ public abstract class StandardVCExprOpVisitorContracts<Result, Arg> : StandardVCExprOpVisitor<Result, Arg> {
+ protected override Result StandardResult(VCExprNAry node, Arg arg) {
+ Contract.Requires(node != null);
+ throw new NotImplementedException();
+ }
+ }
+
+
+ [ContractClass(typeof(StandardVCExprOpVisitorContracts<,>))]
+ public abstract class StandardVCExprOpVisitor<Result, Arg>
+ : IVCExprOpVisitor<Result, Arg> {
+ protected abstract Result StandardResult(VCExprNAry/*!*/ node, Arg arg);
+
+ public virtual Result VisitNotOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitEqOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitNeqOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitAndOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitOrOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitImpliesOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitDistinctOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitLabelOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitSelectOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitStoreOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitBvOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitBvExtractOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitBvConcatOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitIfThenElseOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitCustomOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitAddOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitSubOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitMulOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitDivOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitModOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitRealDivOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitPowOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitLtOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitLeOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitGtOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitGeOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitSubtypeOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitSubtype3Op(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitToIntOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitToRealOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ public virtual Result VisitBoogieFunctionOp(VCExprNAry node, Arg arg) {
+ //Contract.Requires(node != null);
+ return StandardResult(node, arg);
+ }
+ }
+
} \ No newline at end of file
diff --git a/Source/VCExpr/cce.cs b/Source/VCExpr/cce.cs
index ef594484..1e0b12a5 100644
--- a/Source/VCExpr/cce.cs
+++ b/Source/VCExpr/cce.cs
@@ -1,193 +1,193 @@
-using System;
-using SA=System.Attribute;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Text;
-//using Microsoft.Boogie;
-
-/// <summary>
-/// A class containing static methods to extend the functionality of Code Contracts
-/// </summary>
-
-public static class cce {
- //[Pure]
- //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
- // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
- //}
- [Pure]
- public static T NonNull<T>(T t) {
- Contract.Assert(t != null);
- return t;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection) {
- return collection != null && Contract.ForAll(collection, c => c != null);
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
- return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
- }
- //[Pure]
- //public static bool NonNullElements(VariableSeq collection) {
- // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
- //}
- /// <summary>
- /// For possibly-null lists of non-null elements
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="collection"></param>
- /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
- /// <returns></returns>
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
- return (nullability && collection == null) || cce.NonNullElements(collection);
- //Should be the same as:
- /*if(nullability&&collection==null)
- * return true;
- * return cce.NonNullElements(collection)
- */
-
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
- return kvp.Key != null && kvp.Value != null;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
- return iEnumerator != null;
- }
- //[Pure]
- //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
- // return cce.NonNullElements(graph.TopologicalSort());
- //}
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
- [Pure]
- public static bool IsPeerConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposable(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposed(object o) {
- return true;
- }
- [Pure]
- public static bool IsNew(object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- [Pure]
- public static void AssignSame(object o, object p) {
- }
- [Pure]
- public static object ElementProxy(object o) {
- return o;
- }
- [Pure]
- public static bool None(object o) {
- return true;
- }
- [Pure]
- public static bool Different(object o, object p) {
- return true;
- }
- [Pure]
- public static bool New(object o) {
- return true;
- }
- }
- [Pure]
- public static void LoopInvariant(bool p) {
- Contract.Assert(p);
- }
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
- //[Pure]
- //public static bool IsValid(Microsoft.Dafny.Expression expression) {
- // return true;
- //}
- //public static List<T> toList<T>(PureCollections.Sequence s) {
- // List<T> toRet = new List<T>();
- // foreach (T t in s.elems)
- // if(t!=null)
- // toRet.Add(t);
- // return toRet;
- //}
-
- //internal static bool NonNullElements(Set set) {
- // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
- //}
-}
-
-public class PeerAttribute : SA {
-}
-public class RepAttribute : SA {
-}
-public class CapturedAttribute : SA {
-}
-public class NotDelayedAttribute : SA {
-}
-public class NoDefaultContractAttribute : SA {
-}
-public class VerifyAttribute : SA {
- public VerifyAttribute(bool b) {
-
- }
-}
-public class StrictReadonlyAttribute : SA {
-}
-public class AdditiveAttribute : SA {
-}
-public class ReadsAttribute : SA {
- public enum Reads {
- Nothing,
- Everything,
- };
- public ReadsAttribute(object o) {
- }
-}
-public class GlobalAccessAttribute : SA {
- public GlobalAccessAttribute(bool b) {
- }
-}
-public class EscapesAttribute : SA {
- public EscapesAttribute(bool b, bool b_2) {
- }
-}
-public class NeedsContractsAttribute : SA {
- public NeedsContractsAttribute() {
- }
- public NeedsContractsAttribute(bool ret, bool parameters) {
- }
- public NeedsContractsAttribute(bool ret, int[] parameters) {
- }
-}
-public class ImmutableAttribute : SA {
-}
-public class InsideAttribute : SA {
-}
-public class SpecPublicAttribute : SA {
-}
-public class ElementsPeerAttribute : SA {
-}
-public class ResultNotNewlyAllocatedAttribute : SA {
-}
-public class OnceAttribute : SA {
+using System;
+using SA=System.Attribute;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Text;
+//using Microsoft.Boogie;
+
+/// <summary>
+/// A class containing static methods to extend the functionality of Code Contracts
+/// </summary>
+
+public static class cce {
+ //[Pure]
+ //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) {
+ // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents());
+ //}
+ [Pure]
+ public static T NonNull<T>(T t) {
+ Contract.Assert(t != null);
+ return t;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection) {
+ return collection != null && Contract.ForAll(collection, c => c != null);
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) {
+ return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair));
+ }
+ //[Pure]
+ //public static bool NonNullElements(VariableSeq collection) {
+ // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null);
+ //}
+ /// <summary>
+ /// For possibly-null lists of non-null elements
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="collection"></param>
+ /// <param name="nullability">If true, the collection is treated as an IEnumerable&lt;T!&gt;?, rather than an IEnumerable&lt;T!&gt;!</param>
+ /// <returns></returns>
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
+ return (nullability && collection == null) || cce.NonNullElements(collection);
+ //Should be the same as:
+ /*if(nullability&&collection==null)
+ * return true;
+ * return cce.NonNullElements(collection)
+ */
+
+ }
+ [Pure]
+ public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
+ return kvp.Key != null && kvp.Value != null;
+ }
+ [Pure]
+ public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
+ return iEnumerator != null;
+ }
+ //[Pure]
+ //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
+ // return cce.NonNullElements(graph.TopologicalSort());
+ //}
+ [Pure]
+ public static void BeginExpose(object o) {
+ }
+ [Pure]
+ public static void EndExpose() {
+ }
+ [Pure]
+ public static bool IsPeerConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsConsistent(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposable(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsExposed(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool IsNew(object o) {
+ return true;
+ }
+ public static class Owner {
+ [Pure]
+ public static bool Same(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static void AssignSame(object o, object p) {
+ }
+ [Pure]
+ public static object ElementProxy(object o) {
+ return o;
+ }
+ [Pure]
+ public static bool None(object o) {
+ return true;
+ }
+ [Pure]
+ public static bool Different(object o, object p) {
+ return true;
+ }
+ [Pure]
+ public static bool New(object o) {
+ return true;
+ }
+ }
+ [Pure]
+ public static void LoopInvariant(bool p) {
+ Contract.Assert(p);
+ }
+ public class UnreachableException : Exception {
+ public UnreachableException() {
+ }
+ }
+ //[Pure]
+ //public static bool IsValid(Microsoft.Dafny.Expression expression) {
+ // return true;
+ //}
+ //public static List<T> toList<T>(PureCollections.Sequence s) {
+ // List<T> toRet = new List<T>();
+ // foreach (T t in s.elems)
+ // if(t!=null)
+ // toRet.Add(t);
+ // return toRet;
+ //}
+
+ //internal static bool NonNullElements(Set set) {
+ // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
+ //}
+}
+
+public class PeerAttribute : SA {
+}
+public class RepAttribute : SA {
+}
+public class CapturedAttribute : SA {
+}
+public class NotDelayedAttribute : SA {
+}
+public class NoDefaultContractAttribute : SA {
+}
+public class VerifyAttribute : SA {
+ public VerifyAttribute(bool b) {
+
+ }
+}
+public class StrictReadonlyAttribute : SA {
+}
+public class AdditiveAttribute : SA {
+}
+public class ReadsAttribute : SA {
+ public enum Reads {
+ Nothing,
+ Everything,
+ };
+ public ReadsAttribute(object o) {
+ }
+}
+public class GlobalAccessAttribute : SA {
+ public GlobalAccessAttribute(bool b) {
+ }
+}
+public class EscapesAttribute : SA {
+ public EscapesAttribute(bool b, bool b_2) {
+ }
+}
+public class NeedsContractsAttribute : SA {
+ public NeedsContractsAttribute() {
+ }
+ public NeedsContractsAttribute(bool ret, bool parameters) {
+ }
+ public NeedsContractsAttribute(bool ret, int[] parameters) {
+ }
+}
+public class ImmutableAttribute : SA {
+}
+public class InsideAttribute : SA {
+}
+public class SpecPublicAttribute : SA {
+}
+public class ElementsPeerAttribute : SA {
+}
+public class ResultNotNewlyAllocatedAttribute : SA {
+}
+public class OnceAttribute : SA {
} \ No newline at end of file