diff options
author | Dan Liew <daniel.liew@imperial.ac.uk> | 2015-06-28 01:44:30 +0100 |
---|---|---|
committer | Dan Liew <daniel.liew@imperial.ac.uk> | 2015-06-28 01:44:30 +0100 |
commit | 962f8d5252b3f5ec4d19e0cd2a430934bd55cc6d (patch) | |
tree | 27d5f9b0d130c6c1a6758bc0b7456b0aa51e34e0 /Source/VCExpr | |
parent | e11d65009d0b4ba1327f5f5dd6b26367330611f0 (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.cs | 462 | ||||
-rw-r--r-- | Source/VCExpr/Boogie2VCExpr.cs | 2418 | ||||
-rw-r--r-- | Source/VCExpr/Clustering.cs | 1042 | ||||
-rw-r--r-- | Source/VCExpr/LetBindingSorter.cs | 322 | ||||
-rw-r--r-- | Source/VCExpr/NameClashResolver.cs | 392 | ||||
-rw-r--r-- | Source/VCExpr/SimplifyLikeLineariser.cs | 2196 | ||||
-rw-r--r-- | Source/VCExpr/TermFormulaFlattening.cs | 494 | ||||
-rw-r--r-- | Source/VCExpr/TypeErasure.cs | 3238 | ||||
-rw-r--r-- | Source/VCExpr/TypeErasureArguments.cs | 1506 | ||||
-rw-r--r-- | Source/VCExpr/TypeErasurePremisses.cs | 2674 | ||||
-rw-r--r-- | Source/VCExpr/VCExpr.csproj | 446 | ||||
-rw-r--r-- | Source/VCExpr/VCExprAST.cs | 4260 | ||||
-rw-r--r-- | Source/VCExpr/VCExprASTPrinter.cs | 720 | ||||
-rw-r--r-- | Source/VCExpr/VCExprASTVisitors.cs | 3052 | ||||
-rw-r--r-- | Source/VCExpr/cce.cs | 384 |
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<T!>?, rather than an IEnumerable<T!>!</param>
- /// <returns></returns>
- [Pure]
- public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) {
- return (nullability && collection == null) || cce.NonNullElements(collection);
- //Should be the same as:
- /*if(nullability&&collection==null)
- * return true;
- * return cce.NonNullElements(collection)
- */
-
- }
- [Pure]
- public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) {
- return kvp.Key != null && kvp.Value != null;
- }
- [Pure]
- public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) {
- return iEnumerator != null;
- }
- //[Pure]
- //public static bool NonNullElements<T>(Graphing.Graph<T> graph) {
- // return cce.NonNullElements(graph.TopologicalSort());
- //}
- [Pure]
- public static void BeginExpose(object o) {
- }
- [Pure]
- public static void EndExpose() {
- }
- [Pure]
- public static bool IsPeerConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsConsistent(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposable(object o) {
- return true;
- }
- [Pure]
- public static bool IsExposed(object o) {
- return true;
- }
- [Pure]
- public static bool IsNew(object o) {
- return true;
- }
- public static class Owner {
- [Pure]
- public static bool Same(object o, object p) {
- return true;
- }
- [Pure]
- public static void AssignSame(object o, object p) {
- }
- [Pure]
- public static object ElementProxy(object o) {
- return o;
- }
- [Pure]
- public static bool None(object o) {
- return true;
- }
- [Pure]
- public static bool Different(object o, object p) {
- return true;
- }
- [Pure]
- public static bool New(object o) {
- return true;
- }
- }
- [Pure]
- public static void LoopInvariant(bool p) {
- Contract.Assert(p);
- }
- public class UnreachableException : Exception {
- public UnreachableException() {
- }
- }
- //[Pure]
- //public static bool IsValid(Microsoft.Dafny.Expression expression) {
- // return true;
- //}
- //public static List<T> toList<T>(PureCollections.Sequence s) {
- // List<T> toRet = new List<T>();
- // foreach (T t in s.elems)
- // if(t!=null)
- // toRet.Add(t);
- // return toRet;
- //}
-
- //internal static bool NonNullElements(Set set) {
- // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null);
- //}
-}
-
-public class PeerAttribute : SA {
-}
-public class RepAttribute : SA {
-}
-public class CapturedAttribute : SA {
-}
-public class NotDelayedAttribute : SA {
-}
-public class NoDefaultContractAttribute : SA {
-}
-public class VerifyAttribute : SA {
- public VerifyAttribute(bool b) {
-
- }
-}
-public class StrictReadonlyAttribute : SA {
-}
-public class AdditiveAttribute : SA {
-}
-public class ReadsAttribute : SA {
- public enum Reads {
- Nothing,
- Everything,
- };
- public ReadsAttribute(object o) {
- }
-}
-public class GlobalAccessAttribute : SA {
- public GlobalAccessAttribute(bool b) {
- }
-}
-public class EscapesAttribute : SA {
- public EscapesAttribute(bool b, bool b_2) {
- }
-}
-public class NeedsContractsAttribute : SA {
- public NeedsContractsAttribute() {
- }
- public NeedsContractsAttribute(bool ret, bool parameters) {
- }
- public NeedsContractsAttribute(bool ret, int[] parameters) {
- }
-}
-public class ImmutableAttribute : SA {
-}
-public class InsideAttribute : SA {
-}
-public class SpecPublicAttribute : SA {
-}
-public class ElementsPeerAttribute : SA {
-}
-public class ResultNotNewlyAllocatedAttribute : SA {
-}
-public class OnceAttribute : SA {
+using System; +using SA=System.Attribute; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Text; +//using Microsoft.Boogie; + +/// <summary> +/// A class containing static methods to extend the functionality of Code Contracts +/// </summary> + +public static class cce { + //[Pure] + //public static bool NonNullElements<T>(Microsoft.Dafny.Graph<T> collection) { + // return collection != null && cce.NonNullElements(collection.TopologicallySortedComponents()); + //} + [Pure] + public static T NonNull<T>(T t) { + Contract.Assert(t != null); + return t; + } + [Pure] + public static bool NonNullElements<T>(IEnumerable<T> collection) { + return collection != null && Contract.ForAll(collection, c => c != null); + } + [Pure] + public static bool NonNullElements<TKey, TValue>(IDictionary<TKey, TValue> collection) { + return collection != null && Contract.ForAll(collection, pair => NonNullElements(pair)); + } + //[Pure] + //public static bool NonNullElements(VariableSeq collection) { + // return collection != null && Contract.ForAll(0, collection.Length, i => collection[i] != null); + //} + /// <summary> + /// For possibly-null lists of non-null elements + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="collection"></param> + /// <param name="nullability">If true, the collection is treated as an IEnumerable<T!>?, rather than an IEnumerable<T!>!</param> + /// <returns></returns> + [Pure] + public static bool NonNullElements<T>(IEnumerable<T> collection, bool nullability) { + return (nullability && collection == null) || cce.NonNullElements(collection); + //Should be the same as: + /*if(nullability&&collection==null) + * return true; + * return cce.NonNullElements(collection) + */ + + } + [Pure] + public static bool NonNullElements<TKey, TValue>(KeyValuePair<TKey, TValue> kvp) { + return kvp.Key != null && kvp.Value != null; + } + [Pure] + public static bool NonNullElements<T>(IEnumerator<T> iEnumerator) { + return iEnumerator != null; + } + //[Pure] + //public static bool NonNullElements<T>(Graphing.Graph<T> graph) { + // return cce.NonNullElements(graph.TopologicalSort()); + //} + [Pure] + public static void BeginExpose(object o) { + } + [Pure] + public static void EndExpose() { + } + [Pure] + public static bool IsPeerConsistent(object o) { + return true; + } + [Pure] + public static bool IsConsistent(object o) { + return true; + } + [Pure] + public static bool IsExposable(object o) { + return true; + } + [Pure] + public static bool IsExposed(object o) { + return true; + } + [Pure] + public static bool IsNew(object o) { + return true; + } + public static class Owner { + [Pure] + public static bool Same(object o, object p) { + return true; + } + [Pure] + public static void AssignSame(object o, object p) { + } + [Pure] + public static object ElementProxy(object o) { + return o; + } + [Pure] + public static bool None(object o) { + return true; + } + [Pure] + public static bool Different(object o, object p) { + return true; + } + [Pure] + public static bool New(object o) { + return true; + } + } + [Pure] + public static void LoopInvariant(bool p) { + Contract.Assert(p); + } + public class UnreachableException : Exception { + public UnreachableException() { + } + } + //[Pure] + //public static bool IsValid(Microsoft.Dafny.Expression expression) { + // return true; + //} + //public static List<T> toList<T>(PureCollections.Sequence s) { + // List<T> toRet = new List<T>(); + // foreach (T t in s.elems) + // if(t!=null) + // toRet.Add(t); + // return toRet; + //} + + //internal static bool NonNullElements(Set set) { + // return set != null && Contract.ForAll(0,set.Count, i => set[i] != null); + //} +} + +public class PeerAttribute : SA { +} +public class RepAttribute : SA { +} +public class CapturedAttribute : SA { +} +public class NotDelayedAttribute : SA { +} +public class NoDefaultContractAttribute : SA { +} +public class VerifyAttribute : SA { + public VerifyAttribute(bool b) { + + } +} +public class StrictReadonlyAttribute : SA { +} +public class AdditiveAttribute : SA { +} +public class ReadsAttribute : SA { + public enum Reads { + Nothing, + Everything, + }; + public ReadsAttribute(object o) { + } +} +public class GlobalAccessAttribute : SA { + public GlobalAccessAttribute(bool b) { + } +} +public class EscapesAttribute : SA { + public EscapesAttribute(bool b, bool b_2) { + } +} +public class NeedsContractsAttribute : SA { + public NeedsContractsAttribute() { + } + public NeedsContractsAttribute(bool ret, bool parameters) { + } + public NeedsContractsAttribute(bool ret, int[] parameters) { + } +} +public class ImmutableAttribute : SA { +} +public class InsideAttribute : SA { +} +public class SpecPublicAttribute : SA { +} +public class ElementsPeerAttribute : SA { +} +public class ResultNotNewlyAllocatedAttribute : SA { +} +public class OnceAttribute : SA { }
\ No newline at end of file |