From 1188039043117d026e6cdfe13d35aed03880fea7 Mon Sep 17 00:00:00 2001 From: tabarbe Date: Thu, 26 Aug 2010 23:38:33 +0000 Subject: Boogie: AIFramework port part 1/3: Committing new sources. --- Source/AIFramework/AIFramework.csproj | 270 ++-- Source/AIFramework/CommonFunctionSymbols.cs | 810 ++++++++--- Source/AIFramework/Expr.cs | 337 +++-- Source/AIFramework/Functional.cs | 179 ++- Source/AIFramework/Lattice.cs | 1464 ++++++++++++-------- Source/AIFramework/Logger.cs | 85 +- Source/AIFramework/MultiLattice.cs | 1037 +++++++------- Source/AIFramework/Mutable.cs | 35 +- Source/AIFramework/Polyhedra/LinearConstraint.cs | 788 +++++------ .../Polyhedra/LinearConstraintSystem.cs | 1376 +++++++++--------- .../AIFramework/Polyhedra/PolyhedraAbstraction.cs | 1129 +++++++-------- Source/AIFramework/Polyhedra/SimplexTableau.cs | 1080 +++++++-------- .../AIFramework/VariableMap/ConstantAbstraction.cs | 111 +- .../AIFramework/VariableMap/DynamicTypeLattice.cs | 793 ++++++----- Source/AIFramework/VariableMap/Intervals.cs | 884 ++++++------ Source/AIFramework/VariableMap/MicroLattice.cs | 42 +- Source/AIFramework/VariableMap/Nullness.cs | 107 +- .../AIFramework/VariableMap/VariableMapLattice.cs | 370 +++-- 18 files changed, 5980 insertions(+), 4917 deletions(-) (limited to 'Source/AIFramework') diff --git a/Source/AIFramework/AIFramework.csproj b/Source/AIFramework/AIFramework.csproj index 76a83601..bddd07f2 100644 --- a/Source/AIFramework/AIFramework.csproj +++ b/Source/AIFramework/AIFramework.csproj @@ -1,161 +1,109 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {39B0658D-C955-41C5-9A43-48C97A1EF5FD} + Library + Properties + AIFramework + AIFramework + v3.5 + 512 + 0 + true + ..\InterimKey.snk + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + False + False + True + False + False + False + False + False + False + False + False + True + False + False + False + + + + + + + + + + + + + Full + %28none%29 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\..\Binaries\Microsoft.Contracts.dll + + + + + + + + + + + + + + + + + + + + + + + + + + {0C692837-77EC-415F-BF04-395E3ED06E9A} + Basetypes + + + + + + + + \ No newline at end of file diff --git a/Source/AIFramework/CommonFunctionSymbols.cs b/Source/AIFramework/CommonFunctionSymbols.cs index bc59df97..2d98e8bc 100644 --- a/Source/AIFramework/CommonFunctionSymbols.cs +++ b/Source/AIFramework/CommonFunctionSymbols.cs @@ -5,9 +5,10 @@ //----------------------------------------------------------------------------- namespace Microsoft.AbstractInterpretationFramework { - using Microsoft.Contracts; + using System.Diagnostics.Contracts; using System.Collections; - using Microsoft.SpecSharp.Collections; + using System.Collections.Generic; + //using Microsoft.SpecSharp.Collections; using Microsoft.Basetypes; /// @@ -15,27 +16,36 @@ namespace Microsoft.AbstractInterpretationFramework /// public class FunctionSymbol : IFunctionSymbol { - private readonly string! display; - private readonly AIType! typ; + private readonly string/*!*/ display; + private readonly AIType/*!*/ typ; + [ContractInvariantMethod] +void ObjectInvariant() +{ + Contract.Invariant(display != null); + Contract.Invariant(typ != null); +} + - public FunctionSymbol(AIType! typ) + public FunctionSymbol(AIType/*!*/ typ) : this("FunctionSymbol", typ) { + Contract.Requires(typ != null); } - internal FunctionSymbol(string! display, AIType! typ) - { + internal FunctionSymbol(string/*!*/ display, AIType/*!*/ typ){ +Contract.Requires(typ != null); +Contract.Requires(display != null); this.display = display; this.typ = typ; // base(); } - public AIType! AIType { get { return typ; } } + public AIType/*!*/ AIType { get {Contract.Ensures(Contract.Result() != null); return typ; } } [NoDefaultContract] [Pure] - public override string! ToString() - { + public override string/*!*/ ToString() { +Contract.Ensures(Contract.Result() != null); return display; } @@ -52,7 +62,7 @@ namespace Microsoft.AbstractInterpretationFramework /// The intention is that this constructor be called only from the Int.Const method. /// internal IntSymbol(BigNum x) - : base((!)x.ToString(), Int.Type) + : base(cce.NonNull(x.ToString()), Int.Type) { this.Value = x; } @@ -113,7 +123,7 @@ namespace Microsoft.AbstractInterpretationFramework /// The intention is that this constructor be called only from the Double.Const method. /// internal DoubleSymbol(double x) - : base((!)x.ToString(), Double.Type) + : base(cce.NonNull(x.ToString()), Double.Type) { this.Value = x; } @@ -138,11 +148,12 @@ namespace Microsoft.AbstractInterpretationFramework /// public class NamedSymbol : FunctionSymbol { - public string! Value { [NoDefaultContract] get { return (!) this.ToString(); } } + public string/*!*/ Value { [NoDefaultContract] get {Contract.Ensures(Contract.Result() != null); return cce.NonNull(this.ToString()); } } - public NamedSymbol(string! symbol, AIType! typ) - : base(symbol, typ) - { + public NamedSymbol(string/*!*/ symbol, AIType/*!*/ typ) + : base(symbol, typ){ +Contract.Requires(typ != null); +Contract.Requires(symbol != null); } [NoDefaultContract] @@ -182,14 +193,14 @@ namespace Microsoft.AbstractInterpretationFramework /// public class Value : AIType { - private static readonly AIType! valtype = new Value(); - public static AIType! Type { get { return valtype; } } - - private static readonly FunctionType[]! funtypeCache = new FunctionType[5]; - public static FunctionType! FunctionType(int inParameterCount) - requires 0 <= inParameterCount; - // ensures result.Arity == inParameterCount; - { + private static readonly AIType/*!*/ valtype = new Value(); + public static AIType/*!*/ Type { get {Contract.Ensures(Contract.Result() != null); return valtype; } } + + private static readonly FunctionType[]/*!*/ funtypeCache = new FunctionType[5]; + public static FunctionType/*!*/ FunctionType(int inParameterCount) { +Contract.Requires((0 <= inParameterCount)); +Contract.Ensures(Contract.Result() != null); + // Contract.Ensures(Contract.Result<>().Arity == inParameterCount); FunctionType result; if (inParameterCount < funtypeCache.Length) { result = funtypeCache[inParameterCount]; @@ -208,9 +219,19 @@ namespace Microsoft.AbstractInterpretationFramework return result; } - [Once] private static AIType! binreltype; - private static AIType! BinrelType { - get { + [Once] private static AIType/*!*/ binreltype; + [ContractInvariantMethod] +void ObjectInvariant() +{ + Contract.Invariant(binreltype != null); + Contract.Invariant(_eq != null); + Contract.Invariant(_neq != null); + Contract.Invariant(_subtype != null); + Contract.Invariant(_typeof != null); +} + + private static AIType/*!*/ BinrelType { + get {Contract.Ensures(Contract.Result() != null); if (binreltype == null) { binreltype = new FunctionType(Type, Type, Prop.Type); } @@ -218,27 +239,27 @@ namespace Microsoft.AbstractInterpretationFramework } } - [Once] private static FunctionSymbol! _eq; - public static FunctionSymbol! Eq { - get { + [Once] private static FunctionSymbol/*!*/ _eq; + public static FunctionSymbol/*!*/ Eq { + get {Contract.Ensures(Contract.Result() != null); if (_eq == null) { _eq = new FunctionSymbol("=", BinrelType); } return _eq; } } - [Once] private static FunctionSymbol! _neq; - public static FunctionSymbol! Neq { - get { + [Once] private static FunctionSymbol/*!*/ _neq; + public static FunctionSymbol/*!*/ Neq { + get {Contract.Ensures(Contract.Result() != null); if (_neq == null) { _neq = new FunctionSymbol("!=", BinrelType); } return _neq; } } - [Once] private static FunctionSymbol! _subtype; - public static FunctionSymbol! Subtype { - get { + [Once] private static FunctionSymbol/*!*/ _subtype; + public static FunctionSymbol/*!*/ Subtype { + get {Contract.Ensures(Contract.Result() != null); if (_subtype == null) { _subtype = new FunctionSymbol("<:", BinrelType); } @@ -246,18 +267,18 @@ namespace Microsoft.AbstractInterpretationFramework } } - [Once] private static AIType! typeof_type; - private static AIType! TypeofType { - get { + [Once] private static AIType/*!*/ typeof_type; + private static AIType/*!*/ TypeofType { + get {Contract.Ensures(Contract.Result() != null); if (typeof_type == null) { typeof_type = new FunctionType(Ref.Type, Type); } return typeof_type; } } - [Once] private static FunctionSymbol! _typeof; - public static FunctionSymbol! Typeof { - get { + [Once] private static FunctionSymbol/*!*/ _typeof; + public static FunctionSymbol/*!*/ Typeof { + get {Contract.Ensures(Contract.Result() != null); if (_typeof == null) { _typeof = new FunctionSymbol("typeof", TypeofType); } @@ -275,37 +296,37 @@ namespace Microsoft.AbstractInterpretationFramework public class Int : Value { - private static readonly AIType! inttype = new Int(); - public static AIType! Type { get { return inttype; } } + private static readonly AIType/*!*/ inttype = new Int(); + public static AIType/*!*/ Type { get {Contract.Ensures(Contract.Result() != null); return inttype; } } - private static readonly AIType! unaryinttype = new FunctionType(Type, Type); - private static readonly AIType! bininttype = new FunctionType(Type, Type, Type); - private static readonly AIType! relationtype = new FunctionType(Type, Type, Prop.Type); - - private static readonly FunctionSymbol! _negate = new FunctionSymbol("~", unaryinttype); - private static readonly FunctionSymbol! _add = new FunctionSymbol("+", bininttype); - private static readonly FunctionSymbol! _sub = new FunctionSymbol("-", bininttype); - private static readonly FunctionSymbol! _mul = new FunctionSymbol("*", bininttype); - private static readonly FunctionSymbol! _div = new FunctionSymbol("/", bininttype); - private static readonly FunctionSymbol! _mod = new FunctionSymbol("%", bininttype); - private static readonly FunctionSymbol! _atmost = new FunctionSymbol("<=", relationtype); - private static readonly FunctionSymbol! _less = new FunctionSymbol("<", relationtype); - private static readonly FunctionSymbol! _greater = new FunctionSymbol(">", relationtype); - private static readonly FunctionSymbol! _atleast = new FunctionSymbol(">=", relationtype); - - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Negate { get { return _negate; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Add { get { return _add; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Sub { get { return _sub; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Mul { get { return _mul; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Div { get { return _div; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Mod { get { return _mod; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! AtMost { get { return _atmost; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Less { get { return _less; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Greater { get { return _greater; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! AtLeast { get { return _atleast; } } - - public static IntSymbol! Const(BigNum x) - { + private static readonly AIType/*!*/ unaryinttype = new FunctionType(Type, Type); + private static readonly AIType/*!*/ bininttype = new FunctionType(Type, Type, Type); + private static readonly AIType/*!*/ relationtype = new FunctionType(Type, Type, Prop.Type); + + private static readonly FunctionSymbol/*!*/ _negate = new FunctionSymbol("~", unaryinttype); + private static readonly FunctionSymbol/*!*/ _add = new FunctionSymbol("+", bininttype); + private static readonly FunctionSymbol/*!*/ _sub = new FunctionSymbol("-", bininttype); + private static readonly FunctionSymbol/*!*/ _mul = new FunctionSymbol("*", bininttype); + private static readonly FunctionSymbol/*!*/ _div = new FunctionSymbol("/", bininttype); + private static readonly FunctionSymbol/*!*/ _mod = new FunctionSymbol("%", bininttype); + private static readonly FunctionSymbol/*!*/ _atmost = new FunctionSymbol("<=", relationtype); + private static readonly FunctionSymbol/*!*/ _less = new FunctionSymbol("<", relationtype); + private static readonly FunctionSymbol/*!*/ _greater = new FunctionSymbol(">", relationtype); + private static readonly FunctionSymbol/*!*/ _atleast = new FunctionSymbol(">=", relationtype); + + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Negate { get {Contract.Ensures(Contract.Result() != null); return _negate; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Add { get {Contract.Ensures(Contract.Result() != null); return _add; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Sub { get {Contract.Ensures(Contract.Result() != null); return _sub; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Mul { get {Contract.Ensures(Contract.Result() != null); return _mul; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Div { get {Contract.Ensures(Contract.Result() != null); return _div; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Mod { get {Contract.Ensures(Contract.Result() != null); return _mod; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ AtMost { get {Contract.Ensures(Contract.Result() != null); return _atmost; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Less { get {Contract.Ensures(Contract.Result() != null); return _less; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Greater { get {Contract.Ensures(Contract.Result() != null); return _greater; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ AtLeast { get {Contract.Ensures(Contract.Result() != null); return _atleast; } } + + public static IntSymbol/*!*/ Const(BigNum x) { +Contract.Ensures(Contract.Result() != null); // We could cache things here, but for now we don't. return new IntSymbol(x); } @@ -319,11 +340,11 @@ namespace Microsoft.AbstractInterpretationFramework public class Double : Value { - private static readonly AIType! doubletype = new Double(); - public static AIType! Type { get { return doubletype; } } + private static readonly AIType/*!*/ doubletype = new Double(); + public static AIType/*!*/ Type { get {Contract.Ensures(Contract.Result() != null); return doubletype; } } - public static DoubleSymbol! Const(double x) - { + public static DoubleSymbol/*!*/ Const(double x) { +Contract.Ensures(Contract.Result() != null); // We could cache things here, but for now we don't. return new DoubleSymbol(x); } @@ -337,41 +358,41 @@ namespace Microsoft.AbstractInterpretationFramework public class Bv : Value { - private static readonly AIType! bvtype = new Bv(); - public static AIType! Type { get { return bvtype; } } + private static readonly AIType/*!*/ bvtype = new Bv(); + public static AIType/*!*/ Type { get {Contract.Ensures(Contract.Result() != null); return bvtype; } } - private static readonly AIType! unaryinttype = new FunctionType(Type, Type); - private static readonly AIType! bininttype = new FunctionType(Type, Type, Type); - private static readonly AIType! relationtype = new FunctionType(Type, Type, Prop.Type); - - private static readonly FunctionSymbol! _negate = new FunctionSymbol("~", unaryinttype); - private static readonly FunctionSymbol! _add = new FunctionSymbol("+", bininttype); - private static readonly FunctionSymbol! _sub = new FunctionSymbol("-", bininttype); - private static readonly FunctionSymbol! _mul = new FunctionSymbol("*", bininttype); - private static readonly FunctionSymbol! _div = new FunctionSymbol("/", bininttype); - private static readonly FunctionSymbol! _mod = new FunctionSymbol("%", bininttype); - private static readonly FunctionSymbol! _concat = new FunctionSymbol("$concat", bininttype); - private static readonly FunctionSymbol! _extract = new FunctionSymbol("$extract", unaryinttype); - private static readonly FunctionSymbol! _atmost = new FunctionSymbol("<=", relationtype); - private static readonly FunctionSymbol! _less = new FunctionSymbol("<", relationtype); - private static readonly FunctionSymbol! _greater = new FunctionSymbol(">", relationtype); - private static readonly FunctionSymbol! _atleast = new FunctionSymbol(">=", relationtype); - - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Negate { get { return _negate; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Add { get { return _add; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Sub { get { return _sub; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Mul { get { return _mul; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Div { get { return _div; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Mod { get { return _mod; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! AtMost { get { return _atmost; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Less { get { return _less; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Greater { get { return _greater; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! AtLeast { get { return _atleast; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Extract { get { return _extract; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Concat { get { return _concat; } } - - public static BvSymbol! Const(BigNum x, int y) - { + private static readonly AIType/*!*/ unaryinttype = new FunctionType(Type, Type); + private static readonly AIType/*!*/ bininttype = new FunctionType(Type, Type, Type); + private static readonly AIType/*!*/ relationtype = new FunctionType(Type, Type, Prop.Type); + + private static readonly FunctionSymbol/*!*/ _negate = new FunctionSymbol("~", unaryinttype); + private static readonly FunctionSymbol/*!*/ _add = new FunctionSymbol("+", bininttype); + private static readonly FunctionSymbol/*!*/ _sub = new FunctionSymbol("-", bininttype); + private static readonly FunctionSymbol/*!*/ _mul = new FunctionSymbol("*", bininttype); + private static readonly FunctionSymbol/*!*/ _div = new FunctionSymbol("/", bininttype); + private static readonly FunctionSymbol/*!*/ _mod = new FunctionSymbol("%", bininttype); + private static readonly FunctionSymbol/*!*/ _concat = new FunctionSymbol("$concat", bininttype); + private static readonly FunctionSymbol/*!*/ _extract = new FunctionSymbol("$extract", unaryinttype); + private static readonly FunctionSymbol/*!*/ _atmost = new FunctionSymbol("<=", relationtype); + private static readonly FunctionSymbol/*!*/ _less = new FunctionSymbol("<", relationtype); + private static readonly FunctionSymbol/*!*/ _greater = new FunctionSymbol(">", relationtype); + private static readonly FunctionSymbol/*!*/ _atleast = new FunctionSymbol(">=", relationtype); + + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Negate { get {Contract.Ensures(Contract.Result() != null); return _negate; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Add { get {Contract.Ensures(Contract.Result() != null); return _add; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Sub { get {Contract.Ensures(Contract.Result() != null); return _sub; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Mul { get {Contract.Ensures(Contract.Result() != null); return _mul; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Div { get {Contract.Ensures(Contract.Result() != null); return _div; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Mod { get { Contract.Ensures(Contract.Result() != null);return _mod; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ AtMost { get {Contract.Ensures(Contract.Result() != null); return _atmost; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Less { get {Contract.Ensures(Contract.Result() != null); return _less; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Greater { get {Contract.Ensures(Contract.Result() != null); return _greater; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ AtLeast { get {Contract.Ensures(Contract.Result() != null); return _atleast; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Extract { get {Contract.Ensures(Contract.Result() != null); return _extract; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Concat { get {Contract.Ensures(Contract.Result() != null); return _concat; } } + + public static BvSymbol/*!*/ Const(BigNum x, int y) { +Contract.Ensures(Contract.Result() != null); // We could cache things here, but for now we don't. return new BvSymbol(x, y); } @@ -385,12 +406,12 @@ namespace Microsoft.AbstractInterpretationFramework public class Ref : Value { - private static readonly AIType! reftype = new Ref(); - public static AIType! Type { get { return reftype; } } + private static readonly AIType/*!*/ reftype = new Ref(); + public static AIType/*!*/ Type { get {Contract.Ensures(Contract.Result() != null); return reftype; } } - private static readonly FunctionSymbol! _null = new FunctionSymbol("null", Type); + private static readonly FunctionSymbol/*!*/ _null = new FunctionSymbol("null", Type); - public static FunctionSymbol! Null { get { return _null; } } + public static FunctionSymbol/*!*/ Null { get { Contract.Ensures(Contract.Result() != null); return _null; } } /// /// Ref should not be instantiated from the outside, except perhaps in @@ -401,8 +422,8 @@ namespace Microsoft.AbstractInterpretationFramework public class HeapStructure : Value { - private static readonly AIType! reftype = new HeapStructure(); - public static AIType! Type { get { return reftype; } } + private static readonly AIType/*!*/ reftype = new HeapStructure(); + public static AIType/*!*/ Type { get {Contract.Ensures(Contract.Result() != null); return reftype; } } @@ -415,17 +436,17 @@ namespace Microsoft.AbstractInterpretationFramework public class FieldName : Value { - private static readonly AIType! fieldnametype = new FieldName(); - public static AIType! Type { get { return fieldnametype; } } + private static readonly AIType/*!*/ fieldnametype = new FieldName(); + public static AIType/*!*/ Type { get {Contract.Ensures(Contract.Result() != null); return fieldnametype; } } - private static readonly FunctionSymbol! _allocated = new FunctionSymbol("$allocated", FieldName.Type); - public static FunctionSymbol! Allocated { get { return _allocated; } } + private static readonly FunctionSymbol/*!*/ _allocated = new FunctionSymbol("$allocated", FieldName.Type); + public static FunctionSymbol/*!*/ Allocated { get {Contract.Ensures(Contract.Result() != null); return _allocated; } } /// /// Is this a boolean field that monotonically goes from false to true? /// - public static bool IsBooleanMonotonicallyWeakening(IFunctionSymbol! f) - { + public static bool IsBooleanMonotonicallyWeakening(IFunctionSymbol/*!*/ f){ +Contract.Requires(f != null); return f.Equals(Allocated); } @@ -438,43 +459,43 @@ namespace Microsoft.AbstractInterpretationFramework public class Heap : Value { - private static readonly AIType! heaptype = new Heap(); - public static AIType! Type { get { return heaptype; } } + private static readonly AIType/*!*/ heaptype = new Heap(); + public static AIType/*!*/ Type { get {Contract.Ensures(Contract.Result() != null); return heaptype; } } // the types in the following, select1, select2, are hard-coded; // these types may not always be appropriate - private static readonly FunctionSymbol! _select1 = new FunctionSymbol("sel1", + private static readonly FunctionSymbol/*!*/ _select1 = new FunctionSymbol("sel1", // Heap x FieldName -> Prop new FunctionType(Type, FieldName.Type, Prop.Type) ); - public static FunctionSymbol! Select1 { get { return _select1; } } + public static FunctionSymbol/*!*/ Select1 { get {Contract.Ensures(Contract.Result() != null); return _select1; } } - private static readonly FunctionSymbol! _select2 = new FunctionSymbol("sel2", + private static readonly FunctionSymbol/*!*/ _select2 = new FunctionSymbol("sel2", // Heap x Ref x FieldName -> Value new FunctionType(Type, Ref.Type, FieldName.Type, Value.Type) ); - public static FunctionSymbol! Select2 { get { return _select2; } } + public static FunctionSymbol/*!*/ Select2 { get {Contract.Ensures(Contract.Result() != null); return _select2; } } // the types in the following, store1, store2, are hard-coded; // these types may not always be appropriate - private static readonly FunctionSymbol! _update1 = new FunctionSymbol("upd1", + private static readonly FunctionSymbol/*!*/ _update1 = new FunctionSymbol("upd1", // Heap x FieldName x Value -> Heap new FunctionType(Type, FieldName.Type, Value.Type, Type) ); - public static FunctionSymbol! Update1 { get { return _update1; } } + public static FunctionSymbol/*!*/ Update1 { get {Contract.Ensures(Contract.Result() != null); return _update1; } } - private static readonly FunctionSymbol! _update2 = new FunctionSymbol("upd2", + private static readonly FunctionSymbol/*!*/ _update2 = new FunctionSymbol("upd2", // Heap x Ref x FieldName x Value -> Heap new FunctionType(Type, Ref.Type, FieldName.Type, Value.Type, Type) ); - public static FunctionSymbol! Update2 { get { return _update2; } } + public static FunctionSymbol/*!*/ Update2 { get {Contract.Ensures(Contract.Result() != null); return _update2; } } - private static readonly FunctionSymbol! _unsupportedHeapOp = + private static readonly FunctionSymbol/*!*/ _unsupportedHeapOp = new FunctionSymbol("UnsupportedHeapOp", // Heap x FieldName -> Prop new FunctionType(Type, FieldName.Type, Prop.Type) ); - public static FunctionSymbol! UnsupportedHeapOp { get { return _unsupportedHeapOp; } } + public static FunctionSymbol/*!*/ UnsupportedHeapOp { get {Contract.Ensures(Contract.Result() != null); return _unsupportedHeapOp; } } /// /// Heap should not be instantiated from the outside, except perhaps in @@ -527,7 +548,9 @@ namespace Microsoft.AbstractInterpretationFramework // } // // private AIType! typeParameter; -// public AIType! TypeParameter { get { return typeParameter; } } +// public AIType(TypeParameter/*!*/ ){ +//Contract.Requires( != null); + //return typeParameter; } } // // /// // /// List should not be instantiated from the outside. @@ -577,8 +600,12 @@ namespace Microsoft.AbstractInterpretationFramework // protected AIType! type1; // protected AIType! type2; // -// public AIType! Type1 { get { return type1; } } -// public AIType! Type2 { get { return type2; } } +// public AIType(Type1/*!*/ ){ +//Contract.Requires( != null); +// return type1; } } +// public AIType(Type2/*!*/ ){ +//Contract.Requires( != null); +// return type2; } } // // /// // /// Pair should not be instantiated from the outside, except by subclasses. @@ -598,34 +625,40 @@ namespace Microsoft.AbstractInterpretationFramework /// public sealed class Prop : AIType { - private static readonly AIType! proptype = new Prop(); - public static AIType! Type { get { return proptype; } } + private static readonly AIType/*!*/ proptype = new Prop(); + [ContractInvariantMethod] +void ObjectInvariant() +{ + Contract.Invariant(proptype != null); +} + + public static AIType/*!*/ Type { get {Contract.Ensures(Contract.Result() != null); return proptype; } } - private static readonly AIType! unaryproptype = new FunctionType(Type, Type); - private static readonly AIType! binproptype = new FunctionType(Type, Type, Type); - private static readonly AIType! quantifiertype = + private static readonly AIType/*!*/ unaryproptype = new FunctionType(Type, Type); + private static readonly AIType/*!*/ binproptype = new FunctionType(Type, Type, Type); + private static readonly AIType/*!*/ quantifiertype = new FunctionType(new FunctionType(Value.Type, Type), Type); - private static readonly FunctionSymbol! _false = new FunctionSymbol("false", Type); - private static readonly FunctionSymbol! _true = new FunctionSymbol("true", Type); - private static readonly FunctionSymbol! _not = new FunctionSymbol("!", unaryproptype); - private static readonly FunctionSymbol! _and = new FunctionSymbol("/\\", binproptype); - private static readonly FunctionSymbol! _or = new FunctionSymbol("\\/", binproptype); - private static readonly FunctionSymbol! _implies = new FunctionSymbol("==>", binproptype); - private static readonly FunctionSymbol! _exists = new FunctionSymbol("Exists", quantifiertype); - private static readonly FunctionSymbol! _forall = new FunctionSymbol("Forall", quantifiertype); - private static readonly FunctionSymbol! _lambda = new FunctionSymbol("Lambda", quantifiertype); + private static readonly FunctionSymbol/*!*/ _false = new FunctionSymbol("false", Type); + private static readonly FunctionSymbol/*!*/ _true = new FunctionSymbol("true", Type); + private static readonly FunctionSymbol/*!*/ _not = new FunctionSymbol("!", unaryproptype); + private static readonly FunctionSymbol/*!*/ _and = new FunctionSymbol("/\\", binproptype); + private static readonly FunctionSymbol/*!*/ _or = new FunctionSymbol("\\/", binproptype); + private static readonly FunctionSymbol/*!*/ _implies = new FunctionSymbol("==>", binproptype); + private static readonly FunctionSymbol/*!*/ _exists = new FunctionSymbol("Exists", quantifiertype); + private static readonly FunctionSymbol/*!*/ _forall = new FunctionSymbol("Forall", quantifiertype); + private static readonly FunctionSymbol/*!*/ _lambda = new FunctionSymbol("Lambda", quantifiertype); - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! False { get { return _false; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! True { get { return _true; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Not { get { return _not; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! And { [Pure] get { return _and; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Or { get { return _or; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Implies { get { return _implies; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Exists { get { return _exists; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Forall { get { return _forall; } } - [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol! Lambda { get { return _lambda; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ False { get {Contract.Ensures(Contract.Result() != null); return _false; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ True { get {Contract.Ensures(Contract.Result() != null); return _true; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Not { get {Contract.Ensures(Contract.Result() != null); return _not; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ And { [Pure] get {Contract.Ensures(Contract.Result() != null); return _and; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Or { get {Contract.Ensures(Contract.Result() != null); return _or; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Implies { get {Contract.Ensures(Contract.Result() != null); return _implies; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Exists { get {Contract.Ensures(Contract.Result() != null); return _exists; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Forall { get {Contract.Ensures(Contract.Result() != null); return _forall; } } + [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Lambda { get {Contract.Ensures(Contract.Result() != null); return _lambda; } } /// @@ -639,8 +672,11 @@ namespace Microsoft.AbstractInterpretationFramework // Utility Methods // - public static IExpr! SimplifiedAnd(IPropExprFactory! factory, IExpr! e0, IExpr! e1) - { + public static IExpr/*!*/ SimplifiedAnd(IPropExprFactory/*!*/ factory, IExpr/*!*/ e0, IExpr/*!*/ e1){ +Contract.Requires(e1 != null); +Contract.Requires(e0 != null); +Contract.Requires(factory != null); +Contract.Ensures(Contract.Result() != null); IFunApp fun0 = e0 as IFunApp; if (fun0 != null) { @@ -670,18 +706,24 @@ namespace Microsoft.AbstractInterpretationFramework return factory.And(e0, e1); } - public static IExpr! SimplifiedAnd(IPropExprFactory! factory, IEnumerable/**/! exprs) - { - IExpr! result = factory.True; - foreach (IExpr! conjunct in exprs) - { + public static IExpr/*!*/ SimplifiedAnd(IPropExprFactory/*!*/ factory, IEnumerable/**//*!*/ exprs){ +Contract.Requires(exprs != null); +Contract.Requires(factory != null); +Contract.Ensures(Contract.Result() != null); +IExpr/*!*/ result = factory.True; +Contract.Assert(result != null); + foreach(IExpr/*!*/ conjunct in exprs){ +Contract.Assert(conjunct != null); result = SimplifiedAnd(factory, result, conjunct); } return result; } - public static IExpr! SimplifiedOr(IPropExprFactory! factory, IExpr! e0, IExpr! e1) - { + public static IExpr/*!*/ SimplifiedOr(IPropExprFactory/*!*/ factory, IExpr/*!*/ e0, IExpr/*!*/ e1){ +Contract.Requires(e1 != null); +Contract.Requires(e0 != null); +Contract.Requires(factory != null); +Contract.Ensures(Contract.Result() != null); IFunApp fun0 = e0 as IFunApp; if (fun0 != null) { @@ -711,11 +753,14 @@ namespace Microsoft.AbstractInterpretationFramework return factory.Or(e0, e1); } - public static IExpr! SimplifiedOr(IPropExprFactory! factory, IEnumerable/**/! exprs) - { - IExpr! result = factory.False; - foreach (IExpr! disj in exprs) - { + public static IExpr/*!*/ SimplifiedOr(IPropExprFactory/*!*/ factory, IEnumerable/**//*!*/ exprs){ +Contract.Requires(exprs != null); +Contract.Requires(factory != null); +Contract.Ensures(Contract.Result() != null); +IExpr/*!*/ result = factory.False; +Contract.Assert(result != null); + foreach(IExpr/*!*/ disj in exprs){ +Contract.Assert(disj != null); result = SimplifiedOr(factory, result, disj); } return result; @@ -728,9 +773,13 @@ namespace Microsoft.AbstractInterpretationFramework /// /// The expression to examine. /// A list of conjuncts. - internal static IList/**/! BreakConjuncts(IExpr! e) - ensures forall{ IExpr sub in result; sub is IFunApp ==> !((IFunApp) sub).FunctionSymbol.Equals(Prop.And) }; - { + internal static IList/**//*!*/ BreakConjuncts(IExpr/*!*/ e){ +Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.ForAll(0, Contract.Result().Count, i => { + var sub = Contract.Result()[i]; + return !(sub is IFunApp) || !((IFunApp)sub).FunctionSymbol.Equals(Prop.And); + })); return BreakJuncts(e, Prop.And); } @@ -739,16 +788,25 @@ namespace Microsoft.AbstractInterpretationFramework /// /// The expression to examine. /// A list of conjuncts. - internal static IList/**/! BreakDisjuncts(IExpr! e) - ensures forall{ IExpr sub in result; sub is IFunApp ==> !((IFunApp) sub).FunctionSymbol.Equals(Prop.Or) }; - { + internal static IList/**//*!*/ BreakDisjuncts(IExpr/*!*/ e){ +Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.ForAll(0, Contract.Result().Count, i => { + var sub = Contract.Result()[i]; + return !(sub is IFunApp) || !((IFunApp)sub).FunctionSymbol.Equals(Prop.Or); + })); return BreakJuncts(e, Prop.Or); } - private static IList/**/! BreakJuncts(IExpr! e, IFunctionSymbol! sym) - ensures forall{ IExpr sub in result; sub is IFunApp ==> !((IFunApp) sub).FunctionSymbol.Equals(sym) }; - { - ArrayList/**/! result = new ArrayList(); + private static IList/**//*!*/ BreakJuncts(IExpr/*!*/ e, IFunctionSymbol/*!*/ sym){ +Contract.Requires(sym != null); +Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.ForAll(0, Contract.Result().Count, i => { + var sub = Contract.Result()[i]; + return (sub is IFunApp) || !((IFunApp)sub).FunctionSymbol.Equals(sym); + })); + ArrayList/**//*!*/ result = new ArrayList(); IFunApp f = e as IFunApp; if (f != null) @@ -756,8 +814,8 @@ namespace Microsoft.AbstractInterpretationFramework // If it is a sym, go down into sub-expressions. if (f.FunctionSymbol.Equals(sym)) { - foreach (IExpr! arg in f.Arguments) - { + foreach(IExpr/*!*/ arg in f.Arguments){ +Contract.Assert(arg != null); result.AddRange(BreakJuncts(arg,sym)); } } @@ -781,7 +839,7 @@ namespace Microsoft.AbstractInterpretationFramework /// /// The bound variable to use. /// The function body. - public delegate IExpr! FunctionBody(IVariable! var); + public delegate IExpr/*!*/ FunctionBody(IVariable/*!*/ var); /// /// An interface for constructing propositional expressions. @@ -789,30 +847,82 @@ namespace Microsoft.AbstractInterpretationFramework /// This interface should be implemented by the client. An implementation of /// of this class should generally be used as a singleton object. /// + /// + [ContractClass(typeof(IPropExprFactoryContracts))] public interface IPropExprFactory { - IFunApp! False { get /*ensures result.FunctionSymbol.Equals(Prop.False);*/; } - IFunApp! True { get /*ensures result.FunctionSymbol.Equals(Prop.True);*/; } + IFunApp/*!*/ False { get /*ensures result.FunctionSymbol.Equals(Prop.False);*/; } + IFunApp/*!*/ True { get /*ensures result.FunctionSymbol.Equals(Prop.True);*/; } - IFunApp! Not(IExpr! p) /*ensures result.FunctionSymbol.Equals(Prop.Not);*/; + IFunApp/*!*/ Not(IExpr/*!*/ p) /*ensures result.FunctionSymbol.Equals(Prop.Not);*/; - IFunApp! And(IExpr! p, IExpr! q) /*ensures result.FunctionSymbol.Equals(Prop.And);*/; - IFunApp! Or(IExpr! p, IExpr! q) /*ensures result.FunctionSymbol.Equals(Prop.Or);*/; + IFunApp/*!*/ And(IExpr/*!*/ p, IExpr/*!*/ q) /*ensures result.FunctionSymbol.Equals(Prop.And);*/; + IFunApp/*!*/ Or(IExpr/*!*/ p, IExpr/*!*/ q) /*ensures result.FunctionSymbol.Equals(Prop.Or);*/; - IFunApp! Implies(IExpr! p, IExpr! q) /*ensures result.FunctionSymbol.Equals(Prop.Implies);*/; + IFunApp/*!*/ Implies(IExpr/*!*/ p, IExpr/*!*/ q) /*ensures result.FunctionSymbol.Equals(Prop.Implies);*/; } + [ContractClassFor(typeof(IPropExprFactory))] + public abstract class IPropExprFactoryContracts:IPropExprFactory{ + #region IPropExprFactory Members + IFunApp IPropExprFactory.Implies(IExpr p, IExpr q) + { + Contract.Requires(p != null); + Contract.Requires(q != null); + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); + } + +IFunApp IPropExprFactory.False +{ + + get { Contract.Ensures(Contract.Result() != null);throw new System.NotImplementedException(); } +} + +IFunApp IPropExprFactory.True +{ + get {Contract.Ensures(Contract.Result() != null); throw new System.NotImplementedException(); } +} + +IFunApp IPropExprFactory.Not(IExpr p) +{ + Contract.Requires(p != null); + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + +IFunApp IPropExprFactory.And(IExpr p, IExpr q) +{ + Contract.Requires(p != null); + Contract.Requires(q != null); + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + +IFunApp IPropExprFactory.Or(IExpr p, IExpr q) +{Contract.Requires(p != null); + Contract.Requires(q != null); + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + + + +#endregion +} /// /// Like IPropExprFactory, but also with quantifiers. /// + /// + [ContractClass(typeof(IQuantPropExprFactoryContracts))] public interface IQuantPropExprFactory : IPropExprFactory { /// /// Produce an existential given the lambda-expression. /// /// The lambda-expression. /// The existential. - IFunApp! Exists(IFunction! p) /*ensures result.FunctionSymbol.Equals(Prop.Exists);*/; - IFunApp! Forall(IFunction! p) /*ensures result.FunctionSymbol.Equals(Prop.Forall);*/; + IFunApp/*!*/ Exists(IFunction/*!*/ p) /*ensures result.FunctionSymbol.Equals(Prop.Exists);*/; + IFunApp/*!*/ Forall(IFunction/*!*/ p) /*ensures result.FunctionSymbol.Equals(Prop.Forall);*/; /// /// Produce an existential given a callback that can produce a function body given the @@ -821,9 +931,71 @@ namespace Microsoft.AbstractInterpretationFramework /// /// The function body callback. /// The existential. - IFunApp! Exists(AIType paramType, FunctionBody! body) /*ensures result.FunctionSymbol.Equals(Prop.Exists);*/; - IFunApp! Forall(AIType paramType, FunctionBody! body) /*ensures result.FunctionSymbol.Equals(Prop.Forall);*/; + IFunApp/*!*/ Exists(AIType paramType, FunctionBody/*!*/ body) /*ensures result.FunctionSymbol.Equals(Prop.Exists);*/; + IFunApp/*!*/ Forall(AIType paramType, FunctionBody/*!*/ body) /*ensures result.FunctionSymbol.Equals(Prop.Forall);*/; } + [ContractClassFor(typeof(IQuantPropExprFactory))] + public abstract class IQuantPropExprFactoryContracts:IQuantPropExprFactory{ + #region IQuantPropExprFactory Members + +IFunApp IQuantPropExprFactory.Exists(IFunction p) +{ + Contract.Requires(p != null); + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + +IFunApp IQuantPropExprFactory.Forall(IFunction p) +{Contract.Requires(p != null);Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + +IFunApp IQuantPropExprFactory.Exists(AIType paramType, FunctionBody body) +{Contract.Requires(body != null);Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + +IFunApp IQuantPropExprFactory.Forall(AIType paramType, FunctionBody body) +{Contract.Requires(body != null);Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + +#endregion + +#region IPropExprFactory Members + +IFunApp IPropExprFactory.False +{ + get { throw new System.NotImplementedException(); } +} + +IFunApp IPropExprFactory.True +{ + get { throw new System.NotImplementedException(); } +} + +IFunApp IPropExprFactory.Not(IExpr p) +{ + throw new System.NotImplementedException(); +} + +IFunApp IPropExprFactory.And(IExpr p, IExpr q) +{ + throw new System.NotImplementedException(); +} + +IFunApp IPropExprFactory.Or(IExpr p, IExpr q) +{ + throw new System.NotImplementedException(); +} + +IFunApp IPropExprFactory.Implies(IExpr p, IExpr q) +{ + throw new System.NotImplementedException(); +} + +#endregion +} /// /// An interface for constructing value expressions. @@ -831,11 +1003,35 @@ namespace Microsoft.AbstractInterpretationFramework /// This interface should be implemented by the client. An implementation of /// of this class should generally be used as a singleton object. /// + /// + [ContractClass(typeof(IValueExprFactoryContracts))] public interface IValueExprFactory { - IFunApp! Eq(IExpr! e0, IExpr! e1) /*ensures result.FunctionSymbol.Equals(Value.Eq);*/; - IFunApp! Neq(IExpr! e0, IExpr! e1) /*ensures result.FunctionSymbol.Equals(Value.Neq);*/; + IFunApp/*!*/ Eq (IExpr/*!*/ e0, IExpr/*!*/ e1) /*ensures result.FunctionSymbol.Equals(Value.Eq);*/; + IFunApp/*!*/ Neq(IExpr/*!*/ e0, IExpr/*!*/ e1) /*ensures result.FunctionSymbol.Equals(Value.Neq);*/; } + [ContractClassFor(typeof(IValueExprFactory))] + public abstract class IValueExprFactoryContracts:IValueExprFactory{ + #region IValueExprFactory Members + +IFunApp IValueExprFactory.Eq(IExpr e0, IExpr e1) +{ + Contract.Requires(e0 != null); + Contract.Requires(e1 != null); + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + +IFunApp IValueExprFactory.Neq(IExpr e0, IExpr e1) +{ + Contract.Requires(e0 != null); + Contract.Requires(e1 != null); + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + +#endregion +} /// /// An interface for constructing value expressions having to with null. @@ -843,12 +1039,43 @@ namespace Microsoft.AbstractInterpretationFramework /// This interface should be implemented by the client. An implementation of /// of this class should generally be used as a singleton object. /// + /// + [ContractClass(typeof(INullnessFactoryContracts))] public interface INullnessFactory { - IFunApp! Eq(IExpr! e0, IExpr! e1) /*ensures result.FunctionSymbol.Equals(Value.Eq);*/; - IFunApp! Neq(IExpr! e0, IExpr! e1) /*ensures result.FunctionSymbol.Equals(Value.Neq);*/; - IFunApp! Null { get; /*ensures result.FunctionSymbol.Equals(Ref.Null);*/ } + IFunApp/*!*/ Eq(IExpr/*!*/ e0, IExpr/*!*/ e1) /*ensures result.FunctionSymbol.Equals(Value.Eq);*/; + IFunApp/*!*/ Neq(IExpr/*!*/ e0, IExpr/*!*/ e1) /*ensures result.FunctionSymbol.Equals(Value.Neq);*/; + IFunApp/*!*/ Null { get; /*ensures result.FunctionSymbol.Equals(Ref.Null);*/ } } + [ContractClassFor(typeof(INullnessFactory))] + public abstract class INullnessFactoryContracts:INullnessFactory{ +#region INullnessFactory Members + +IFunApp INullnessFactory.Eq(IExpr e0, IExpr e1) +{ + Contract.Requires(e0 != null); + Contract.Requires(e1 != null); + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + +IFunApp INullnessFactory.Neq(IExpr e0, IExpr e1) +{ + Contract.Requires(e0 != null); + Contract.Requires(e1 != null); + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + +IFunApp INullnessFactory.Null +{ + get { + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); } +} + +#endregion +} /// /// An interface for constructing integer expressions. @@ -856,9 +1083,35 @@ namespace Microsoft.AbstractInterpretationFramework /// This interface should be implemented by the client. An implementation of /// of this class should generally be used as a singleton object. /// + /// + [ContractClass(typeof(IIntExprFactoryContracts))] public interface IIntExprFactory : IValueExprFactory { - IFunApp! Const(BigNum i) /*ensures result.FunctionSymbol.Equals(new IntSymbol(i));*/; + IFunApp/*!*/ Const(BigNum i) /*ensures result.FunctionSymbol.Equals(new IntSymbol(i));*/; + } + [ContractClassFor(typeof(IIntExprFactory))] + public abstract class IIntExprFactoryContracts : IIntExprFactory { + + #region IIntExprFactory Members + + IFunApp IIntExprFactory.Const(BigNum i) { + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); + } + + #endregion + + #region IValueExprFactory Members + + IFunApp IValueExprFactory.Eq(IExpr e0, IExpr e1) { + throw new System.NotImplementedException(); + } + + IFunApp IValueExprFactory.Neq(IExpr e0, IExpr e1) { + throw new System.NotImplementedException(); + } + + #endregion } /// @@ -867,20 +1120,88 @@ namespace Microsoft.AbstractInterpretationFramework /// This interface should be implemented by the client. An implementation of /// of this class should generally be used as a singleton object. /// + /// + [ContractClass(typeof(ILinearExprFactoryContracts))] public interface ILinearExprFactory : IIntExprFactory { - IFunApp! AtMost(IExpr! e0, IExpr! e1) /*ensures result.FunctionSymbol.Equals(Value.AtMost);*/; - IFunApp! Add(IExpr! e0, IExpr! e1) /*ensures result.FunctionSymbol.Equals(Value.Add);*/; + IFunApp/*!*/ AtMost(IExpr/*!*/ e0, IExpr/*!*/ e1) /*ensures result.FunctionSymbol.Equals(Value.AtMost);*/; + IFunApp/*!*/ Add(IExpr/*!*/ e0, IExpr/*!*/ e1) /*ensures result.FunctionSymbol.Equals(Value.Add);*/; /// /// If "var" is null, returns an expression representing r. /// Otherwise, returns an expression representing r*var. /// - IExpr! Term(Microsoft.Basetypes.Rational r, IVariable var); + IExpr/*!*/ Term(Microsoft.Basetypes.Rational r, IVariable var); - IFunApp! False { get /*ensures result.FunctionSymbol.Equals(Prop.False);*/; } - IFunApp! True { get /*ensures result.FunctionSymbol.Equals(Prop.True);*/; } - IFunApp! And(IExpr! p, IExpr! q) /*ensures result.FunctionSymbol.Equals(Prop.And);*/; + IFunApp/*!*/ False { get /*ensures result.FunctionSymbol.Equals(Prop.False);*/; } + IFunApp/*!*/ True { get /*ensures result.FunctionSymbol.Equals(Prop.True);*/; } + IFunApp/*!*/ And(IExpr/*!*/ p, IExpr/*!*/ q) /*ensures result.FunctionSymbol.Equals(Prop.And);*/; } + [ContractClassFor(typeof(ILinearExprFactory))] + public abstract class ILinearExprFactoryContracts:ILinearExprFactory{ + + #region ILinearExprFactory Members + +IFunApp ILinearExprFactory.AtMost(IExpr e0, IExpr e1) +{ + Contract.Requires(e0 != null); + Contract.Requires(e1 != null); + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + +IFunApp ILinearExprFactory.Add(IExpr e0, IExpr e1) +{ + Contract.Requires(e0 != null); + Contract.Requires(e1 != null);Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + +IExpr ILinearExprFactory.Term(Rational r, IVariable var) +{ + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + +IFunApp ILinearExprFactory.False +{ + get {Contract.Ensures(Contract.Result() != null); throw new System.NotImplementedException(); } +} + +IFunApp ILinearExprFactory.True +{ + get { Contract.Ensures(Contract.Result() != null);throw new System.NotImplementedException(); } +} + +IFunApp ILinearExprFactory.And(IExpr p, IExpr q) +{ + Contract.Requires(p != null); + Contract.Requires(q != null); + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + +#endregion + +#region IIntExprFactory Members + +IFunApp IIntExprFactory.Const(BigNum i) { + throw new System.NotImplementedException(); +} + +#endregion + +#region IValueExprFactory Members + +IFunApp IValueExprFactory.Eq(IExpr e0, IExpr e1) { + throw new System.NotImplementedException(); +} + +IFunApp IValueExprFactory.Neq(IExpr e0, IExpr e1) { + throw new System.NotImplementedException(); +} + +#endregion + } /// /// An interface for constructing type expressions and performing some type operations. @@ -889,39 +1210,96 @@ namespace Microsoft.AbstractInterpretationFramework /// This interface should be implemented by the client. An implementation of /// of this class should generally be used as a singleton object. /// + /// + [ContractClass(typeof(ITypeExprFactoryContracts))] public interface ITypeExprFactory { /// /// Returns an expression denoting the top of the type hierarchy. /// - IExpr! RootType { get; } + IExpr/*!*/ RootType { get; } /// /// Returns true iff "t" denotes a type constant. /// [Pure] - bool IsTypeConstant(IExpr! t); + bool IsTypeConstant(IExpr/*!*/ t); /// /// Returns true iff t0 and t1 are types such that t0 and t1 are equal. /// [Pure] - bool IsTypeEqual(IExpr! t0, IExpr! t1); + bool IsTypeEqual(IExpr/*!*/ t0, IExpr/*!*/ t1); /// /// Returns true iff t0 and t1 are types such that t0 is a subtype of t1. /// [Pure] - bool IsSubType(IExpr! t0, IExpr! t1); + bool IsSubType(IExpr/*!*/ t0, IExpr/*!*/ t1); /// /// Returns the most derived supertype of both "t0" and "t1". A precondition is /// that "t0" and "t1" both represent types. /// - IExpr! JoinTypes(IExpr! t0, IExpr! t1); + IExpr/*!*/ JoinTypes(IExpr/*!*/ t0, IExpr/*!*/ t1); - IFunApp! IsExactlyA(IExpr! e, IExpr! type) /*requires IsTypeConstant(type); ensures result.FunctionSymbol.Equals(Value.Eq);*/; - IFunApp! IsA(IExpr! e, IExpr! type) /*requires IsTypeConstant(type); ensures result.FunctionSymbol.Equals(Value.Subtype);*/; + IFunApp/*!*/ IsExactlyA(IExpr/*!*/ e, IExpr/*!*/ type) /*requires IsTypeConstant(type); ensures result.FunctionSymbol.Equals(Value.Eq);*/; + IFunApp/*!*/ IsA(IExpr/*!*/ e, IExpr/*!*/ type) /*requires IsTypeConstant(type); ensures result.FunctionSymbol.Equals(Value.Subtype);*/; } + [ContractClassFor(typeof(ITypeExprFactory))] + public abstract class ITypeExprFactoryContracts:ITypeExprFactory{ + + #region ITypeExprFactory Members + +IExpr ITypeExprFactory.RootType +{ + get {Contract.Ensures(Contract.Result() != null); throw new System.NotImplementedException(); } +} + +bool ITypeExprFactory.IsTypeConstant(IExpr t) +{ + Contract.Requires(t != null); + throw new System.NotImplementedException(); +} + +bool ITypeExprFactory.IsTypeEqual(IExpr t0, IExpr t1) +{ + Contract.Requires(t0 != null); + Contract.Requires(t1 != null); + throw new System.NotImplementedException(); +} + +bool ITypeExprFactory.IsSubType(IExpr t0, IExpr t1) +{ + Contract.Requires(t0 != null); + Contract.Requires(t1 != null); + throw new System.NotImplementedException(); +} + +IExpr ITypeExprFactory.JoinTypes(IExpr t0, IExpr t1) +{ + Contract.Requires(t0 != null); + Contract.Requires(t1 != null); + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + +IFunApp ITypeExprFactory.IsExactlyA(IExpr e, IExpr type) +{ + Contract.Requires(e != null); + Contract.Requires(type != null); + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} + +IFunApp ITypeExprFactory.IsA(IExpr e, IExpr type) +{ + Contract.Requires(e != null); + Contract.Requires(type != null); + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); +} +#endregion } +} \ No newline at end of file diff --git a/Source/AIFramework/Expr.cs b/Source/AIFramework/Expr.cs index 1f21f84a..58473592 100644 --- a/Source/AIFramework/Expr.cs +++ b/Source/AIFramework/Expr.cs @@ -16,7 +16,8 @@ namespace Microsoft.AbstractInterpretationFramework { using System.Collections; - using Microsoft.Contracts; + using System; + using System.Diagnostics.Contracts; //----------------------------- Expressions ----------------------------- @@ -28,6 +29,7 @@ namespace Microsoft.AbstractInterpretationFramework /// This only serves as a place for operations on expressions. Clients /// should implement directly IVariable, IFunApp, ... /// + [ContractClass(typeof(IExprContracts))] public interface IExpr { /// @@ -35,34 +37,62 @@ namespace Microsoft.AbstractInterpretationFramework /// /// The expression visitor. /// The result of the visit. - [Pure] object DoVisit(ExprVisitor! visitor); + [Pure] object DoVisit(ExprVisitor/*!*/ visitor); // TODO: Type checking of the expressions. } + [ContractClassFor(typeof(IExpr))] + public abstract class IExprContracts:IExpr{ + #region IExpr Members + +public object DoVisit(ExprVisitor visitor) +{ + Contract.Requires(visitor != null); + throw new System.NotImplementedException(); +} + +#endregion +} /// /// An interface for variables. /// /// This interface should be implemented by the client. /// + [ContractClass(typeof(IVariableContracts))] public interface IVariable : IExpr { - string! Name { get; } // Each client must define the name for variables + string/*!*/ Name { get; } // Each client must define the name for variables + } + [ContractClassFor(typeof(IVariable))] + public abstract class IVariableContracts:IVariable{ + string IVariable.Name{get{Contract.Ensures(Contract.Result() != null);throw new NotImplementedException();} + + } + + #region IExpr Members + + object IExpr.DoVisit(ExprVisitor visitor) { + throw new NotImplementedException(); } + #endregion + } + /// /// An interface for function applications. /// /// This interface should be implemented by the client. /// + /// + [ContractClass(typeof(IFunAppContracts))] public interface IFunApp : IExpr { - IFunctionSymbol! FunctionSymbol { get; } - IList/**/! Arguments + IFunctionSymbol/*!*/ FunctionSymbol { get; } + IList/**//*!*/ Arguments { - [Pure][Rep] get - ensures result.IsReadOnly; - ; + [Pure][Rep] get; + } /// @@ -72,23 +102,103 @@ namespace Microsoft.AbstractInterpretationFramework /// /// The new arguments. /// A copy of the function with the new arguments. - IFunApp! CloneWithArguments(IList/**/! args) - //TODO requires this.Arguments.Count == args.Count; + IFunApp/*!*/ CloneWithArguments(IList/**//*!*/ args) + //TODO Contract.Requires(this.Arguments.Count == args.Count); ; } + [ContractClassFor(typeof(IFunApp))] +public abstract class IFunAppContracts:IFunApp{ + +#region IFunApp Members + +public IFunctionSymbol FunctionSymbol +{ + get {Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); } +} + +public IList Arguments +{ + get {Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result().IsReadOnly); + throw new System.NotImplementedException(); } +} + +public IFunApp CloneWithArguments(IList args) +{ + Contract.Requires(args != null); + Contract.Ensures(Contract.Result() != null); + + + throw new System.NotImplementedException(); +} + +#endregion + +#region IExpr Members + +object IExpr.DoVisit(ExprVisitor visitor) { + throw new NotImplementedException(); +} + +#endregion +} /// /// An interface for anonymous functions (i.e., lambda expressions) /// + [ContractClass(typeof(IFunctionContracts))] public interface IFunction : IExpr { - IVariable! Param { get; } - AIType! ParamType { get; } - IExpr! Body { get; } + IVariable/*!*/ Param { get; } + AIType/*!*/ ParamType { get; } + IExpr/*!*/ Body { get; } + + IFunction/*!*/ CloneWithBody(IExpr/*!*/ body); + } + [ContractClassFor(typeof(IFunction))] + public abstract class IFunctionContracts:IFunction{ + + #region IFunction Members + + IVariable IFunction.Param { + get { + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } + } - IFunction! CloneWithBody(IExpr! body); + AIType IFunction.ParamType { + get { + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } } + IExpr IFunction.Body { + get { + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } + } + + IFunction IFunction.CloneWithBody(IExpr body) { + Contract.Requires(body != null); + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } + + #endregion + + #region IExpr Members + + object IExpr.DoVisit(ExprVisitor visitor) { + throw new NotImplementedException(); + } + + #endregion + } + /// /// An interface representing an expression that at any moment could, in principle, evaluate /// to a different value. That is, the abstract interpreter should treat these IExpr's @@ -100,25 +210,32 @@ namespace Microsoft.AbstractInterpretationFramework /// /// An abstract class that provides an interface for expression visitors. /// + [ContractClass(typeof(ExprVisitorContracts))] public abstract class ExprVisitor { - public abstract object Default(IExpr! expr); + public abstract object Default(IExpr/*!*/ expr); - public virtual object VisitVariable(IVariable! var) - { + public virtual object VisitVariable(IVariable/*!*/ var){ +Contract.Requires(var != null); return Default(var); } - public virtual object VisitFunApp(IFunApp! funapp) - { + public virtual object VisitFunApp(IFunApp/*!*/ funapp){ +Contract.Requires(funapp != null); return Default(funapp); } - public virtual object VisitFunction(IFunction! fun) - { + public virtual object VisitFunction(IFunction/*!*/ fun){ +Contract.Requires(fun != null); return Default(fun); } } + [ContractClassFor(typeof(ExprVisitor))] + public abstract class ExprVisitorContracts:ExprVisitor{ + public override object Default(IExpr expr) +{ + Contract.Requires(expr != null); throw new NotImplementedException(); +}} /// /// A utility class for dealing with expressions. @@ -131,8 +248,11 @@ namespace Microsoft.AbstractInterpretationFramework /// The expression to substitute. /// The variable to substitute for. /// The expression to substitute into. - public static IExpr! Substitute(IExpr! subst, IVariable! var, IExpr! inexpr) - { + public static IExpr/*!*/ Substitute(IExpr/*!*/ subst, IVariable/*!*/ var, IExpr/*!*/ inexpr){ +Contract.Requires(inexpr != null); +Contract.Requires(var != null); +Contract.Requires(subst != null); +Contract.Ensures(Contract.Result() != null); IExpr result = null; if (inexpr is IVariable) @@ -141,14 +261,20 @@ namespace Microsoft.AbstractInterpretationFramework } else if (inexpr is IFunApp) { - IFunApp! funapp = (IFunApp!)inexpr; + IFunApp/*!*/ funapp = (IFunApp/*!*/)cce.NonNull(inexpr); IList newargs = null; - newargs = new ArrayList{ IExpr! arg in funapp.Arguments; Substitute(subst, var, arg) }; + + var x = new System.Collections.Generic.List(); + foreach (IExpr arg in funapp.Arguments){ + x.Add(Substitute(subst,var, arg)); + } + newargs = new ArrayList(x); + //newargs = new ArrayList{ IExpr/*!*/ arg in funapp.Arguments; Substitute(subst, var, arg) }; result = funapp.CloneWithArguments(newargs); } else if (inexpr is IFunction) { - IFunction! fun = (IFunction!)inexpr; + IFunction/*!*/ fun = (IFunction/*!*/)cce.NonNull(inexpr); if (fun.Param.Equals(var)) result = fun; @@ -161,7 +287,7 @@ namespace Microsoft.AbstractInterpretationFramework } else { - assert false; + {Contract.Assert(false);throw new cce.UnreachableException();} } return result; @@ -179,10 +305,11 @@ namespace Microsoft.AbstractInterpretationFramework // out z) // which sees if 'e' matches Prop.Imp(Prop.And(x,y),z) binding x,y,z to the subtrees. // - public delegate bool Matcher(IExpr! expr); + public delegate bool Matcher(IExpr/*!*/ expr); - private static IFunApp/*?*/ MatchFunctionSymbol(IExpr! expr, IFunctionSymbol! f) - { + private static IFunApp/*?*/ MatchFunctionSymbol(IExpr/*!*/ expr, IFunctionSymbol/*!*/ f){ +Contract.Requires(f != null); +Contract.Requires(expr != null); IFunApp app = expr as IFunApp; if (app != null) { @@ -195,15 +322,17 @@ namespace Microsoft.AbstractInterpretationFramework return null; } - public static bool Match(IExpr! expr, IFunctionSymbol! f, params Matcher[]! subs) - { + public static bool Match(IExpr/*!*/ expr, IFunctionSymbol/*!*/ f, params Matcher[]/*!*/ subs){ +Contract.Requires(subs != null); +Contract.Requires(f != null); +Contract.Requires(expr != null); IFunApp app = MatchFunctionSymbol(expr,f); if (app != null) { int i = 0; // Note ***0*** - foreach (Matcher! s in subs) - { - if (!s((IExpr!)app.Arguments[i])) { return false; } + foreach(Matcher/*!*/ s in subs){ +Contract.Assert(s != null); + if (!s(cce.NonNull((IExpr)app.Arguments[i]))) { return false; } i++; } return true; @@ -212,19 +341,21 @@ namespace Microsoft.AbstractInterpretationFramework } // Unary Binding - public static bool Match(IExpr! expr, IFunctionSymbol! f, out IExpr arg0, params Matcher[]! subs) - { + public static bool Match(IExpr/*!*/ expr, IFunctionSymbol/*!*/ f, out IExpr arg0, params Matcher[]/*!*/ subs){ +Contract.Requires(subs != null); +Contract.Requires(f != null); +Contract.Requires(expr != null); arg0 = null; IFunApp app = MatchFunctionSymbol(expr,f); if (app != null) { - arg0 = (IExpr!)app.Arguments[0]; + arg0 = (IExpr/*!*/)cce.NonNull(app.Arguments[0]); int i = 1; // Note ***1*** - foreach (Matcher! s in subs) - { - if (!s((IExpr!)app.Arguments[i])) { return false; } + foreach(Matcher/*!*/ s in subs){ +Contract.Assert(s != null); + if (!s(cce.NonNull((IExpr/*!*/)app.Arguments[i]))) { return false; } i++; } return true; @@ -233,21 +364,24 @@ namespace Microsoft.AbstractInterpretationFramework } // Binary Binding - public static bool Match(IExpr! expr, IFunctionSymbol! f, Matcher! sub0, out IExpr arg1, params Matcher[]! subs) - { + public static bool Match(IExpr/*!*/ expr, IFunctionSymbol/*!*/ f, Matcher/*!*/ sub0, out IExpr arg1, params Matcher[]/*!*/ subs){ +Contract.Requires(subs != null); +Contract.Requires(sub0 != null); +Contract.Requires(f != null); +Contract.Requires(expr != null); arg1 = null; IFunApp app = MatchFunctionSymbol(expr,f); if (app != null) { - if (!sub0((IExpr!)app.Arguments[0])) { return false; } + if (!sub0(cce.NonNull((IExpr/*!*/)app.Arguments[0]))) { return false; } - arg1 = (IExpr!)app.Arguments[1]; + arg1 = (IExpr/*!*/)cce.NonNull(app.Arguments[1]); int i = 2; // Note ***2*** - foreach (Matcher! s in subs) - { - if (!s((IExpr!)app.Arguments[i])) { return false; } + foreach(Matcher/*!*/ s in subs){ +Contract.Assert(s != null); + if (!s(cce.NonNull((IExpr)app.Arguments[i]))) { return false; } i++; } return true; @@ -255,21 +389,23 @@ namespace Microsoft.AbstractInterpretationFramework else { return false; } } - public static bool Match(IExpr! expr, IFunctionSymbol! f, out IExpr arg0, out IExpr arg1, params Matcher[]! subs) - { + public static bool Match(IExpr/*!*/ expr, IFunctionSymbol/*!*/ f, out IExpr arg0, out IExpr arg1, params Matcher[]/*!*/ subs){ +Contract.Requires(subs != null); +Contract.Requires(f != null); +Contract.Requires(expr != null); arg0 = null; arg1 = null; IFunApp app = MatchFunctionSymbol(expr,f); if (app != null) { - arg0 = (IExpr!)app.Arguments[0]; - arg1 = (IExpr!)app.Arguments[1]; + arg0 = (IExpr/*!*/)cce.NonNull(app.Arguments[0]); + arg1 = (IExpr/*!*/)cce.NonNull(app.Arguments[1]); int i = 2; // Note ***2*** - foreach (Matcher! s in subs) - { - if (!s((IExpr!)app.Arguments[i])) { return false; } + foreach(Matcher/*!*/ s in subs){ +Contract.Assert(s != null); + if (!s(cce.NonNull((IExpr/*!*/)app.Arguments[i]))) { return false; } i++; } return true; @@ -278,8 +414,10 @@ namespace Microsoft.AbstractInterpretationFramework } // Ternary Binding - public static bool Match(IExpr! expr, IFunctionSymbol! f, out IExpr arg0, out IExpr arg1, out IExpr arg2, params Matcher[]! subs) - { + public static bool Match(IExpr/*!*/ expr, IFunctionSymbol/*!*/ f, out IExpr arg0, out IExpr arg1, out IExpr arg2, params Matcher[]/*!*/ subs){ +Contract.Requires(subs != null); +Contract.Requires(f != null); +Contract.Requires(expr != null); arg0 = null; arg1 = null; arg2 = null; @@ -287,14 +425,14 @@ namespace Microsoft.AbstractInterpretationFramework IFunApp app = MatchFunctionSymbol(expr,f); if (app != null) { - arg0 = (IExpr!)app.Arguments[0]; - arg1 = (IExpr!)app.Arguments[1]; - arg2 = (IExpr!)app.Arguments[2]; + arg0 = (IExpr/*!*/)cce.NonNull(app.Arguments[0]); + arg1 = (IExpr/*!*/)cce.NonNull(app.Arguments[1]); + arg2 = (IExpr/*!*/)cce.NonNull(app.Arguments[2]); int i = 3; // Note ***3*** - foreach (Matcher! s in subs) - { - if (!s((IExpr!)app.Arguments[i])) { return false; } + foreach(Matcher/*!*/ s in subs){ +Contract.Assert(s != null); + if (!s(cce.NonNull((IExpr/*!*/)app.Arguments[i]))) { return false; } i++; } return true; @@ -317,11 +455,25 @@ namespace Microsoft.AbstractInterpretationFramework /// This interface should be implemented by abstract domains, but client /// expressions need keep track of function symbols. /// + [ContractClass(typeof(IFunctionSymbolContracts))] public interface IFunctionSymbol { - AIType! AIType { [Rep][ResultNotNewlyAllocated] + AIType/*!*/ AIType { [Rep][ResultNotNewlyAllocated] get; } } + [ContractClassFor(typeof(IFunctionSymbol))] + public abstract class IFunctionSymbolContracts:IFunctionSymbol{ + #region IFunctionSymbol Members + + AIType IFunctionSymbol.AIType { + get { + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } + } + + #endregion + } /// /// The type of the arguments to ExprUtil.Match, a poor man's pattern @@ -345,31 +497,39 @@ namespace Microsoft.AbstractInterpretationFramework /// public sealed class FunctionType : AIType { - /*[Own]*/ private readonly IList/**/! argTypes; - /*[Own]*/ private readonly AIType! retType; + /*[Own]*/ private readonly IList/**//*!*/ argTypes; + /*[Own]*/ private readonly AIType/*!*/ retType; + [ContractInvariantMethod] +void ObjectInvariant() +{ + Contract.Invariant(argTypes != null); + Contract.Invariant(retType != null); +} - public FunctionType(params AIType[]! types) - requires types.Length >= 2; - { + + public FunctionType(params AIType[]/*!*/ types){ +Contract.Requires(types != null); + Contract.Requires(types.Length >= 2); AIType type = types[types.Length-1]; - assume type != null; + Contract.Assume(type != null); this.retType = type; ArrayList argTypes = new ArrayList(); for (int i = 0; i < types.Length-1; i++) { type = types[i]; - assume type != null; + Contract.Assume(type != null); argTypes.Add(types); } this.argTypes = ArrayList.ReadOnly(argTypes); } - public IList/**/! Arguments + public IList/**//*!*/ Arguments { [Pure][Rep] get - ensures result.IsReadOnly; - { + { + Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result().IsReadOnly); return argTypes; } } @@ -379,9 +539,9 @@ namespace Microsoft.AbstractInterpretationFramework get { return argTypes.Count; } } - public AIType! ReturnType + public AIType/*!*/ ReturnType { - get { return retType; } + get {Contract.Ensures(Contract.Result() != null); return retType; } } /* TODO Do we have the invariant that two functions are equal iff they're the same object. @@ -418,6 +578,8 @@ namespace Microsoft.AbstractInterpretationFramework /// An interface that specifies a queryable object that can answer /// whether a predicate holds. /// + /// + [ContractClass(typeof(IQueryableContracts))] public interface IQueryable { /// @@ -425,14 +587,31 @@ namespace Microsoft.AbstractInterpretationFramework /// /// The given predicate. /// Yes, No, or Maybe. - Answer CheckPredicate(IExpr! pred); + Answer CheckPredicate(IExpr/*!*/ pred); /// /// A simplified interface for disequalities. One can always /// implement this by calling CheckPredicate, but it may be /// more efficient with this method. /// - Answer CheckVariableDisequality(IVariable! var1, IVariable! var2); + Answer CheckVariableDisequality(IVariable/*!*/ var1, IVariable/*!*/ var2); + } + [ContractClassFor(typeof(IQueryable))] + public abstract class IQueryableContracts : IQueryable { + #region IQueryable Members + + public Answer CheckPredicate(IExpr pred) { + Contract.Requires(pred != null); + throw new NotImplementedException(); + } + + public Answer CheckVariableDisequality(IVariable var1, IVariable var2) { + Contract.Requires(var1 != null); + Contract.Requires(var2 != null); + throw new NotImplementedException(); + } + + #endregion } public static class QueryUtil @@ -453,6 +632,8 @@ namespace Microsoft.AbstractInterpretationFramework //----------------------------- Exceptions ----------------------------- + public class CheckedException : System.Exception { + } public class TypeError : CheckedException { } diff --git a/Source/AIFramework/Functional.cs b/Source/AIFramework/Functional.cs index bee40031..e61adcc1 100644 --- a/Source/AIFramework/Functional.cs +++ b/Source/AIFramework/Functional.cs @@ -3,7 +3,7 @@ // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- -using Microsoft.Contracts; +using System.Diagnostics.Contracts; namespace Microsoft.AbstractInterpretationFramework.Collections { @@ -11,25 +11,26 @@ namespace Microsoft.AbstractInterpretationFramework.Collections /// Represents a functional collection of key/value pairs. /// 2 + [ContractClass(typeof(IFunctionalMapContracts))] public interface IFunctionalMap : System.Collections.ICollection, System.Collections.IEnumerable { /// Adds an element with the provided key and value to the . /// The to use as the value of the element to add. /// The to use as the key of the element to add. /// 2 - IFunctionalMap! Add(object! key, object value); + IFunctionalMap/*!*/ Add(object/*!*/ key, object value); /// /// Set the value of the key (that is already in the map) /// - IFunctionalMap! Set(object! key, object value); + IFunctionalMap/*!*/ Set(object/*!*/ key, object value); /// Determines whether the contains an element with the specified key. /// true if the contains an element with the key; otherwise, false. /// The key to locate in the . /// 2 [Pure] - bool Contains(object! key); + bool Contains(object/*!*/ key); /// Returns an for the . /// An for the . @@ -45,15 +46,107 @@ namespace Microsoft.AbstractInterpretationFramework.Collections /// Removes the element with the specified key from the . /// The key of the element to remove. /// 2 - IFunctionalMap! Remove(object! key); + IFunctionalMap/*!*/ Remove(object/*!*/ key); /// Gets an containing the values in the . /// An containing the values in the . /// 2 System.Collections.ICollection Values { get; } - object this [object! key] { get; /*set;*/ } + object this [object/*!*/ key] { get; /*set;*/ } } + [ContractClassFor(typeof(IFunctionalMap))] + public abstract class IFunctionalMapContracts:IFunctionalMap{ + + #region IFunctionalMap Members + +IFunctionalMap IFunctionalMap.Add(object key, object value) +{ + Contract.Requires(key != null); + Contract.Ensures(Contract.Result() != null); + + throw new System.NotImplementedException(); +} + +IFunctionalMap IFunctionalMap.Set(object key, object value) +{ + Contract.Requires(key != null); + Contract.Ensures(Contract.Result() != null); + + throw new System.NotImplementedException(); +} + +bool IFunctionalMap.Contains(object key) +{ + Contract.Requires(key != null); + + throw new System.NotImplementedException(); +} + +IDictionaryEnumerator IFunctionalMap.GetEnumerator() +{ + throw new System.NotImplementedException(); +} + +ICollection IFunctionalMap.Keys +{ + get { throw new System.NotImplementedException(); } +} + +IFunctionalMap IFunctionalMap.Remove(object key) +{ + Contract.Requires(key != null); + Contract.Ensures(Contract.Result() != null); + + throw new System.NotImplementedException(); +} + +ICollection IFunctionalMap.Values +{ + get { throw new System.NotImplementedException(); } +} + +object IFunctionalMap.this[object key] +{ + get {Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); } +} + +#endregion + +#region ICollection Members + +void ICollection.CopyTo(System.Array array, int index) +{ + throw new System.NotImplementedException(); +} + +int ICollection.Count +{ + get { throw new System.NotImplementedException(); } +} + +bool ICollection.IsSynchronized +{ + get { throw new System.NotImplementedException(); } +} + +object ICollection.SyncRoot +{ + get { throw new System.NotImplementedException(); } +} + +#endregion + +#region IEnumerable Members + +IEnumerator IEnumerable.GetEnumerator() +{ + throw new System.NotImplementedException(); +} + +#endregion +} @@ -64,7 +157,13 @@ namespace Microsoft.AbstractInterpretationFramework.Collections /// class FunctionalHashtable : IFunctionalMap { - private readonly Hashtable! h; + private readonly Hashtable/*!*/ h; + [ContractInvariantMethod] +void ObjectInvariant() +{ + Contract.Invariant(h != null); +} + /// /// Cannot directly construct an instance of a FunctionalHashtbl. @@ -78,43 +177,48 @@ namespace Microsoft.AbstractInterpretationFramework.Collections /// /// Cannot directly construct an instance of a FunctionalHashtbl. /// - private FunctionalHashtable(Hashtable! h) - { + private FunctionalHashtable(Hashtable/*!*/ h){ +Contract.Requires(h != null); this.h = h; // base(); } - private static readonly IFunctionalMap! empty = new FunctionalHashtable(); - public static IFunctionalMap! Empty { get { return empty; } } + private static readonly IFunctionalMap/*!*/ empty = new FunctionalHashtable(); + public static IFunctionalMap/*!*/ Empty { get {Contract.Ensures(Contract.Result() != null); + return empty; } } - public IFunctionalMap! Add(object! key, object value) - { + public IFunctionalMap/*!*/ Add(object/*!*/ key, object value){ +Contract.Requires(key != null); +Contract.Ensures(Contract.Result() != null); Hashtable r = h.Clone() as Hashtable; - assume r != null; + Contract.Assume(r != null); r.Add(key, value); return new FunctionalHashtable(r); } - public IFunctionalMap! Set(object! key, object value) - { + public IFunctionalMap/*!*/ Set(object/*!*/ key, object value){ +Contract.Requires(key != null); +Contract.Ensures(Contract.Result() != null); Hashtable r = h.Clone() as Hashtable; - assume r != null; - assert this.Contains(key); // The entry must be defined + Contract.Assume(r != null); + Contract.Assert( this.Contains(key)); // The entry must be defined r[key] = value; return new FunctionalHashtable(r); } [Pure] - public bool Contains(object! key) - { + public bool Contains(object/*!*/ key){ +Contract.Requires(key != null); return h.Contains(key); } [Pure] [GlobalAccess(false)] [Escapes(true,false)] - IEnumerator! IEnumerable.GetEnumerator() + IEnumerator/*!*/ IEnumerable.GetEnumerator() { + Contract.Ensures(Contract.Result() != null); + return h.GetEnumerator(); } @@ -129,10 +233,11 @@ namespace Microsoft.AbstractInterpretationFramework.Collections get { return h.Keys; } } - public IFunctionalMap! Remove(object! key) - { + public IFunctionalMap/*!*/ Remove(object/*!*/ key){ +Contract.Requires(key != null); +Contract.Ensures(Contract.Result() != null); Hashtable r = h.Clone() as Hashtable; - assume r != null; + Contract.Assume(r != null); r.Remove(key); return new FunctionalHashtable(r); } @@ -143,9 +248,9 @@ namespace Microsoft.AbstractInterpretationFramework.Collections } - public object this[object! key] + public object this[object/*!*/ key] { - get { return h[key]; } + get {Contract.Requires(key != null); return h[key]; } } public int Count @@ -157,14 +262,18 @@ namespace Microsoft.AbstractInterpretationFramework.Collections { [Pure] get { return h.IsSynchronized; } } - - public object! SyncRoot + + public object/*!*/ SyncRoot { - [Pure] get { return h.SyncRoot; } + [Pure] + get { + Contract.Ensures(Contract.Result() != null); + return h.SyncRoot; + } } - public void CopyTo(System.Array! a, int index) - { + public void CopyTo(System.Array/*!*/ a, int index){ +Contract.Requires(a != null); h.CopyTo(a, index); } } @@ -236,8 +345,8 @@ namespace Microsoft.AbstractInterpretationFramework.Collections.Generic return h; } - public override string! ToString() - { + public override string/*!*/ ToString() { +Contract.Ensures(Contract.Result() != null); return string.Format("({0},{1})", first, second); } } @@ -276,8 +385,8 @@ namespace Microsoft.AbstractInterpretationFramework.Collections.Generic return h; } - public override string! ToString() - { + public override string/*!*/ ToString() { +Contract.Ensures(Contract.Result() != null); return string.Format("({0},{1},{2})", first, second, third); } } diff --git a/Source/AIFramework/Lattice.cs b/Source/AIFramework/Lattice.cs index 2ecc49f8..cb5d3cc7 100644 --- a/Source/AIFramework/Lattice.cs +++ b/Source/AIFramework/Lattice.cs @@ -3,683 +3,957 @@ // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- -namespace Microsoft.AbstractInterpretationFramework -{ - using Microsoft.Contracts; - using System.Collections; - using G = System.Collections.Generic; - using System.Diagnostics; - using Microsoft.AbstractInterpretationFramework.Collections; - using Microsoft.Boogie; - using IMutableSet = Microsoft.Boogie.Set; - using ISet = Microsoft.Boogie.Set; - using HashSet = Microsoft.Boogie.Set; - using ArraySet = Microsoft.Boogie.Set; +namespace Microsoft.AbstractInterpretationFramework { + using System; + using System.Diagnostics.Contracts; + using System.Collections; + using G = System.Collections.Generic; + using System.Diagnostics; + using Microsoft.AbstractInterpretationFramework.Collections; + using Microsoft.Boogie; + using IMutableSet = Microsoft.Boogie.Set; + using ISet = Microsoft.Boogie.Set; + using HashSet = Microsoft.Boogie.Set; + using ArraySet = Microsoft.Boogie.Set; + + + + /// + /// Specifies the operations (e.g., join) on a mathematical lattice that depend + /// only on the elements of the lattice. + /// + [ContractClass(typeof(MathematicalLatticeContracts))] + public abstract class MathematicalLattice { + #region Element + /// + /// An element of the lattice. This class should be derived from in any + /// implementation of MathematicalLattice. + /// + [ContractClass(typeof(ElementContracts))] + public abstract class Element : System.ICloneable { + /// + /// Print out a debug-useful representation of the internal data structure of the lattice element. + /// + public virtual void Dump(string/*!*/ msg) { + Contract.Requires(msg != null); + System.Console.WriteLine("Dump({0}) = {1}", msg, this); + } + + public abstract Element/*!*/ Clone(); + object/*!*/ System.ICloneable.Clone() { + return this.Clone(); + } + + public abstract G.ICollection/*!*/ FreeVariables(); + } + [ContractClassFor(typeof(Element))] + public abstract class ElementContracts : Element { + public override Element Clone() { + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + + } + + public override System.Collections.Generic.ICollection FreeVariables() { + Contract.Ensures(cce.NonNullElements(Contract.Result>())); + Contract.Ensures(Contract.Result>().IsReadOnly); + throw new System.NotImplementedException(); + } + } + #endregion + public abstract Element/*!*/ Top { + get; + } + public abstract Element/*!*/ Bottom { + get; + } + + public abstract bool IsTop(Element/*!*/ e); + public abstract bool IsBottom(Element/*!*/ e); /// - /// Specifies the operations (e.g., join) on a mathematical lattice that depend - /// only on the elements of the lattice. + /// Returns true if a <= this. /// - public abstract class MathematicalLattice - { - /// - /// An element of the lattice. This class should be derived from in any - /// implementation of MathematicalLattice. - /// - public abstract class Element : System.ICloneable { - /// - /// Print out a debug-useful representation of the internal data structure of the lattice element. - /// - public virtual void Dump(string! msg) { - System.Console.WriteLine("Dump({0}) = {1}", msg, this); - } - - public abstract Element! Clone(); - object! System.ICloneable.Clone() { return this.Clone(); } - - public abstract G.ICollection! FreeVariables() - ensures result.IsReadOnly; - } + protected abstract bool AtMost(Element/*!*/ a, Element/*!*/ b); + /* The following cases are handled elsewhere and need not be considered in subclass. */ + // requires a.GetType() == b.GetType(); + // requires ! a.IsTop; + // requires ! a.IsBottom; + // requires ! b.IsTop; + // requires ! b.IsBottom; + + + protected Answer TrivialLowerThan(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + if (a.GetType() != b.GetType()) { + throw new System.InvalidOperationException( + "operands to <= must be of same Element type" + ); + } + if (IsBottom(a)) { + return Answer.Yes; + } + if (IsTop(b)) { + return Answer.Yes; + } + if (IsTop(a)) { + return Answer.No; + } + if (IsBottom(b)) { + return Answer.No; + } + + return Answer.Maybe; + } - public abstract Element! Top { get; } - public abstract Element! Bottom { get; } - - public abstract bool IsTop(Element! e); - public abstract bool IsBottom(Element! e); - - /// - /// Returns true if a <= this. - /// - protected abstract bool AtMost(Element! a, Element! b) - /* The following cases are handled elsewhere and need not be considered in subclass. */ - // requires a.GetType() == b.GetType(); - // requires ! a.IsTop; - // requires ! a.IsBottom; - // requires ! b.IsTop; - // requires ! b.IsBottom; - ; - - protected Answer TrivialLowerThan(Element! a, Element! b) - { - if (a.GetType() != b.GetType()) - { - throw new System.InvalidOperationException( - "operands to <= must be of same Element type" - ); - } - if (IsBottom(a)) { return Answer.Yes; } - if (IsTop(b)) { return Answer.Yes; } - if (IsTop(a)) { return Answer.No; } - if (IsBottom(b)) { return Answer.No; } - - return Answer.Maybe; - } + // Is 'a' better information than 'b'? + // + public bool LowerThan(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + Answer ans = TrivialLowerThan(a, b); + return ans != Answer.Maybe ? ans == Answer.Yes : AtMost(a, b); + } - // Is 'a' better information than 'b'? - // - public bool LowerThan(Element! a, Element! b) - { - Answer ans = TrivialLowerThan(a,b); - return ans != Answer.Maybe ? ans == Answer.Yes : AtMost(a, b); - } + // Is 'a' worse information than 'b'? + // + public bool HigherThan(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + return LowerThan(b, a); + } - // Is 'a' worse information than 'b'? - // - public bool HigherThan(Element! a, Element! b) - { - return LowerThan(b, a); - } + // Are 'a' and 'b' equivalent? + // + public bool Equivalent(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + return LowerThan(a, b) && LowerThan(b, a); + } - // Are 'a' and 'b' equivalent? - // - public bool Equivalent(Element! a, Element! b) - { - return LowerThan(a, b) && LowerThan(b, a); - } + public abstract Element/*!*/ NontrivialJoin(Element/*!*/ a, Element/*!*/ b); + /* The following cases are handled elsewhere and need not be considered in subclass. */ + // requires a.GetType() == b.GetType(); + // requires ! a.IsTop; + // requires ! a.IsBottom; + // requires ! b.IsTop; + // requires ! b.IsBottom; + + + protected Element/*?*/ TrivialJoin(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + if (a.GetType() != b.GetType()) { + throw new System.InvalidOperationException( + "operands to Join must be of same Lattice.Element type" + ); + } + if (IsTop(a)) { + return a; + } + if (IsTop(b)) { + return b; + } + if (IsBottom(a)) { + return b; + } + if (IsBottom(b)) { + return a; + } + + return null; + } - public abstract Element! NontrivialJoin(Element! a, Element! b) - /* The following cases are handled elsewhere and need not be considered in subclass. */ - // requires a.GetType() == b.GetType(); - // requires ! a.IsTop; - // requires ! a.IsBottom; - // requires ! b.IsTop; - // requires ! b.IsBottom; - ; - - protected Element/*?*/ TrivialJoin(Element! a, Element! b) - { - if (a.GetType() != b.GetType()) - { - throw new System.InvalidOperationException( - "operands to Join must be of same Lattice.Element type" - ); - } - if (IsTop(a)) { return a; } - if (IsTop(b)) { return b; } - if (IsBottom(a)) { return b; } - if (IsBottom(b)) { return a; } - - return null; - } + public Element/*!*/ Join(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + Element/*?*/ r = TrivialJoin(a, b); + return r != null ? r : NontrivialJoin(a, b); + } - public Element! Join(Element! a, Element! b) - { - Element/*?*/ r = TrivialJoin(a,b); - return r != null ? r : NontrivialJoin(a, b); - } + public abstract Element/*!*/ NontrivialMeet(Element/*!*/ a, Element/*!*/ b) + /* The following cases are handled elsewhere and need not be considered in subclass. */ + // requires a.GetType() == b.GetType(); + // requires ! a.IsTop; + // requires ! a.IsBottom; + // requires ! b.IsTop; + // requires ! b.IsBottom; + ; + + protected Element/*?*/ TrivialMeet(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + if (a.GetType() != b.GetType()) { + throw new System.InvalidOperationException( + "operands to Meet must be of same Lattice.Element type" + ); + } + if (IsTop(a)) { + return b; + } + if (IsTop(b)) { + return a; + } + if (IsBottom(a)) { + return a; + } + if (IsBottom(b)) { + return b; + } + + return null; + } - public abstract Element! NontrivialMeet(Element! a, Element! b) - /* The following cases are handled elsewhere and need not be considered in subclass. */ - // requires a.GetType() == b.GetType(); - // requires ! a.IsTop; - // requires ! a.IsBottom; - // requires ! b.IsTop; - // requires ! b.IsBottom; - ; - - protected Element/*?*/ TrivialMeet(Element! a, Element! b) - { - if (a.GetType() != b.GetType()) - { - throw new System.InvalidOperationException( - "operands to Meet must be of same Lattice.Element type" - ); - } - if (IsTop(a)) { return b; } - if (IsTop(b)) { return a; } - if (IsBottom(a)) { return a; } - if (IsBottom(b)) { return b; } - - return null; - } + public Element/*!*/ Meet(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + Element/*?*/ r = TrivialMeet(a, b); + return r != null ? r : NontrivialMeet(a, b); + } - public Element! Meet(Element! a, Element! b) - { - Element/*?*/ r = TrivialMeet(a,b); - return r != null ? r : NontrivialMeet(a, b); - } + public abstract Element/*!*/ Widen(Element/*!*/ a, Element/*!*/ b); - public abstract Element! Widen(Element! a, Element! b); + public virtual void Validate() { + Debug.Assert(IsTop(Top)); + Debug.Assert(IsBottom(Bottom)); + Debug.Assert(!IsBottom(Top)); + Debug.Assert(!IsTop(Bottom)); - public virtual void Validate() - { - Debug.Assert(IsTop(Top)); - Debug.Assert(IsBottom(Bottom)); - Debug.Assert(!IsBottom(Top)); - Debug.Assert(!IsTop(Bottom)); + Debug.Assert(LowerThan(Top, Top)); + Debug.Assert(LowerThan(Bottom, Top)); + Debug.Assert(LowerThan(Bottom, Bottom)); - Debug.Assert(LowerThan(Top, Top)); - Debug.Assert(LowerThan(Bottom, Top)); - Debug.Assert(LowerThan(Bottom, Bottom)); + Debug.Assert(IsTop(Join(Top, Top))); + Debug.Assert(IsBottom(Join(Bottom, Bottom))); + } + } + [ContractClassFor(typeof(MathematicalLattice))] + public abstract class MathematicalLatticeContracts : MathematicalLattice { + public override MathematicalLattice.Element Top { + get { + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } + } - Debug.Assert(IsTop(Join(Top, Top))); - Debug.Assert(IsBottom(Join(Bottom, Bottom))); - } + public override MathematicalLattice.Element Bottom { + get { + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } } + public override bool IsTop(MathematicalLattice.Element e) { + Contract.Requires(e != null); + throw new NotImplementedException(); + } - /// - /// Provides an abstract interface for the operations of a lattice specific - /// to abstract interpretation (i.e., that deals with the expression language). - /// - public abstract class Lattice : MathematicalLattice - { - internal readonly IValueExprFactory! valueExprFactory; - - public Lattice(IValueExprFactory! valueExprFactory) - { - this.valueExprFactory = valueExprFactory; - // base(); - } + public override bool IsBottom(MathematicalLattice.Element e) { + Contract.Requires(e != null); + throw new NotImplementedException(); + } - #region Primitives that commands translate into + protected override bool AtMost(MathematicalLattice.Element a, MathematicalLattice.Element b) { + Contract.Requires(a != null); + Contract.Requires(b != null); + throw new NotImplementedException(); + } - public abstract Element! Eliminate(Element! e, IVariable! variable); + public override MathematicalLattice.Element NontrivialJoin(MathematicalLattice.Element a, MathematicalLattice.Element b) { + Contract.Requires(a != null); + Contract.Requires(b != null); + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } - public abstract Element! Rename(Element! e, IVariable! oldName, IVariable! newName); + public override MathematicalLattice.Element NontrivialMeet(MathematicalLattice.Element a, MathematicalLattice.Element b) { + Contract.Requires(a != null); + Contract.Requires(b != null); + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } - public abstract Element! Constrain(Element! e, IExpr! expr); + public override MathematicalLattice.Element Widen(MathematicalLattice.Element a, MathematicalLattice.Element b) { + Contract.Requires(a != null); + Contract.Requires(b != null); + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } + } + + + /// + /// Provides an abstract interface for the operations of a lattice specific + /// to abstract interpretation (i.e., that deals with the expression language). + /// + [ContractClass(typeof(LatticeContracts))] + public abstract class Lattice : MathematicalLattice { + internal readonly IValueExprFactory/*!*/ valueExprFactory; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(valueExprFactory != null); + } - #endregion + public Lattice(IValueExprFactory/*!*/ valueExprFactory) { + Contract.Requires(valueExprFactory != null); + this.valueExprFactory = valueExprFactory; + // base(); + } -// TODO keep this? -// public Element! Eliminate(Element! e, VariableSeq! variables) -// { -// Lattice.Element result = e; -// foreach (IVariable var in variables) -// { -// result = this.Eliminate(result, var); -// } -// return result; -// } + #region Primitives that commands translate into + public abstract Element/*!*/ Eliminate(Element/*!*/ e, IVariable/*!*/ variable); - //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - // Note! - // - // Concrete classes that implement Lattice must implement one of the AtMost - // overloads. We provide here a default implementation for one given a "real" - // implementation of the other. Otherwise, there will be an infinite loop! - //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + public abstract Element/*!*/ Rename(Element/*!*/ e, IVariable/*!*/ oldName, IVariable/*!*/ newName); - protected override bool AtMost(Element! a, Element! b) - { - return AtMost(a, IdentityCombineNameMap.Map, b, IdentityCombineNameMap.Map); - } + public abstract Element/*!*/ Constrain(Element/*!*/ e, IExpr/*!*/ expr); - protected virtual bool AtMost(Element! a, ICombineNameMap! aToResult, Element! b, ICombineNameMap! bToResult) - { - return AtMost(ApplyCombineNameMap(a,aToResult), ApplyCombineNameMap(b,bToResult)); - } + #endregion - public bool LowerThan(Element! a, ICombineNameMap! aToResult, Element! b, ICombineNameMap! bToResult) - { - Answer ans = TrivialLowerThan(a,b); - return ans != Answer.Maybe ? ans == Answer.Yes : AtMost(a, aToResult, b, bToResult); - } - - public bool HigherThan(Element! a, ICombineNameMap! aToResult, Element! b, ICombineNameMap! bToResult) - { - return LowerThan(b, bToResult, a, aToResult); - } + // TODO keep this? + // public Element! Eliminate(Element! e, VariableSeq! variables) + // { + // Lattice.Element result = e; + // foreach (IVariable var in variables) + // { + // result = this.Eliminate(result, var); + // } + // return result; + // } - //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - // Note! - // - // Concrete classes that implement Lattice must implement one of the NontrivialJoin - // overloads. We provide here a default implementation for one given a "real" - // implementation of the other. Otherwise, there will be an infinite loop! - //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - public override Element! NontrivialJoin(Element! a, Element! b) - { - return NontrivialJoin(a, IdentityCombineNameMap.Map, b, IdentityCombineNameMap.Map); - } + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // Note! + // + // Concrete classes that implement Lattice must implement one of the AtMost + // overloads. We provide here a default implementation for one given a "real" + // implementation of the other. Otherwise, there will be an infinite loop! + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - public virtual Element! NontrivialJoin(Element! a, ICombineNameMap! aToResult, Element! b, ICombineNameMap! bToResult) - { - return NontrivialJoin(ApplyCombineNameMap(a,aToResult), ApplyCombineNameMap(b,bToResult)); - } + protected override bool AtMost(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + return AtMost(a, IdentityCombineNameMap.Map, b, IdentityCombineNameMap.Map); + } - public Element! Join(Element! a, ICombineNameMap! aToResult, Element! b, ICombineNameMap! bToResult) - { - Element/*?*/ r = TrivialJoin(a,b); - return r != null ? r : NontrivialJoin(a, aToResult, b, bToResult); - } - - - //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - // Note! - // - // Concrete classes that implement Lattice must implement one of the Widen - // overloads. We provide here a default implementation for one given a "real" - // implementation of the other. Otherwise, there will be an infinite loop! - //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - public override Element! Widen(Element! a, Element! b) - { - return Widen(a, IdentityCombineNameMap.Map, b, IdentityCombineNameMap.Map); - } + protected virtual bool AtMost(Element/*!*/ a, ICombineNameMap/*!*/ aToResult, Element/*!*/ b, ICombineNameMap/*!*/ bToResult) { + Contract.Requires(bToResult != null); + Contract.Requires(b != null); + Contract.Requires(aToResult != null); + Contract.Requires(a != null); + return AtMost(ApplyCombineNameMap(a, aToResult), ApplyCombineNameMap(b, bToResult)); + } - public virtual Element! Widen(Element! a, ICombineNameMap! aToResult, Element! b, ICombineNameMap! bToResult) - { - return Widen(ApplyCombineNameMap(a,aToResult), ApplyCombineNameMap(b,bToResult)); - } + public bool LowerThan(Element/*!*/ a, ICombineNameMap/*!*/ aToResult, Element/*!*/ b, ICombineNameMap/*!*/ bToResult) { + Contract.Requires(bToResult != null); + Contract.Requires(b != null); + Contract.Requires(aToResult != null); + Contract.Requires(a != null); + Answer ans = TrivialLowerThan(a, b); + return ans != Answer.Maybe ? ans == Answer.Yes : AtMost(a, aToResult, b, bToResult); + } + public bool HigherThan(Element/*!*/ a, ICombineNameMap/*!*/ aToResult, Element/*!*/ b, ICombineNameMap/*!*/ bToResult) { + Contract.Requires(bToResult != null); + Contract.Requires(b != null); + Contract.Requires(aToResult != null); + Contract.Requires(a != null); + return LowerThan(b, bToResult, a, aToResult); + } - /// - /// Returns the predicate that corresponds to the given lattice element. - /// - public abstract IExpr! ToPredicate(Element! e); - - /// - /// Allows the lattice to specify whether it understands a particular function symbol. - /// - /// The lattice is always allowed to return "true" even when it really can't do anything - /// with such functions; however, it is advantageous to say "false" when possible to - /// avoid being called to do certain things. - /// - /// The arguments to a function are provided for context so that the lattice can say - /// true or false for the same function symbol in different situations. For example, - /// a lattice may understand the multiplication of a variable and a constant but not - /// of two variables. The implementation of a lattice should not hold on to the - /// arguments. - /// - /// The function symbol. - /// The argument context. - /// True if it may understand f, false if it does not understand f. - public abstract bool Understands(IFunctionSymbol! f, IList/**/! args); - - /// - /// Return an expression that is equivalent to the given expression that does not - /// contain the given variable according to the lattice element and queryable. - /// - /// The lattice element. - /// A queryable for asking addtional information. - /// The expression to find an equivalent expression. - /// The variable to eliminate. - /// The set of variables that can't be used in the resulting expression. - /// - /// An equivalent expression to without - /// or null if not possible. - /// - public abstract IExpr/*?*/ EquivalentExpr(Element! e, IQueryable! q, IExpr! expr, IVariable! var, Set/**/! prohibitedVars); - - /// - /// Answers a query about whether the given predicate holds given the lattice element. - /// - /// The lattice element. - /// The predicate. - /// Yes, No, or Maybe. - public abstract Answer CheckPredicate(Element! e, IExpr! pred); - - /// - /// Answers a disequality about two variables. The same information could be obtained - /// by asking CheckPredicate, but a different implementation may be simpler and more - /// efficient. - /// - /// The lattice element. - /// The first variable. - /// The second variable. - /// Yes, No, or Maybe. - public abstract Answer CheckVariableDisequality(Element! e, IVariable! var1, IVariable! var2); - - /// - /// A default implementation of the given - /// the appropriate expression factories by calling CheckPredicate. - /// - protected Answer DefaultCheckVariableDisequality( - IPropExprFactory! propExprFactory, IValueExprFactory! valExprFactory, - Element! e, IVariable! var1, IVariable! var2) - { - return this.CheckPredicate(e, propExprFactory.Not(valExprFactory.Eq(var1, var2))); - } - private Element! ApplyCombineNameMap(Element! e, ICombineNameMap! eToResult) - { - Element! result = e; - - foreach (G.KeyValuePair*/!> entry in eToResult.GetSourceToResult()) - { - IVariable! sourceName = entry.Key; - ISet/**/!>! emptyDictionary1 = new G.Dictionary*/!>(); - private static readonly G.Dictionary! emptyDictionary2 = new G.Dictionary(); - - public ISet/**//*?*/ GetResultNames(IVariable! srcname) - { - ArraySet a = new ArraySet(); - a.Add(srcname); - return a; - } - - public IVariable/*?*/ GetSourceName(IVariable! resname) - { - return resname; - } - - //TODO: uncomment when works in compiler - //public G.IEnumerable*/!>> GetSourceToResult() - public IEnumerable! GetSourceToResult() - { - return emptyDictionary1; - } - - //public G.IEnumerable> GetResultToSource() - public IEnumerable! GetResultToSource() - { - return emptyDictionary2; - } - - private IdentityCombineNameMap() { } - } + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // Note! + // + // Concrete classes that implement Lattice must implement one of the NontrivialJoin + // overloads. We provide here a default implementation for one given a "real" + // implementation of the other. Otherwise, there will be an infinite loop! + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - public abstract string! ToString(Element! e); // for debugging - - #region Support for MultiLattice to uniquely number every subclass of Lattice - - private static Hashtable/**/! indexMap = new Hashtable(); - private static Hashtable/**/! reverseIndexMap = new Hashtable(); - private static int globalCount = 0; - - protected virtual object! UniqueId { get { return (!)this.GetType(); } } - - public int Index - { - get - { - object unique = this.UniqueId; - if (indexMap.ContainsKey(unique)) - { - object index = indexMap[unique]; - assert index != null; // this does nothing for nonnull analysis - if (index != null) { return (int)index; } - return 0; - } - else - { - int myIndex = globalCount++; - indexMap[unique] = myIndex; - reverseIndexMap[myIndex] = this; - return myIndex; - } - } - } + public override Element/*!*/ NontrivialJoin(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + return NontrivialJoin(a, IdentityCombineNameMap.Map, b, IdentityCombineNameMap.Map); + } + + public virtual Element/*!*/ NontrivialJoin(Element/*!*/ a, ICombineNameMap/*!*/ aToResult, Element/*!*/ b, ICombineNameMap/*!*/ bToResult) { + Contract.Requires(bToResult != null); + Contract.Requires(b != null); + Contract.Requires(aToResult != null); + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + return NontrivialJoin(ApplyCombineNameMap(a, aToResult), ApplyCombineNameMap(b, bToResult)); + } + + public Element/*!*/ Join(Element/*!*/ a, ICombineNameMap/*!*/ aToResult, Element/*!*/ b, ICombineNameMap/*!*/ bToResult) { + Contract.Requires(bToResult != null); + Contract.Requires(b != null); + Contract.Requires(aToResult != null); + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + Element/*?*/ r = TrivialJoin(a, b); + return r != null ? r : NontrivialJoin(a, aToResult, b, bToResult); + } - public static Lattice GetGlobalLattice(int i) { return reverseIndexMap[i] as Lattice; } - #endregion - public static bool LogSwitch = false; + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // Note! + // + // Concrete classes that implement Lattice must implement one of the Widen + // overloads. We provide here a default implementation for one given a "real" + // implementation of the other. Otherwise, there will be an infinite loop! + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + public override Element/*!*/ Widen(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + return Widen(a, IdentityCombineNameMap.Map, b, IdentityCombineNameMap.Map); } + public virtual Element/*!*/ Widen(Element/*!*/ a, ICombineNameMap/*!*/ aToResult, Element/*!*/ b, ICombineNameMap/*!*/ bToResult) { + Contract.Requires(bToResult != null); + Contract.Requires(b != null); + Contract.Requires(aToResult != null); + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + return Widen(ApplyCombineNameMap(a, aToResult), ApplyCombineNameMap(b, bToResult)); + } + + /// - /// Defines the relation between names used in the respective input lattice elements to the - /// various combination operators (Join,Widen,Meet,AtMost) and the names that should be used - /// in the resulting lattice element. + /// A default implementation of the given + /// the appropriate expression factories by calling CheckPredicate. /// - public interface ICombineNameMap - { - ISet/**//*?*/ GetResultNames(IVariable! srcname); - IVariable/*?*/ GetSourceName(IVariable! resname); - - //TODO: uncommet when works in compiler - //G.IEnumerable*/!>> GetSourceToResult(); - IEnumerable! GetSourceToResult(); - //G.IEnumerable> GetResultToSource(); - IEnumerable! GetResultToSource(); + protected Answer DefaultCheckVariableDisequality(IPropExprFactory/*!*/ propExprFactory, IValueExprFactory/*!*/ valExprFactory, Element/*!*/ e, IVariable/*!*/ var1, IVariable/*!*/ var2) { + Contract.Requires(propExprFactory != null); + Contract.Requires(valExprFactory != null); + Contract.Requires(e != null); + Contract.Requires(var1 != null); + Contract.Requires(var2 != null); + return this.CheckPredicate(e, propExprFactory.Not(valExprFactory.Eq(var1, var2))); + } + + private Element/*!*/ ApplyCombineNameMap(Element/*!*/ e, ICombineNameMap/*!*/ eToResult) { + Contract.Requires(eToResult != null); + Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); + Element/*!*/ result = e; + + foreach (G.KeyValuePair*//*!*/> entry in eToResult.GetSourceToResult()) { + IVariable/*!*/ sourceName = entry.Key; + Contract.Assert(sourceName != null); + ISet/**//*!*/>/*!*/ emptyDictionary1 = new G.Dictionary*//*!*/>(); + private static readonly G.Dictionary/*!*/ emptyDictionary2 = new G.Dictionary(); + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(Map != null); + Contract.Invariant(cce.NonNullElements(emptyDictionary1) && Contract.ForAll(emptyDictionary1.Values, set =>/*cce.NonNullElements(set)*/set != null)); + Contract.Invariant(cce.NonNullElements(emptyDictionary2)); + Contract.Invariant(indexMap != null); + Contract.Invariant(reverseIndexMap != null); + + } + + + public ISet/**//*?*/ GetResultNames(IVariable/*!*/ srcname) { + Contract.Requires(srcname != null); + ArraySet a = new ArraySet(); + a.Add(srcname); + return a; + } + + public IVariable/*?*/ GetSourceName(IVariable/*!*/ resname) { + Contract.Requires(resname != null); + return resname; + } + + //TODO: uncomment when works in compiler + //public G.IEnumerable*/!>> GetSourceToResult() + public IEnumerable/*!*/ GetSourceToResult() { + Contract.Ensures(Contract.Result() != null); + return emptyDictionary1; + } + + //public G.IEnumerable> GetResultToSource() + public IEnumerable/*!*/ GetResultToSource() { + Contract.Ensures(Contract.Result() != null); + return emptyDictionary2; + } + + private IdentityCombineNameMap() { + } + } + + #region Support for MultiLattice to uniquely number every subclass of Lattice + + + private static Hashtable/**//*!*/ indexMap = new Hashtable(); + private static Hashtable/**//*!*/ reverseIndexMap = new Hashtable(); + private static int globalCount = 0; + + protected virtual object/*!*/ UniqueId { + get { + Contract.Ensures(Contract.Result() != null); + return cce.NonNull(this.GetType()); + } } + public int Index { + get { + object unique = this.UniqueId; + if (indexMap.ContainsKey(unique)) { + object index = indexMap[unique]; + Contract.Assert(index != null); // this does nothing for nonnull analysis + if (index != null) { + return (int)index; + } + return 0; + } else { + int myIndex = globalCount++; + indexMap[unique] = myIndex; + reverseIndexMap[myIndex] = this; + return myIndex; + } + } + } + + public static Lattice GetGlobalLattice(int i) { + return reverseIndexMap[i] as Lattice; + } + #endregion + + public static bool LogSwitch = false; /// - /// Provides statistics on the number of times an operation is performed - /// and forwards the real operations to the given lattice in the constructor. + /// Returns the predicate that corresponds to the given lattice element. /// - public class StatisticsLattice : Lattice - { - readonly Lattice! lattice; - int eliminateCount; - int renameCount; - int constrainCount; - int toPredicateCount; - int atMostCount; - int topCount; - int bottomCount; - int isTopCount; - int isBottomCount; - int joinCount; - int meetCount; - int widenCount; - int understandsCount; - int equivalentExprCount; - int checkPredicateCount; - int checkVariableDisequalityCount; - - public StatisticsLattice(Lattice! lattice) - : base(lattice.valueExprFactory) - { - this.lattice = lattice; - // base(lattice.valueExprFactory); - } + public abstract IExpr/*!*/ ToPredicate(Element/*!*/ e); - public override Element! Eliminate(Element! e, IVariable! variable) - { - eliminateCount++; - return lattice.Eliminate(e, variable); - } + /// + /// Allows the lattice to specify whether it understands a particular function symbol. + /// + /// The lattice is always allowed to return "true" even when it really can't do anything + /// with such functions; however, it is advantageous to say "false" when possible to + /// avoid being called to do certain things. + /// + /// The arguments to a function are provided for context so that the lattice can say + /// true or false for the same function symbol in different situations. For example, + /// a lattice may understand the multiplication of a variable and a constant but not + /// of two variables. The implementation of a lattice should not hold on to the + /// arguments. + /// + /// The function symbol. + /// The argument context. + /// True if it may understand f, false if it does not understand f. + public abstract bool Understands(IFunctionSymbol/*!*/ f, IList/**//*!*/ args); - public override Element! Rename(Element! e, IVariable! oldName, IVariable! newName) - { - renameCount++; - return lattice.Rename(e, oldName, newName); - } + /// + /// Return an expression that is equivalent to the given expression that does not + /// contain the given variable according to the lattice element and queryable. + /// + /// The lattice element. + /// A queryable for asking addtional information. + /// The expression to find an equivalent expression. + /// The variable to eliminate. + /// The set of variables that can't be used in the resulting expression. + /// + /// An equivalent expression to without + /// or null if not possible. + /// + public abstract IExpr/*?*/ EquivalentExpr(Element/*!*/ e, IQueryable/*!*/ q, IExpr/*!*/ expr, IVariable/*!*/ var, Set/**//*!*/ prohibitedVars); - public override Element! Constrain(Element! e, IExpr! expr) - { - constrainCount++; - return lattice.Constrain(e, expr); - } + /// + /// Answers a query about whether the given predicate holds given the lattice element. + /// + /// The lattice element. + /// The predicate. + /// Yes, No, or Maybe. + public abstract Answer CheckPredicate(Element/*!*/ e, IExpr/*!*/ pred); + /// + /// Answers a disequality about two variables. The same information could be obtained + /// by asking CheckPredicate, but a different implementation may be simpler and more + /// efficient. + /// + /// The lattice element. + /// The first variable. + /// The second variable. + /// Yes, No, or Maybe. + public abstract Answer CheckVariableDisequality(Element/*!*/ e, IVariable/*!*/ var1, IVariable/*!*/ var2); + + public abstract string/*!*/ ToString(Element/*!*/ e); // for debugging + + } + [ContractClassFor(typeof(Lattice))] + abstract class LatticeContracts : Lattice { + public LatticeContracts() + : base(null) { + } + public override IExpr ToPredicate(MathematicalLattice.Element e) { + Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } + public override bool Understands(IFunctionSymbol f, IList args) { + Contract.Requires(f != null); + Contract.Requires(args != null); + throw new NotImplementedException(); + } + public override IExpr EquivalentExpr(MathematicalLattice.Element e, IQueryable q, IExpr expr, IVariable var, Set prohibitedVars) { + Contract.Requires(e != null); + Contract.Requires(q != null); + Contract.Requires(expr != null); + Contract.Requires(var != null); + Contract.Requires(prohibitedVars != null); + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } + public override Answer CheckPredicate(MathematicalLattice.Element e, IExpr pred) { + Contract.Requires(e != null); + Contract.Requires(pred != null); + throw new NotImplementedException(); + } + public override Answer CheckVariableDisequality(MathematicalLattice.Element e, IVariable var1, IVariable var2) { + Contract.Requires(e != null); + Contract.Requires(var1 != null); + Contract.Requires(var2 != null); + throw new NotImplementedException(); + } + public override string ToString(Element e) { + Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } + public override MathematicalLattice.Element Eliminate(MathematicalLattice.Element e, IVariable variable) { + Contract.Requires(e != null); + Contract.Requires(variable != null); + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } + public override MathematicalLattice.Element Rename(MathematicalLattice.Element e, IVariable oldName, IVariable newName) { + Contract.Requires(e != null); + Contract.Requires(oldName != null); + Contract.Requires(newName != null); + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } + public override MathematicalLattice.Element Constrain(MathematicalLattice.Element e, IExpr expr) { + Contract.Requires(e != null); + Contract.Requires(expr != null); + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } + } + + /// + /// Defines the relation between names used in the respective input lattice elements to the + /// various combination operators (Join,Widen,Meet,AtMost) and the names that should be used + /// in the resulting lattice element. + /// + [ContractClass(typeof(ICombineNameMapContracts))] + public interface ICombineNameMap { + ISet/**//*?*/ GetResultNames(IVariable/*!*/ srcname); + IVariable/*?*/ GetSourceName(IVariable/*!*/ resname); + + //TODO: uncommet when works in compiler + //G.IEnumerable*/!>> GetSourceToResult(); + IEnumerable/*!*/ GetSourceToResult(); + //G.IEnumerable> GetResultToSource(); + IEnumerable/*!*/ GetResultToSource(); + } + [ContractClassFor(typeof(ICombineNameMap))] + public abstract class ICombineNameMapContracts : ICombineNameMap { + #region ICombineNameMap Members + + public Set GetResultNames(IVariable srcname) { + Contract.Requires(srcname != null); + throw new NotImplementedException(); + } - public override bool Understands(IFunctionSymbol! f, IList! args) - { - understandsCount++; - return lattice.Understands(f, args); - } + public IVariable GetSourceName(IVariable resname) { + Contract.Requires(resname != null); + throw new NotImplementedException(); + } + public IEnumerable GetSourceToResult() { + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } - public override IExpr/*?*/ EquivalentExpr(Element! e, IQueryable! q, IExpr! expr, IVariable! var, ISet/**/! prohibitedVars) - { - equivalentExprCount++; - return lattice.EquivalentExpr(e, q, expr, var, prohibitedVars); - } + public IEnumerable GetResultToSource() { + Contract.Ensures(Contract.Result() != null); + throw new NotImplementedException(); + } + #endregion + } + + /// + /// Provides statistics on the number of times an operation is performed + /// and forwards the real operations to the given lattice in the constructor. + /// + public class StatisticsLattice : Lattice { + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(lattice != null); + } - public override Answer CheckPredicate(Element! e, IExpr! pred) - { - checkPredicateCount++; - return lattice.CheckPredicate(e, pred); - } + readonly Lattice/*!*/ lattice; + int eliminateCount; + int renameCount; + int constrainCount; + int toPredicateCount; + int atMostCount; + int topCount; + int bottomCount; + int isTopCount; + int isBottomCount; + int joinCount; + int meetCount; + int widenCount; + int understandsCount; + int equivalentExprCount; + int checkPredicateCount; + int checkVariableDisequalityCount; + + public StatisticsLattice(Lattice/*!*/ lattice) + : base(lattice.valueExprFactory) { + Contract.Requires(lattice != null); + this.lattice = lattice; + // base(lattice.valueExprFactory); + } + public override Element/*!*/ Eliminate(Element/*!*/ e, IVariable/*!*/ variable) { + Contract.Requires(variable != null); + Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); + eliminateCount++; + return lattice.Eliminate(e, variable); + } - public override Answer CheckVariableDisequality(Element! e, IVariable! var1, IVariable! var2) - { - checkVariableDisequalityCount++; - return lattice.CheckVariableDisequality(e, var1, var2); - } + public override Element/*!*/ Rename(Element/*!*/ e, IVariable/*!*/ oldName, IVariable/*!*/ newName) { + Contract.Requires(newName != null); + Contract.Requires(oldName != null); + Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); + renameCount++; + return lattice.Rename(e, oldName, newName); + } + public override Element/*!*/ Constrain(Element/*!*/ e, IExpr/*!*/ expr) { + Contract.Requires(expr != null); + Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); + constrainCount++; + return lattice.Constrain(e, expr); + } - public override IExpr! ToPredicate(Element! e) - { - toPredicateCount++; - return lattice.ToPredicate(e); - } + public override bool Understands(IFunctionSymbol/*!*/ f, IList/*!*/ args) { + Contract.Requires(args != null); + Contract.Requires(f != null); + understandsCount++; + return lattice.Understands(f, args); + } - public override string! ToString(Element! e) - { - return lattice.ToString(e); - } - [Pure] - public override string! ToString() - { - return string.Format( - "StatisticsLattice: #Eliminate={0} #Rename={1} #Constrain={2} #ToPredicate={3} " + - "#Understands={4} #EquivalentExpr={5} #CheckPredicate={6} #CheckVariableDisequality={7} " + - "#AtMost={8} #Top={9} #Bottom={9} #IsTop={10} #IsBottom={11} " + - "#NonTrivialJoin={12} #NonTrivialMeet={13} #Widen={14}", - eliminateCount, renameCount, constrainCount, toPredicateCount, - understandsCount, equivalentExprCount, checkPredicateCount, checkVariableDisequalityCount, - atMostCount, topCount, bottomCount, isTopCount, isBottomCount, - joinCount, meetCount, widenCount); - } + public override IExpr/*?*/ EquivalentExpr(Element/*!*/ e, IQueryable/*!*/ q, IExpr/*!*/ expr, IVariable/*!*/ var, ISet/**//*!*/ prohibitedVars) { + Contract.Requires(prohibitedVars != null); + Contract.Requires(var != null); + Contract.Requires(expr != null); + Contract.Requires(q != null); + Contract.Requires(e != null); + equivalentExprCount++; + return lattice.EquivalentExpr(e, q, expr, var, prohibitedVars); + } - protected override bool AtMost(Element! a, Element! b) - { - atMostCount++; - return lattice.LowerThan(a, b); - } - public override Element! Top - { - get - { - topCount++; - return lattice.Top; - } - } - public override Element! Bottom - { - get - { - bottomCount++; - return lattice.Bottom; - } - } + public override Answer CheckPredicate(Element/*!*/ e, IExpr/*!*/ pred) { + Contract.Requires(pred != null); + Contract.Requires(e != null); + checkPredicateCount++; + return lattice.CheckPredicate(e, pred); + } - public override bool IsTop(Element! e) - { - isTopCount++; - return lattice.IsTop(e); - } - public override bool IsBottom(Element! e) - { - isBottomCount++; - return lattice.IsBottom(e); - } + public override Answer CheckVariableDisequality(Element/*!*/ e, IVariable/*!*/ var1, IVariable/*!*/ var2) { + Contract.Requires(var2 != null); + Contract.Requires(var1 != null); + Contract.Requires(e != null); + checkVariableDisequalityCount++; + return lattice.CheckVariableDisequality(e, var1, var2); + } - public override Element! NontrivialJoin(Element! a, Element! b) - { - joinCount++; - return lattice.NontrivialJoin(a, b); - } - public override Element! NontrivialMeet(Element! a, Element! b) - { - meetCount++; - return lattice.NontrivialMeet(a, b); - } - public override Element! Widen(Element! a, Element! b) - { - widenCount++; - return lattice.Widen(a, b); - } + public override IExpr/*!*/ ToPredicate(Element/*!*/ e) { + Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); + toPredicateCount++; + return lattice.ToPredicate(e); + } - public override void Validate() - { - base.Validate(); - lattice.Validate(); - } - - protected override object! UniqueId - { - get - { - // use the base id, not the underlying-lattice id (is that the right thing to do?) - return base.UniqueId; - } - } + public override string/*!*/ ToString(Element/*!*/ e) { + Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); + return lattice.ToString(e); } + [Pure] + public override string/*!*/ ToString() { + Contract.Ensures(Contract.Result() != null); + return string.Format( + "StatisticsLattice: #Eliminate={0} #Rename={1} #Constrain={2} #ToPredicate={3} " + + "#Understands={4} #EquivalentExpr={5} #CheckPredicate={6} #CheckVariableDisequality={7} " + + "#AtMost={8} #Top={9} #Bottom={9} #IsTop={10} #IsBottom={11} " + + "#NonTrivialJoin={12} #NonTrivialMeet={13} #Widen={14}", + eliminateCount, renameCount, constrainCount, toPredicateCount, + understandsCount, equivalentExprCount, checkPredicateCount, checkVariableDisequalityCount, + atMostCount, topCount, bottomCount, isTopCount, isBottomCount, + joinCount, meetCount, widenCount); + } - public sealed class LatticeQueryable : IQueryable - { - private Lattice! lattice; - private Lattice.Element! element; + protected override bool AtMost(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + atMostCount++; + return lattice.LowerThan(a, b); + } - public LatticeQueryable(Lattice! lattice, Lattice.Element! element) - { - this.lattice = lattice; - this.element = element; - // base(); - } + public override Element/*!*/ Top { + get { + Contract.Ensures(Contract.Result() != null); + topCount++; + return lattice.Top; + } + } + public override Element/*!*/ Bottom { + get { + Contract.Ensures(Contract.Result() != null); + bottomCount++; + return lattice.Bottom; + } + } - public Answer CheckPredicate(IExpr! pred) - { - return lattice.CheckPredicate(element, pred); - } + public override bool IsTop(Element/*!*/ e) { + Contract.Requires(e != null); + isTopCount++; + return lattice.IsTop(e); + } - public Answer CheckVariableDisequality(IVariable! var1, IVariable! var2) - { - return lattice.CheckVariableDisequality(element, var1, var2); - } + public override bool IsBottom(Element/*!*/ e) { + Contract.Requires(e != null); + isBottomCount++; + return lattice.IsBottom(e); + } + + public override Element/*!*/ NontrivialJoin(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + joinCount++; + return lattice.NontrivialJoin(a, b); + } + + public override Element/*!*/ NontrivialMeet(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + meetCount++; + return lattice.NontrivialMeet(a, b); + } + + public override Element/*!*/ Widen(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + widenCount++; + return lattice.Widen(a, b); + } + + public override void Validate() { + base.Validate(); + lattice.Validate(); + } + + protected override object/*!*/ UniqueId { + get { + Contract.Ensures(Contract.Result() != null); + // use the base id, not the underlying-lattice id (is that the right thing to do?) + return base.UniqueId; + } + } + } + + + public sealed class LatticeQueryable : IQueryable { + private Lattice/*!*/ lattice; + private Lattice.Element/*!*/ element; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(lattice != null); + Contract.Invariant(element != null); + } + + + public LatticeQueryable(Lattice/*!*/ lattice, Lattice.Element/*!*/ element) { + Contract.Requires(element != null); + Contract.Requires(lattice != null); + this.lattice = lattice; + this.element = element; + // base(); + } + + public Answer CheckPredicate(IExpr/*!*/ pred) { + Contract.Requires(pred != null); + return lattice.CheckPredicate(element, pred); + } + + public Answer CheckVariableDisequality(IVariable/*!*/ var1, IVariable/*!*/ var2) { + Contract.Requires(var2 != null); + Contract.Requires(var1 != null); + return lattice.CheckVariableDisequality(element, var1, var2); } + } } diff --git a/Source/AIFramework/Logger.cs b/Source/AIFramework/Logger.cs index 12c3ba08..aa7c5979 100644 --- a/Source/AIFramework/Logger.cs +++ b/Source/AIFramework/Logger.cs @@ -3,47 +3,54 @@ // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- -namespace Microsoft.AbstractInterpretationFramework -{ - using System; - using System.Diagnostics; +namespace Microsoft.AbstractInterpretationFramework { + using System; + using System.Diagnostics; + using System.Diagnostics.Contracts; - public class Logger - { - private string! dbgmsgContext; - private static int contextWidth = 0; - - public bool Enabled = false; + public class Logger { + private string/*!*/ dbgmsgContext; + private static int contextWidth = 0; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(dbgmsgContext != null); + Contract.Invariant(dbgmsgIndent != null); + } - public Logger(string! contextMsg) - { - this.dbgmsgContext = "[" + contextMsg + "] "; - contextWidth = Math.Max(contextWidth, contextMsg.Length + 3); - // base(); - } - private static System.Text.StringBuilder! dbgmsgIndent = new System.Text.StringBuilder(); - public void DbgMsgIndent() { dbgmsgIndent.Append(' ', 2); } - public void DbgMsgUnindent() - { if (dbgmsgIndent.Length >= 2) dbgmsgIndent.Remove(0,2); } + public bool Enabled = false; - [ConditionalAttribute("DEBUG")] - public void DbgMsg(string msg) - { - if (Enabled) - Debug.WriteLine(dbgmsgContext.PadRight(contextWidth) + dbgmsgIndent + msg); - } - [ConditionalAttribute("DEBUG")] - public void DbgMsgNoLine(string msg) - { - if (Enabled) - Debug.Write(dbgmsgContext.PadRight(contextWidth) + dbgmsgIndent + msg); - } - [ConditionalAttribute("DEBUG")] - public void DbgMsgPlain(string msg) - { - if (Enabled) - Debug.Write(msg); - } - } + public Logger(string/*!*/ contextMsg) { + Contract.Requires(contextMsg != null); + this.dbgmsgContext = "[" + contextMsg + "] "; + contextWidth = Math.Max(contextWidth, contextMsg.Length + 3); + // base(); + } + + private static System.Text.StringBuilder/*!*/ dbgmsgIndent = new System.Text.StringBuilder(); + + public void DbgMsgIndent() { + dbgmsgIndent.Append(' ', 2); + } + public void DbgMsgUnindent() { + if (dbgmsgIndent.Length >= 2) + dbgmsgIndent.Remove(0, 2); + } + + [ConditionalAttribute("DEBUG")] + public void DbgMsg(string msg) { + if (Enabled) + Debug.WriteLine(dbgmsgContext.PadRight(contextWidth) + dbgmsgIndent + msg); + } + [ConditionalAttribute("DEBUG")] + public void DbgMsgNoLine(string msg) { + if (Enabled) + Debug.Write(dbgmsgContext.PadRight(contextWidth) + dbgmsgIndent + msg); + } + [ConditionalAttribute("DEBUG")] + public void DbgMsgPlain(string msg) { + if (Enabled) + Debug.Write(msg); + } + } } diff --git a/Source/AIFramework/MultiLattice.cs b/Source/AIFramework/MultiLattice.cs index 514e2548..e12e2d59 100644 --- a/Source/AIFramework/MultiLattice.cs +++ b/Source/AIFramework/MultiLattice.cs @@ -3,560 +3,643 @@ // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- -namespace Microsoft.AbstractInterpretationFramework -{ - using Microsoft.Contracts; - using System.Collections; - using System.Collections.Generic; - using System.Diagnostics; - using Microsoft.AbstractInterpretationFramework.Collections; +namespace Microsoft.AbstractInterpretationFramework { + using System.Diagnostics.Contracts; + using System.Collections; + using System.Collections.Generic; + using System.Diagnostics; + using Microsoft.AbstractInterpretationFramework.Collections; + + using Microsoft.Boogie; + using ISet = Microsoft.Boogie.Set; + + + /// + /// The cartesian product lattice. + /// + public class MultiLattice : Lattice, IEnumerable { + internal class Elt : Element { + public /*MaybeNull*/Element[] elementPerLattice; + + public Elt(int domainCount, bool isBottom) { + this.elementPerLattice = (domainCount == 0 && isBottom) ? null : new Element[domainCount]; + } + + private Elt(Elt/*!*/ other) { + Contract.Requires(other != null); + Element[] otherEPL = other.elementPerLattice; + if (otherEPL != null) { + Element[] newEPL = new Element[otherEPL.Length]; + for (int i = 0; i < newEPL.Length; i++) { + newEPL[i] = (Element)(cce.NonNull(otherEPL[i])).Clone(); + } + this.elementPerLattice = newEPL; + } + } + + public override Element/*!*/ Clone() { + Contract.Ensures(Contract.Result() != null); + return new Elt(this); + } + + [Pure] + public override string/*!*/ ToString() { + Contract.Ensures(Contract.Result() != null); + // string s = "MultiLattice+Elt{"; + // string sep = ""; + // Element[] epl = this.elementPerLattice; + // if (epl != null) + // { + // foreach (Element! e in epl) + // { + // s += sep + e.ToString(); + // sep = ", "; + // } + // } + // return s + "}"; + if (elementPerLattice == null) + return ""; + System.Text.StringBuilder buffer = new System.Text.StringBuilder(); + for (int i = 0; i < this.Count; i++) { + if (i > 0) + buffer.Append("; "); + buffer.AppendFormat("{0}", elementPerLattice[i]); + } + return buffer.ToString(); + } + + public override void Dump(string/*!*/ msg) { + Contract.Requires(msg != null); + System.Console.WriteLine("MultiLattice.Elt.Dump({0})", msg); + Element[] epl = this.elementPerLattice; + if (epl != null) { + foreach (Element/*!*/ e in epl) { + Contract.Assert(e != null); + e.Dump(msg); + } + } + } + + [Pure] + public override ICollection/*!*/ FreeVariables() { + Contract.Ensures(cce.NonNullElements(Contract.Result>())); + List/*!*/ list = new List(); + for (int i = 0; i < this.Count; i++) { + list.AddRange(cce.NonNull(this[i]).FreeVariables()); + } + return cce.NonNull(list.AsReadOnly()); + } + + public static Elt/*!*/ Top(ArrayList/**//*!*/ lattices) { + Contract.Requires(lattices != null); + Contract.Ensures(Contract.Result() != null); + Elt multiValue = new Elt(lattices.Count, false); + for (int i = 0; i < lattices.Count; i++) { + Lattice d = (Lattice/*!*/)cce.NonNull(lattices[i]); + multiValue[d.Index] = d.Top; + } + Debug.Assert(multiValue.IsValid); + return multiValue; + } + + + public static Elt/*!*/ Bottom(ArrayList/**//*!*/ lattices) { + Contract.Requires(lattices != null); + Contract.Ensures(Contract.Result() != null); + Elt multiValue = new Elt(lattices.Count, true); + for (int i = 0; i < lattices.Count; i++) { + Lattice d = (Lattice/*!*/)cce.NonNull(lattices[i]); + multiValue[d.Index] = d.Bottom; + } + Debug.Assert(multiValue.IsValid); + return multiValue; + } + + public bool IsValid { + get { + if (this.elementPerLattice == null) { + return true; /*bottom*/ + } + + Element[] epl = this.elementPerLattice; + for (int i = 0; i < epl.Length; i++) { + if (epl[i] == null) { + return false; + } + } + return true; + } + } - using Microsoft.Boogie; - using ISet = Microsoft.Boogie.Set; + public int Count { + get { + return this.elementPerLattice == null ? 0 : this.elementPerLattice.Length; + } + } + public bool Contains(int i) { + return 0 <= i && i < this.Count; + } - /// - /// The cartesian product lattice. - /// - public class MultiLattice : Lattice, IEnumerable - { - internal class Elt : Element - { - public /*MaybeNull*/Element[] elementPerLattice; - - public Elt(int domainCount, bool isBottom) - { - this.elementPerLattice = (domainCount == 0 && isBottom) ? null : new Element[domainCount]; - } - - private Elt(Elt! other) - { - Element[] otherEPL = other.elementPerLattice; - if (otherEPL != null) - { - Element[] newEPL = new Element[otherEPL.Length]; - for (int i = 0; i < newEPL.Length; i++) - { - newEPL[i] = (Element) ((!)otherEPL[i]).Clone(); - } - this.elementPerLattice = newEPL; - } - } - - public override Element! Clone() - { - return new Elt(this); - } + public Element this[int i] // just syntactic sugar + { + get { + Element[] epl = this.elementPerLattice; + return epl == null ? null : epl[i]; + } + set { + Element[] epl = this.elementPerLattice; + if (epl == null) + return; + epl[i] = value; + } + } - [Pure] - public override string! ToString() - { -// string s = "MultiLattice+Elt{"; -// string sep = ""; -// Element[] epl = this.elementPerLattice; -// if (epl != null) -// { -// foreach (Element! e in epl) -// { -// s += sep + e.ToString(); -// sep = ", "; -// } -// } -// return s + "}"; - if (elementPerLattice == null) return ""; - System.Text.StringBuilder buffer = new System.Text.StringBuilder(); - for (int i = 0; i < this.Count; i++) - { - if (i > 0) buffer.Append("; "); - buffer.AppendFormat("{0}", elementPerLattice[i]); - } - return buffer.ToString(); - } + } // class - public override void Dump(string! msg) { - System.Console.WriteLine("MultiLattice.Elt.Dump({0})", msg); - Element[] epl = this.elementPerLattice; - if (epl != null) { - foreach (Element! e in epl) { - e.Dump(msg); - } - } - } - - [Pure] - public override ICollection! FreeVariables() - { - List! list = new List(); - for (int i = 0; i < this.Count; i++) - { - list.AddRange(((!)this[i]).FreeVariables()); - } - return (!)list.AsReadOnly(); - } - public static Elt! Top(ArrayList/**/! lattices) - { - Elt multiValue = new Elt(lattices.Count, false); - for (int i = 0; i < lattices.Count; i++) - { - Lattice d = (Lattice!)lattices[i]; - multiValue[d.Index] = d.Top; - } - Debug.Assert(multiValue.IsValid); - return multiValue; - } + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(lattices != null); + Contract.Invariant(propExprFactory != null); + } + ArrayList/**//*!*/ lattices = new ArrayList(); - public static Elt! Bottom(ArrayList/**/! lattices) - { - Elt multiValue = new Elt(lattices.Count, true); - for (int i = 0; i < lattices.Count; i++) - { - Lattice d = (Lattice!)lattices[i]; - multiValue[d.Index] = d.Bottom; - } - Debug.Assert(multiValue.IsValid); - return multiValue; - } + private readonly IPropExprFactory/*!*/ propExprFactory; - public bool IsValid - { - get - { - if (this.elementPerLattice == null) { return true; /*bottom*/ } - - Element[] epl = this.elementPerLattice; - for (int i = 0; i < epl.Length; i++) - { - if (epl[i] == null) { return false; } - } - return true; - } - } - public int Count { get { return this.elementPerLattice == null ? 0 : this.elementPerLattice.Length; } } + public MultiLattice(IPropExprFactory/*!*/ propExprFactory, IValueExprFactory/*!*/ valueExprFactory) + : base(valueExprFactory) { + Contract.Requires(valueExprFactory != null); + Contract.Requires(propExprFactory != null); + this.propExprFactory = propExprFactory; + // base(valueExprFactory); + } - public bool Contains(int i) { return 0 <= i && i < this.Count; } - public Element this[int i] // just syntactic sugar - { - get { Element[] epl = this.elementPerLattice; return epl == null ? null : epl[i]; } - set { Element[] epl = this.elementPerLattice; if (epl == null) return; epl[i] = value; } - } - } // class + public void AddLattice(Lattice lattice) { + this.lattices.Add(lattice); + } + + private Lattice/*!*/ SubLattice(int i) { + Contract.Ensures(Contract.Result() != null); + return (Lattice/*!*/)cce.NonNull(this.lattices[i]); + } + public override Element/*!*/ Top { + get { + Contract.Ensures(Contract.Result() != null); + return Elt.Top(this.lattices); + } + } - ArrayList/**/! lattices = new ArrayList(); + public override Element/*!*/ Bottom { + get { + Contract.Ensures(Contract.Result() != null); + return Elt.Bottom(this.lattices); + } + } - private readonly IPropExprFactory! propExprFactory; - public MultiLattice(IPropExprFactory! propExprFactory, IValueExprFactory! valueExprFactory) - : base(valueExprFactory) - { - this.propExprFactory = propExprFactory; - // base(valueExprFactory); + + public override bool IsBottom(Element/*!*/ element) { + Contract.Requires(element != null); + Elt e = (Elt)element; + // The program is errorneous/nonterminating if any subdomain knows it is. + // + if (e.elementPerLattice == null) { + return true; + } + for (int i = 0; i < e.Count; i++) { + if (SubLattice(i).IsBottom(cce.NonNull(e[i]))) { + return true; } + } + return false; + } - + public override bool IsTop(Element/*!*/ element) { + Contract.Requires(element != null); + Elt e = (Elt)element; + if (e.elementPerLattice == null) { + return false; + } + // The multidomain knows nothing about the program only if no subdomain + // knows anything about it. + // + for (int i = 0; i < e.Count; i++) { + if (!SubLattice(i).IsTop(cce.NonNull(e[i]))) { + return false; + } + } + return true; + } - public void AddLattice(Lattice lattice) { this.lattices.Add(lattice); } + protected override bool AtMost(Element/*!*/ first, Element/*!*/ second) { + Contract.Requires(second != null); + Contract.Requires(first != null); + Elt a = (Elt)first; + Elt b = (Elt)second; + + for (int i = 0; i < a.Count; i++) { + Element thisElement = cce.NonNull(a[i]); + Element thatElement = cce.NonNull(b[i]); + if (thisElement.GetType() != thatElement.GetType()) { + throw new System.InvalidOperationException( + "AtMost called on MultiDomain objects with different lattices" + ); + } + if (!SubLattice(i).LowerThan(thisElement, thatElement)) { + return false; + } + } + return true; + } - private Lattice! SubLattice(int i) { return (Lattice!)this.lattices[i]; } + protected override bool AtMost(Element/*!*/ first, ICombineNameMap/*!*/ firstToResult, Element/*!*/ second, ICombineNameMap/*!*/ secondToResult) { + Contract.Requires(secondToResult != null); + Contract.Requires(second != null); + Contract.Requires(firstToResult != null); + Contract.Requires(first != null); + Elt a = (Elt)first; + Elt b = (Elt)second; + + for (int i = 0; i < a.Count; i++) { + Element thisElement = cce.NonNull(a[i]); + Element thatElement = cce.NonNull(b[i]); + if (thisElement.GetType() != thatElement.GetType()) { + throw new System.InvalidOperationException( + "AtMost called on MultiDomain objects with different lattices" + ); + } + if (!SubLattice(i).LowerThan(thisElement, firstToResult, thatElement, secondToResult)) { + return false; + } + } + return true; + } - public override Element! Top { get { return Elt.Top(this.lattices); } } + private enum CombineOp { + Meet, + Join, + Widen + } - public override Element! Bottom { get { return Elt.Bottom(this.lattices); } } + private Element/*!*/ Combine(Element/*!*/ first, ICombineNameMap/*?*/ firstToResult, Element/*!*/ second, ICombineNameMap/*?*/ secondToResult, CombineOp c) { + Contract.Requires(second != null); + Contract.Requires(first != null); + Contract.Ensures(Contract.Result() != null); + Elt a = (Elt)first; + Elt b = (Elt)second; + + int unionCount = System.Math.Max(a.Count, b.Count); + Elt combined = new Elt(unionCount, IsBottom(a) && IsBottom(b)); + for (int i = 0; i < unionCount; i++) { + bool thisExists = a.Contains(i); + bool thatExists = b.Contains(i); + + if (thisExists && thatExists) { + Lattice.Element suba = a[i]; + Lattice.Element subb = b[i]; + Contract.Assert(suba != null && subb != null); + + switch (c) { + case CombineOp.Meet: + combined[i] = SubLattice(i).Meet(suba, subb); + break; + case CombineOp.Join: + if (firstToResult != null && secondToResult != null) + combined[i] = SubLattice(i).Join(suba, firstToResult, subb, secondToResult); + else + combined[i] = SubLattice(i).Join(suba, subb); + break; + case CombineOp.Widen: + if (firstToResult != null && secondToResult != null) + combined[i] = SubLattice(i).Widen(suba, firstToResult, subb, secondToResult); + else + combined[i] = SubLattice(i).Widen(suba, subb); + break; + } + } else if (thisExists) { + combined[i] = a[i]; + } else { + combined[i] = b[i]; + } + } + Debug.Assert(combined.IsValid); + return combined; + } + public override Element/*!*/ NontrivialJoin(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires((b != null)); + Contract.Requires((a != null)); + Contract.Ensures(Contract.Result() != null); + return this.Combine(a, null, b, null, CombineOp.Join); + } + public override Element/*!*/ NontrivialJoin(Element/*!*/ a, ICombineNameMap/*!*/ aToResult, Element/*!*/ b, ICombineNameMap/*!*/ bToResult) { + Contract.Requires((bToResult != null)); + Contract.Requires((b != null)); + Contract.Requires((aToResult != null)); + Contract.Requires((a != null)); + Contract.Ensures(Contract.Result() != null); + return this.Combine(a, aToResult, b, bToResult, CombineOp.Join); + } + public override Element/*!*/ NontrivialMeet(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires((b != null)); + Contract.Requires((a != null)); + Contract.Ensures(Contract.Result() != null); + return this.Combine(a, null, b, null, CombineOp.Meet); + } - public override bool IsBottom(Element! element) - { - Elt e = (Elt)element; - // The program is errorneous/nonterminating if any subdomain knows it is. - // - if (e.elementPerLattice == null) { return true; } - for (int i = 0; i < e.Count; i++) { if (SubLattice(i).IsBottom((!)e[i])) { return true; } } - return false; - } + public override Element/*!*/ Widen(Element/*!*/ a, Element/*!*/ b) { + Contract.Requires((b != null)); + Contract.Requires((a != null)); + Contract.Ensures(Contract.Result() != null); + return this.Combine(a, null, b, null, CombineOp.Widen); + } - public override bool IsTop(Element! element) - { - Elt e = (Elt)element; - if (e.elementPerLattice == null) { return false; } - // The multidomain knows nothing about the program only if no subdomain - // knows anything about it. - // - for (int i = 0; i < e.Count; i++) { if (!SubLattice(i).IsTop((!)e[i])) { return false; } } - return true; - } + public override Element/*!*/ Widen(Element/*!*/ a, ICombineNameMap/*!*/ aToResult, Element/*!*/ b, ICombineNameMap/*!*/ bToResult) { + Contract.Requires((bToResult != null)); + Contract.Requires((b != null)); + Contract.Requires((aToResult != null)); - protected override bool AtMost(Element! first, Element! second) - { - Elt a = (Elt)first; - Elt b = (Elt)second; - - for (int i = 0; i < a.Count; i++) - { - Element thisElement = (!) a[i]; - Element thatElement = (!) b[i]; - if (thisElement.GetType() != thatElement.GetType()) - { - throw new System.InvalidOperationException( - "AtMost called on MultiDomain objects with different lattices" - ); - } - if (!SubLattice(i).LowerThan(thisElement, thatElement)) { return false; } - } - return true; - } - - protected override bool AtMost(Element! first, ICombineNameMap! firstToResult, Element! second, ICombineNameMap! secondToResult) - { - Elt a = (Elt)first; - Elt b = (Elt)second; - - for (int i = 0; i < a.Count; i++) - { - Element thisElement = (!) a[i]; - Element thatElement = (!) b[i]; - if (thisElement.GetType() != thatElement.GetType()) - { - throw new System.InvalidOperationException( - "AtMost called on MultiDomain objects with different lattices" - ); - } - if (!SubLattice(i).LowerThan(thisElement, firstToResult, thatElement, secondToResult)) { return false; } - } - return true; - } + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + return this.Combine(a, aToResult, b, bToResult, CombineOp.Widen); + } + public override Element/*!*/ Eliminate(Element/*!*/ element, IVariable/*!*/ variable) { + Contract.Requires(variable != null); + Contract.Requires(element != null); + Contract.Ensures(Contract.Result() != null); + Elt e = (Elt)element; + if (IsBottom(e)) { + return e; + } + Elt newValue = new Elt(e.Count, false); + for (int i = 0; i < this.lattices.Count; i++) { + newValue[i] = SubLattice(i).Eliminate(cce.NonNull(e[i]), variable); + } + return newValue; + } - private enum CombineOp { Meet, Join, Widen } - - private Element! Combine(Element! first, ICombineNameMap/*?*/ firstToResult, Element! second, ICombineNameMap/*?*/ secondToResult, CombineOp c) - { - Elt a = (Elt)first; - Elt b = (Elt)second; - - int unionCount = System.Math.Max(a.Count, b.Count); - Elt combined = new Elt(unionCount, IsBottom(a) && IsBottom(b)); - for (int i = 0; i < unionCount; i++) - { - bool thisExists = a.Contains(i); - bool thatExists = b.Contains(i); - - if (thisExists && thatExists) - { - Lattice.Element suba = a[i]; - Lattice.Element subb = b[i]; - assert suba != null && subb != null; - - switch (c) - { - case CombineOp.Meet: - combined[i] = SubLattice(i).Meet(suba, subb); - break; - case CombineOp.Join: - if (firstToResult != null && secondToResult != null) - combined[i] = SubLattice(i).Join(suba, firstToResult, subb, secondToResult); - else - combined[i] = SubLattice(i).Join(suba, subb); - break; - case CombineOp.Widen: - if (firstToResult != null && secondToResult != null) - combined[i] = SubLattice(i).Widen(suba, firstToResult, subb, secondToResult); - else - combined[i] = SubLattice(i).Widen(suba, subb); - break; - } - } - else if (thisExists) - { - combined[i] = a[i]; - } - else - { - combined[i] = b[i]; - } - } - Debug.Assert(combined.IsValid); - return combined; - } - public override Element! NontrivialJoin(Element! a, Element! b) { return this.Combine(a, null, b, null, CombineOp.Join); } + public override Element/*!*/ Constrain(Element/*!*/ element, IExpr/*!*/ expr) { + Contract.Requires(expr != null); + Contract.Requires(element != null); + Contract.Ensures(Contract.Result() != null); + Elt e = (Elt)element; + if (IsBottom(e)) { + return e; + } + Elt newValue = new Elt(e.Count, false); + for (int i = 0; i < this.lattices.Count; i++) { + newValue[i] = SubLattice(i).Constrain(cce.NonNull(e[i]), expr); + } + return newValue; + } - public override Element! NontrivialJoin(Element! a, ICombineNameMap! aToResult, Element! b, ICombineNameMap! bToResult) { return this.Combine(a, aToResult, b, bToResult, CombineOp.Join); } - public override Element! NontrivialMeet(Element! a, Element! b) { return this.Combine(a, null, b, null, CombineOp.Meet); } + public override Element/*!*/ Rename(Element/*!*/ element, IVariable/*!*/ oldName, IVariable/*!*/ newName) { + Contract.Requires(newName != null); + Contract.Requires(oldName != null); + Contract.Requires(element != null); + Contract.Ensures(Contract.Result() != null); + Elt e = (Elt)element; + if (IsBottom(e)) { + return e; + } + Elt newValue = new Elt(e.Count, false); + for (int i = 0; i < this.lattices.Count; i++) { + newValue[i] = SubLattice(i).Rename(cce.NonNull(e[i]), oldName, newName); + } + return newValue; + } - public override Element! Widen(Element! a, Element! b) { return this.Combine(a, null, b, null, CombineOp.Widen); } - public override Element! Widen(Element! a, ICombineNameMap! aToResult, Element! b, ICombineNameMap! bToResult) { return this.Combine(a, aToResult, b, bToResult, CombineOp.Widen); } + public override bool Understands(IFunctionSymbol/*!*/ f, IList/*!*/ args) { + Contract.Requires(args != null); + Contract.Requires(f != null); + bool result = false; - public override Element! Eliminate(Element! element, IVariable! variable) - { - Elt e = (Elt)element; - if (IsBottom(e)) - { - return e; - } - Elt newValue = new Elt(e.Count, false); - for (int i = 0; i < this.lattices.Count; i++) - { - newValue[i] = SubLattice(i).Eliminate((!) e[i], variable); - } - return newValue; - } + for (int i = 0; i < this.lattices.Count; i++) { + result = (result || SubLattice(i).Understands(f, args)); + } + return result; + } - public override Element! Constrain(Element! element, IExpr! expr) - { - Elt e = (Elt)element; - if (IsBottom(e)) - { - return e; - } - Elt newValue = new Elt(e.Count, false); - for (int i = 0; i < this.lattices.Count; i++) - { - newValue[i] = SubLattice(i).Constrain((!)e[i], expr); - } - return newValue; - } + public override string/*!*/ ToString(Element/*!*/ element) { + Contract.Requires(element != null); + Contract.Ensures(Contract.Result() != null); + Elt e = (Elt)element; + return e.ToString(); + } - public override Element! Rename(Element! element, IVariable! oldName, IVariable! newName) - { - Elt e = (Elt)element; - if (IsBottom(e)) - { - return e; - } - Elt newValue = new Elt(e.Count, false); - for (int i = 0; i < this.lattices.Count; i++) - { - newValue[i] = SubLattice(i).Rename((!)e[i], oldName, newName); - } - return newValue; - } + public override IExpr/*!*/ ToPredicate(Element/*!*/ element) { + Contract.Requires(element != null); + Contract.Ensures(Contract.Result() != null); + Elt e = (Elt)element; - public override bool Understands(IFunctionSymbol! f, IList! args) - { - bool result = false; + IExpr result = propExprFactory.True; + for (int i = 0; i < e.Count; i++) { + IExpr conjunct = SubLattice(i).ToPredicate(cce.NonNull(e[i])); + Contract.Assert(conjunct != null); - for (int i = 0; i < this.lattices.Count; i++) - { - result = (result || SubLattice(i).Understands(f, args)); - } + result = Prop.SimplifiedAnd(propExprFactory, conjunct, result); + } + return result; + } - return result; - } + /// + /// Return an expression that is equivalent to the given expression that does not + /// contain the given variable according to the lattice element and queryable. + /// + /// Simply asks each sublattice to try to generate an equivalent expression. We + /// do not try to combine information to infer new equivalences here. + /// + /// The lattice element. + /// A queryable for asking addtional information. + /// The expression to find an equivalent expression. + /// The variable to eliminate. + /// + /// An equivalent expression to without + /// or null if not possible. + /// + public override IExpr/*?*/ EquivalentExpr(Element/*!*/ element, IQueryable/*!*/ q, IExpr/*!*/ expr, IVariable/*!*/ var, Set/**//*!*/ prohibitedVars) { + Contract.Requires(prohibitedVars != null); + Contract.Requires(var != null); + Contract.Requires(expr != null); + Contract.Requires(q != null); + Contract.Requires(element != null); + Elt/*!*/ e = (Elt/*!*/)cce.NonNull(element); + + for (int i = 0; i < e.Count; i++) { + IExpr equivexpr = SubLattice(i).EquivalentExpr(cce.NonNull(e[i]), q, expr, var, prohibitedVars); + + if (equivexpr != null) + return equivexpr; + } + + return null; + } - public override string! ToString(Element! element) - { - Elt e = (Elt)element; - return e.ToString(); - } + public override Answer CheckPredicate(Element/*!*/ element, IExpr/*!*/ pred) { + Contract.Requires(pred != null); + Contract.Requires(element != null); + Elt/*!*/ e = (Elt/*!*/)cce.NonNull(element); + for (int i = 0; i < e.Count; i++) { + Answer ans = SubLattice(i).CheckPredicate(cce.NonNull(e[i]), pred); - public override IExpr! ToPredicate(Element! element) - { - Elt e = (Elt)element; - - IExpr result = propExprFactory.True; - for (int i = 0; i < e.Count; i++) - { - IExpr conjunct = SubLattice(i).ToPredicate((!)e[i]); - assert conjunct != null; + if (ans == Answer.Yes || ans == Answer.No) + return ans; + } - result = Prop.SimplifiedAnd(propExprFactory, conjunct, result); - } - return result; - } - - /// - /// Return an expression that is equivalent to the given expression that does not - /// contain the given variable according to the lattice element and queryable. - /// - /// Simply asks each sublattice to try to generate an equivalent expression. We - /// do not try to combine information to infer new equivalences here. - /// - /// The lattice element. - /// A queryable for asking addtional information. - /// The expression to find an equivalent expression. - /// The variable to eliminate. - /// - /// An equivalent expression to without - /// or null if not possible. - /// - public override IExpr/*?*/ EquivalentExpr(Element! element, IQueryable! q, IExpr! expr, IVariable! var, Set/**/! prohibitedVars) - { - Elt! e = (Elt!)element; - - for (int i = 0; i < e.Count; i++) - { - IExpr equivexpr = SubLattice(i).EquivalentExpr((!)e[i], q, expr, var, prohibitedVars); - - if (equivexpr != null) - return equivexpr; - } + return Answer.Maybe; + } - return null; - } + public override Answer CheckVariableDisequality(Element/*!*/ element, IVariable/*!*/ var1, IVariable/*!*/ var2) { + Contract.Requires(var2 != null); + Contract.Requires(var1 != null); + Contract.Requires(element != null); + Elt/*!*/ e = (Elt/*!*/)cce.NonNull(element); - public override Answer CheckPredicate(Element! element, IExpr! pred) - { - Elt! e = (Elt!)element; + for (int i = 0; i < e.Count; i++) { + Answer ans = SubLattice(i).CheckVariableDisequality(cce.NonNull(e[i]), var1, var2); - for (int i = 0; i < e.Count; i++) - { - Answer ans = SubLattice(i).CheckPredicate((!)e[i], pred); + if (ans == Answer.Yes || ans == Answer.No) + return ans; + } - if (ans == Answer.Yes || ans == Answer.No) - return ans; - } + return Answer.Maybe; + } - return Answer.Maybe; - } - public override Answer CheckVariableDisequality(Element! element, IVariable! var1, IVariable! var2) - { - Elt! e = (Elt!)element; + public override void Validate() { + base.Validate(); + foreach (Lattice/*!*/ l in lattices) { + Contract.Assert(l != null); + l.Validate(); + } + } - for (int i = 0; i < e.Count; i++) - { - Answer ans = SubLattice(i).CheckVariableDisequality((!)e[i], var1, var2); + /// + /// The enumeration over a MultiLattice is its sublattices. + /// + /// An enumerator over the sublattices. + [Pure] + [GlobalAccess(false)] + [Escapes(true, false)] + public IEnumerator/**//*!*/ GetEnumerator() { + Contract.Ensures(Contract.Result() != null); + return lattices.GetEnumerator(); + } - if (ans == Answer.Yes || ans == Answer.No) - return ans; - } + /// + /// Return an enumerable over a mapping of sublattices to the their corresponding + /// lattice elements given a MultiLattice element. + /// + /// The MultiLattice element. + /// + /// An enumerable that yields an IDictionaryEnumerator over the + /// (Lattice, Lattice.Element) pairs. + /// + public IEnumerable/*!*/ Subelements(Element/*!*/ element) { + Contract.Requires(element != null); + Contract.Ensures(Contract.Result() != null); + return new SubelementsEnumerable(this, (Elt/*!*/)cce.NonNull(element)); + } - return Answer.Maybe; + /// + /// An enumerator over the sublattices and elements. + /// + private sealed class SubelementsEnumerable : IEnumerable { + private sealed class SubelementsEnumerator : IDictionaryEnumerator { + private readonly IEnumerator/**//*!*/ multiLatticeIter; + private readonly IEnumerator/**//*!*/ multiElementIter; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(multiElementIter != null); + Contract.Invariant(multiLatticeIter != null); } + public SubelementsEnumerator(MultiLattice/*!*/ multiLattice, Elt/*!*/ multiElement) { + Contract.Requires(multiElement != null); + Contract.Requires(multiLattice != null); + Contract.Requires(multiElement.elementPerLattice != null); + this.multiLatticeIter = multiLattice.lattices.GetEnumerator(); + this.multiElementIter = multiElement.elementPerLattice.GetEnumerator(); + // base(); + } - public override void Validate() - { - base.Validate(); - foreach (Lattice! l in lattices) - { - l.Validate(); - } + public DictionaryEntry Entry { + get { + return new DictionaryEntry(cce.NonNull(multiLatticeIter.Current), multiElementIter.Current); + } } - /// - /// The enumeration over a MultiLattice is its sublattices. - /// - /// An enumerator over the sublattices. - [Pure] [GlobalAccess(false)] [Escapes(true,false)] - public IEnumerator/**/! GetEnumerator() - { - return lattices.GetEnumerator(); + public object Key { + get { + return multiLatticeIter.Current; + } } - /// - /// Return an enumerable over a mapping of sublattices to the their corresponding - /// lattice elements given a MultiLattice element. - /// - /// The MultiLattice element. - /// - /// An enumerable that yields an IDictionaryEnumerator over the - /// (Lattice, Lattice.Element) pairs. - /// - public IEnumerable! Subelements(Element! element) - { - return new SubelementsEnumerable(this, (Elt!) element); + public object Value { + get { + return multiElementIter.Current; + } } - /// - /// An enumerator over the sublattices and elements. - /// - private sealed class SubelementsEnumerable : IEnumerable - { - private sealed class SubelementsEnumerator : IDictionaryEnumerator - { - private readonly IEnumerator/**/! multiLatticeIter; - private readonly IEnumerator/**/! multiElementIter; - - public SubelementsEnumerator(MultiLattice! multiLattice, Elt! multiElement) - requires multiElement.elementPerLattice != null; - { - this.multiLatticeIter = multiLattice.lattices.GetEnumerator(); - this.multiElementIter = multiElement.elementPerLattice.GetEnumerator(); - // base(); - } - - public DictionaryEntry Entry - { - get - { - return new DictionaryEntry((!)multiLatticeIter.Current, multiElementIter.Current); - } - } - - public object Key - { - get - { - return multiLatticeIter.Current; - } - } - - public object Value - { - get - { - return multiElementIter.Current; - } - } - - public object Current - { - get - { - return this.Entry; - } - } - - public bool MoveNext() - { - return multiLatticeIter.MoveNext() && multiElementIter.MoveNext(); - } - - public void Reset() - { - multiLatticeIter.Reset(); - multiElementIter.Reset(); - } - } + public object Current { + get { + return this.Entry; + } + } - private MultiLattice! multiLattice; - private Elt! multiElement; - - public SubelementsEnumerable(MultiLattice! multiLattice, Elt! multiElement) - { - this.multiLattice = multiLattice; - this.multiElement = multiElement; - // base(); - } + public bool MoveNext() { + return multiLatticeIter.MoveNext() && multiElementIter.MoveNext(); + } - [Pure] [GlobalAccess(false)] [Escapes(true,false)] - public IEnumerator! GetEnumerator() - { - return new SubelementsEnumerator(multiLattice, multiElement); - } + public void Reset() { + multiLatticeIter.Reset(); + multiElementIter.Reset(); } + } + + private MultiLattice/*!*/ multiLattice; + private Elt/*!*/ multiElement; + + public SubelementsEnumerable(MultiLattice/*!*/ multiLattice, Elt/*!*/ multiElement) { + Contract.Requires(multiElement != null); + Contract.Requires(multiLattice != null); + this.multiLattice = multiLattice; + this.multiElement = multiElement; + // base(); + } + + [Pure] + [GlobalAccess(false)] + [Escapes(true, false)] + public IEnumerator/*!*/ GetEnumerator() { + Contract.Ensures(Contract.Result() != null); + return new SubelementsEnumerator(multiLattice, multiElement); + } + } - } + } } diff --git a/Source/AIFramework/Mutable.cs b/Source/AIFramework/Mutable.cs index 6b5e0a20..f24b65c6 100644 --- a/Source/AIFramework/Mutable.cs +++ b/Source/AIFramework/Mutable.cs @@ -3,10 +3,11 @@ // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- +using System.Diagnostics.Contracts; namespace Microsoft.AbstractInterpretationFramework.Collections { using System.Collections; - using Microsoft.Contracts; + using System.Diagnostics.Contracts; /// /// Extend sets for using as a IWorkList. @@ -33,7 +34,7 @@ namespace Microsoft.AbstractInterpretationFramework.Collections IEnumerator iter = GetEnumerator(); iter.MoveNext(); - object result = (!)iter.Current; + object result = cce.NonNull(iter.Current); Remove(result); return result; @@ -50,7 +51,8 @@ namespace Microsoft.AbstractInterpretationFramework.Collections } // ICollection members - public void CopyTo (System.Array! a, int i) { + public void CopyTo (System.Array/*!*/ a, int i){ +Contract.Requires(a != null); if (this.Count > a.Length - i) throw new System.ArgumentException(); int j = i; foreach(object o in this){ @@ -58,7 +60,8 @@ namespace Microsoft.AbstractInterpretationFramework.Collections } return; } - object! ICollection.SyncRoot { [Pure] get { return this; } } + object/*!*/ ICollection.SyncRoot { [Pure] get {Contract.Ensures(Contract.Result() != null); + return this; } } public bool IsSynchronized { get { return false; } } } @@ -70,9 +73,14 @@ namespace Microsoft.AbstractInterpretationFramework.Collections.Generic public class HashMultiset { - private readonly IDictionary! dict; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(dict != null); + } + + private readonly IDictionary/*!*/ dict; - //invariant forall{KeyValuePair entry in dict; entry.Value >= 1}; + //Contract.Invariant(Contract.ForAll(dict , entry => entry.Value >= 1)); public HashMultiset() { @@ -86,8 +94,9 @@ namespace Microsoft.AbstractInterpretationFramework.Collections.Generic // base(); } - public void Add(T t) - { expose (this) { + public void Add(T t) { + cce.BeginExpose(this); + { if (dict.ContainsKey(t)) { dict[t] = dict[t] + 1; @@ -96,16 +105,20 @@ namespace Microsoft.AbstractInterpretationFramework.Collections.Generic { dict.Add(t,1); } - }} + } + cce.EndExpose(); + } public void Remove(T t) { if (dict.ContainsKey(t)) - { expose (this) { + { cce.BeginExpose(this); { int count = dict[t]; if (count == 1) { dict.Remove(t); } else { dict[t] = count - 1; } - }} + } + cce.EndExpose(); + } } public bool Contains(T t) diff --git a/Source/AIFramework/Polyhedra/LinearConstraint.cs b/Source/AIFramework/Polyhedra/LinearConstraint.cs index 087c3696..ce5c23a2 100644 --- a/Source/AIFramework/Polyhedra/LinearConstraint.cs +++ b/Source/AIFramework/Polyhedra/LinearConstraint.cs @@ -3,59 +3,55 @@ // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- -using Microsoft.Contracts; -namespace Microsoft.AbstractInterpretationFramework -{ - using System; - using System.Compiler; - using System.Collections; - using Microsoft.Basetypes; - using IMutableSet = Microsoft.Boogie.Set; - using HashSet = Microsoft.Boogie.Set; - using ISet = Microsoft.Boogie.Set; - - - /// - /// Represents a single linear constraint, coefficients are stored as Rationals. - /// - public class LinearConstraint - { - - public enum ConstraintRelation - { - EQ, // equal - LE, // less-than or equal - } +using System.Diagnostics.Contracts; +namespace Microsoft.AbstractInterpretationFramework { + using System; + //using System.Compiler; + using System.Collections; + using Microsoft.Basetypes; + using IMutableSet = Microsoft.Boogie.Set; + using HashSet = Microsoft.Boogie.Set; + using ISet = Microsoft.Boogie.Set; + + + /// + /// Represents a single linear constraint, coefficients are stored as Rationals. + /// + public class LinearConstraint { + + public enum ConstraintRelation { + EQ, // equal + LE, // less-than or equal + } + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(coefficients != null); + } - public readonly ConstraintRelation Relation; - internal Hashtable /*IVariable->Rational*/! coefficients = new Hashtable /*IVariable->Rational*/ (); - internal Rational rhs; + public readonly ConstraintRelation Relation; + internal Hashtable /*IVariable->Rational*//*!*/ coefficients = new Hashtable /*IVariable->Rational*/ (); + internal Rational rhs; - public LinearConstraint (ConstraintRelation rel) - { - Relation = rel; - } + public LinearConstraint(ConstraintRelation rel) { + Relation = rel; + } - [Pure] - public override string! ToString() - { - string s = null; - foreach (DictionaryEntry /*IVariable->Rational*/ entry in coefficients) - { - if (s == null) - { - s = ""; - } - else - { - s += " + "; - } - s += String.Format("{0}*{1}", entry.Value, entry.Key); - } - System.Diagnostics.Debug.Assert(s != null, "malformed LinearConstraint: no variables"); - s += String.Format(" {0} {1}", Relation == ConstraintRelation.EQ ? "==" : "<=", rhs); - return s; + [Pure] + public override string/*!*/ ToString() { + Contract.Ensures(Contract.Result() != null); + string s = null; + foreach (DictionaryEntry /*IVariable->Rational*/ entry in coefficients) { + if (s == null) { + s = ""; + } else { + s += " + "; } + s += String.Format("{0}*{1}", entry.Value, entry.Key); + } + System.Diagnostics.Debug.Assert(s != null, "malformed LinearConstraint: no variables"); + s += String.Format(" {0} {1}", Relation == ConstraintRelation.EQ ? "==" : "<=", rhs); + return s; + } #if DONT_KNOW_HOW_TO_TAKE_THE_TYPE_OF_AN_IVARIABLE_YET @@ -79,51 +75,42 @@ namespace Microsoft.AbstractInterpretationFramework /// not required elsewhere in this class. /// /// - public IExpr! ConvertToExpression(ILinearExprFactory! factory) - { + public IExpr/*!*/ ConvertToExpression(ILinearExprFactory/*!*/ factory) { + Contract.Requires(factory != null); + Contract.Ensures(Contract.Result() != null); IExpr leftSum = null; IExpr rightSum = null; - foreach (DictionaryEntry /*object->Rational*/ entry in coefficients) - { + foreach (DictionaryEntry /*object->Rational*/ entry in coefficients) { IVariable var = (IVariable)entry.Key; - Rational coeff = (Rational) ((!)entry.Value); - if (coeff.IsPositive) - { + Rational coeff = (Rational)(cce.NonNull(entry.Value)); + if (coeff.IsPositive) { leftSum = AddTerm(factory, leftSum, coeff, var); - } - else if (coeff.IsNegative) - { + } else if (coeff.IsNegative) { rightSum = AddTerm(factory, rightSum, -coeff, var); - } - else - { + } else { // ignore the term is coeff==0 } } - if (leftSum == null && rightSum == null) - { + if (leftSum == null && rightSum == null) { // there are no variables in this constraint if (Relation == ConstraintRelation.EQ ? rhs.IsZero : rhs.IsNonNegative) { - return factory.True; + return factory.True; } else { - return factory.False; + return factory.False; } } - if (leftSum == null || (rightSum != null && rhs.IsNegative)) - { + if (leftSum == null || (rightSum != null && rhs.IsNegative)) { // show the constant on the left side leftSum = AddTerm(factory, leftSum, -rhs, null); - } - else if (rightSum == null || rhs.IsPositive) - { + } else if (rightSum == null || rhs.IsPositive) { // show the constant on the right side rightSum = AddTerm(factory, rightSum, rhs, null); } - assert leftSum != null; - assert rightSum != null; + Contract.Assert(leftSum != null); + Contract.Assert(rightSum != null); return Relation == ConstraintRelation.EQ ? factory.Eq(leftSum, rightSum) : factory.AtMost(leftSum, rightSum); } @@ -137,198 +124,189 @@ namespace Microsoft.AbstractInterpretationFramework /// /// /// - static IExpr! AddTerm(ILinearExprFactory! factory, /*MayBeNull*/ IExpr sum, Rational r, /*MayBeNull*/ IVariable x) - { - IExpr! product = factory.Term(r, x); + static IExpr/*!*/ AddTerm(ILinearExprFactory/*!*/ factory, /*MayBeNull*/ IExpr sum, Rational r, /*MayBeNull*/ IVariable x) { + Contract.Requires(factory != null); + Contract.Ensures(Contract.Result() != null); + IExpr/*!*/ product = factory.Term(r, x); + Contract.Assert(product != null); if (sum == null) { return product; } else { return factory.Add(sum, product); } } + public System.Collections.Generic.IEnumerable GetDefinedDimensionsGeneric() { + Contract.Ensures(Contract.Result>() != null); + foreach (IVariable/*!*/ dim in coefficients.Keys) { + Contract.Assert(dim != null); + yield return dim; + } + } + public ISet /*IVariable!*//*!*/ GetDefinedDimensions() { + Contract.Ensures(Contract.Result() != null); + HashSet /*IVariable!*/ dims = new HashSet /*IVariable!*/ (coefficients.Count); + int j = 0; + foreach (IVariable/*!*/ dim in coefficients.Keys) { + Contract.Assert(dim != null); + dims.Add(dim); + j++; + } + System.Diagnostics.Debug.Assert(j == coefficients.Count); + return dims; + } - public ISet /*IVariable!*/! GetDefinedDimensions() - { - HashSet /*IVariable!*/ dims = new HashSet /*IVariable!*/ (coefficients.Count); - int j = 0; - foreach (IVariable! dim in coefficients.Keys) - { - dims.Add(dim); - j++; - } - System.Diagnostics.Debug.Assert(j == coefficients.Count); - return dims; - } - - /// - /// Returns true iff all of the coefficients in the constraint are 0. In that - /// case, the constraint has the form 0 <= C for some constant C; hence, the - /// constraint is either unsatisfiable or trivially satisfiable. - /// - /// - public bool IsConstant() - { - foreach (Rational coeff in coefficients.Values) - { - if (coeff.IsNonZero) - { - return false; - } - } - return true; + /// + /// Returns true iff all of the coefficients in the constraint are 0. In that + /// case, the constraint has the form 0 <= C for some constant C; hence, the + /// constraint is either unsatisfiable or trivially satisfiable. + /// + /// + public bool IsConstant() { + foreach (Rational coeff in coefficients.Values) { + if (coeff.IsNonZero) { + return false; } + } + return true; + } /// /// For an equality constraint, returns 0 == rhs. /// For an inequality constraint, returns 0 <= rhs. /// - public bool IsConstantSatisfiable() - { - if (Relation == ConstraintRelation.EQ) - { + public bool IsConstantSatisfiable() { + if (Relation == ConstraintRelation.EQ) { return rhs.IsZero; - } - else - { + } else { return rhs.IsNonNegative; } } - /// - /// Returns 0 if "this" and "c" are not equivalent constraints. If "this" and "c" - /// are equivalent constraints, the non-0 return value "m" satisfies "this == m*c". - /// - /// - /// - public Rational IsEquivalent(LinearConstraint! c) - { - // "m" is the scale factor. If it is 0, it hasn't been used yet. If it - // is non-0, it will remain that value throughout, and it then says that - // for every dimension "d", "this[d] == m * c[d]". - Rational m = Rational.ZERO; - - ArrayList /*IVariable*/ dd = new ArrayList /*IVariable*/ (); - foreach (IVariable! d in this.GetDefinedDimensions()) - { - if (!dd.Contains(d)) { dd.Add(d); } - } - foreach (IVariable! d in c.GetDefinedDimensions()) - { - if (!dd.Contains(d)) { dd.Add(d); } - } - - foreach (IVariable! d in dd) - { - Rational a = this[d]; - Rational b = c[d]; - - if (a.IsZero || b.IsZero) - { - if (a.IsNonZero || b.IsNonZero) - { - return Rational.ZERO; // not equivalent - } - } - else if (m.IsZero) - { - m = a / b; - } - else if (a != m * b) - { - return Rational.ZERO; // not equivalent - } - } - - // we expect there to have been some non-zero coefficient, so "m" should have been used by now - System.Diagnostics.Debug.Assert(m.IsNonZero); + /// + /// Returns 0 if "this" and "c" are not equivalent constraints. If "this" and "c" + /// are equivalent constraints, the non-0 return value "m" satisfies "this == m*c". + /// + /// + /// + public Rational IsEquivalent(LinearConstraint/*!*/ c) { + Contract.Requires(c != null); + // "m" is the scale factor. If it is 0, it hasn't been used yet. If it + // is non-0, it will remain that value throughout, and it then says that + // for every dimension "d", "this[d] == m * c[d]". + Rational m = Rational.ZERO; + + ArrayList /*IVariable*/ dd = new ArrayList /*IVariable*/ (); + foreach (IVariable/*!*/ d in this.GetDefinedDimensions()) { + Contract.Assert(d != null); + if (!dd.Contains(d)) { + dd.Add(d); + } + } + foreach (IVariable/*!*/ d in c.GetDefinedDimensions()) { + Contract.Assert(d != null); + if (!dd.Contains(d)) { + dd.Add(d); + } + } - // finally, check the rhs - if (this.rhs == m * c.rhs) - { - return m; // equivalent - } - else - { - return Rational.ZERO; // not equivalent - } + foreach (IVariable/*!*/ d in dd) { + Contract.Assert(d != null); + Rational a = this[d]; + Rational b = c[d]; + + if (a.IsZero || b.IsZero) { + if (a.IsNonZero || b.IsNonZero) { + return Rational.ZERO; // not equivalent + } + } else if (m.IsZero) { + m = a / b; + } else if (a != m * b) { + return Rational.ZERO; // not equivalent } + } - /// - /// Splits an equality constraint into two inequality constraints, the conjunction of - /// which equals the equality constraint. Assumes "this" is a equality constraint. - /// - /// - /// - public void GenerateInequalityConstraints(out LinearConstraint a, out LinearConstraint b) - { - System.Diagnostics.Debug.Assert(this.Relation == ConstraintRelation.EQ); + // we expect there to have been some non-zero coefficient, so "m" should have been used by now + System.Diagnostics.Debug.Assert(m.IsNonZero); - a = new LinearConstraint(ConstraintRelation.LE); - a.coefficients = (Hashtable)this.coefficients.Clone(); - a.rhs = this.rhs; + // finally, check the rhs + if (this.rhs == m * c.rhs) { + return m; // equivalent + } else { + return Rational.ZERO; // not equivalent + } + } - b = new LinearConstraint(ConstraintRelation.LE); - b.coefficients = new Hashtable /*IVariable->Rational*/ (); - foreach (DictionaryEntry entry in this.coefficients) - { - b.coefficients[entry.Key] = -(Rational) ((!)entry.Value); - } - b.rhs = -this.rhs; - } + /// + /// Splits an equality constraint into two inequality constraints, the conjunction of + /// which equals the equality constraint. Assumes "this" is a equality constraint. + /// + /// + /// + public void GenerateInequalityConstraints(out LinearConstraint a, out LinearConstraint b) { + System.Diagnostics.Debug.Assert(this.Relation == ConstraintRelation.EQ); + + a = new LinearConstraint(ConstraintRelation.LE); + a.coefficients = (Hashtable)this.coefficients.Clone(); + a.rhs = this.rhs; + + b = new LinearConstraint(ConstraintRelation.LE); + b.coefficients = new Hashtable /*IVariable->Rational*/ (); + foreach (DictionaryEntry entry in this.coefficients) { + b.coefficients[entry.Key] = -(Rational)(cce.NonNull(entry.Value)); + } + b.rhs = -this.rhs; + } - public void SetCoefficient(IVariable! dimension, Rational coefficient) - { - coefficients[dimension] = coefficient; - } + public void SetCoefficient(IVariable/*!*/ dimension, Rational coefficient) { + Contract.Requires(dimension != null); + coefficients[dimension] = coefficient; + } - /// - /// Removes dimension "dim" from the constraint. Only dimensions with coefficient 0 can - /// be removed. - /// - /// - public void RemoveDimension(IVariable! dim) - { - object val = coefficients[dim]; - if (val != null) - { + /// + /// Removes dimension "dim" from the constraint. Only dimensions with coefficient 0 can + /// be removed. + /// + /// + public void RemoveDimension(IVariable/*!*/ dim) { + Contract.Requires(dim != null); + object val = coefficients[dim]; + if (val != null) { #if FIXED_SERIALIZER - assert ((Rational)val).IsZero; -#endif - coefficients.Remove(dim); - } - } + Contract.Assert(((Rational)val).IsZero); +#endif + coefficients.Remove(dim); + } + } - /// - /// The getter returns 0 if the dimension is not present. - /// - public Rational this [IVariable! dimension] - { - get - { - object z = coefficients[dimension]; - if (z == null) - { - return Rational.ZERO; - } - else - { - return (Rational)z; - } - } - set { SetCoefficient(dimension, value); } + /// + /// The getter returns 0 if the dimension is not present. + /// + public Rational this[IVariable/*!*/ dimension] { + get { + Contract.Requires(dimension != null); + + + object z = coefficients[dimension]; + if (z == null) { + return Rational.ZERO; + } else { + return (Rational)z; } + } + set { + SetCoefficient(dimension, value); + } + } - public LinearConstraint Rename(IVariable! oldName, IVariable! newName) - { + public LinearConstraint Rename(IVariable/*!*/ oldName, IVariable/*!*/ newName) { + Contract.Requires(newName != null); + Contract.Requires(oldName != null); object /*Rational*/ z = coefficients[oldName]; - if (z == null) - { + if (z == null) { return this; - } - else - { + } else { System.Diagnostics.Debug.Assert(z is Rational); - Hashtable /*IVariable->Rational*/ newCoeffs = (Hashtable! /*IVariable->Rational*/)coefficients.Clone(); + Hashtable /*IVariable->Rational*/ newCoeffs = (Hashtable/*!*/ /*IVariable->Rational*/)cce.NonNull(coefficients.Clone()); newCoeffs.Remove(oldName); newCoeffs.Add(newName, z); @@ -339,26 +317,22 @@ namespace Microsoft.AbstractInterpretationFramework } } - public LinearConstraint Clone() - { - LinearConstraint z = new LinearConstraint(Relation); - z.coefficients = (Hashtable /*IVariable->Rational*/)this.coefficients.Clone(); - z.rhs = this.rhs; - return z; - } + public LinearConstraint Clone() { + LinearConstraint z = new LinearConstraint(Relation); + z.coefficients = (Hashtable /*IVariable->Rational*/)this.coefficients.Clone(); + z.rhs = this.rhs; + return z; + } /// /// Returns a constraint like "this", but with the given relation "r". /// /// - public LinearConstraint! ChangeRelation(ConstraintRelation rel) - { - if (Relation == rel) - { + public LinearConstraint/*!*/ ChangeRelation(ConstraintRelation rel) { + Contract.Ensures(Contract.Result() != null); + if (Relation == rel) { return this; - } - else - { + } else { LinearConstraint z = new LinearConstraint(rel); z.coefficients = (Hashtable)this.coefficients.Clone(); z.rhs = this.rhs; @@ -370,38 +344,36 @@ namespace Microsoft.AbstractInterpretationFramework /// Returns a constraint like "this", but, conceptually, with the inequality relation >=. /// /// - public LinearConstraint! ChangeRelationToAtLeast() - { + public LinearConstraint/*!*/ ChangeRelationToAtLeast() { + Contract.Ensures(Contract.Result() != null); LinearConstraint z = new LinearConstraint(ConstraintRelation.LE); - foreach (DictionaryEntry /*IVariable->Rational*/ entry in this.coefficients) - { - z.coefficients.Add(entry.Key, -(Rational) ((!)entry.Value)); + foreach (DictionaryEntry /*IVariable->Rational*/ entry in this.coefficients) { + z.coefficients.Add(entry.Key, -(Rational)(cce.NonNull(entry.Value))); } z.rhs = -this.rhs; return z; } /// - /// Returns the left-hand side of the constraint evaluated at the point "v". - /// Any coordinate not present in "v" is treated as if it were 0. - /// Stated differently, this routine treats the left-hand side of the constraint - /// as a row vector and "v" as a column vector, and then returns the dot-product - /// of the two. - /// - /// - /// - public Rational EvaluateLhs(FrameElement! v) - { - Rational q = Rational.ZERO; - foreach (DictionaryEntry /*IVariable,Rational*/ term in coefficients) - { - IVariable dim = (IVariable!)term.Key; - Rational a = (Rational) ((!)term.Value); - Rational x = v[dim]; - q += a * x; - } - return q; - } + /// Returns the left-hand side of the constraint evaluated at the point "v". + /// Any coordinate not present in "v" is treated as if it were 0. + /// Stated differently, this routine treats the left-hand side of the constraint + /// as a row vector and "v" as a column vector, and then returns the dot-product + /// of the two. + /// + /// + /// + public Rational EvaluateLhs(FrameElement/*!*/ v) { + Contract.Requires(v != null); + Rational q = Rational.ZERO; + foreach (DictionaryEntry /*IVariable,Rational*/ term in coefficients) { + IVariable dim = (IVariable/*!*/)cce.NonNull(term.Key); + Rational a = (Rational)(cce.NonNull(term.Value)); + Rational x = v[dim]; + q += a * x; + } + return q; + } /// /// Determines whether or not a given vertex or ray saturates the constraint. @@ -409,166 +381,151 @@ namespace Microsoft.AbstractInterpretationFramework /// /// true if "fe" is a vertex; false if "fe" is a ray /// - public bool IsSaturatedBy(FrameElement! fe, bool vertex) - { + public bool IsSaturatedBy(FrameElement/*!*/ fe, bool vertex) { + Contract.Requires(fe != null); Rational lhs = EvaluateLhs(fe); Rational rhs = vertex ? this.rhs : Rational.ZERO; return lhs == rhs; } - /// - /// Changes the current constraint A*X <= B into (A + m*aa)*X <= B + m*bb, - /// where "cc" is the constraint aa*X <= bb. - /// - /// - /// - /// - public void AddMultiple(Rational m, LinearConstraint! cc) - { - foreach (DictionaryEntry /*IVariable->Rational*/ entry in cc.coefficients) - { - IVariable dim = (IVariable)entry.Key; - Rational d = m * (Rational) ((!)entry.Value); - if (d.IsNonZero) - { - object prev = coefficients[dim]; - if (prev == null) - { - coefficients[dim] = d; - } - else - { - coefficients[dim] = (Rational)prev + d; - } - } - } - rhs += m * cc.rhs; - } - - /// - /// Try to reduce the magnitude of the coefficients used. - /// Has a side effect on the coefficients, but leaves the meaning of the linear constraint - /// unchanged. - /// - public void Normalize() { - // compute the gcd of the numerators and the gcd of the denominators - Rational gcd = rhs; - foreach (Rational r in coefficients.Values) { - gcd = Rational.Gcd(gcd, r); - } - // Change all coefficients, to divide their numerators with gcdNum and to - // divide their denominators with gcdDen. - Hashtable /*IVariable->Rational*/ newCoefficients = new Hashtable /*IVariable->Rational*/ (coefficients.Count); - foreach (DictionaryEntry /*IVarianble->Rational*/ e in coefficients) { - Rational r = (Rational) ((!)e.Value); - if (r.IsNonZero) { - newCoefficients.Add(e.Key, new Rational(r.Numerator / gcd.Numerator, r.Denominator / gcd.Denominator)); - } else { - newCoefficients.Add(e.Key, r); - } - } - - coefficients = newCoefficients; - rhs = rhs.IsNonZero ? (Rational)new Rational(rhs.Numerator / gcd.Numerator, rhs.Denominator / gcd.Denominator) : rhs; + /// + /// Changes the current constraint A*X <= B into (A + m*aa)*X <= B + m*bb, + /// where "cc" is the constraint aa*X <= bb. + /// + /// + /// + /// + public void AddMultiple(Rational m, LinearConstraint/*!*/ cc) { + Contract.Requires(cc != null); + foreach (DictionaryEntry /*IVariable->Rational*/ entry in cc.coefficients) { + IVariable dim = (IVariable)entry.Key; + Rational d = m * (Rational)(cce.NonNull(entry.Value)); + if (d.IsNonZero) { + object prev = coefficients[dim]; + if (prev == null) { + coefficients[dim] = d; + } else { + coefficients[dim] = (Rational)prev + d; + } } + } + rhs += m * cc.rhs; } /// - /// Represents a frame element (vector of dimension/value tuples). Used only - /// internally in class LinearConstraintSystem and its communication with class - /// LinearConstraint. + /// Try to reduce the magnitude of the coefficients used. + /// Has a side effect on the coefficients, but leaves the meaning of the linear constraint + /// unchanged. /// - public class FrameElement - { + public void Normalize() { + // compute the gcd of the numerators and the gcd of the denominators + Rational gcd = rhs; + foreach (Rational r in coefficients.Values) { + gcd = Rational.Gcd(gcd, r); + } + // Change all coefficients, to divide their numerators with gcdNum and to + // divide their denominators with gcdDen. + Hashtable /*IVariable->Rational*/ newCoefficients = new Hashtable /*IVariable->Rational*/ (coefficients.Count); + foreach (DictionaryEntry /*IVarianble->Rational*/ e in coefficients) { + Rational r = (Rational)(cce.NonNull(e.Value)); + if (r.IsNonZero) { + newCoefficients.Add(e.Key, new Rational(r.Numerator / gcd.Numerator, r.Denominator / gcd.Denominator)); + } else { + newCoefficients.Add(e.Key, r); + } + } - Hashtable /*IVariable->Rational*/! terms = new Hashtable /*IVariable->Rational*/ (); + coefficients = newCoefficients; + rhs = rhs.IsNonZero ? (Rational)new Rational(rhs.Numerator / gcd.Numerator, rhs.Denominator / gcd.Denominator) : rhs; + } + } + + /// + /// Represents a frame element (vector of dimension/value tuples). Used only + /// internally in class LinearConstraintSystem and its communication with class + /// LinearConstraint. + /// + public class FrameElement { + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(terms != null); + } - /// - /// Constructs an empty FrameElement. To add dimensions, call AddCoordinate after construction. - /// - public FrameElement() - { - } + Hashtable /*IVariable->Rational*//*!*/ terms = new Hashtable /*IVariable->Rational*/ (); - /// - /// This method is to be thought of as being part of the FrameElement object's construction process. - /// Assumes "dimension" is not already in FrameElement. - /// - /// - /// - public void AddCoordinate(IVariable! dimension, Rational value) - { - terms.Add(dimension, value); - } + /// + /// Constructs an empty FrameElement. To add dimensions, call AddCoordinate after construction. + /// + public FrameElement() { + } - [Pure] - public override string! ToString() - { - string s = null; - foreach (DictionaryEntry item in terms) - { - if (s == null) - { - s = "("; - } - else - { - s += ", "; - } - s += String.Format("<{0},{1}>", item.Key, (Rational) ((!)item.Value)); - } - if (s == null) - { - s = "("; - } - return s + ")"; - } + /// + /// This method is to be thought of as being part of the FrameElement object's construction process. + /// Assumes "dimension" is not already in FrameElement. + /// + /// + /// + public void AddCoordinate(IVariable/*!*/ dimension, Rational value) { + Contract.Requires(dimension != null); + terms.Add(dimension, value); + } - public IMutableSet /*IVariable!*/! GetDefinedDimensions() - { - HashSet /*IVariable!*/! dims = new HashSet /*IVariable!*/ (terms.Count); - foreach (IVariable! dim in terms.Keys) - { - dims.Add(dim); - } - System.Diagnostics.Debug.Assert(dims.Count == terms.Count); - return dims; + [Pure] + public override string/*!*/ ToString() { + Contract.Ensures(Contract.Result() != null); + string s = null; + foreach (DictionaryEntry item in terms) { + if (s == null) { + s = "("; + } else { + s += ", "; } + s += String.Format("<{0},{1}>", item.Key, (Rational)(cce.NonNull(item.Value))); + } + if (s == null) { + s = "("; + } + return s + ")"; + } - /// - /// The getter returns the value at the given dimension, or 0 if that dimension is not defined. - /// - public Rational this [IVariable! dimension] - { - get - { - object z = terms[dimension]; - if (z == null) - { - return Rational.ZERO; - } - else - { - return (Rational)z; - } - } - set - { - terms[dimension] = value; - } + public IMutableSet /*IVariable!*//*!*/ GetDefinedDimensions() { + Contract.Ensures(Contract.Result() != null); + HashSet /*IVariable!*//*!*/ dims = new HashSet /*IVariable!*/ (terms.Count); + foreach (IVariable/*!*/ dim in terms.Keys) { + Contract.Assert(dim != null); + dims.Add(dim); + } + System.Diagnostics.Debug.Assert(dims.Count == terms.Count); + return dims; + } + + /// + /// The getter returns the value at the given dimension, or 0 if that dimension is not defined. + /// + public Rational this[IVariable/*!*/ dimension] { + get { + //Contract.Ensures(Contract.Result() != null); + object z = terms[dimension]; + if (z == null) { + return Rational.ZERO; + } else { + return (Rational)z; } + } + set { + terms[dimension] = value; + } + } - public FrameElement Rename(IVariable! oldName, IVariable! newName) - { + public FrameElement Rename(IVariable/*!*/ oldName, IVariable/*!*/ newName) { + Contract.Requires(newName != null); + Contract.Requires(oldName != null); object /*Rational*/ z = terms[oldName]; - if (z == null) - { + if (z == null) { return this; - } - else - { + } else { System.Diagnostics.Debug.Assert(z is Rational); - Hashtable /*IVariable->Rational*/ newTerms = (Hashtable! /*IVariable->Rational*/)terms.Clone(); + Hashtable /*IVariable->Rational*/ newTerms = (Hashtable/*!*/ /*IVariable->Rational*/)cce.NonNull(terms.Clone()); newTerms.Remove(oldName); newTerms.Add(newName, z); @@ -578,11 +535,10 @@ namespace Microsoft.AbstractInterpretationFramework } } - public FrameElement Clone() - { - FrameElement z = new FrameElement(); - z.terms = (Hashtable /*IVariable->Rational*/)this.terms.Clone(); - return z; - } + public FrameElement Clone() { + FrameElement z = new FrameElement(); + z.terms = (Hashtable /*IVariable->Rational*/)this.terms.Clone(); + return z; } + } } diff --git a/Source/AIFramework/Polyhedra/LinearConstraintSystem.cs b/Source/AIFramework/Polyhedra/LinearConstraintSystem.cs index e444b0ca..8e5fdf86 100644 --- a/Source/AIFramework/Polyhedra/LinearConstraintSystem.cs +++ b/Source/AIFramework/Polyhedra/LinearConstraintSystem.cs @@ -3,33 +3,39 @@ // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- -namespace Microsoft.AbstractInterpretationFramework -{ - using System.Collections; - using System.Collections.Generic; - using System.Diagnostics; - using System; - using Microsoft.SpecSharp.Collections; - using Microsoft.Contracts; - using Microsoft.Basetypes; - using IMutableSet = Microsoft.Boogie.Set; - using HashSet = Microsoft.Boogie.Set; - using ISet = Microsoft.Boogie.Set; - - /// - /// Represents a system of linear constraints (constraint/frame representations). - /// - public class LinearConstraintSystem - { +namespace Microsoft.AbstractInterpretationFramework { + using System.Collections; + using System.Collections.Generic; + using System.Diagnostics; + using System; + //using Microsoft.SpecSharp.Collections; + using System.Diagnostics.Contracts; + using Microsoft.Basetypes; + using IMutableSet = Microsoft.Boogie.Set; + using HashSet = Microsoft.Boogie.Set; + using ISet = Microsoft.Boogie.Set; + + /// + /// Represents a system of linear constraints (constraint/frame representations). + /// + public class LinearConstraintSystem { // -------------------------------------------------------------------------------------------------------- // ------------------ Data structure ---------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------- public /*maybe null*/ ArrayList /*LinearConstraint!*/ Constraints; - /*maybe null*/ ArrayList /*FrameElement!*/ FrameVertices; - /*maybe null*/ ArrayList /*FrameElement!*/ FrameRays; - IMutableSet/*IVariable!*/! FrameDimensions; - /*maybe null*/ ArrayList /*FrameElement!*/ FrameLines; + /*maybe null*/ + ArrayList /*FrameElement!*/ FrameVertices; + /*maybe null*/ + ArrayList /*FrameElement!*/ FrameRays; + IMutableSet/*IVariable!*//*!*/ FrameDimensions; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(FrameDimensions != null); + } + + /*maybe null*/ + ArrayList /*FrameElement!*/ FrameLines; // Invariant: Either all of Constraints, FrameVertices, FrameRays, and FrameLines are // null, or all are non-null. // Invariant: Any dimension mentioned in Constraints, FrameVertices, FrameRays, or @@ -37,36 +43,32 @@ namespace Microsoft.AbstractInterpretationFramework // The meaning of FrameDimensions is that for any dimension x not in FrameDimensions, // there is an implicit line along dimension x (that is, ()). - void CheckInvariant() - { - if (Constraints == null) - { + void CheckInvariant() { + if (Constraints == null) { System.Diagnostics.Debug.Assert(FrameVertices == null); System.Diagnostics.Debug.Assert(FrameRays == null); System.Diagnostics.Debug.Assert(FrameLines == null); System.Diagnostics.Debug.Assert(FrameDimensions.Count == 0); - } - else - { + } else { System.Diagnostics.Debug.Assert(FrameVertices != null); System.Diagnostics.Debug.Assert(FrameRays != null); System.Diagnostics.Debug.Assert(FrameLines != null); - foreach (LinearConstraint! cc in Constraints) - { + foreach (LinearConstraint/*!*/ cc in Constraints) { + Contract.Assert(cc != null); #if FIXED_DESERIALIZER - assert Forall{IVariable! var in cc.GetDefinedDimensions(); FrameDimensions.Contains(var)}; -#endif - assert cc.coefficients.Count != 0; + Contract.Assert(Contract.ForAll(cc.GetDefinedDimensions() , var=> FrameDimensions.Contains(var))); +#endif + Contract.Assert(cc.coefficients.Count != 0); } - foreach (ArrayList /*FrameElement*/! FrameComponent in new ArrayList /*FrameElement*/ [] {FrameVertices, FrameRays, FrameLines}) - { - foreach (FrameElement fe in FrameComponent) - { - if (fe == null) continue; + foreach (ArrayList /*FrameElement*//*!*/ FrameComponent in new ArrayList /*FrameElement*/ [] { FrameVertices, FrameRays, FrameLines }) { + Contract.Assert(FrameComponent != null); + foreach (FrameElement fe in FrameComponent) { + if (fe == null) + continue; #if FIXED_DESERIALIZER - assert Forall{IVariable! var in fe.GetDefinedDimensions(); FrameDimensions.Contains(var)}; -#endif + Contract.Assert(Contract.ForAll(fe.GetDefinedDimensions() , var=> FrameDimensions.Contains(var))); +#endif } } } @@ -81,10 +83,9 @@ namespace Microsoft.AbstractInterpretationFramework /// an unsatisfiable system of constraints. /// [NotDelayed] - public LinearConstraintSystem() - { + public LinearConstraintSystem() { FrameDimensions = new HashSet /*IVariable!*/ (); - base(); + //:base(); CheckInvariant(); } @@ -94,19 +95,20 @@ namespace Microsoft.AbstractInterpretationFramework /// /// [NotDelayed] - public LinearConstraintSystem(ArrayList /*LinearConstraint!*/! cs) + public LinearConstraintSystem(ArrayList /*LinearConstraint!*//*!*/ cs) { + Contract.Requires(cs != null); #if BUG_159_HAS_BEEN_FIXED - requires Forall{LinearConstraint! cc in cs; cc.coefficients.Count != 0}; + Contract.Requires(Contract.ForAll(cs) , cc=> cc.coefficients.Count != 0); #endif - { + ArrayList constraints = new ArrayList /*LinearConstraint!*/ (cs.Count); - foreach (LinearConstraint! cc in cs) - { + foreach (LinearConstraint/*!*/ cc in cs) { + Contract.Assert(cc != null); constraints.Add(cc); } Constraints = constraints; FrameDimensions = new HashSet /*IVariable!*/ (); // to please compiler; this value will be overridden in the call to GenerateFrameConstraints below - base(); + //:base(); GenerateFrameFromConstraints(); SimplifyConstraints(); @@ -123,12 +125,13 @@ namespace Microsoft.AbstractInterpretationFramework /// /// [NotDelayed] - LinearConstraintSystem(FrameElement! v) - { - IMutableSet! frameDims = v.GetDefinedDimensions(); + LinearConstraintSystem(FrameElement/*!*/ v) { + Contract.Requires(v != null); + IMutableSet/*!*/ frameDims = v.GetDefinedDimensions(); + Contract.Assert(frameDims != null); ArrayList /*LinearConstraint!*/ constraints = new ArrayList /*LinearConstraint!*/ (); - foreach (IVariable! dim in frameDims) - { + foreach (IVariable/*!*/ dim in frameDims) { + Contract.Assert(dim != null); LinearConstraint lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ); lc.SetCoefficient(dim, Rational.ONE); lc.rhs = v[dim]; @@ -144,12 +147,11 @@ namespace Microsoft.AbstractInterpretationFramework FrameRays = new ArrayList /*FrameElement*/ (); FrameLines = new ArrayList /*FrameElement*/ (); - base(); + //:base(); CheckInvariant(); } - void ChangeIntoBottom() - { + void ChangeIntoBottom() { Constraints = null; FrameVertices = null; FrameRays = null; @@ -162,54 +164,47 @@ namespace Microsoft.AbstractInterpretationFramework // ------------------ Public operations and their support routines ---------------------------------------- // -------------------------------------------------------------------------------------------------------- - public bool IsBottom() - { + public bool IsBottom() { return Constraints == null; } - public bool IsTop() - { + public bool IsTop() { return Constraints != null && Constraints.Count == 0; } [Pure] - public override string! ToString() - { - if (Constraints == null) - { + public override string/*!*/ ToString() { + Contract.Ensures(Contract.Result() != null); + if (Constraints == null) { return ""; - } - else if (Constraints.Count == 0) - { + } else if (Constraints.Count == 0) { return ""; - } - else - { + } else { string z = null; - foreach (LinearConstraint! lc in Constraints) - { + foreach (LinearConstraint/*!*/ lc in Constraints) { + Contract.Assert(lc != null); string s = lc.ToString(); - if (z == null) - { + if (z == null) { z = s; - } - else - { + } else { z += " AND " + s; } } - assert z != null; + Contract.Assert(z != null); return z; } } - public ICollection! FreeVariables() - ensures result.IsReadOnly; - { - List list = new List(); - foreach (IVariable! v in FrameDimensions) { list.Add(v); } - return (!)list.AsReadOnly(); + public ICollection/*!*/ FreeVariables() { + Contract.Ensures(cce.NonNullElements(Contract.Result>())); + Contract.Ensures(Contract.Result>().IsReadOnly); + List list = new List(); + foreach (IVariable/*!*/ v in FrameDimensions) { + Contract.Assert(v != null); + list.Add(v); + } + return cce.NonNull(list.AsReadOnly()); } /// @@ -217,8 +212,9 @@ namespace Microsoft.AbstractInterpretationFramework /// not required elsewhere in this class. /// /// - public IExpr! ConvertToExpression(ILinearExprFactory! factory) - { + public IExpr/*!*/ ConvertToExpression(ILinearExprFactory/*!*/ factory) { + Contract.Requires(factory != null); + Contract.Ensures(Contract.Result() != null); if (this.Constraints == null) { return factory.False; } @@ -227,12 +223,12 @@ namespace Microsoft.AbstractInterpretationFramework } IExpr result = null; - foreach (LinearConstraint! lc in Constraints) - { + foreach (LinearConstraint/*!*/ lc in Constraints) { + Contract.Assert(lc != null); IExpr conjunct = lc.ConvertToExpression(factory); result = (result == null) ? conjunct : (IExpr)factory.And(conjunct, result); } - assert result != null; + Contract.Assert(result != null); return result; } @@ -240,14 +236,11 @@ namespace Microsoft.AbstractInterpretationFramework /* IsSubset(): determines if 'lcs' is a subset of 'this' * -- See Cousot/Halbwachs 1978, section */ - public bool IsSubset(LinearConstraintSystem! lcs) - { - if (lcs.IsBottom()) - { + public bool IsSubset(LinearConstraintSystem/*!*/ lcs) { + Contract.Requires(lcs != null); + if (lcs.IsBottom()) { return true; - } - else if (this.IsBottom()) - { + } else if (this.IsBottom()) { return false; #if DEBUG #else @@ -256,11 +249,10 @@ namespace Microsoft.AbstractInterpretationFramework } else if (lcs.IsTop()) { // optimization -- this case not needed for correctness return false; #endif - } - else - { + } else { // phase 0: check if frame dimensions are a superset of the constraint dimensions - ISet /*IVariable!*/! frameDims = lcs.GetDefinedDimensions(); + ISet /*IVariable!*//*!*/ frameDims = lcs.GetDefinedDimensions(); + Contract.Assert(frameDims != null); #if DEBUG_PRINT Console.WriteLine("DEBUG: IsSubset:"); Console.WriteLine(" --- this:"); @@ -269,14 +261,14 @@ namespace Microsoft.AbstractInterpretationFramework lcs.Dump(); Console.WriteLine(" ---"); #endif - foreach (LinearConstraint! cc in (!)this.Constraints) - { + foreach (LinearConstraint/*!*/ cc in cce.NonNull(this.Constraints)) { + Contract.Assert(cc != null); #if DEBUG_PRINT Console.WriteLine(" cc: {0}", cc); Console.WriteLine(" cc.GetDefinedDimensions(): {0}", cc.GetDefinedDimensions()); #endif - if (!forall{IVariable! var in cc.GetDefinedDimensions(); frameDims.Contains(var)}) - { + + if (!Contract.ForAll(cc.GetDefinedDimensionsGeneric(), var => frameDims.Contains(var))) { #if DEBUG_PRINT Console.WriteLine(" ---> phase 0 subset violated, return false from IsSubset"); #endif @@ -286,25 +278,20 @@ namespace Microsoft.AbstractInterpretationFramework } // phase 1: check frame vertices against each constraint... - foreach (FrameElement! v in (!)lcs.FrameVertices) - { - foreach (LinearConstraint! cc in this.Constraints) - { + foreach (FrameElement/*!*/ v in cce.NonNull(lcs.FrameVertices)) { + Contract.Assert(v != null); + foreach (LinearConstraint/*!*/ cc in this.Constraints) { + Contract.Assert(cc != null); Rational q = cc.EvaluateLhs(v); - if (cc.Relation == LinearConstraint.ConstraintRelation.LE) - { - if (!(q <= cc.rhs)) - { + if (cc.Relation == LinearConstraint.ConstraintRelation.LE) { + if (!(q <= cc.rhs)) { #if DEBUG_PRINT Console.WriteLine(" ---> phase 1a subset violated, return false from IsSubset"); #endif return false; } - } - else - { - if (!(q == cc.rhs)) - { + } else { + if (!(q == cc.rhs)) { #if DEBUG_PRINT Console.WriteLine(" ---> phase 1b subset violated, return false from IsSubset"); #endif @@ -333,27 +320,22 @@ namespace Microsoft.AbstractInterpretationFramework // a1*r1 + a2*r2 + ... + an*rn <= 0 // If the constraint is an equality constraint, we simply replace "<=" with "==" // above. - foreach (FrameElement! r in (!)lcs.FrameRays) - { + foreach (FrameElement/*!*/ r in cce.NonNull(lcs.FrameRays)) { + Contract.Assert(r != null); System.Diagnostics.Debug.Assert(r != null, "encountered a null ray..."); - foreach (LinearConstraint! cc in this.Constraints) - { + foreach (LinearConstraint/*!*/ cc in this.Constraints) { + Contract.Assert(cc != null); System.Diagnostics.Debug.Assert(cc != null, "encountered an null constraint..."); Rational q = cc.EvaluateLhs(r); - if (cc.Relation == LinearConstraint.ConstraintRelation.LE) - { - if (q.IsPositive) - { + if (cc.Relation == LinearConstraint.ConstraintRelation.LE) { + if (q.IsPositive) { #if DEBUG_PRINT Console.WriteLine(" ---> phase 2a subset violated, return false from IsSubset"); #endif return false; } - } - else - { - if (q.IsNonZero) - { + } else { + if (q.IsNonZero) { #if DEBUG_PRINT Console.WriteLine(" ---> phase 2b subset violated, return false from IsSubset"); #endif @@ -379,15 +361,14 @@ namespace Microsoft.AbstractInterpretationFramework // Putting (*) and (**) together, we conclude that we need to check: // a1*L1 + a2*L2 + ... + an*Ln == 0 // If the constraint is an equality constraint, we end up with the same equation. - foreach (FrameElement! line in (!)lcs.FrameLines) - { + foreach (FrameElement/*!*/ line in cce.NonNull(lcs.FrameLines)) { + Contract.Assert(line != null); System.Diagnostics.Debug.Assert(line != null, "encountered a null line..."); - foreach (LinearConstraint! cc in this.Constraints) - { + foreach (LinearConstraint/*!*/ cc in this.Constraints) { + Contract.Assert(cc != null); System.Diagnostics.Debug.Assert(cc != null, "encountered an null constraint..."); Rational q = cc.EvaluateLhs(line); - if (q.IsNonZero) - { + if (q.IsNonZero) { #if DEBUG_PRINT Console.WriteLine(" ---> phase 3 subset violated, return false from IsSubset"); #endif @@ -402,10 +383,11 @@ namespace Microsoft.AbstractInterpretationFramework return true; } - public LinearConstraintSystem! Meet(LinearConstraintSystem! lcs) - requires this.Constraints != null; - requires lcs.Constraints != null; - { + public LinearConstraintSystem/*!*/ Meet(LinearConstraintSystem/*!*/ lcs) { + Contract.Requires(lcs != null); + Contract.Requires((this.Constraints != null)); + Contract.Requires((lcs.Constraints != null)); + Contract.Ensures(Contract.Result() != null); ArrayList /*LinearConstraint*/ clist = new ArrayList(this.Constraints.Count + lcs.Constraints.Count); clist.AddRange(this.Constraints); clist.AddRange(lcs.Constraints); @@ -436,43 +418,35 @@ namespace Microsoft.AbstractInterpretationFramework /// /// #if DEBUG_PRINT - public LinearConstraintSystem JoinX(LinearConstraintSystem lcs) + public LinearConstraintSystem JoinX(LinearConstraintSystem lcs) { #else - public LinearConstraintSystem! Join(LinearConstraintSystem! lcs) + public LinearConstraintSystem/*!*/ Join(LinearConstraintSystem/*!*/ lcs) { + Contract.Requires(lcs != null); + Contract.Ensures(Contract.Result() != null); #endif - { - if (this.IsBottom()) - { - return (!) lcs.Clone(); - } - else if (lcs.IsBottom()) - { - return (!) this.Clone(); - } - else if (this.IsTop() || lcs.IsTop()) - { + + if (this.IsBottom()) { + return cce.NonNull(lcs.Clone()); + } else if (lcs.IsBottom()) { + return cce.NonNull(this.Clone()); + } else if (this.IsTop() || lcs.IsTop()) { return new LinearConstraintSystem(new ArrayList /*LinearConstraint*/ ()); - } - else - { - LinearConstraintSystem! z; + } else { + LinearConstraintSystem/*!*/ z; // Start from the "larger" of the two frames (this is just a heuristic measure intended // to save work). - assume this.FrameVertices != null; - assume this.FrameRays != null; - assume this.FrameLines != null; - assume lcs.FrameVertices != null; - assume lcs.FrameRays != null; - assume lcs.FrameLines != null; + Contract.Assume(this.FrameVertices != null); + Contract.Assume(this.FrameRays != null); + Contract.Assume(this.FrameLines != null); + Contract.Assume(lcs.FrameVertices != null); + Contract.Assume(lcs.FrameRays != null); + Contract.Assume(lcs.FrameLines != null); if (this.FrameVertices.Count + this.FrameRays.Count + this.FrameLines.Count - this.FrameDimensions.Count < - lcs.FrameVertices.Count + lcs.FrameRays.Count + lcs.FrameLines.Count - lcs.FrameDimensions.Count) - { - z = (!) lcs.Clone(); + lcs.FrameVertices.Count + lcs.FrameRays.Count + lcs.FrameLines.Count - lcs.FrameDimensions.Count) { + z = cce.NonNull(lcs.Clone()); lcs = this; - } - else - { - z = (!) this.Clone(); + } else { + z = cce.NonNull(this.Clone()); } #if DEBUG_PRINT Console.WriteLine("DEBUG: LinearConstraintSystem.Join ---------------"); @@ -483,17 +457,16 @@ namespace Microsoft.AbstractInterpretationFramework #endif // Start by explicating the implicit lines of z for the dimensions dims(lcs)-dims(z). - foreach (IVariable! dim in lcs.FrameDimensions) - { - if (!z.FrameDimensions.Contains(dim)) - { + foreach (IVariable/*!*/ dim in lcs.FrameDimensions) { + Contract.Assert(dim != null); + if (!z.FrameDimensions.Contains(dim)) { z.FrameDimensions.Add(dim); FrameElement line = new FrameElement(); line.AddCoordinate(dim, Rational.ONE); // Note: AddLine is not called (because the line already exists in z--it's just that // it was represented implicitly). Instead, just tack the explicit representation onto // FrameLines. - assume z.FrameLines != null; + Contract.Assume(z.FrameLines != null); z.FrameLines.Add(line); #if DEBUG_PRINT Console.WriteLine("Join: After explicating line: {0}", line); @@ -503,24 +476,24 @@ namespace Microsoft.AbstractInterpretationFramework } // Now, the vertices, rays, and lines can be added. - foreach (FrameElement! v in lcs.FrameVertices) - { + foreach (FrameElement/*!*/ v in lcs.FrameVertices) { + Contract.Assert(v != null); z.AddVertex(v); #if DEBUG_PRINT Console.WriteLine("Join: After adding vertex: {0}", v); z.Dump(); #endif } - foreach (FrameElement! r in lcs.FrameRays) - { + foreach (FrameElement/*!*/ r in lcs.FrameRays) { + Contract.Assert(r != null); z.AddRay(r); #if DEBUG_PRINT Console.WriteLine("Join: After adding ray: {0}", r); z.Dump(); #endif } - foreach (FrameElement! l in lcs.FrameLines) - { + foreach (FrameElement/*!*/ l in lcs.FrameLines) { + Contract.Assert(l != null); z.AddLine(l); #if DEBUG_PRINT Console.WriteLine("Join: After adding line: {0}", l); @@ -528,10 +501,9 @@ namespace Microsoft.AbstractInterpretationFramework #endif } // also add to z the implicit lines of lcs - foreach (IVariable! dim in z.FrameDimensions) - { - if (!lcs.FrameDimensions.Contains(dim)) - { + foreach (IVariable/*!*/ dim in z.FrameDimensions) { + Contract.Assert(dim != null); + if (!lcs.FrameDimensions.Contains(dim)) { // "dim" is a dimension that's explicit in "z" but implicit in "lcs" FrameElement line = new FrameElement(); line.AddCoordinate(dim, Rational.ONE); @@ -574,35 +546,30 @@ namespace Microsoft.AbstractInterpretationFramework #endif #if DEBUG_PRINT - public LinearConstraintSystem WidenX(LinearConstraintSystem lcs) + public LinearConstraintSystem WidenX(LinearConstraintSystem lcs){ #else - public LinearConstraintSystem! Widen(LinearConstraintSystem! lcs) -#endif - { - if (this.IsBottom()) - { - return (!) lcs.Clone(); - } - else if (lcs.IsBottom()) - { - return (!) this.Clone(); - } - else if (this.IsTop() || lcs.IsTop()) - { + public LinearConstraintSystem/*!*/ Widen(LinearConstraintSystem/*!*/ lcs) { + Contract.Requires(lcs != null); + Contract.Ensures(Contract.Result() != null); +#endif + if (this.IsBottom()) { + return cce.NonNull(lcs.Clone()); + } else if (lcs.IsBottom()) { + return cce.NonNull(this.Clone()); + } else if (this.IsTop() || lcs.IsTop()) { return new LinearConstraintSystem(new ArrayList /*LinearConstraint*/ ()); } // create new LCS, we will add only verified constraints to this... ArrayList /*LinearConstraint*/ newConstraints = new ArrayList /*LinearConstraint*/ (); - assume this.Constraints != null; - foreach (LinearConstraint! ccX in this.Constraints) - { + Contract.Assume(this.Constraints != null); + foreach (LinearConstraint/*!*/ ccX in this.Constraints) { + Contract.Assert(ccX != null); LinearConstraint cc = ccX; #if DEBUG_PRINT Console.WriteLine("Widen checking: Starting to check constraint: {0}", cc); #endif - if (cc.IsConstant()) - { + if (cc.IsConstant()) { // (Can this ever occur in the stable state of a LinearConstraintSystem? --KRML) // constraint is unaffected by the frame components #if DEBUG_PRINT @@ -614,21 +581,17 @@ namespace Microsoft.AbstractInterpretationFramework // PHASE I: verify constraints against all frame vertices... - foreach (FrameElement! vertex in (!)lcs.FrameVertices) - { + foreach (FrameElement/*!*/ vertex in cce.NonNull(lcs.FrameVertices)) { + Contract.Assert(vertex != null); Rational lhs = cc.EvaluateLhs(vertex); - if (lhs > cc.rhs) - { + if (lhs > cc.rhs) { // the vertex does not satisfy the inequality <= - if (cc.Relation == LinearConstraint.ConstraintRelation.LE) - { + if (cc.Relation == LinearConstraint.ConstraintRelation.LE) { #if DEBUG_PRINT Console.WriteLine("Widen checking: throwing out because of vertex: {0}", vertex); #endif goto CHECK_NEXT_CONSTRAINT; - } - else - { + } else { // ... but it does satisfy the inequality >= #if DEBUG_PRINT Console.WriteLine("Widen checking: throwing out <= because of vertex: {0}", vertex); @@ -638,9 +601,7 @@ namespace Microsoft.AbstractInterpretationFramework Console.WriteLine("Widen checking: left with constraint: {0}", cc); #endif } - } - else if (cc.Relation == LinearConstraint.ConstraintRelation.EQ && lhs < cc.rhs) - { + } else if (cc.Relation == LinearConstraint.ConstraintRelation.EQ && lhs < cc.rhs) { // the vertex does not satisfy the inequality >=, and the constraint is an equality constraint #if DEBUG_PRINT Console.WriteLine("Widen checking: throwing out >= because of vertex: {0}", vertex); @@ -654,22 +615,18 @@ namespace Microsoft.AbstractInterpretationFramework // PHASE II: verify constraints against all frame rays... - foreach (FrameElement! ray in (!)lcs.FrameRays) - { + foreach (FrameElement/*!*/ ray in cce.NonNull(lcs.FrameRays)) { + Contract.Assert(ray != null); // The following assumes the constraint to have some dimension with a non-zero coefficient Rational lhs = cc.EvaluateLhs(ray); - if (lhs.IsPositive) - { + if (lhs.IsPositive) { // the ray does not satisfy the inequality <= - if (cc.Relation == LinearConstraint.ConstraintRelation.LE) - { + if (cc.Relation == LinearConstraint.ConstraintRelation.LE) { #if DEBUG_PRINT Console.WriteLine("Widen checking: throwing out because of ray: {0}", ray); #endif goto CHECK_NEXT_CONSTRAINT; - } - else - { + } else { // ... but it does satisfy the inequality >= #if DEBUG_PRINT Console.WriteLine("Widen checking: throwing out <= because of ray: {0}", ray); @@ -679,9 +636,7 @@ namespace Microsoft.AbstractInterpretationFramework Console.WriteLine("Widen checking: left with contraint: {0}", cc); #endif } - } - else if (cc.Relation == LinearConstraint.ConstraintRelation.EQ && lhs.IsNegative) - { + } else if (cc.Relation == LinearConstraint.ConstraintRelation.EQ && lhs.IsNegative) { // the ray does not satisfy the inequality >=, and the constraint is an equality constraint #if DEBUG_PRINT Console.WriteLine("Widen checking: throwing out >= because of ray: {0}", ray); @@ -695,12 +650,11 @@ namespace Microsoft.AbstractInterpretationFramework // PHASE III: verify constraints against all frame lines... - foreach (FrameElement! line in (!)lcs.FrameLines) - { + foreach (FrameElement/*!*/ line in cce.NonNull(lcs.FrameLines)) { + Contract.Assert(line != null); // The following assumes the constraint to have some dimension with a non-zero coefficient Rational lhs = cc.EvaluateLhs(line); - if (!lhs.IsZero) - { + if (!lhs.IsZero) { // The line satisfies neither the inequality <= nor the equality == #if DEBUG_PRINT Console.WriteLine("Widen checking: throwing out because of line: {0}", line); @@ -715,7 +669,8 @@ namespace Microsoft.AbstractInterpretationFramework #endif newConstraints.Add(cc); - CHECK_NEXT_CONSTRAINT: {} + CHECK_NEXT_CONSTRAINT: { + } #if DEBUG_PRINT Console.WriteLine("Widen checking: done with that constraint"); #endif @@ -725,8 +680,8 @@ namespace Microsoft.AbstractInterpretationFramework } #if DEBUG_PRINT - public LinearConstraintSystem Project(IVariable! dim) - { + public LinearConstraintSystem Project(IVariable/*!*/ dim){ +Contract.Requires(dim != null); Console.WriteLine("==================================================================================="); Console.WriteLine("DEBUG: Project(dim={0})", dim); Console.WriteLine("Project: this="); @@ -741,19 +696,24 @@ namespace Microsoft.AbstractInterpretationFramework #endif #if DEBUG_PRINT - public LinearConstraintSystem ProjectX(IVariable! dim) + public LinearConstraintSystem ProjectX(IVariable/*!*/ dim){Contract.Requires(dim != null);Contract.Requires(this.Constraints != null); #else - public LinearConstraintSystem! Project(IVariable! dim) + public LinearConstraintSystem/*!*/ Project(IVariable/*!*/ dim) { + Contract.Requires(dim != null); + Contract.Requires(this.Constraints != null); + Contract.Ensures(Contract.Result() != null); #endif - requires this.Constraints != null; - { - ArrayList /*LinearConstraint!*/! cc = Project(dim, Constraints); + + + ArrayList /*LinearConstraint!*//*!*/ cc = Project(dim, Constraints); + Contract.Assert(cc != null); return new LinearConstraintSystem(cc); } #if DEBUG_PRINT - public LinearConstraintSystem Rename(IVariable! oldName, IVariable! newName) - { + public LinearConstraintSystem Rename(IVariable/*!*/ oldName, IVariable/*!*/ newName){ +Contract.Requires(newName != null); +Contract.Requires(oldName != null); Console.WriteLine("==================================================================================="); Console.WriteLine("DEBUG: Rename(oldName={0}, newName={1})", oldName, newName); Console.WriteLine("Rename: this="); @@ -768,45 +728,49 @@ namespace Microsoft.AbstractInterpretationFramework #endif #if DEBUG_PRINT - public LinearConstraintSystem RenameX(IVariable! oldName, IVariable! newName) + public LinearConstraintSystem RenameX(IVariable/*!*/ oldName, IVariable/*!*/ newName){Contract.Requires(oldName != null);Contract.Requires(newName != null); #else - public LinearConstraintSystem! Rename(IVariable! oldName, IVariable! newName) + public LinearConstraintSystem/*!*/ Rename(IVariable/*!*/ oldName, IVariable/*!*/ newName) { + Contract.Requires(oldName != null); + Contract.Requires(newName != null); + Contract.Ensures(Contract.Result() != null); #endif - { - if (this.Constraints == null) - { + if (this.Constraints == null) { System.Diagnostics.Debug.Assert(this.FrameVertices == null); System.Diagnostics.Debug.Assert(this.FrameRays == null); System.Diagnostics.Debug.Assert(this.FrameLines == null); return this; } - IMutableSet /*IVariable!*/! dims = this.FrameDimensions; - if (!dims.Contains(oldName)) - { + IMutableSet /*IVariable!*//*!*/ dims = this.FrameDimensions; + Contract.Assert(dims != null); + if (!dims.Contains(oldName)) { return this; } LinearConstraintSystem z = new LinearConstraintSystem(); - z.FrameDimensions = (HashSet! /*IVariable!*/)dims.Clone(); + z.FrameDimensions = cce.NonNull((HashSet/*!*/ /*IVariable!*/)dims.Clone()); z.FrameDimensions.Remove(oldName); z.FrameDimensions.Add(newName); z.Constraints = new ArrayList /*LinearConstraint!*/ (this.Constraints.Count); - foreach (LinearConstraint! lc in (!)this.Constraints) - { + foreach (LinearConstraint/*!*/ lc in cce.NonNull(this.Constraints)) { + Contract.Assert(lc != null); z.Constraints.Add(lc.Rename(oldName, newName)); } - z.FrameVertices = RenameInFE((!)this.FrameVertices, oldName, newName); - z.FrameRays = RenameInFE((!)this.FrameRays, oldName, newName); - z.FrameLines = RenameInFE((!)this.FrameLines, oldName, newName); + z.FrameVertices = RenameInFE(cce.NonNull(this.FrameVertices), oldName, newName); + z.FrameRays = RenameInFE(cce.NonNull(this.FrameRays), oldName, newName); + z.FrameLines = RenameInFE(cce.NonNull(this.FrameLines), oldName, newName); return z; } - static ArrayList /*FrameElement*/ RenameInFE(ArrayList! /*FrameElement*/ list, IVariable! oldName, IVariable! newName) - { - ArrayList/*FrameElement!*/! z = new ArrayList/*FrameElement!*/ (list.Count); - foreach (FrameElement! fe in list) - { + static ArrayList /*FrameElement*/ RenameInFE(ArrayList/*!*/ /*FrameElement*/ list, IVariable/*!*/ oldName, IVariable/*!*/ newName) { + Contract.Requires(list != null); + Contract.Requires(newName != null); + Contract.Requires(oldName != null); + ArrayList/*FrameElement!*//*!*/ z = new ArrayList/*FrameElement!*/ (list.Count); + Contract.Assert(z != null); + foreach (FrameElement/*!*/ fe in list) { + Contract.Assert(fe != null); z.Add(fe.Rename(oldName, newName)); } System.Diagnostics.Debug.Assert(z.Count == list.Count); @@ -824,88 +788,73 @@ namespace Microsoft.AbstractInterpretationFramework /// /// /// - static ArrayList /*LinearConstraint!*/! Project(IVariable! dim, ArrayList /*LinearConstraint!*/! constraints) - { + static ArrayList /*LinearConstraint!*//*!*/ Project(IVariable/*!*/ dim, ArrayList /*LinearConstraint!*//*!*/ constraints) { + Contract.Requires(constraints != null); + Contract.Requires(dim != null); + Contract.Ensures(Contract.Result() != null); // Sort the inequality constaints into ones where dimension "dim" is 0, negative, and // positive, respectively. Put equality constraints with a non-0 "dim" into "eq". - ArrayList /*LinearConstraint!*/! final = new ArrayList /*LinearConstraint!*/ (); - ArrayList /*LinearConstraint!*/! negative = new ArrayList /*LinearConstraint!*/ (); - ArrayList /*LinearConstraint!*/! positive = new ArrayList /*LinearConstraint!*/ (); - ArrayList /*LinearConstraint!*/! eq = new ArrayList /*LinearConstraint!*/ (); - foreach (LinearConstraint! cc in constraints) - { + ArrayList /*LinearConstraint!*//*!*/ final = new ArrayList /*LinearConstraint!*/ (); + ArrayList /*LinearConstraint!*//*!*/ negative = new ArrayList /*LinearConstraint!*/ (); + ArrayList /*LinearConstraint!*//*!*/ positive = new ArrayList /*LinearConstraint!*/ (); + ArrayList /*LinearConstraint!*//*!*/ eq = new ArrayList /*LinearConstraint!*/ (); + foreach (LinearConstraint/*!*/ cc in constraints) { + Contract.Assert(cc != null); Rational coeff = cc[dim]; - if (coeff.IsZero) - { - LinearConstraint lc = (!) cc.Clone(); - if (!lc.IsConstant()) - { + if (coeff.IsZero) { + LinearConstraint lc = cce.NonNull(cc.Clone()); + if (!lc.IsConstant()) { lc.RemoveDimension(dim); final.Add(lc); } - } - else if (cc.Relation == LinearConstraint.ConstraintRelation.EQ) - { + } else if (cc.Relation == LinearConstraint.ConstraintRelation.EQ) { eq.Add(cc); - } - else if (coeff.IsNegative) - { + } else if (coeff.IsNegative) { negative.Add(cc); - } - else - { + } else { System.Diagnostics.Debug.Assert(coeff.IsPositive); positive.Add(cc); - } + } } - if (eq.Count != 0) - { - LinearConstraint eqConstraint = (LinearConstraint!)eq[eq.Count-1]; - eq.RemoveAt(eq.Count-1); + if (eq.Count != 0) { + LinearConstraint eqConstraint = (LinearConstraint/*!*/)cce.NonNull(eq[eq.Count - 1]); + eq.RemoveAt(eq.Count - 1); Rational eqC = -eqConstraint[dim]; - foreach (ArrayList /*LinearConstraint!*/! list in new ArrayList[]{eq, negative, positive}) - { - foreach (LinearConstraint! lcX in list) - { - LinearConstraint lc = (!) lcX.Clone(); - lc.AddMultiple(lc[dim]/eqC, eqConstraint); + foreach (ArrayList /*LinearConstraint!*/ list in new ArrayList[] { eq, negative, positive }) { + Contract.Assert(list != null); + foreach (LinearConstraint/*!*/ lcX in list) { + Contract.Assert(lcX != null); + LinearConstraint lc = cce.NonNull(lcX.Clone()); + lc.AddMultiple(lc[dim] / eqC, eqConstraint); System.Diagnostics.Debug.Assert(lc[dim].IsZero); - if (!lc.IsConstant()) - { + if (!lc.IsConstant()) { lc.RemoveDimension(dim); final.Add(lc); - } - else - { + } else { System.Diagnostics.Debug.Assert(lc.IsConstantSatisfiable()); } } } - } - else - { + } else { // Consider all pairs of constraints with (negative,positive) coefficients of "dim". - foreach (LinearConstraint! cn in negative) - { + foreach (LinearConstraint/*!*/ cn in negative) { + Contract.Assert(cn != null); Rational dn = -cn[dim]; System.Diagnostics.Debug.Assert(dn.IsNonNegative); - foreach (LinearConstraint! cp in positive) - { + foreach (LinearConstraint/*!*/ cp in positive) { + Contract.Assert(cp != null); Rational dp = cp[dim]; LinearConstraint lc = new LinearConstraint(LinearConstraint.ConstraintRelation.LE); lc.AddMultiple(dn, cp); lc.AddMultiple(dp, cn); System.Diagnostics.Debug.Assert(lc[dim].IsZero); - if (!lc.IsConstant()) - { + if (!lc.IsConstant()) { lc.RemoveDimension(dim); final.Add(lc); - } - else - { + } else { System.Diagnostics.Debug.Assert(lc.IsConstantSatisfiable()); } } @@ -922,17 +871,15 @@ namespace Microsoft.AbstractInterpretationFramework /// /// If the set of Constraints is unsatisfiable, then "this" is changed into Bottom. /// - void GenerateFrameFromConstraints() - { - if (Constraints == null) - { + void GenerateFrameFromConstraints() { + if (Constraints == null) { FrameVertices = null; FrameRays = null; FrameLines = null; FrameDimensions = new HashSet /*IVariable!*/ (); return; } - + // Step 1 (see Cousot and Halbwachs, section 3.4.3): create a Simplex Tableau. #if DEBUG_PRINT Console.WriteLine("DEBUG: --- GenerateFrameFromConstraint ---"); @@ -964,8 +911,7 @@ namespace Microsoft.AbstractInterpretationFramework Console.WriteLine("Tableau after Step 3:"); tableau.Dump(); #endif - if (!tableau.IsFeasibleBasis) - { + if (!tableau.IsFeasibleBasis) { // The polyhedron is empty (according to Cousot and Halbwachs) ChangeIntoBottom(); return; @@ -974,29 +920,25 @@ namespace Microsoft.AbstractInterpretationFramework FrameVertices = new ArrayList /*FrameElement*/ (); FrameRays = new ArrayList /*FrameElement*/ (); FrameLines = new ArrayList /*FrameElement*/ (); - if (FrameDimensions.Count == 0) - { + if (FrameDimensions.Count == 0) { // top element return; } - if (tableau.AllInitialVarsInBasis) - { + if (tableau.AllInitialVarsInBasis) { // All initial variables are in basis; there are no lines. #if DEBUG_PRINT Console.WriteLine("Tableau after Steps 2 and 3 (all initial variables in basis):"); tableau.Dump(); #endif - } - else - { + } else { // There are lines #if DEBUG_PRINT Console.WriteLine("Tableau after Steps 2 and 3 (NOT all initial variables in basis--there are lines):"); tableau.Dump(); #endif // Step 4.2: Pick out the lines, then produce the tableau for a new polyhedron without those lines. - ArrayList /*LinearConstraint*/ moreConstraints = (ArrayList! /*LinearConstraint*/) Constraints.Clone(); + ArrayList /*LinearConstraint*/ moreConstraints = cce.NonNull((ArrayList/*!*/ /*LinearConstraint*/)Constraints.Clone()); tableau.ProduceLines(FrameLines, moreConstraints); tableau = new SimplexTableau(moreConstraints); #if DEBUG_PRINT @@ -1034,35 +976,33 @@ namespace Microsoft.AbstractInterpretationFramework #endif } - class LambdaDimension : IVariable - { + class LambdaDimension : IVariable { readonly int id; static int count = 0; /// /// Return the name of the variable /// - public string! Name - { - get - { + public string Name { + get { + Contract.Ensures(Contract.Result() != null); + return this.ToString(); } - } + } - public LambdaDimension() - { + public LambdaDimension() { id = count; count++; } [Pure] - public override string! ToString() - { + public override string/*!*/ ToString() { + Contract.Ensures(Contract.Result() != null); return "lambda" + id; } [Pure] - public object DoVisit(ExprVisitor! visitor) - { + public object DoVisit(ExprVisitor/*!*/ visitor) { + Contract.Requires(visitor != null); return visitor.VisitVariable(this); } } @@ -1076,9 +1016,9 @@ namespace Microsoft.AbstractInterpretationFramework /// Assumes Constraints (and the frame fields) to be non-null. /// /// - void AddVertex(FrameElement! vertex) - requires this.FrameVertices != null; - { + void AddVertex(FrameElement/*!*/ vertex) { + Contract.Requires(vertex != null); + Contract.Requires(this.FrameVertices != null); #if DEBUG_PRINT Console.WriteLine("DEBUG: AddVertex called on {0}", vertex); Console.WriteLine(" Initial constraints:"); @@ -1089,11 +1029,11 @@ namespace Microsoft.AbstractInterpretationFramework FrameVertices.Add(vertex.Clone()); #if FIXED_DESERIALIZER - assert Forall{IVariable! var in vertex.GetDefinedDimensions(); FrameDimensions.Contains(var)}; -#endif + Contract.Assert(Contract.ForAll(vertex.GetDefinedDimensions() , var=> FrameDimensions.Contains(var))); +#endif // We use a new temporary dimension. - IVariable! lambda = new LambdaDimension(); + IVariable/*!*/ lambda = new LambdaDimension(); // We change the constraints A*X <= B into // A*X + (A*vector - B)*lambda <= A*vector. @@ -1109,8 +1049,8 @@ namespace Microsoft.AbstractInterpretationFramework // = { A*vector is a row vector whose every row i is the dot-product of // row i of A with the column vector "vector" } // A[k]*vector - B[k] - foreach (LinearConstraint! cc in (!)Constraints) - { + foreach (LinearConstraint/*!*/ cc in cce.NonNull(Constraints)) { + Contract.Assert(cc != null); Rational d = cc.EvaluateLhs(vertex); cc.SetCoefficient(lambda, d - cc.rhs); cc.rhs = d; @@ -1153,9 +1093,9 @@ namespace Microsoft.AbstractInterpretationFramework /// Assumes Constraints (and the frame fields) to be non-null. /// /// - void AddRay(FrameElement! ray) - requires this.FrameRays != null; - { + void AddRay(FrameElement/*!*/ ray) { + Contract.Requires(ray != null); + Contract.Requires(this.FrameRays != null); #if DEBUG_PRINT Console.WriteLine("DEBUG: AddRay called on {0}", ray); Console.WriteLine(" Initial constraints:"); @@ -1166,11 +1106,11 @@ namespace Microsoft.AbstractInterpretationFramework FrameRays.Add(ray.Clone()); #if FIXED_DESERIALIZER - assert Forall{IVariable! var in ray.GetDefinedDimensions(); FrameDimensions.Contains(var)}; -#endif + Contract.Assert(Contract.ForAll(ray.GetDefinedDimensions() , var=> FrameDimensions.Contains(var))); +#endif // We use a new temporary dimension. - IVariable! lambda = new LambdaDimension(); + IVariable/*!*/ lambda = new LambdaDimension(); // We change the constraints A*X <= B into // A*X - (A*ray)*lambda <= B. @@ -1183,8 +1123,8 @@ namespace Microsoft.AbstractInterpretationFramework // = { A*ray is a row vector whose every row i is the dot-product of // row i of A with the column vector "ray" } // A[k]*ray - foreach (LinearConstraint! cc in (!)Constraints) - { + foreach (LinearConstraint/*!*/ cc in cce.NonNull(Constraints)) { + Contract.Assert(cc != null); Rational d = cc.EvaluateLhs(ray); cc.SetCoefficient(lambda, -d); } @@ -1221,9 +1161,9 @@ namespace Microsoft.AbstractInterpretationFramework /// Assumes Constraints (and the frame fields) to be non-null. /// /// - void AddLine(FrameElement! line) - requires this.FrameLines != null; - { + void AddLine(FrameElement/*!*/ line) { + Contract.Requires(line != null); + Contract.Requires(this.FrameLines != null); // Note: The code for AddLine is identical to that of AddRay, except the AddLine // does not introduce the constraint 0 <= lambda. (One could imagine sharing the // code between AddRay and AddLine.) @@ -1237,11 +1177,11 @@ namespace Microsoft.AbstractInterpretationFramework FrameLines.Add(line.Clone()); #if FIXED_DESERIALIZER - assert Forall{IVariable! var in line.GetDefinedDimensions(); FrameDimensions.Contains(var)}; -#endif + Contract.Assert(Contract.ForAll(line.GetDefinedDimensions() , var=> FrameDimensions.Contains(var))); +#endif // We use a new temporary dimension. - IVariable! lambda = new LambdaDimension(); + IVariable/*!*/ lambda = new LambdaDimension(); // We change the constraints A*X <= B into // A*X - (A*line)*lambda <= B. @@ -1254,8 +1194,8 @@ namespace Microsoft.AbstractInterpretationFramework // = { A*line is a row vector whose every row i is the dot-product of // row i of A with the column vector "line" } // A[k]*line - foreach (LinearConstraint! cc in (!)Constraints) - { + foreach (LinearConstraint/*!*/ cc in cce.NonNull(Constraints)) { + Contract.Assert(cc != null); Rational d = cc.EvaluateLhs(line); cc.SetCoefficient(lambda, -d); } @@ -1278,17 +1218,15 @@ namespace Microsoft.AbstractInterpretationFramework #endif } - ISet /*IVariable!*/! GetDefinedDimensions() - { - HashSet /*IVariable!*/! dims = new HashSet /*IVariable!*/ (); - foreach (ArrayList p in new ArrayList[]{FrameVertices, FrameRays, FrameLines}) - { - if (p != null) - { - foreach (FrameElement! element in p) - { - foreach (IVariable! dim in element.GetDefinedDimensions()) - { + ISet /*IVariable!*//*!*/ GetDefinedDimensions() { + Contract.Ensures(Contract.Result() != null); + HashSet /*IVariable!*//*!*/ dims = new HashSet /*IVariable!*/ (); + foreach (ArrayList p in new ArrayList[] { FrameVertices, FrameRays, FrameLines }) { + if (p != null) { + foreach (FrameElement/*!*/ element in p) { + Contract.Assert(element != null); + foreach (IVariable/*!*/ dim in element.GetDefinedDimensions()) { + Contract.Assert(dim != null); dims.Add(dim); } } @@ -1304,19 +1242,22 @@ namespace Microsoft.AbstractInterpretationFramework /// /// Uses the Constraints to simplify the frame. See section 3.4.4 of Cousot and Halbwachs. /// - void SimplifyFrame() - requires this.Constraints != null; - { - SimplificationStatus[]! status; + void SimplifyFrame() { + Contract.Requires(this.Constraints != null); + SimplificationStatus[]/*!*/ status; - SimplifyFrameElements((!)FrameVertices, true, Constraints, out status); + SimplifyFrameElements(cce.NonNull(FrameVertices), true, Constraints, out status); RemoveIrrelevantFrameElements(FrameVertices, status, null); - SimplifyFrameElements((!)FrameRays, false, Constraints, out status); + SimplifyFrameElements(cce.NonNull(FrameRays), false, Constraints, out status); RemoveIrrelevantFrameElements(FrameRays, status, FrameLines); } - enum SimplificationStatus { Irrelevant, Relevant, More }; + enum SimplificationStatus { + Irrelevant, + Relevant, + More + }; /// /// For each i, sets status[i] to: @@ -1330,32 +1271,26 @@ namespace Microsoft.AbstractInterpretationFramework /// true if "ff" contains vertices; false if "ff" contains rays /// /// - static void SimplifyFrameElements(ArrayList! /*FrameElement*/ ff, bool vertices, - ArrayList! /*LinearConstraint*/ constraints, - out SimplificationStatus[]! status) - { + static void SimplifyFrameElements(ArrayList/*!*/ /*FrameElement*/ ff, bool vertices, ArrayList/*!*/ /*LinearConstraint*/ constraints, out SimplificationStatus[]/*!*/ status) { + Contract.Requires(ff != null); + Contract.Requires(constraints != null); + Contract.Requires(Contract.ValueAtReturn(out status) != null); status = new SimplificationStatus[ff.Count]; bool[,] sat = new bool[ff.Count, constraints.Count]; - for (int i = 0; i < ff.Count; i++) - { - FrameElement f = (FrameElement!)ff[i]; + for (int i = 0; i < ff.Count; i++) { + FrameElement f = (FrameElement/*!*/)cce.NonNull(ff[i]); int cnt = 0; - for (int c = 0; c < constraints.Count; c++) - { - LinearConstraint lc = (LinearConstraint!)constraints[c]; + for (int c = 0; c < constraints.Count; c++) { + LinearConstraint lc = (LinearConstraint/*!*/)cce.NonNull(constraints[c]); bool s = lc.IsSaturatedBy(f, vertices); - if (s) - { - sat[i,c] = true; + if (s) { + sat[i, c] = true; cnt++; } } - if (!vertices && cnt == constraints.Count) - { + if (!vertices && cnt == constraints.Count) { status[i] = SimplificationStatus.More; - } - else - { + } else { status[i] = SimplificationStatus.Relevant; } } @@ -1368,81 +1303,65 @@ namespace Microsoft.AbstractInterpretationFramework /// /// /// - static void CheckPairSimplifications(bool[,]! sat, SimplificationStatus[]! status) - requires sat.GetLength(0) == status.Length; - { + static void CheckPairSimplifications(bool[,]/*!*/ sat, SimplificationStatus[]/*!*/ status) { + Contract.Requires(status != null); + Contract.Requires(sat != null); + Contract.Requires(sat.GetLength(0) == status.Length); int M = sat.GetLength(0); int N = sat.GetLength(1); - for (int i = 0; i < M-1; i++) - { - if (status[i] != SimplificationStatus.Relevant) - { + for (int i = 0; i < M - 1; i++) { + if (status[i] != SimplificationStatus.Relevant) { continue; } - for (int j = i+1; j < M; j++) - { - if (status[j] != SimplificationStatus.Relevant) - { + for (int j = i + 1; j < M; j++) { + if (status[j] != SimplificationStatus.Relevant) { continue; } // check (sat[i,*] <= sat[j,*]) and (sat[i,*] >= sat[j,*]) int cmp = 0; // -1: (sat[i,*] <= sat[j,*]), 0: equal, 1: (sat[i,*] >= sat[j,*]) - for (int c = 0; c < N; c++) - { - if (cmp < 0) - { - if (sat[i,c] && !sat[j,c]) - { + for (int c = 0; c < N; c++) { + if (cmp < 0) { + if (sat[i, c] && !sat[j, c]) { // incomparable goto NEXT_PAIR; } - } - else if (0 < cmp) - { - if (!sat[i,c] && sat[j,c]) - { + } else if (0 < cmp) { + if (!sat[i, c] && sat[j, c]) { // incomparable goto NEXT_PAIR; } - } - else if (sat[i,c] != sat[j,c]) - { - if (!sat[i,c]) - { + } else if (sat[i, c] != sat[j, c]) { + if (!sat[i, c]) { cmp = -1; - } - else - { + } else { cmp = 1; } } } - if (cmp <= 0) - { + if (cmp <= 0) { // sat[i,*] <= sat[j,*] holds, so mark i as irrelevant status[i] = SimplificationStatus.Irrelevant; goto NEXT_OUTER; - } - else - { + } else { // sat[i,*] >= sat[j,*] holds, so mark j as irrelevant status[j] = SimplificationStatus.Irrelevant; } - NEXT_PAIR: {} + NEXT_PAIR: { + } + } + NEXT_OUTER: { } - NEXT_OUTER: {} } } - static void RemoveIrrelevantFrameElements(ArrayList! /*FrameElement*/ ff, SimplificationStatus[]! status, - /*maybe null*/ ArrayList /*FrameElement*/ lines) - requires ff.Count == status.Length; - { - for (int j = ff.Count - 1; 0 <= j; j--) - { - switch (status[j]) - { + static void RemoveIrrelevantFrameElements(ArrayList/*!*/ /*FrameElement*/ ff, SimplificationStatus[]/*!*/ status, + /*maybe null*/ ArrayList /*FrameElement*/ lines) { + Contract.Requires(ff != null); + Contract.Requires(status != null); + Contract.Requires(ff.Count == status.Length); + for (int j = ff.Count - 1; 0 <= j; j--) { + switch (status[j]) { case SimplificationStatus.Relevant: break; case SimplificationStatus.Irrelevant: @@ -1458,7 +1377,7 @@ namespace Microsoft.AbstractInterpretationFramework Console.WriteLine("Changing ray into line: {0}", f); #endif ff.RemoveAt(j); - assert lines != null; + Contract.Assert(lines != null); lines.Add(f); break; } @@ -1471,55 +1390,45 @@ namespace Microsoft.AbstractInterpretationFramework /// Note: This code does not necessarily eliminate all irrelevant equalities; Cousot and /// Halbwachs only claim that the technique eliminates all irrelevant inequalities. /// - void SimplifyConstraints() - { - if (Constraints == null) - { + void SimplifyConstraints() { + if (Constraints == null) { return; } - assume this.FrameVertices != null; - assume this.FrameRays != null; + Contract.Assume(this.FrameVertices != null); + Contract.Assume(this.FrameRays != null); SimplificationStatus[] status = new SimplificationStatus[Constraints.Count]; - /*readonly*/ int feCount = FrameVertices.Count + FrameRays.Count; + /*readonly*/ + int feCount = FrameVertices.Count + FrameRays.Count; // Create a table that keeps track of which constraints are satisfied by which vertices and rays bool[,] sat = new bool[Constraints.Count, FrameVertices.Count + FrameRays.Count]; - for (int i = 0; i < Constraints.Count; i++) - { + for (int i = 0; i < Constraints.Count; i++) { status[i] = SimplificationStatus.Relevant; - LinearConstraint lc = (LinearConstraint!)Constraints[i]; + LinearConstraint lc = (LinearConstraint/*!*/)cce.NonNull(Constraints[i]); int cnt = 0; // number of vertices and rays that saturate lc - for (int j = 0; j < FrameVertices.Count; j++) - { - FrameElement vertex = (FrameElement!)FrameVertices[j]; - if (lc.IsSaturatedBy(vertex, true)) - { - sat[i,j] = true; + for (int j = 0; j < FrameVertices.Count; j++) { + FrameElement vertex = (FrameElement/*!*/)cce.NonNull(FrameVertices[j]); + if (lc.IsSaturatedBy(vertex, true)) { + sat[i, j] = true; cnt++; } } - if (cnt == 0) - { + if (cnt == 0) { // no vertex saturates the constraint, so the constraint is irrelevant status[i] = SimplificationStatus.Irrelevant; continue; } - for (int j = 0; j < FrameRays.Count; j++) - { - FrameElement ray = (FrameElement!)FrameRays[j]; - if (lc.IsSaturatedBy(ray, false)) - { + for (int j = 0; j < FrameRays.Count; j++) { + FrameElement ray = (FrameElement/*!*/)cce.NonNull(FrameRays[j]); + if (lc.IsSaturatedBy(ray, false)) { sat[i, FrameVertices.Count + j] = true; cnt++; } } - if (cnt == feCount) - { + if (cnt == feCount) { status[i] = SimplificationStatus.More; - } - else - { + } else { // Cousot and Halbwachs says that all equalities are found in the way we just tested. // If I understand that right, then we should not get here if the constraint is an // equality constraint. The following assertion tests my understanding. --KRML @@ -1530,10 +1439,8 @@ namespace Microsoft.AbstractInterpretationFramework CheckPairSimplifications(sat, status); // Finally, make the changes to the list of constraints - for (int i = Constraints.Count - 1; 0 <= i; i--) - { - switch (status[i]) - { + for (int i = Constraints.Count - 1; 0 <= i; i--) { + switch (status[i]) { case SimplificationStatus.Relevant: break; case SimplificationStatus.Irrelevant: @@ -1543,9 +1450,8 @@ namespace Microsoft.AbstractInterpretationFramework Constraints.RemoveAt(i); break; case SimplificationStatus.More: - LinearConstraint lc = (LinearConstraint!)Constraints[i]; - if (lc.Relation == LinearConstraint.ConstraintRelation.LE) - { + LinearConstraint lc = (LinearConstraint/*!*/)cce.NonNull(Constraints[i]); + if (lc.Relation == LinearConstraint.ConstraintRelation.LE) { #if DEBUG_PRINT Console.WriteLine("Converting the following constraint into an equality: {0}", lc); #endif @@ -1555,9 +1461,10 @@ namespace Microsoft.AbstractInterpretationFramework break; } } - - foreach (LinearConstraint! lc in Constraints) { - lc.Normalize(); + + foreach (LinearConstraint/*!*/ lc in Constraints) { + Contract.Assert(lc != null); + lc.Normalize(); } } @@ -1565,292 +1472,285 @@ namespace Microsoft.AbstractInterpretationFramework // ------------------ Cloning routines -------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------- - public LinearConstraintSystem! Clone() - { - LinearConstraintSystem z = new LinearConstraintSystem(); - z.FrameDimensions = (IMutableSet /*IVariable!*/!)this.FrameDimensions.Clone(); - if (this.Constraints != null) - { - z.Constraints = DeeperListCopy_LC(this.Constraints); - z.FrameVertices = DeeperListCopy_FE((!)this.FrameVertices); - z.FrameRays = DeeperListCopy_FE((!)this.FrameRays); - z.FrameLines = DeeperListCopy_FE((!)this.FrameLines); - } - else - { - System.Diagnostics.Debug.Assert(this.FrameVertices == null); - System.Diagnostics.Debug.Assert(this.FrameRays == null); - System.Diagnostics.Debug.Assert(this.FrameLines == null); - // the constructor should already have set these fields of z to null - System.Diagnostics.Debug.Assert(z.Constraints == null); - System.Diagnostics.Debug.Assert(z.FrameVertices == null); - System.Diagnostics.Debug.Assert(z.FrameRays == null); - System.Diagnostics.Debug.Assert(z.FrameLines == null); - } - return z; - } + public LinearConstraintSystem/*!*/ Clone() { + Contract.Ensures(Contract.Result() != null); + LinearConstraintSystem z = new LinearConstraintSystem(); + z.FrameDimensions = (IMutableSet /*IVariable!*//*!*/)cce.NonNull(this.FrameDimensions.Clone()); + if (this.Constraints != null) { + z.Constraints = DeeperListCopy_LC(this.Constraints); + z.FrameVertices = DeeperListCopy_FE(cce.NonNull(this.FrameVertices)); + z.FrameRays = DeeperListCopy_FE(cce.NonNull(this.FrameRays)); + z.FrameLines = DeeperListCopy_FE(cce.NonNull(this.FrameLines)); + } else { + System.Diagnostics.Debug.Assert(this.FrameVertices == null); + System.Diagnostics.Debug.Assert(this.FrameRays == null); + System.Diagnostics.Debug.Assert(this.FrameLines == null); + // the constructor should already have set these fields of z to null + System.Diagnostics.Debug.Assert(z.Constraints == null); + System.Diagnostics.Debug.Assert(z.FrameVertices == null); + System.Diagnostics.Debug.Assert(z.FrameRays == null); + System.Diagnostics.Debug.Assert(z.FrameLines == null); + } + return z; + } - /// - /// Clones "list" and the elements of "list". - /// - /// - /// - ArrayList /*LinearConstraint*/ DeeperListCopy_LC(ArrayList! /*LinearConstraint*/ list) - { - ArrayList /*LinearConstraint*/ z = new ArrayList /*LinearConstraint*/ (list.Count); - foreach (LinearConstraint! lc in list) - { - z.Add(lc.Clone()); - } - System.Diagnostics.Debug.Assert(z.Count == list.Count); - return z; - } + /// + /// Clones "list" and the elements of "list". + /// + /// + /// + ArrayList /*LinearConstraint*/ DeeperListCopy_LC(ArrayList/*!*/ /*LinearConstraint*/ list) { + Contract.Requires(list != null); + ArrayList /*LinearConstraint*/ z = new ArrayList /*LinearConstraint*/ (list.Count); + foreach (LinearConstraint/*!*/ lc in list) { + Contract.Assert(lc != null); + z.Add(lc.Clone()); + } + System.Diagnostics.Debug.Assert(z.Count == list.Count); + return z; + } - /// - /// Clones "list" and the elements of "list". - /// - /// - /// - ArrayList /*FrameElement*/ DeeperListCopy_FE(ArrayList! /*FrameElement*/ list) - { - ArrayList /*FrameElement*/ z = new ArrayList /*FrameElement*/ (list.Count); - foreach (FrameElement! fe in list) - { - z.Add(fe.Clone()); - } - System.Diagnostics.Debug.Assert(z.Count == list.Count); - return z; - } + /// + /// Clones "list" and the elements of "list". + /// + /// + /// + ArrayList /*FrameElement*/ DeeperListCopy_FE(ArrayList/*!*/ /*FrameElement*/ list) { + Contract.Requires(list != null); + ArrayList /*FrameElement*/ z = new ArrayList /*FrameElement*/ (list.Count); + foreach (FrameElement/*!*/ fe in list) { + Contract.Assert(fe != null); + z.Add(fe.Clone()); + } + System.Diagnostics.Debug.Assert(z.Count == list.Count); + return z; + } // -------------------------------------------------------------------------------------------------------- // ------------------ Debugging and unit test routines ---------------------------------------------------- // -------------------------------------------------------------------------------------------------------- - public void Dump() - { - Console.WriteLine(" Constraints:"); - if (Constraints == null) - { - Console.WriteLine(" "); - } - else - { - foreach (LinearConstraint cc in Constraints) - { - Console.WriteLine(" {0}", cc); - } - } - - Console.WriteLine(" FrameDimensions: {0}", FrameDimensions); - - Console.WriteLine(" FrameVerticies:"); - if (FrameVertices == null) - { - Console.WriteLine(" "); - } - else - { - foreach (FrameElement fe in FrameVertices) - { - Console.WriteLine(" {0}", fe); - } - } + public void Dump() { + Console.WriteLine(" Constraints:"); + if (Constraints == null) { + Console.WriteLine(" "); + } else { + foreach (LinearConstraint cc in Constraints) { + Console.WriteLine(" {0}", cc); + } + } - Console.WriteLine(" FrameRays:"); - if (FrameRays == null) - { - Console.WriteLine(" "); - } - else - { - foreach (FrameElement fe in FrameRays) - { - Console.WriteLine(" {0}", fe); - } - } + Console.WriteLine(" FrameDimensions: {0}", FrameDimensions); - Console.WriteLine(" FrameLines:"); - if (FrameLines == null) - { - Console.WriteLine(" "); - } - else - { - foreach (FrameElement fe in FrameLines) - { - Console.WriteLine(" {0}", fe); - } - } + Console.WriteLine(" FrameVerticies:"); + if (FrameVertices == null) { + Console.WriteLine(" "); + } else { + foreach (FrameElement fe in FrameVertices) { + Console.WriteLine(" {0}", fe); } + } - class TestVariable : IVariable { - readonly string! name; - - public string! Name - { - get - { - return name; - } - } - - public TestVariable(string! name) { - this.name = name; - } - [Pure] - public object DoVisit(ExprVisitor! visitor) { - return visitor.VisitVariable(this); - } + Console.WriteLine(" FrameRays:"); + if (FrameRays == null) { + Console.WriteLine(" "); + } else { + foreach (FrameElement fe in FrameRays) { + Console.WriteLine(" {0}", fe); } - - public static void RunValidationA() - { - IVariable! dim1 = new TestVariable("X"); - IVariable! dim2 = new TestVariable("Y"); - IVariable! dim3 = new TestVariable("Z"); - - FrameElement s1 = new FrameElement(); - s1.AddCoordinate(dim1, Rational.ONE); - s1.AddCoordinate(dim2, Rational.MINUS_ONE); - s1.AddCoordinate(dim3, Rational.ZERO); - FrameElement s2 = new FrameElement(); - s2.AddCoordinate(dim1, Rational.MINUS_ONE); - s2.AddCoordinate(dim2, Rational.ONE); - s2.AddCoordinate(dim3, Rational.ZERO); - FrameElement r1 = new FrameElement(); - r1.AddCoordinate(dim1, Rational.ZERO); - r1.AddCoordinate(dim2, Rational.ZERO); - r1.AddCoordinate(dim3, Rational.ONE); - FrameElement d1 = new FrameElement(); - d1.AddCoordinate(dim1, Rational.ONE); - d1.AddCoordinate(dim2, Rational.ONE); - d1.AddCoordinate(dim3, Rational.ZERO); - - // create lcs from frame -- cf. Cousot/Halbwachs 1978, section 3.3.1.1 - LinearConstraintSystem lcs = new LinearConstraintSystem(s1); - lcs.Dump(); - - lcs.AddVertex(s2); - lcs.Dump(); - - lcs.AddRay(r1); - lcs.Dump(); - - lcs.AddLine(d1); - lcs.Dump(); - - lcs.SimplifyConstraints(); - lcs.Dump(); + } -#if LATER - lcs.GenerateFrameFromConstraints(); // should give us back the original frame... -#endif - Console.WriteLine("IsSubset? {0}", lcs.IsSubset(lcs.Clone())); - lcs.Dump(); + Console.WriteLine(" FrameLines:"); + if (FrameLines == null) { + Console.WriteLine(" "); + } else { + foreach (FrameElement fe in FrameLines) { + Console.WriteLine(" {0}", fe); } + } + } - /// - /// Tests the example in section 3.4.3 of Cousot and Halbwachs. - /// - public static void RunValidationB() - { - IVariable! X = new TestVariable("X"); - IVariable! Y = new TestVariable("Y"); - IVariable! Z = new TestVariable("Z"); - ArrayList /*LinearConstraint*/ cs = new ArrayList /*LinearConstraint*/ (); - - LinearConstraint c = new LinearConstraint(LinearConstraint.ConstraintRelation.LE); - c.SetCoefficient(X, Rational.MINUS_ONE); - c.SetCoefficient(Y, Rational.ONE); - c.SetCoefficient(Z, Rational.MINUS_ONE); - c.rhs = Rational.ZERO; - cs.Add(c); - - c = new LinearConstraint(LinearConstraint.ConstraintRelation.LE); - c.SetCoefficient(X, Rational.MINUS_ONE); - c.rhs = Rational.MINUS_ONE; - cs.Add(c); - - c = new LinearConstraint(LinearConstraint.ConstraintRelation.LE); - c.SetCoefficient(X, Rational.MINUS_ONE); - c.SetCoefficient(Y, Rational.MINUS_ONE); - c.SetCoefficient(Z, Rational.ONE); - c.rhs = Rational.ZERO; - cs.Add(c); - - c = new LinearConstraint(LinearConstraint.ConstraintRelation.LE); - c.SetCoefficient(Y, Rational.MINUS_ONE); - c.SetCoefficient(Z, Rational.ONE); - c.rhs = Rational.FromInt(3); - cs.Add(c); - - LinearConstraintSystem lcs = new LinearConstraintSystem(cs); - Console.WriteLine("==================== The final linear constraint system ===================="); - lcs.Dump(); + class TestVariable : IVariable { + readonly string/*!*/ name; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(name != null); + } + + + public string/*!*/ Name { + get { + Contract.Ensures(Contract.Result() != null); + + return name; } + } - public static void RunValidationC() - { - // Run the example in section 3.4.3 of Cousot and Halbwachs backwards, that is, from - // from to constraints. - IVariable! dim1 = new TestVariable("X"); - IVariable! dim2 = new TestVariable("Y"); - IVariable! dim3 = new TestVariable("Z"); + public TestVariable(string/*!*/ name) { + Contract.Requires(name != null); + this.name = name; + } + [Pure] + public object DoVisit(ExprVisitor/*!*/ visitor) { + Contract.Requires(visitor != null); + return visitor.VisitVariable(this); + } + } - FrameElement s0 = new FrameElement(); - s0.AddCoordinate(dim1, Rational.ONE); - s0.AddCoordinate(dim2, Rational.FromInts(1, 2)); - s0.AddCoordinate(dim3, Rational.FromInts(-1, 2)); + public static void RunValidationA() { + IVariable/*!*/ dim1 = new TestVariable("X"); + IVariable/*!*/ dim2 = new TestVariable("Y"); + IVariable/*!*/ dim3 = new TestVariable("Z"); + Contract.Assert(dim1 != null); + Contract.Assert(dim2 != null); + Contract.Assert(dim3 != null); + + FrameElement s1 = new FrameElement(); + s1.AddCoordinate(dim1, Rational.ONE); + s1.AddCoordinate(dim2, Rational.MINUS_ONE); + s1.AddCoordinate(dim3, Rational.ZERO); + FrameElement s2 = new FrameElement(); + s2.AddCoordinate(dim1, Rational.MINUS_ONE); + s2.AddCoordinate(dim2, Rational.ONE); + s2.AddCoordinate(dim3, Rational.ZERO); + FrameElement r1 = new FrameElement(); + r1.AddCoordinate(dim1, Rational.ZERO); + r1.AddCoordinate(dim2, Rational.ZERO); + r1.AddCoordinate(dim3, Rational.ONE); + FrameElement d1 = new FrameElement(); + d1.AddCoordinate(dim1, Rational.ONE); + d1.AddCoordinate(dim2, Rational.ONE); + d1.AddCoordinate(dim3, Rational.ZERO); + + // create lcs from frame -- cf. Cousot/Halbwachs 1978, section 3.3.1.1 + LinearConstraintSystem lcs = new LinearConstraintSystem(s1); + lcs.Dump(); - FrameElement s1 = new FrameElement(); - s1.AddCoordinate(dim1, Rational.ONE); - s1.AddCoordinate(dim2, Rational.FromInts(-1, 2)); - s1.AddCoordinate(dim3, Rational.FromInts(1, 2)); + lcs.AddVertex(s2); + lcs.Dump(); - FrameElement s2 = new FrameElement(); - s2.AddCoordinate(dim1, Rational.FromInt(3)); - s2.AddCoordinate(dim2, Rational.FromInts(-3, 2)); - s2.AddCoordinate(dim3, Rational.FromInts(3, 2)); + lcs.AddRay(r1); + lcs.Dump(); - FrameElement r0 = new FrameElement(); - r0.AddCoordinate(dim1, Rational.ONE); - r0.AddCoordinate(dim2, Rational.FromInts(1, 2)); - r0.AddCoordinate(dim3, Rational.FromInts(-1, 2)); + lcs.AddLine(d1); + lcs.Dump(); - FrameElement r1 = new FrameElement(); - r1.AddCoordinate(dim1, Rational.ONE); - r1.AddCoordinate(dim2, Rational.ZERO); - r1.AddCoordinate(dim3, Rational.ZERO); + lcs.SimplifyConstraints(); + lcs.Dump(); + +#if LATER + lcs.GenerateFrameFromConstraints(); // should give us back the original frame... +#endif + Console.WriteLine("IsSubset? {0}", lcs.IsSubset(lcs.Clone())); + lcs.Dump(); + } - FrameElement d0 = new FrameElement(); - d0.AddCoordinate(dim1, Rational.ZERO); - d0.AddCoordinate(dim2, Rational.ONE); - d0.AddCoordinate(dim3, Rational.ONE); + /// + /// Tests the example in section 3.4.3 of Cousot and Halbwachs. + /// + public static void RunValidationB() { + IVariable/*!*/ X = new TestVariable("X"); + IVariable/*!*/ Y = new TestVariable("Y"); + IVariable/*!*/ Z = new TestVariable("Z"); + Contract.Assert(X != null); + Contract.Assert(Y != null); + Contract.Assert(Z != null); + ArrayList /*LinearConstraint*/ cs = new ArrayList /*LinearConstraint*/ (); + + LinearConstraint c = new LinearConstraint(LinearConstraint.ConstraintRelation.LE); + c.SetCoefficient(X, Rational.MINUS_ONE); + c.SetCoefficient(Y, Rational.ONE); + c.SetCoefficient(Z, Rational.MINUS_ONE); + c.rhs = Rational.ZERO; + cs.Add(c); + + c = new LinearConstraint(LinearConstraint.ConstraintRelation.LE); + c.SetCoefficient(X, Rational.MINUS_ONE); + c.rhs = Rational.MINUS_ONE; + cs.Add(c); + + c = new LinearConstraint(LinearConstraint.ConstraintRelation.LE); + c.SetCoefficient(X, Rational.MINUS_ONE); + c.SetCoefficient(Y, Rational.MINUS_ONE); + c.SetCoefficient(Z, Rational.ONE); + c.rhs = Rational.ZERO; + cs.Add(c); + + c = new LinearConstraint(LinearConstraint.ConstraintRelation.LE); + c.SetCoefficient(Y, Rational.MINUS_ONE); + c.SetCoefficient(Z, Rational.ONE); + c.rhs = Rational.FromInt(3); + cs.Add(c); + + LinearConstraintSystem lcs = new LinearConstraintSystem(cs); + Console.WriteLine("==================== The final linear constraint system ===================="); + lcs.Dump(); + } - LinearConstraintSystem lcs = new LinearConstraintSystem(s0); - lcs.Dump(); + public static void RunValidationC() { + // Run the example in section 3.4.3 of Cousot and Halbwachs backwards, that is, from + // from to constraints. + IVariable/*!*/ dim1 = new TestVariable("X"); + IVariable/*!*/ dim2 = new TestVariable("Y"); + IVariable/*!*/ dim3 = new TestVariable("Z"); + Contract.Assert(dim1 != null); + Contract.Assert(dim2 != null); + Contract.Assert(dim3 != null); + + FrameElement s0 = new FrameElement(); + s0.AddCoordinate(dim1, Rational.ONE); + s0.AddCoordinate(dim2, Rational.FromInts(1, 2)); + s0.AddCoordinate(dim3, Rational.FromInts(-1, 2)); + + FrameElement s1 = new FrameElement(); + s1.AddCoordinate(dim1, Rational.ONE); + s1.AddCoordinate(dim2, Rational.FromInts(-1, 2)); + s1.AddCoordinate(dim3, Rational.FromInts(1, 2)); + + FrameElement s2 = new FrameElement(); + s2.AddCoordinate(dim1, Rational.FromInt(3)); + s2.AddCoordinate(dim2, Rational.FromInts(-3, 2)); + s2.AddCoordinate(dim3, Rational.FromInts(3, 2)); + + FrameElement r0 = new FrameElement(); + r0.AddCoordinate(dim1, Rational.ONE); + r0.AddCoordinate(dim2, Rational.FromInts(1, 2)); + r0.AddCoordinate(dim3, Rational.FromInts(-1, 2)); + + FrameElement r1 = new FrameElement(); + r1.AddCoordinate(dim1, Rational.ONE); + r1.AddCoordinate(dim2, Rational.ZERO); + r1.AddCoordinate(dim3, Rational.ZERO); + + FrameElement d0 = new FrameElement(); + d0.AddCoordinate(dim1, Rational.ZERO); + d0.AddCoordinate(dim2, Rational.ONE); + d0.AddCoordinate(dim3, Rational.ONE); + + LinearConstraintSystem lcs = new LinearConstraintSystem(s0); + lcs.Dump(); - lcs.AddVertex(s1); - lcs.Dump(); + lcs.AddVertex(s1); + lcs.Dump(); - lcs.AddVertex(s2); - lcs.Dump(); + lcs.AddVertex(s2); + lcs.Dump(); - lcs.AddRay(r0); - lcs.Dump(); + lcs.AddRay(r0); + lcs.Dump(); - lcs.AddRay(r1); - lcs.Dump(); + lcs.AddRay(r1); + lcs.Dump(); - lcs.AddLine(d0); - lcs.Dump(); + lcs.AddLine(d0); + lcs.Dump(); - lcs.SimplifyConstraints(); - lcs.Dump(); + lcs.SimplifyConstraints(); + lcs.Dump(); #if LATER lcs.GenerateFrameFromConstraints(); // should give us back the original frame... #endif - } } + } } \ No newline at end of file diff --git a/Source/AIFramework/Polyhedra/PolyhedraAbstraction.cs b/Source/AIFramework/Polyhedra/PolyhedraAbstraction.cs index fdb8d86d..60aceb7f 100644 --- a/Source/AIFramework/Polyhedra/PolyhedraAbstraction.cs +++ b/Source/AIFramework/Polyhedra/PolyhedraAbstraction.cs @@ -3,13 +3,12 @@ // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- -namespace Microsoft.AbstractInterpretationFramework -{ +namespace Microsoft.AbstractInterpretationFramework { using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; - using Microsoft.Contracts; + using System.Diagnostics.Contracts; using Microsoft.Basetypes; using ISet = Microsoft.Boogie.Set; @@ -19,95 +18,102 @@ namespace Microsoft.AbstractInterpretationFramework /// /// Represents an invariant over linear variable constraints, represented by a polyhedron. /// - public class PolyhedraLattice : Lattice - { - private static readonly Logger! log = new Logger("Polyhedra"); + public class PolyhedraLattice : Lattice { + private static readonly Logger/*!*/ log = new Logger("Polyhedra"); - private class PolyhedraLatticeElement : Element - { + private class PolyhedraLatticeElement : Element { + + public LinearConstraintSystem/*!*/ lcs; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(lcs != null); + } - public LinearConstraintSystem! lcs; /// /// Creates a top or bottom elements, according to parameter "top". /// - public PolyhedraLatticeElement (bool top) - { - if (top) - { + public PolyhedraLatticeElement(bool top) { + if (top) { lcs = new LinearConstraintSystem(new ArrayList /*LinearConstraint*/ ()); - } - else - { + } else { lcs = new LinearConstraintSystem(); } } [Pure] - public override string! ToString() - { + public override string/*!*/ ToString() { + Contract.Ensures(Contract.Result() != null); return lcs.ToString(); } - public override void Dump(string! msg) { + public override void Dump(string/*!*/ msg) { + Contract.Requires(msg != null); System.Console.WriteLine("PolyhedraLatticeElement.Dump({0}):", msg); lcs.Dump(); } [Pure] - public override ICollection! FreeVariables() - { + public override ICollection/*!*/ FreeVariables() { + Contract.Ensures(cce.NonNullElements(Contract.Result>())); return lcs.FreeVariables(); } - public PolyhedraLatticeElement (LinearConstraintSystem! lcs) - { + public PolyhedraLatticeElement(LinearConstraintSystem/*!*/ lcs) { + Contract.Requires(lcs != null); this.lcs = lcs; } - public override Element! Clone () - { - return new PolyhedraLatticeElement( (!) lcs.Clone()); + public override Element/*!*/ Clone() { + Contract.Ensures(Contract.Result() != null); + return new PolyhedraLatticeElement(cce.NonNull(lcs.Clone())); } } // class - readonly ILinearExprFactory! factory; - readonly IPropExprFactory! propFactory; + readonly ILinearExprFactory/*!*/ factory; + readonly IPropExprFactory/*!*/ propFactory; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(log != null); + Contract.Invariant(factory != null); + Contract.Invariant(propFactory != null); + } - public PolyhedraLattice(ILinearExprFactory! linearFactory, IPropExprFactory! propFactory) - : base(linearFactory) - { - log.Enabled = Lattice.LogSwitch; - this.factory = linearFactory; - this.propFactory = propFactory; - // base(linearFactory); + + public PolyhedraLattice(ILinearExprFactory/*!*/ linearFactory, IPropExprFactory/*!*/ propFactory) + : base(linearFactory) { + Contract.Requires(propFactory != null); + Contract.Requires(linearFactory != null); + log.Enabled = Lattice.LogSwitch; + this.factory = linearFactory; + this.propFactory = propFactory; + // base(linearFactory); } - public override Element! Top - { - get - { - return new PolyhedraLatticeElement(true); - } - } + public override Element/*!*/ Top { + get { + Contract.Ensures(Contract.Result() != null); + return new PolyhedraLatticeElement(true); + } + } - public override Element! Bottom - { - get - { - return new PolyhedraLatticeElement(false); - } - } + public override Element/*!*/ Bottom { + get { + Contract.Ensures(Contract.Result() != null); - public override bool IsBottom (Element! element) - { + return new PolyhedraLatticeElement(false); + } + } + + public override bool IsBottom(Element/*!*/ element) { + Contract.Requires(element != null); PolyhedraLatticeElement e = (PolyhedraLatticeElement)element; return e.lcs.IsBottom(); } - public override bool IsTop (Element! element) - { + public override bool IsTop(Element/*!*/ element) { + Contract.Requires(element != null); PolyhedraLatticeElement e = (PolyhedraLatticeElement)element; return e.lcs.IsTop(); } @@ -118,32 +124,39 @@ namespace Microsoft.AbstractInterpretationFramework /// /// /// - protected override bool AtMost (Element! first, Element! second) // this <= that + protected override bool AtMost(Element/*!*/ first, Element/*!*/ second) // this <= that { - PolyhedraLatticeElement a = (PolyhedraLatticeElement) first; - PolyhedraLatticeElement b = (PolyhedraLatticeElement) second; + Contract.Requires(first != null); + Contract.Requires(second != null); + PolyhedraLatticeElement a = (PolyhedraLatticeElement)first; + PolyhedraLatticeElement b = (PolyhedraLatticeElement)second; return b.lcs.IsSubset(a.lcs); } - public override string! ToString (Element! e) - { - return ((PolyhedraLatticeElement)e).lcs.ToString(); - } + public override string/*!*/ ToString(Element/*!*/ e) { + Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); + return ((PolyhedraLatticeElement)e).lcs.ToString(); + } - public override IExpr! ToPredicate(Element! element) - { - PolyhedraLatticeElement e = (PolyhedraLatticeElement)element; - return e.lcs.ConvertToExpression(factory); - } + public override IExpr/*!*/ ToPredicate(Element/*!*/ element) { + Contract.Requires(element != null); + Contract.Ensures(Contract.Result() != null); + PolyhedraLatticeElement e = (PolyhedraLatticeElement)element; + return e.lcs.ConvertToExpression(factory); + } - public override Lattice.Element! NontrivialJoin (Element! first, Element! second) - { - log.DbgMsg("Joining ..."); log.DbgMsgIndent(); - PolyhedraLatticeElement aa = (PolyhedraLatticeElement) first; - PolyhedraLatticeElement bb = (PolyhedraLatticeElement) second; + public override Lattice.Element/*!*/ NontrivialJoin(Element/*!*/ first, Element/*!*/ second) { + Contract.Requires(second != null); + Contract.Requires(first != null); + Contract.Ensures(Contract.Result() != null); + log.DbgMsg("Joining ..."); + log.DbgMsgIndent(); + PolyhedraLatticeElement aa = (PolyhedraLatticeElement)first; + PolyhedraLatticeElement bb = (PolyhedraLatticeElement)second; PolyhedraLatticeElement result = new PolyhedraLatticeElement(aa.lcs.Join(bb.lcs)); log.DbgMsg(string.Format("{0} |_| {1} --> {2}", this.ToString(first), this.ToString(second), this.ToString(result))); log.DbgMsgUnindent(); @@ -151,152 +164,191 @@ namespace Microsoft.AbstractInterpretationFramework } - public override Lattice.Element! NontrivialMeet (Element! first, Element! second) - { - PolyhedraLatticeElement aa = (PolyhedraLatticeElement) first; - PolyhedraLatticeElement bb = (PolyhedraLatticeElement) second; + public override Lattice.Element/*!*/ NontrivialMeet(Element/*!*/ first, Element/*!*/ second) { + Contract.Requires(second != null); + Contract.Requires(first != null); + Contract.Ensures(Contract.Result() != null); + PolyhedraLatticeElement aa = (PolyhedraLatticeElement)first; + PolyhedraLatticeElement bb = (PolyhedraLatticeElement)second; return new PolyhedraLatticeElement(aa.lcs.Meet(bb.lcs)); } - public override Lattice.Element! Widen (Element! first, Element! second) - { - log.DbgMsg("Widening ..."); log.DbgMsgIndent(); - PolyhedraLatticeElement aa = (PolyhedraLatticeElement)first; - PolyhedraLatticeElement bb = (PolyhedraLatticeElement)second; - - LinearConstraintSystem lcs = aa.lcs.Widen(bb.lcs); - PolyhedraLatticeElement result = new PolyhedraLatticeElement(lcs); - log.DbgMsg(string.Format("{0} |_| {1} --> {2}", this.ToString(first), this.ToString(second), this.ToString(result))); - log.DbgMsgUnindent(); - return result; - } + public override Lattice.Element/*!*/ Widen(Element/*!*/ first, Element/*!*/ second) { + Contract.Requires(second != null); + Contract.Requires(first != null); + Contract.Ensures(Contract.Result() != null); + log.DbgMsg("Widening ..."); + log.DbgMsgIndent(); + PolyhedraLatticeElement aa = (PolyhedraLatticeElement)first; + PolyhedraLatticeElement bb = (PolyhedraLatticeElement)second; + LinearConstraintSystem lcs = aa.lcs.Widen(bb.lcs); + PolyhedraLatticeElement result = new PolyhedraLatticeElement(lcs); + log.DbgMsg(string.Format("{0} |_| {1} --> {2}", this.ToString(first), this.ToString(second), this.ToString(result))); + log.DbgMsgUnindent(); + return result; + } - public override Element! Eliminate (Element! e, IVariable! variable) - { + + public override Element/*!*/ Eliminate(Element/*!*/ e, IVariable/*!*/ variable) { + Contract.Requires(variable != null); + Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); log.DbgMsg(string.Format("Eliminating {0} ...", variable)); - + PolyhedraLatticeElement ple = (PolyhedraLatticeElement)e; - if (ple.lcs.IsBottom()) - { + if (ple.lcs.IsBottom()) { return ple; } return new PolyhedraLatticeElement(ple.lcs.Project(variable)); } - public override Element! Rename (Element! e, IVariable! oldName, IVariable! newName) - { + public override Element/*!*/ Rename(Element/*!*/ e, IVariable/*!*/ oldName, IVariable/*!*/ newName) { + Contract.Requires(newName != null); + Contract.Requires(oldName != null); + Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); log.DbgMsg(string.Format("Renaming {0} to {1} in {2} ...", oldName, newName, this.ToString(e))); - + PolyhedraLatticeElement ple = (PolyhedraLatticeElement)e; - if (ple.lcs.IsBottom()) - { + if (ple.lcs.IsBottom()) { return ple; } return new PolyhedraLatticeElement(ple.lcs.Rename(oldName, newName)); } - public override bool Understands(IFunctionSymbol! f, IList/**/! args) { - return f is IntSymbol || - f.Equals(Int.Add) || - f.Equals(Int.Sub) || - f.Equals(Int.Negate) || - f.Equals(Int.Mul) || - f.Equals(Int.Eq) || - f.Equals(Int.Neq) || - f.Equals(Prop.Not) || - f.Equals(Int.AtMost) || - f.Equals(Int.Less) || - f.Equals(Int.Greater) || - f.Equals(Int.AtLeast); - } - - public override Answer CheckVariableDisequality(Element! e, IVariable! var1, IVariable! var2) { - PolyhedraLatticeElement! ple = (PolyhedraLatticeElement)e; - assume ple.lcs.Constraints != null; - ArrayList /*LinearConstraint!*/! clist = (ArrayList /*LinearConstraint!*/!)ple.lcs.Constraints.Clone(); - LinearConstraint! lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ); - lc.SetCoefficient(var1, Rational.ONE); - lc.SetCoefficient(var2, Rational.MINUS_ONE); - clist.Add(lc); - LinearConstraintSystem newLcs = new LinearConstraintSystem(clist); - if (newLcs.IsBottom()) { - return Answer.Yes; - } else { - return Answer.Maybe; - } + public override bool Understands(IFunctionSymbol/*!*/ f, IList/**//*!*/ args) { + Contract.Requires(args != null); + Contract.Requires(f != null); + return f is IntSymbol || + f.Equals(Int.Add) || + f.Equals(Int.Sub) || + f.Equals(Int.Negate) || + f.Equals(Int.Mul) || + f.Equals(Int.Eq) || + f.Equals(Int.Neq) || + f.Equals(Prop.Not) || + f.Equals(Int.AtMost) || + f.Equals(Int.Less) || + f.Equals(Int.Greater) || + f.Equals(Int.AtLeast); } - public override Answer CheckPredicate(Element! e, IExpr! pred) { - PolyhedraLatticeElement! ple = (PolyhedraLatticeElement)Constrain(e, pred); - if (ple.lcs.IsBottom()) { - return Answer.No; - } - - // Note, "pred" may contain expressions that are not understood by the propFactory (in - // particular, this may happen because--currently, and perhaps is a design we'll want - // to change in the future--propFactory deals with BoogiePL expressions whereas "pred" - // may also refer to Equivalences.UninterpFun expressions). Thus, we cannot just - // call propFactory.Not(pred) to get the negation of "pred". - pred = new PolyhedraLatticeNegation(pred); - ple = (PolyhedraLatticeElement)Constrain(e, pred); - if (ple.lcs.IsBottom()) { - return Answer.Yes; - } else { - return Answer.Maybe; - } + public override Answer CheckVariableDisequality(Element/*!*/ e, IVariable/*!*/ var1, IVariable/*!*/ var2) { + Contract.Requires(var2 != null); + Contract.Requires(var1 != null); + Contract.Requires(e != null); + PolyhedraLatticeElement/*!*/ ple = (PolyhedraLatticeElement)cce.NonNull(e); + Contract.Assume(ple.lcs.Constraints != null); + ArrayList /*LinearConstraint!*//*!*/ clist = (ArrayList /*LinearConstraint!*/)cce.NonNull(ple.lcs.Constraints.Clone()); + LinearConstraint/*!*/ lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ); + Contract.Assert(lc != null); + lc.SetCoefficient(var1, Rational.ONE); + lc.SetCoefficient(var2, Rational.MINUS_ONE); + clist.Add(lc); + LinearConstraintSystem newLcs = new LinearConstraintSystem(clist); + if (newLcs.IsBottom()) { + return Answer.Yes; + } else { + return Answer.Maybe; + } } - - class PolyhedraLatticeNegation : IFunApp - { - IExpr! arg; - - public PolyhedraLatticeNegation(IExpr! arg) { + + public override Answer CheckPredicate(Element/*!*/ e, IExpr/*!*/ pred) { + Contract.Requires(pred != null); + Contract.Requires(e != null); + PolyhedraLatticeElement/*!*/ ple = (PolyhedraLatticeElement)Constrain(e, pred); + Contract.Assert(ple != null); + if (ple.lcs.IsBottom()) { + return Answer.No; + } + + // Note, "pred" may contain expressions that are not understood by the propFactory (in + // particular, this may happen because--currently, and perhaps is a design we'll want + // to change in the future--propFactory deals with BoogiePL expressions whereas "pred" + // may also refer to Equivalences.UninterpFun expressions). Thus, we cannot just + // call propFactory.Not(pred) to get the negation of "pred". + pred = new PolyhedraLatticeNegation(pred); + ple = (PolyhedraLatticeElement)Constrain(e, pred); + if (ple.lcs.IsBottom()) { + return Answer.Yes; + } else { + return Answer.Maybe; + } + } + + class PolyhedraLatticeNegation : IFunApp { + IExpr/*!*/ arg; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(arg != null); + } + + + public PolyhedraLatticeNegation(IExpr/*!*/ arg) { + Contract.Requires(arg != null); this.arg = arg; // base(); } - - [Pure] public object DoVisit(ExprVisitor! visitor) { + + [Pure] + public object DoVisit(ExprVisitor/*!*/ visitor) { + Contract.Requires(visitor != null); return visitor.VisitFunApp(this); } - - public IFunctionSymbol! FunctionSymbol { get { return Prop.Not; } } - public IList/**/! Arguments { + public IFunctionSymbol/*!*/ FunctionSymbol { + get { + Contract.Ensures(Contract.Result() != null); + return Prop.Not; + } + } + + public IList/**//*!*/ Arguments { get { + Contract.Ensures(Contract.Result() != null); + IExpr[] args = new IExpr[] { arg }; - return ArrayList.ReadOnly(args); + return ArrayList.ReadOnly(args); } } - public IFunApp! CloneWithArguments(IList/**/! args) { - assert args.Count == 1; - return new PolyhedraLatticeNegation((IExpr!)args[0]); + public IFunApp/*!*/ CloneWithArguments(IList/**//*!*/ args) { + Contract.Requires(args != null); + Contract.Ensures(Contract.Result() != null); + Contract.Assert(args.Count == 1); + return new PolyhedraLatticeNegation((IExpr/*!*/)cce.NonNull(args[0])); } } - public override IExpr/*?*/ EquivalentExpr(Element! e, IQueryable! q, IExpr! expr, IVariable! var, ISet/**/! prohibitedVars) { - // BUGBUG: TODO: this method can be implemented in a more precise way - return null; + public override IExpr/*?*/ EquivalentExpr(Element/*!*/ e, IQueryable/*!*/ q, IExpr/*!*/ expr, IVariable/*!*/ var, ISet/**//*!*/ prohibitedVars) { + Contract.Requires(prohibitedVars != null); + Contract.Requires(var != null); + Contract.Requires(expr != null); + Contract.Requires(q != null); + Contract.Requires(e != null); + // BUGBUG: TODO: this method can be implemented in a more precise way + return null; } - public override Element! Constrain (Element! e, IExpr! expr) - { + public override Element/*!*/ Constrain(Element/*!*/ e, IExpr/*!*/ expr) { + Contract.Requires(expr != null); + Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); log.DbgMsg(string.Format("Constraining with {0} into {1} ...", expr, this.ToString(e))); - + PolyhedraLatticeElement ple = (PolyhedraLatticeElement)e; - if (ple.lcs.IsBottom()) - { + if (ple.lcs.IsBottom()) { return ple; } LinearCondition le = LinearExpressionBuilder.AsCondition(expr); if (le != null) { // update the polyhedron according to the linear expression - assume ple.lcs.Constraints != null; - ArrayList /*LinearConstraint*/ clist = (ArrayList! /*LinearConstraint*/)ple.lcs.Constraints.Clone(); + Contract.Assume(ple.lcs.Constraints != null); + ArrayList /*LinearConstraint*/ clist = (ArrayList/*!*/ /*LinearConstraint*/)cce.NonNull(ple.lcs.Constraints.Clone()); le.AddToConstraintSystem(clist); LinearConstraintSystem newLcs = new LinearConstraintSystem(clist); @@ -308,437 +360,404 @@ namespace Microsoft.AbstractInterpretationFramework } // class + /// + /// A LinearCondition follows this grammar: + /// LinearCondition ::= unsatisfiable + /// | LinearConstraint + /// | ! LinearConstraint + /// Note that negations are distributed to the leaves. + /// + /// + [ContractClass(typeof(LinearConditionContracts))] + abstract class LinearCondition { + /// + /// Adds constraints to the list "clist". If "this" + /// entails some disjunctive constraints, they may not be added. + /// + /// + public abstract void AddToConstraintSystem(ArrayList/*!*/ /*LinearConstraint*/ clist); + } + [ContractClassFor(typeof(LinearCondition))] + abstract class LinearConditionContracts : LinearCondition { + public override void AddToConstraintSystem(ArrayList clist) { + Contract.Requires(clist != null); + throw new NotImplementedException(); + } + } + + class LCBottom : LinearCondition { + public override void AddToConstraintSystem(ArrayList/*!*/ /*LinearConstraint*/ clist) { + Contract.Requires(clist != null); + // make an unsatisfiable constraint + LinearConstraint lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ); + lc.rhs = Rational.FromInt(1); + clist.Add(lc); + } + } + + class LinearConditionLiteral : LinearCondition { + public readonly bool positive; + public readonly LinearConstraint/*!*/ constraint; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(constraint != null); + } + /// - /// A LinearCondition follows this grammar: - /// LinearCondition ::= unsatisfiable - /// | LinearConstraint - /// | ! LinearConstraint - /// Note that negations are distributed to the leaves. + /// Precondition: positive || constraint.Relation == LinearConstraint.ConstraintRelation.EQ /// - abstract class LinearCondition - { - /// - /// Adds constraints to the list "clist". If "this" - /// entails some disjunctive constraints, they may not be added. - /// - /// - public abstract void AddToConstraintSystem(ArrayList! /*LinearConstraint*/ clist); + /// + /// + public LinearConditionLiteral(bool positive, LinearConstraint/*!*/ constraint) { + Contract.Requires(constraint != null); + Contract.Requires(positive || constraint.Relation == LinearConstraint.ConstraintRelation.EQ); + this.positive = positive; + this.constraint = constraint; + } + public override void AddToConstraintSystem(ArrayList/*!*/ /*LinearConstraint*/ clist) { + Contract.Requires(clist != null); + if (positive) { + clist.Add(constraint); + } else { + Contract.Assert(constraint.Relation == LinearConstraint.ConstraintRelation.EQ); + // the constraint is disjunctive, so just ignore it + } } + } - class LCBottom : LinearCondition + class LinearExpressionBuilder { + /// + /// Builds a linear condition from "e", if possible; returns null if not possible. + /// + /// + /// + public static /*maybe null*/ LinearCondition AsCondition(IExpr e) /* throws ArithmeticException */ { - public override void AddToConstraintSystem(ArrayList! /*LinearConstraint*/ clist) - { - // make an unsatisfiable constraint - LinearConstraint lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ); - lc.rhs = Rational.FromInt(1); - clist.Add(lc); - } + return GetCond(e, true); } - class LinearConditionLiteral : LinearCondition + static /*maybe null*/ LinearCondition GetCond(IExpr e, bool positive) /* throws ArithmeticException */ { - public readonly bool positive; - public readonly LinearConstraint! constraint; - /// - /// Precondition: positive || constraint.Relation == LinearConstraint.ConstraintRelation.EQ - /// - /// - /// - public LinearConditionLiteral(bool positive, LinearConstraint! constraint) - requires positive || constraint.Relation == LinearConstraint.ConstraintRelation.EQ; - { - this.positive = positive; - this.constraint = constraint; + IFunApp funapp = e as IFunApp; + if (funapp == null) { + return null; + } + IFunctionSymbol/*!*/ s = funapp.FunctionSymbol; + Contract.Assert(s != null); + if ((positive && s.Equals(Prop.False)) || + (!positive && s.Equals(Prop.True))) { + return new LCBottom(); + } else if (s.Equals(Prop.Not)) { + Contract.Assert(funapp.Arguments.Count == 1); + return GetCond((IExpr/*!*/)cce.NonNull(funapp.Arguments[0]), !positive); + } else if (funapp.Arguments.Count == 2) { + IExpr/*!*/ arg0 = (IExpr/*!*/)cce.NonNull(funapp.Arguments[0]); + IExpr/*!*/ arg1 = (IExpr/*!*/)cce.NonNull(funapp.Arguments[1]); + LinearExpr le0 = AsExpr(arg0); + if (le0 == null) { + return null; } - public override void AddToConstraintSystem(ArrayList! /*LinearConstraint*/ clist) - { - if (positive) - { - clist.Add(constraint); - } - else - { - assert constraint.Relation == LinearConstraint.ConstraintRelation.EQ; - // the constraint is disjunctive, so just ignore it - } + LinearExpr le1 = AsExpr(arg1); + if (le1 == null) { + return null; + } + + LinearConstraint constraint = null; + bool sense = true; + if ((positive && s.Equals(Int.Less)) || (!positive && s.Equals(Int.AtLeast))) { + constraint = MakeConstraint(le0, le1, LinearConstraint.ConstraintRelation.LE, BigNum.ONE); + } else if ((positive && s.Equals(Int.AtMost)) || (!positive && s.Equals(Int.Greater))) { + constraint = MakeConstraint(le0, le1, LinearConstraint.ConstraintRelation.LE, BigNum.ZERO); + } else if ((positive && s.Equals(Int.AtLeast)) || (!positive && s.Equals(Int.Less))) { + constraint = MakeConstraint(le1, le0, LinearConstraint.ConstraintRelation.LE, BigNum.ZERO); + } else if ((positive && s.Equals(Int.Greater)) || (!positive && s.Equals(Int.AtMost))) { + constraint = MakeConstraint(le1, le0, LinearConstraint.ConstraintRelation.LE, BigNum.ONE); + } else if (s.Equals(Int.Eq)) { + constraint = MakeConstraint(le0, le1, LinearConstraint.ConstraintRelation.EQ, BigNum.ZERO); + sense = positive; + } else if (s.Equals(Int.Neq)) { + constraint = MakeConstraint(le0, le1, LinearConstraint.ConstraintRelation.EQ, BigNum.ZERO); + sense = !positive; + } + if (constraint != null) { + if (constraint.coefficients.Count != 0) { + return new LinearConditionLiteral(sense, constraint); + } else if (constraint.IsConstantSatisfiable()) { + return null; + } else { + return new LCBottom(); + } } + } + return null; } - class LinearExpressionBuilder + public static LinearConstraint MakeConstraint(LinearExpr/*!*/ le0, LinearExpr/*!*/ le1, + LinearConstraint.ConstraintRelation rel, BigNum constantOffset) /* throws ArithmeticException */ { - /// - /// Builds a linear condition from "e", if possible; returns null if not possible. - /// - /// - /// - public static /*maybe null*/ LinearCondition AsCondition(IExpr e) /* throws ArithmeticException */ - { - return GetCond(e, true); - } + Contract.Requires(le0 != null); + Contract.Requires(le1 != null); + le1.Negate(); + le0.Add(le1); + le0.AddConstant(constantOffset); + return le0.ToConstraint(rel); + } - static /*maybe null*/ LinearCondition GetCond(IExpr e, bool positive) /* throws ArithmeticException */ - { - IFunApp funapp = e as IFunApp; - if (funapp == null) { - return null; - } - IFunctionSymbol! s = funapp.FunctionSymbol; - if ((positive && s.Equals(Prop.False)) || - (!positive && s.Equals(Prop.True))) { - return new LCBottom(); - } else if (s.Equals(Prop.Not)) { - assert funapp.Arguments.Count == 1; - return GetCond((IExpr!)funapp.Arguments[0], !positive); - } else if (funapp.Arguments.Count == 2) { - IExpr! arg0 = (IExpr!)funapp.Arguments[0]; - IExpr! arg1 = (IExpr!)funapp.Arguments[1]; - LinearExpr le0 = AsExpr(arg0); - if (le0 == null) { - return null; - } - LinearExpr le1 = AsExpr(arg1); - if (le1 == null) { - return null; - } - - LinearConstraint constraint = null; - bool sense = true; - if ((positive && s.Equals(Int.Less)) || (!positive && s.Equals(Int.AtLeast))) - { - constraint = MakeConstraint(le0, le1, LinearConstraint.ConstraintRelation.LE, BigNum.ONE); - } - else if ((positive && s.Equals(Int.AtMost)) || (!positive && s.Equals(Int.Greater))) - { - constraint = MakeConstraint(le0, le1, LinearConstraint.ConstraintRelation.LE, BigNum.ZERO); - } - else if ((positive && s.Equals(Int.AtLeast)) || (!positive && s.Equals(Int.Less))) - { - constraint = MakeConstraint(le1, le0, LinearConstraint.ConstraintRelation.LE, BigNum.ZERO); - } - else if ((positive && s.Equals(Int.Greater)) || (!positive && s.Equals(Int.AtMost))) - { - constraint = MakeConstraint(le1, le0, LinearConstraint.ConstraintRelation.LE, BigNum.ONE); - } - else if (s.Equals(Int.Eq)) - { - constraint = MakeConstraint(le0, le1, LinearConstraint.ConstraintRelation.EQ, BigNum.ZERO); - sense = positive; - } - else if (s.Equals(Int.Neq)) - { - constraint = MakeConstraint(le0, le1, LinearConstraint.ConstraintRelation.EQ, BigNum.ZERO); - sense = !positive; - } - if (constraint != null) { - if (constraint.coefficients.Count != 0) { - return new LinearConditionLiteral(sense, constraint); - } else if (constraint.IsConstantSatisfiable()) { - return null; - } else { - return new LCBottom(); - } - } - } + /// + /// Builds a linear expression from "e", if possible; returns null if not possible. + /// + /// + /// + public static /*maybe null*/ LinearExpr AsExpr(IExpr/*!*/ e) /* throws ArithmeticException */ + { + Contract.Requires(e != null); + if (e is IVariable) { + // Note, without a type for the variable, we don't know if the identifier is intended to hold an integer value. + // However, it seems that no harm can be caused by here treating the identifier as if it held an + // integer value, because other parts of this method will reject the expression as a linear expression + // if non-numeric operations other than equality are applied to the identifier. + return new LinearExpr((IVariable)e); + } else if (e is IFunApp) { + IFunApp/*!*/ funapp = (IFunApp)e; + Contract.Assert(funapp != null); + IFunctionSymbol/*!*/ s = funapp.FunctionSymbol; + Contract.Assert(s != null); + + if (s is IntSymbol) { + return new LinearExpr(((IntSymbol)s).Value); + } else if (s.Equals(Int.Negate)) { + Contract.Assert(funapp.Arguments.Count == 1); + LinearExpr le = AsExpr((IExpr/*!*/)cce.NonNull(funapp.Arguments[0])); + if (le != null) { + le.Negate(); + return le; + } + } else if (s.Equals(Int.Add) || s.Equals(Int.Sub) || s.Equals(Int.Mul)) { + Contract.Assert(funapp.Arguments.Count == 2); + IExpr/*!*/ arg0 = (IExpr/*!*/)cce.NonNull(funapp.Arguments[0]); + IExpr/*!*/ arg1 = (IExpr/*!*/)cce.NonNull(funapp.Arguments[1]); + LinearExpr le0 = AsExpr(arg0); + if (le0 == null) { return null; - } + } + LinearExpr le1 = AsExpr(arg1); + if (le1 == null) { + return null; + } - public static LinearConstraint MakeConstraint(LinearExpr! le0, LinearExpr! le1, - LinearConstraint.ConstraintRelation rel, BigNum constantOffset) /* throws ArithmeticException */ - { + if (s.Equals(Int.Add)) { + le0.Add(le1); + return le0; + } else if (s.Equals(Int.Sub)) { le1.Negate(); le0.Add(le1); - le0.AddConstant(constantOffset); - return le0.ToConstraint(rel); - } - - /// - /// Builds a linear expression from "e", if possible; returns null if not possible. - /// - /// - /// - public static /*maybe null*/ LinearExpr AsExpr(IExpr! e) /* throws ArithmeticException */ - { - if (e is IVariable) { - // Note, without a type for the variable, we don't know if the identifier is intended to hold an integer value. - // However, it seems that no harm can be caused by here treating the identifier as if it held an - // integer value, because other parts of this method will reject the expression as a linear expression - // if non-numeric operations other than equality are applied to the identifier. - return new LinearExpr((IVariable)e); - } else if (e is IFunApp) { - IFunApp! funapp = (IFunApp)e; - IFunctionSymbol! s = funapp.FunctionSymbol; - - if (s is IntSymbol) { - return new LinearExpr(((IntSymbol)s).Value); - } else if (s.Equals(Int.Negate)) { - assert funapp.Arguments.Count == 1; - LinearExpr le = AsExpr((IExpr!)funapp.Arguments[0]); - if (le != null) { - le.Negate(); - return le; - } - } else if (s.Equals(Int.Add) || s.Equals(Int.Sub) || s.Equals(Int.Mul)) { - assert funapp.Arguments.Count == 2; - IExpr! arg0 = (IExpr!)funapp.Arguments[0]; - IExpr! arg1 = (IExpr!)funapp.Arguments[1]; - LinearExpr le0 = AsExpr(arg0); - if (le0 == null) { - return null; - } - LinearExpr le1 = AsExpr(arg1); - if (le1 == null) { - return null; - } - - if (s.Equals(Int.Add)) { - le0.Add(le1); - return le0; - } else if (s.Equals(Int.Sub)) { - le1.Negate(); - le0.Add(le1); - return le0; - } else if (s.Equals(Int.Mul)) { - BigNum x; - if (le0.AsConstant(out x)) - { - le1.Multiply(x); - return le1; - } - else if (le1.AsConstant(out x)) - { - le0.Multiply(x); - return le0; - } - } - } + return le0; + } else if (s.Equals(Int.Mul)) { + BigNum x; + if (le0.AsConstant(out x)) { + le1.Multiply(x); + return le1; + } else if (le1.AsConstant(out x)) { + le0.Multiply(x); + return le0; } - return null; + } } + } + return null; } - - class LinearExpr - { - BigNum constant; - Term terms; + } + + class LinearExpr { + BigNum constant; + Term terms; + + class Term { + public BigNum coeff; // non-0, if the node is used + public IVariable/*!*/ var; + public Term next; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(var != null); + } - class Term - { - public BigNum coeff; // non-0, if the node is used - public IVariable! var; - public Term next; - - public Term(BigNum coeff, IVariable! var) - { - this.coeff = coeff; - this.var = var; - // base(); - } - } + public Term(BigNum coeff, IVariable/*!*/ var) { + Contract.Requires(var != null); + this.coeff = coeff; + this.var = var; + // base(); + } + } - public LinearExpr(BigNum x) - { - constant = x; - } + public LinearExpr(BigNum x) { + constant = x; + } - public LinearExpr(IVariable! var) - { - constant = BigNum.ZERO; - terms = new Term(BigNum.ONE, var); - } + public LinearExpr(IVariable/*!*/ var) { + Contract.Requires(var != null); + constant = BigNum.ZERO; + terms = new Term(BigNum.ONE, var); + } - public ISet /*IVariable!*/ GetDefinedDimensions() - { - HashSet /*IVariable!*/! dims = new HashSet /*IVariable!*/ (); - for (Term current = terms; current != null; current = current.next) - { - dims.Add(current.var); - } - return dims; - } + public ISet /*IVariable!*/ GetDefinedDimensions() { + HashSet /*IVariable!*//*!*/ dims = new HashSet /*IVariable!*/ (); + for (Term current = terms; current != null; current = current.next) { + dims.Add(current.var); + } + return dims; + } - public BigNum TermCoefficient(/*MayBeNull*/ IVariable! var) - { - BigNum z = BigNum.ZERO; - if (var == null) - { - z = this.constant; - } - else if (terms != null) - { - Term current = terms; - while (current != null) - { - if (current.var == var) - { - break; - } - current = current.next; - } - if (current != null) - { - z = current.coeff; - } - } - return z; + public BigNum TermCoefficient(/*MayBeNull*/ IVariable/*!*/ var) { + Contract.Requires(var != null); + BigNum z = BigNum.ZERO; + if (var == null) { + z = this.constant; + } else if (terms != null) { + Term current = terms; + while (current != null) { + if (current.var == var) { + break; + } + current = current.next; } - - public bool AsConstant(out BigNum x) - { - if (terms == null) - { - x = constant; - return true; - } - else - { - x = BigNum.FromInt(-70022); // to please complier - return false; - } + if (current != null) { + z = current.coeff; } - - public void Negate() /* throws ArithmeticException */ - { - checked - { - constant = -constant; - } + } + return z; + } - for (Term t = terms; t != null; t = t.next) - { - checked - { - t.coeff = -t.coeff; - } - } + public bool AsConstant(out BigNum x) { + if (terms == null) { + x = constant; + return true; + } else { + x = BigNum.FromInt(-70022); // to please complier + return false; + } + } + + public void Negate() /* throws ArithmeticException */ + { + checked { + constant = -constant; + } + + for (Term t = terms; t != null; t = t.next) { + checked { + t.coeff = -t.coeff; } + } + } - /// - /// Adds "x" to "this". - /// - /// - public void AddConstant(BigNum x) /* throws ArithmeticException */ + /// + /// Adds "x" to "this". + /// + /// + public void AddConstant(BigNum x) /* throws ArithmeticException */ + { + checked { + constant += x; + } + } + + /// + /// Adds "le" to "this". Afterwards, "le" should not be used, because it will have been destroyed. + /// + /// + public void Add(LinearExpr/*!*/ le) /* throws ArithmeticException */ { - checked - { - constant += x; + Contract.Requires(le != null); + Contract.Requires(le != this); + checked { + constant += le.constant; + } + le.constant = BigNum.FromInt(-70029); // "le" should no longer be used; assign it a strange value so that misuse is perhaps more easily detected + + // optimization: + if (le.terms == null) { + return; + } else if (terms == null) { + terms = le.terms; + le.terms = null; + return; + } + + // merge the two term lists + // Use a nested loop, which is quadratic in time complexity, but we hope the lists will be small + Term newTerms = null; + while (le.terms != null) { + // take off next term from "le" + Term t = le.terms; + le.terms = t.next; + t.next = null; + + for (Term u = terms; u != null; u = u.next) { + if (u.var == t.var) { + checked { + u.coeff += t.coeff; } + goto NextOuter; + } } + t.next = newTerms; + newTerms = t; - /// - /// Adds "le" to "this". Afterwards, "le" should not be used, because it will have been destroyed. - /// - /// - public void Add(LinearExpr! le) /* throws ArithmeticException */ - requires le != this; - { - checked - { - constant += le.constant; - } - le.constant = BigNum.FromInt(-70029); // "le" should no longer be used; assign it a strange value so that misuse is perhaps more easily detected - - // optimization: - if (le.terms == null) - { - return; - } - else if (terms == null) - { - terms = le.terms; - le.terms = null; - return; - } + NextOuter: + ; + } - // merge the two term lists - // Use a nested loop, which is quadratic in time complexity, but we hope the lists will be small - Term newTerms = null; - while (le.terms != null) - { - // take off next term from "le" - Term t = le.terms; - le.terms = t.next; - t.next = null; - - for (Term u = terms; u != null; u = u.next) - { - if (u.var == t.var) - { - checked - { - u.coeff += t.coeff; - } - goto NextOuter; - } - } - t.next = newTerms; - newTerms = t; - - NextOuter: ; - } + // finally, include all non-0 terms + while (terms != null) { + // take off next term from "this" + Term t = terms; + terms = t.next; - // finally, include all non-0 terms - while (terms != null) - { - // take off next term from "this" - Term t = terms; - terms = t.next; - - if (!t.coeff.IsZero) - { - t.next = newTerms; - newTerms = t; - } - } - terms = newTerms; + if (!t.coeff.IsZero) { + t.next = newTerms; + newTerms = t; } + } + terms = newTerms; + } - public void Multiply(BigNum x) /* throws ArithmeticException */ - { - if (x.IsZero) - { - constant = BigNum.ZERO; - terms = null; - } - else - { - for (Term t = terms; t != null; t = t.next) - { - checked - { - t.coeff *= x; - } - } - checked - { + public void Multiply(BigNum x) /* throws ArithmeticException */ + { + if (x.IsZero) { + constant = BigNum.ZERO; + terms = null; + } else { + for (Term t = terms; t != null; t = t.next) { + checked { + t.coeff *= x; + } + } + checked { constant *= x; } } - } + } - public bool IsInvertible(IVariable! var) - { - for (Term t = terms; t != null; t = t.next) - { - if (t.var == var) - { - System.Diagnostics.Debug.Assert(!t.coeff.IsZero); - return true; - } - } - return false; + public bool IsInvertible(IVariable/*!*/ var) { + Contract.Requires(var != null); + for (Term t = terms; t != null; t = t.next) { + if (t.var == var) { + System.Diagnostics.Debug.Assert(!t.coeff.IsZero); + return true; } + } + return false; + } - public LinearConstraint ToConstraint(LinearConstraint.ConstraintRelation rel) /* throws ArithmeticException */ - { - LinearConstraint constraint = new LinearConstraint(rel); - for (Term t = terms; t != null; t = t.next) - { - constraint.SetCoefficient(t.var, t.coeff.ToRational); - } - BigNum rhs = -constant; - constraint.rhs = rhs.ToRational; - return constraint; - } + public LinearConstraint ToConstraint(LinearConstraint.ConstraintRelation rel) /* throws ArithmeticException */ + { + LinearConstraint constraint = new LinearConstraint(rel); + for (Term t = terms; t != null; t = t.next) { + constraint.SetCoefficient(t.var, t.coeff.ToRational); + } + BigNum rhs = -constant; + constraint.rhs = rhs.ToRational; + return constraint; } + } } diff --git a/Source/AIFramework/Polyhedra/SimplexTableau.cs b/Source/AIFramework/Polyhedra/SimplexTableau.cs index b6f4095c..4b5eaf43 100644 --- a/Source/AIFramework/Polyhedra/SimplexTableau.cs +++ b/Source/AIFramework/Polyhedra/SimplexTableau.cs @@ -3,115 +3,103 @@ // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- -namespace Microsoft.AbstractInterpretationFramework -{ - using System.Collections; - using System; - using Microsoft.Contracts; - using Microsoft.Basetypes; - using IMutableSet = Microsoft.Boogie.Set; - using HashSet = Microsoft.Boogie.Set; - +namespace Microsoft.AbstractInterpretationFramework { + using System.Collections; + using System; + using System.Diagnostics.Contracts; + using Microsoft.Basetypes; + using IMutableSet = Microsoft.Boogie.Set; + using HashSet = Microsoft.Boogie.Set; + + + /// + /// Used by LinearConstraintSystem.GenerateFrameFromConstraints. + /// + public class SimplexTableau { + readonly int rows; + readonly int columns; + readonly Rational[,]/*!*/ m; + + readonly int numInitialVars; + readonly int numSlackVars; + readonly int rhsColumn; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(m != null); + Contract.Invariant(inBasis != null); + Contract.Invariant(basisColumns != null); + } - /// - /// Used by LinearConstraintSystem.GenerateFrameFromConstraints. - /// - public class SimplexTableau - { - readonly int rows; - readonly int columns; - readonly Rational[,]! m; - - readonly int numInitialVars; - readonly int numSlackVars; - readonly int rhsColumn; - - readonly ArrayList /*IVariable!*/! dims; - readonly int[]! basisColumns; - readonly int[]! inBasis; - bool constructionDone = false; - - void CheckInvariant() - { - assert(rows == m.GetLength(0)); - assert(1 <= columns && columns == m.GetLength(1)); - assert(0 <= numInitialVars); - assert(0 <= numSlackVars && numSlackVars <= rows); - assert(numInitialVars + numSlackVars + 1 == columns); - assert(rhsColumn == columns - 1); - assert(dims.Count == numInitialVars); - assert(basisColumns.Length == rows); - assert(inBasis.Length == numInitialVars + numSlackVars); - - bool[] b = new bool[numInitialVars + numSlackVars]; - int numColumnsInBasis = 0; - int numUninitializedRowInfo = 0; - for (int i = 0; i < rows; i++) - { - int c = basisColumns[i]; - if (c == rhsColumn) - { - // all coefficients in this row are 0 (but the right-hand side may be non-0) - for (int j = 0; j < rhsColumn; j++) - { - assert m[i,j].IsZero; - } - numColumnsInBasis++; - } - else if (c == -1) - { - assert(!constructionDone); - numUninitializedRowInfo++; - } - else - { - // basis column is a column - assert(0 <= c && c < numInitialVars + numSlackVars); - // basis column is unique - assert(!b[c]); - b[c] = true; - // column is marked as being in basis - assert(inBasis[c] == i); - // basis column really is a basis column - for (int j = 0; j < rows; j++) - { - if (j == i) - { - assert m[j,c].HasValue(1);// == (Rational)new Rational(1)); - } - else - { - assert m[j,c].IsZero; - } - } - } - } - // no other columns are marked as being in basis - foreach (int i in inBasis) - { - if (0 <= i) - { - assert(i < rows); - numColumnsInBasis++; - } - else - { - assert(i == -1); - } + readonly ArrayList /*IVariable!*//*!*/ dims; + readonly int[]/*!*/ basisColumns; + readonly int[]/*!*/ inBasis; + bool constructionDone = false; + + void CheckInvariant() { + Contract.Assert(rows == m.GetLength(0)); + Contract.Assert(1 <= columns && columns == m.GetLength(1)); + Contract.Assert(0 <= numInitialVars); + Contract.Assert(0 <= numSlackVars && numSlackVars <= rows); + Contract.Assert(numInitialVars + numSlackVars + 1 == columns); + Contract.Assert(rhsColumn == columns - 1); + Contract.Assert(dims.Count == numInitialVars); + Contract.Assert(basisColumns.Length == rows); + Contract.Assert(inBasis.Length == numInitialVars + numSlackVars); + + bool[] b = new bool[numInitialVars + numSlackVars]; + int numColumnsInBasis = 0; + int numUninitializedRowInfo = 0; + for (int i = 0; i < rows; i++) { + int c = basisColumns[i]; + if (c == rhsColumn) { + // all coefficients in this row are 0 (but the right-hand side may be non-0) + for (int j = 0; j < rhsColumn; j++) { + Contract.Assert(m[i, j].IsZero); + } + numColumnsInBasis++; + } else if (c == -1) { + Contract.Assert(!constructionDone); + numUninitializedRowInfo++; + } else { + // basis column is a column + Contract.Assert(0 <= c && c < numInitialVars + numSlackVars); + // basis column is unique + Contract.Assert(!b[c]); + b[c] = true; + // column is marked as being in basis + Contract.Assert(inBasis[c] == i); + // basis column really is a basis column + for (int j = 0; j < rows; j++) { + if (j == i) { + Contract.Assert(m[j, c].HasValue(1));// == (Rational)new Rational(1))); + } else { + Contract.Assert(m[j, c].IsZero); } - assert(rows - numUninitializedRowInfo <= numColumnsInBasis && numColumnsInBasis <= rows); - assert(!constructionDone || numUninitializedRowInfo == 0); + } } + } + // no other columns are marked as being in basis + foreach (int i in inBasis) { + if (0 <= i) { + Contract.Assert(i < rows); + numColumnsInBasis++; + } else { + Contract.Assert(i == -1); + } + } + Contract.Assert(rows - numUninitializedRowInfo <= numColumnsInBasis && numColumnsInBasis <= rows); + Contract.Assert(!constructionDone || numUninitializedRowInfo == 0); + } - /// - /// Constructs a matrix that represents the constraints "constraints", adding slack - /// variables for the inequalities among "constraints". Puts the matrix in canonical - /// form. - /// - /// - [NotDelayed] - public SimplexTableau(ArrayList /*LinearConstraint*/! constraints) - { + /// + /// Constructs a matrix that represents the constraints "constraints", adding slack + /// variables for the inequalities among "constraints". Puts the matrix in canonical + /// form. + /// + /// + [NotDelayed] + public SimplexTableau(ArrayList /*LinearConstraint*//*!*/ constraints) { + Contract.Requires(constraints != null); #if DEBUG_PRINT Console.WriteLine("DEBUG: SimplexTableau constructor called with:"); foreach (LinearConstraint lc in constraints) @@ -119,249 +107,222 @@ namespace Microsoft.AbstractInterpretationFramework Console.WriteLine(" {0}", lc); } #endif - // Note: This implementation is not particularly efficient, but it'll do for now. + // Note: This implementation is not particularly efficient, but it'll do for now. + + ArrayList dims = this.dims = new ArrayList /*IVariable!*/ (); + int slacks = 0; + foreach (LinearConstraint/*!*/ cc in constraints) { + Contract.Assert(cc != null); + foreach (IVariable/*!*/ dim in cc.coefficients.Keys) { + Contract.Assert(dim != null); + if (!dims.Contains(dim)) { + dims.Add(dim); + } + } + if (cc.Relation == LinearConstraint.ConstraintRelation.LE) { + slacks++; + } + } - ArrayList dims = this.dims = new ArrayList /*IVariable!*/ (); - int slacks = 0; - foreach (LinearConstraint! cc in constraints) - { - foreach (IVariable! dim in cc.coefficients.Keys) - { - if (!dims.Contains(dim)) - { - dims.Add(dim); - } - } - if (cc.Relation == LinearConstraint.ConstraintRelation.LE) - { - slacks++; - } - } + int numInitialVars = this.numInitialVars = dims.Count; + int numSlackVars = this.numSlackVars = slacks; + int rows = this.rows = constraints.Count; + int columns = this.columns = numInitialVars + numSlackVars + 1; + this.m = new Rational[rows, columns]; + this.rhsColumn = columns - 1; + this.basisColumns = new int[rows]; + this.inBasis = new int[columns - 1]; - int numInitialVars = this.numInitialVars = dims.Count; - int numSlackVars = this.numSlackVars = slacks; - int rows = this.rows = constraints.Count; - int columns = this.columns = numInitialVars + numSlackVars + 1; - this.m = new Rational[rows, columns]; - this.rhsColumn = columns-1; - this.basisColumns = new int[rows]; - this.inBasis = new int[columns-1]; - - base(); - - for (int i = 0; i < inBasis.Length; i++) - { - inBasis[i] = -1; - } + //:base(); - // Fill in the matrix - int r = 0; - int iSlack = 0; - foreach (LinearConstraint! cc in constraints) - { - for (int i = 0; i < dims.Count; i++) - { - m[r,i] = cc[(IVariable!)dims[i]]; - } - if (cc.Relation == LinearConstraint.ConstraintRelation.LE) - { - m[r, numInitialVars + iSlack] = Rational.ONE; - basisColumns[r] = numInitialVars + iSlack; - inBasis[numInitialVars + iSlack] = r; - iSlack++; - } - else - { - basisColumns[r] = -1; // special value to communicate to Pivot that basis column i hasn't been set up yet - } - m[r,rhsColumn] = cc.rhs; - r++; - } - assert(r == constraints.Count); - assert(iSlack == numSlackVars); + for (int i = 0; i < inBasis.Length; i++) { + inBasis[i] = -1; + } + + // Fill in the matrix + int r = 0; + int iSlack = 0; + foreach (LinearConstraint/*!*/ cc in constraints) { + Contract.Assert(cc != null); + for (int i = 0; i < dims.Count; i++) { + m[r, i] = cc[(IVariable)cce.NonNull(dims[i])]; + } + if (cc.Relation == LinearConstraint.ConstraintRelation.LE) { + m[r, numInitialVars + iSlack] = Rational.ONE; + basisColumns[r] = numInitialVars + iSlack; + inBasis[numInitialVars + iSlack] = r; + iSlack++; + } else { + basisColumns[r] = -1; // special value to communicate to Pivot that basis column i hasn't been set up yet + } + m[r, rhsColumn] = cc.rhs; + r++; + } + Contract.Assert(r == constraints.Count); + Contract.Assert(iSlack == numSlackVars); #if DEBUG_PRINT Console.WriteLine("DEBUG: Intermediate tableau state in SimplexTableau constructor:"); Dump(); #endif - // Go through the rows with uninitialized basis columns. These correspond to equality constraints. - // For each one, find an initial variable (non-slack variable) whose column we can make the basis - // column of the row. - for (int i = 0; i < rows; i++) - { - if (basisColumns[i] != -1) - { - continue; - } - // Find a non-0 column in row i that we can make a basis column. Since rows corresponding - // to equality constraints don't have slack variables and since the pivot operations performed - // by iterations of this loop don't introduce any non-0 coefficients in the slack-variable - // columns of these rows, we only need to look through the columns corresponding to initial - // variables. - for (int j = 0; j < numInitialVars; j++) - { - if (m[i,j].IsNonZero) - { + // Go through the rows with uninitialized basis columns. These correspond to equality constraints. + // For each one, find an initial variable (non-slack variable) whose column we can make the basis + // column of the row. + for (int i = 0; i < rows; i++) { + if (basisColumns[i] != -1) { + continue; + } + // Find a non-0 column in row i that we can make a basis column. Since rows corresponding + // to equality constraints don't have slack variables and since the pivot operations performed + // by iterations of this loop don't introduce any non-0 coefficients in the slack-variable + // columns of these rows, we only need to look through the columns corresponding to initial + // variables. + for (int j = 0; j < numInitialVars; j++) { + if (m[i, j].IsNonZero) { #if DEBUG_PRINT Console.WriteLine("-- About to Pivot({0},{1})", i, j); #endif - assert(inBasis[j] == -1); - Pivot(i,j); + Contract.Assert(inBasis[j] == -1); + Pivot(i, j); #if DEBUG_PRINT Console.WriteLine("Tableau after Pivot:"); Dump(); - #endif - goto SET_UP_NEXT_INBASIS_COLUMN; - } - } - // Check the assertion in the comment above, that is, that columns corresponding to slack variables - // are 0 in this row. - for (int j = numInitialVars; j < rhsColumn; j++) - { - assert m[i,j].IsZero; - } - // There is no column in this row that we can put into basis. - basisColumns[i] = rhsColumn; - SET_UP_NEXT_INBASIS_COLUMN: {} - } - - constructionDone = true; - CheckInvariant(); +#endif + goto SET_UP_NEXT_INBASIS_COLUMN; + } } - - public IMutableSet! /*IVariable!*/ GetDimensions() - { - HashSet /*IVariable!*/ z = new HashSet /*IVariable!*/ (); - foreach (IVariable! dim in dims) - { - z.Add(dim); - } - return z; + // Check the assertion in the comment above, that is, that columns corresponding to slack variables + // are 0 in this row. + for (int j = numInitialVars; j < rhsColumn; j++) { + Contract.Assert(m[i, j].IsZero); } - - public Rational this [int r, int c] - { - get - { - return m[r,c]; - } - set - { - m[r,c] = value; - } + // There is no column in this row that we can put into basis. + basisColumns[i] = rhsColumn; + SET_UP_NEXT_INBASIS_COLUMN: { } + } - /// - /// Applies the Pivot Operation on row "r" and column "c". - /// - /// This method can be called when !constructionDone, that is, at a time when not all basis - /// columns have been set up (indicated by -1 in basisColumns). This method helps set up - /// those basis columns. - /// - /// The return value is an undo record that can be used with UnPivot. - /// - /// - /// - public Rational[]! Pivot(int r, int c) - { - assert(0 <= r && r < rows); - assert(0 <= c && c < columns-1); - assert(m[r,c].IsNonZero); - assert(inBasis[c] == -1); // follows from invariant and m[r,c] != 0 - assert(basisColumns[r] != rhsColumn); // follows from invariant and m[r,c] != 0 - - Rational[] undo = new Rational[rows+1]; - for (int i = 0; i < rows; i++) - { - undo[i] = m[i,c]; - } + constructionDone = true; + CheckInvariant(); + } - // scale the pivot row - Rational q = m[r,c]; - if (q != Rational.ONE) - { - for (int j = 0; j < columns; j++) - { - m[r,j] /= q; - } - } + public IMutableSet/*!*/ /*IVariable!*/ GetDimensions() { + Contract.Ensures(Contract.Result() != null); + HashSet /*IVariable!*/ z = new HashSet /*IVariable!*/ (); + foreach (IVariable/*!*/ dim in dims) { + Contract.Assert(dim != null); + z.Add(dim); + } + return z; + } - // subtract a multiple of the pivot row from all other rows - for (int i = 0; i < rows; i++) - { - if (i != r) - { - q = m[i,c]; - if (q.IsNonZero) - { - for (int j = 0; j < columns; j++) - { - m[i,j] -= q * m[r,j]; - } - } - } - } + public Rational this[int r, int c] { + get { + return m[r, c]; + } + set { + m[r, c] = value; + } + } - // update basis information - int prevCol = basisColumns[r]; - undo[rows] = Rational.FromInt(prevCol); - basisColumns[r] = c; - if (prevCol != -1) - { - inBasis[prevCol] = -1; - } - inBasis[c] = r; + /// + /// Applies the Pivot Operation on row "r" and column "c". + /// + /// This method can be called when !constructionDone, that is, at a time when not all basis + /// columns have been set up (indicated by -1 in basisColumns). This method helps set up + /// those basis columns. + /// + /// The return value is an undo record that can be used with UnPivot. + /// + /// + /// + public Rational[]/*!*/ Pivot(int r, int c) { + Contract.Ensures(Contract.Result() != null); + Contract.Assert(0 <= r && r < rows); + Contract.Assert(0 <= c && c < columns - 1); + Contract.Assert(m[r, c].IsNonZero); + Contract.Assert(inBasis[c] == -1); // follows from invariant and m[r,c] != 0 + Contract.Assert(basisColumns[r] != rhsColumn); // follows from invariant and m[r,c] != 0 + + Rational[] undo = new Rational[rows + 1]; + for (int i = 0; i < rows; i++) { + undo[i] = m[i, c]; + } - return undo; + // scale the pivot row + Rational q = m[r, c]; + if (q != Rational.ONE) { + for (int j = 0; j < columns; j++) { + m[r, j] /= q; } + } - /// - /// If the last operation applied to the tableau was: - /// undo = Pivot(i,j); - /// then UnPivot(i, j, undo) undoes the pivot operation. - /// Note: This operation is not supported for any call to Pivot before constructionDone - /// is set to true. - /// - /// - /// - /// - void UnPivot(int r, int c, Rational[]! undo) - { - assert(0 <= r && r < rows); - assert(0 <= c && c < columns-1); - assert(m[r,c].HasValue(1)); - assert(undo.Length == rows+1); - - // add a multiple of the pivot row to all other rows - for (int i = 0; i < rows; i++) - { - if (i != r) - { - Rational q = undo[i]; - if (q.IsNonZero) - { - for (int j = 0; j < columns; j++) - { - m[i,j] += q * m[r,j]; - } - } - } + // subtract a multiple of the pivot row from all other rows + for (int i = 0; i < rows; i++) { + if (i != r) { + q = m[i, c]; + if (q.IsNonZero) { + for (int j = 0; j < columns; j++) { + m[i, j] -= q * m[r, j]; } + } + } + } - // scale the pivot row - Rational p = undo[r]; - for (int j = 0; j < columns; j++) - { - m[r,j] *= p; - } + // update basis information + int prevCol = basisColumns[r]; + undo[rows] = Rational.FromInt(prevCol); + basisColumns[r] = c; + if (prevCol != -1) { + inBasis[prevCol] = -1; + } + inBasis[c] = r; - // update basis information - int prevCol = undo[rows].AsInteger; - assert(prevCol != -1); - basisColumns[r] = prevCol; - inBasis[c] = -1; - inBasis[prevCol] = r; + return undo; + } + + /// + /// If the last operation applied to the tableau was: + /// undo = Pivot(i,j); + /// then UnPivot(i, j, undo) undoes the pivot operation. + /// Note: This operation is not supported for any call to Pivot before constructionDone + /// is set to true. + /// + /// + /// + /// + void UnPivot(int r, int c, Rational[]/*!*/ undo) { + Contract.Requires(undo != null); + Contract.Assert(0 <= r && r < rows); + Contract.Assert(0 <= c && c < columns - 1); + Contract.Assert(m[r, c].HasValue(1)); + Contract.Assert(undo.Length == rows + 1); + + // add a multiple of the pivot row to all other rows + for (int i = 0; i < rows; i++) { + if (i != r) { + Rational q = undo[i]; + if (q.IsNonZero) { + for (int j = 0; j < columns; j++) { + m[i, j] += q * m[r, j]; + } + } } + } + + // scale the pivot row + Rational p = undo[r]; + for (int j = 0; j < columns; j++) { + m[r, j] *= p; + } + + // update basis information + int prevCol = undo[rows].AsInteger; + Contract.Assert(prevCol != -1); + basisColumns[r] = prevCol; + inBasis[c] = -1; + inBasis[prevCol] = r; + } /// /// Returns true iff the current basis of the system of constraints modeled by the simplex tableau @@ -372,34 +333,27 @@ namespace Microsoft.AbstractInterpretationFramework /// CAVEAT: I have no particular reason to believe that the algorithm used here will terminate. --KRML /// /// - public bool IsFeasibleBasis - { - get - { + public bool IsFeasibleBasis { + get { // while there is a slack variable in basis whose row has a negative right-hand side - while (true) - { + while (true) { bool feasibleBasis = true; - for (int c = numInitialVars; c < rhsColumn; c++) - { + for (int c = numInitialVars; c < rhsColumn; c++) { int k = inBasis[c]; - if (0 <= k && k < rhsColumn && m[k,rhsColumn].IsNegative) - { - assert(m[k,c].HasValue(1)); // c is in basis + if (0 <= k && k < rhsColumn && m[k, rhsColumn].IsNegative) { + Contract.Assert(m[k, c].HasValue(1)); // c is in basis // Try to pivot on a different slack variable in this row - for (int i = numInitialVars; i < rhsColumn; i++) - { - if (m[k,i].IsNegative) - { - assert(c != i); // c is in basis, so m[k,c]==1, which is not negative + for (int i = numInitialVars; i < rhsColumn; i++) { + if (m[k, i].IsNegative) { + Contract.Assert(c != i); // c is in basis, so m[k,c]==1, which is not negative Pivot(k, i); #if DEBUG_PRINT Console.WriteLine("Tableau after Pivot operation on ({0},{1}) in IsFeasibleBasis:", k, i); Dump(); #endif - assert(inBasis[c] == -1); - assert(inBasis[i] == k); - assert(m[k,rhsColumn].IsNonNegative); + Contract.Assert(inBasis[c] == -1); + Contract.Assert(inBasis[i] == k); + Contract.Assert(m[k, rhsColumn].IsNonNegative); goto START_ANEW; } } @@ -407,23 +361,20 @@ namespace Microsoft.AbstractInterpretationFramework } } return feasibleBasis; - START_ANEW: ; + START_ANEW: + ; } - return false; // make compiler shut up + return false; // make compiler shut up } } /// /// Whether or not all initial variables (the non-slack variables) are in basis) /// - public bool AllInitialVarsInBasis - { - get - { - for (int i = 0; i < numInitialVars; i++) - { - if (inBasis[i] == -1) - { + public bool AllInitialVarsInBasis { + get { + for (int i = 0; i < numInitialVars; i++) { + if (inBasis[i] == -1) { return false; } } @@ -431,139 +382,128 @@ namespace Microsoft.AbstractInterpretationFramework } } - /// - /// Adds as many initial variables as possible to the basis. - /// - /// - public void AddInitialVarsToBasis() - { - // while there exists an initial variable not in the basis and not satisfying - // condition 3.4.2.2 in Cousot and Halbwachs, perform a pivot operation - while (true) - { - for (int i = 0; i < numInitialVars; i++) - { - if (inBasis[i] == -1) - { - // initial variable i is not in the basis - for (int j = 0; j < rows; j++) - { - if (m[j,i].IsNonZero) - { - int k = basisColumns[j]; - if (numInitialVars <= k && k < rhsColumn) - { - // slack variable k is in basis for row j - Pivot(j, i); - assert(inBasis[k] == -1); - assert(inBasis[i] == j && basisColumns[j] == i); - goto START_ANEW; - } - } - } - } + /// + /// Adds as many initial variables as possible to the basis. + /// + /// + public void AddInitialVarsToBasis() { + // while there exists an initial variable not in the basis and not satisfying + // condition 3.4.2.2 in Cousot and Halbwachs, perform a pivot operation + while (true) { + for (int i = 0; i < numInitialVars; i++) { + if (inBasis[i] == -1) { + // initial variable i is not in the basis + for (int j = 0; j < rows; j++) { + if (m[j, i].IsNonZero) { + int k = basisColumns[j]; + if (numInitialVars <= k && k < rhsColumn) { + // slack variable k is in basis for row j + Pivot(j, i); + Contract.Assert(inBasis[k] == -1); + Contract.Assert(inBasis[i] == j && basisColumns[j] == i); + goto START_ANEW; } - // No more initial variables can be moved into basis. - return; - START_ANEW: {} + } } + } } + // No more initial variables can be moved into basis. + return; + START_ANEW: { + } + } + } - /// - /// Adds to "lines" the lines implied by initial-variable columns not in basis - /// (see section 3.4.2 of Cousot and Halbwachs), and adds to "constraints" the - /// constraints to exclude those lines (see step 4.2 of section 3.4.3 of - /// Cousot and Halbwachs). - /// - /// - /// - public void ProduceLines(ArrayList /*FrameElement*/! lines, ArrayList /*LinearConstraint*/! constraints) - { - // for every initial variable not in basis - for (int i0 = 0; i0 < numInitialVars; i0++) - { - if (inBasis[i0] == -1) - { - FrameElement fe = new FrameElement(); - LinearConstraint lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ); - for (int i = 0; i < numInitialVars; i++) - { - if (i == i0) - { - fe.AddCoordinate((IVariable!)dims[i], Rational.ONE); - lc.SetCoefficient((IVariable!)dims[i], Rational.ONE); - } - else if (inBasis[i] != -1) - { - // i is a basis column - assert(m[inBasis[i],i].HasValue(1)); - Rational val = -m[inBasis[i],i0]; - fe.AddCoordinate((IVariable!)dims[i], val); - lc.SetCoefficient((IVariable!)dims[i], val); - } - } - lines.Add(fe); - constraints.Add(lc); - } + /// + /// Adds to "lines" the lines implied by initial-variable columns not in basis + /// (see section 3.4.2 of Cousot and Halbwachs), and adds to "constraints" the + /// constraints to exclude those lines (see step 4.2 of section 3.4.3 of + /// Cousot and Halbwachs). + /// + /// + /// + public void ProduceLines(ArrayList /*FrameElement*//*!*/ lines, ArrayList /*LinearConstraint*//*!*/ constraints) { + Contract.Requires(constraints != null); + Contract.Requires(lines != null); + // for every initial variable not in basis + for (int i0 = 0; i0 < numInitialVars; i0++) { + if (inBasis[i0] == -1) { + FrameElement fe = new FrameElement(); + LinearConstraint lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ); + for (int i = 0; i < numInitialVars; i++) { + if (i == i0) { + fe.AddCoordinate((IVariable)cce.NonNull(dims[i]), Rational.ONE); + lc.SetCoefficient((IVariable)cce.NonNull(dims[i]), Rational.ONE); + } else if (inBasis[i] != -1) { + // i is a basis column + Contract.Assert(m[inBasis[i], i].HasValue(1)); + Rational val = -m[inBasis[i], i0]; + fe.AddCoordinate((IVariable)cce.NonNull(dims[i]), val); + lc.SetCoefficient((IVariable)cce.NonNull(dims[i]), val); } + } + lines.Add(fe); + constraints.Add(lc); } + } + } - /// - /// From a feasible point where all initial variables are in the basis, traverses - /// all feasible bases containing all initial variables. For each such basis, adds - /// the vertices to "vertices" and adds to "rays" the extreme rays. See step 4.2 - /// in section 3.4.3 of Cousot and Halbwachs. - /// A more efficient algorithm is found in the paper "An algorithm for - /// determining all extreme points of a convex polytope" by N. E. Dyer and L. G. Proll, - /// Mathematical Programming, 12, 1977. - /// Assumes that the tableau is in a state where all initial variables are in the basis. - /// This method has no net effect on the tableau. - /// Note: Duplicate vertices and rays may be added. - /// - /// - /// - public void TraverseVertices(ArrayList! /*FrameElement*/ vertices, ArrayList! /*FrameElement*/ rays) - { - ArrayList /*bool[]*/ basesSeenSoFar = new ArrayList /*bool[]*/ (); - TraverseBases(basesSeenSoFar, vertices, rays); - } + /// + /// From a feasible point where all initial variables are in the basis, traverses + /// all feasible bases containing all initial variables. For each such basis, adds + /// the vertices to "vertices" and adds to "rays" the extreme rays. See step 4.2 + /// in section 3.4.3 of Cousot and Halbwachs. + /// A more efficient algorithm is found in the paper "An algorithm for + /// determining all extreme points of a convex polytope" by N. E. Dyer and L. G. Proll, + /// Mathematical Programming, 12, 1977. + /// Assumes that the tableau is in a state where all initial variables are in the basis. + /// This method has no net effect on the tableau. + /// Note: Duplicate vertices and rays may be added. + /// + /// + /// + public void TraverseVertices(ArrayList/*!*/ /*FrameElement*/ vertices, ArrayList/*!*/ /*FrameElement*/ rays) { + Contract.Requires(vertices != null); + Contract.Requires(rays != null); + ArrayList /*bool[]*/ basesSeenSoFar = new ArrayList /*bool[]*/ (); + TraverseBases(basesSeenSoFar, vertices, rays); + } - /// - /// Worker method of TraverseVertices. - /// This method has no net effect on the tableau. - /// - /// - /// - /// - void TraverseBases(ArrayList /*bool[]*/! basesSeenSoFar, ArrayList /*FrameElement*/! vertices, ArrayList /*FrameElement*/! rays) - { - CheckInvariant(); - - bool[] thisBasis = new bool[numSlackVars]; - for (int i = numInitialVars; i < rhsColumn; i++) - { - if (inBasis[i] != -1) - { - thisBasis[i-numInitialVars] = true; - } - } - foreach (bool[]! basis in basesSeenSoFar) - { - assert(basis.Length == numSlackVars); - for (int i = 0; i < numSlackVars; i++) - { - if (basis[i] != thisBasis[i]) - { - goto COMPARE_WITH_NEXT_BASIS; - } - } - // thisBasis and basis are the same--that is, basisColumns has been visited before--so - // we don't traverse anything from here - return; - COMPARE_WITH_NEXT_BASIS: {} - } - // basisColumns has not been seen before; record thisBasis and continue with the traversal here - basesSeenSoFar.Add(thisBasis); + /// + /// Worker method of TraverseVertices. + /// This method has no net effect on the tableau. + /// + /// + /// + /// + void TraverseBases(ArrayList /*bool[]*//*!*/ basesSeenSoFar, ArrayList /*FrameElement*//*!*/ vertices, ArrayList /*FrameElement*//*!*/ rays) { + Contract.Requires(rays != null); + Contract.Requires(vertices != null); + Contract.Requires(basesSeenSoFar != null); + CheckInvariant(); + + bool[] thisBasis = new bool[numSlackVars]; + for (int i = numInitialVars; i < rhsColumn; i++) { + if (inBasis[i] != -1) { + thisBasis[i - numInitialVars] = true; + } + } + foreach (bool[]/*!*/ basis in basesSeenSoFar) { + Contract.Assert(basis != null); + Contract.Assert(basis.Length == numSlackVars); + for (int i = 0; i < numSlackVars; i++) { + if (basis[i] != thisBasis[i]) { + goto COMPARE_WITH_NEXT_BASIS; + } + } + // thisBasis and basis are the same--that is, basisColumns has been visited before--so + // we don't traverse anything from here + return; + COMPARE_WITH_NEXT_BASIS: { + } + } + // basisColumns has not been seen before; record thisBasis and continue with the traversal here + basesSeenSoFar.Add(thisBasis); #if DEBUG_PRINT Console.Write("TraverseBases, new basis: "); @@ -573,39 +513,31 @@ namespace Microsoft.AbstractInterpretationFramework Console.WriteLine(); Dump(); #endif - // Add vertex - FrameElement v = new FrameElement(); - for (int i = 0; i < rows; i++) - { - int j = basisColumns[i]; - if (j < numInitialVars) - { - v.AddCoordinate((IVariable!)dims[j], m[i,rhsColumn]); - } - } + // Add vertex + FrameElement v = new FrameElement(); + for (int i = 0; i < rows; i++) { + int j = basisColumns[i]; + if (j < numInitialVars) { + v.AddCoordinate((IVariable)cce.NonNull(dims[j]), m[i, rhsColumn]); + } + } #if DEBUG_PRINT Console.WriteLine(" Adding vertex: {0}", v); #endif - vertices.Add(v); + vertices.Add(v); - // Add rays. Traverse all columns corresponding to slack variables that + // Add rays. Traverse all columns corresponding to slack variables that // are not in basis (see second bullet of section 3.4.2 of Cousot and Halbwachs). - for (int i0 = numInitialVars; i0 < rhsColumn; i0++) - { - if (inBasis[i0] != -1) - { + for (int i0 = numInitialVars; i0 < rhsColumn; i0++) { + if (inBasis[i0] != -1) { // skip those slack-variable columns that are in basis continue; } // check if slack-variable, non-basis column i corresponds to an extreme ray - for (int row = 0; row < rows; row++) - { - if (m[row,i0].IsPositive) - { - for (int k = numInitialVars; k < rhsColumn; k++) - { - if (inBasis[k] != -1 && m[row,k].IsNonZero) - { + for (int row = 0; row < rows; row++) { + if (m[row, i0].IsPositive) { + for (int k = numInitialVars; k < rhsColumn; k++) { + if (inBasis[k] != -1 && m[row, k].IsNonZero) { // does not correspond to an extreme ray goto CHECK_NEXT_SLACK_VAR; } @@ -614,104 +546,86 @@ namespace Microsoft.AbstractInterpretationFramework } // corresponds to an extreme ray FrameElement ray = new FrameElement(); - for (int i = 0; i < numInitialVars; i++) - { + for (int i = 0; i < numInitialVars; i++) { int j0 = inBasis[i]; - Rational val = -m[j0,i0]; - ray.AddCoordinate((IVariable!)dims[i], val); + Rational val = -m[j0, i0]; + ray.AddCoordinate((IVariable)cce.NonNull(dims[i]), val); } #if DEBUG_PRINT Console.WriteLine(" Adding ray: {0}", ray); #endif rays.Add(ray); - CHECK_NEXT_SLACK_VAR: {} + CHECK_NEXT_SLACK_VAR: { + } } - // Continue traversal - for (int i = numInitialVars; i < rhsColumn; i++) - { - int j = inBasis[i]; - if (j != -1) - { - // try moving i out of basis and some other slack-variable column into basis - for (int k = numInitialVars; k < rhsColumn; k++) - { - if (inBasis[k] == -1 && m[j,k].IsPositive) - { - Rational[] undo = Pivot(j, k); - // check if the new basis is feasible - for (int p = 0; p < rows; p++) - { - int c = basisColumns[p]; - if (numInitialVars <= c && c < rhsColumn && m[p,rhsColumn].IsNegative) - { - // not feasible - goto AFTER_TRAVERSE; - } - } - TraverseBases(basesSeenSoFar, vertices, rays); - AFTER_TRAVERSE: - UnPivot(j, k, undo); - } - } + // Continue traversal + for (int i = numInitialVars; i < rhsColumn; i++) { + int j = inBasis[i]; + if (j != -1) { + // try moving i out of basis and some other slack-variable column into basis + for (int k = numInitialVars; k < rhsColumn; k++) { + if (inBasis[k] == -1 && m[j, k].IsPositive) { + Rational[] undo = Pivot(j, k); + // check if the new basis is feasible + for (int p = 0; p < rows; p++) { + int c = basisColumns[p]; + if (numInitialVars <= c && c < rhsColumn && m[p, rhsColumn].IsNegative) { + // not feasible + goto AFTER_TRAVERSE; } + } + TraverseBases(basesSeenSoFar, vertices, rays); + AFTER_TRAVERSE: + UnPivot(j, k, undo); } + } } + } + } - public void Dump() - { - // names - Console.Write(" "); - for (int i = 0; i < numInitialVars; i++) - { - Console.Write(" {0,4} ", dims[i]); - } - Console.WriteLine(); - // numbers - Console.Write(" "); - for (int i = 0; i < columns; i++) - { - if (i == numInitialVars || i == rhsColumn) - { - Console.Write("|"); - } - Console.Write(" {0,4}", i); - if (i < rhsColumn && inBasis[i] != -1) - { - Console.Write("* "); - assert(basisColumns[inBasis[i]] == i); - } - else - { - Console.Write(" "); - } - } - Console.WriteLine(); - // line - Console.Write(" "); - for (int i = 0; i < columns; i++) - { - if (i == numInitialVars || i == rhsColumn) - { - Console.Write("+"); - } - Console.Write("---------"); - } - Console.WriteLine(); + public void Dump() { + // names + Console.Write(" "); + for (int i = 0; i < numInitialVars; i++) { + Console.Write(" {0,4} ", dims[i]); + } + Console.WriteLine(); + // numbers + Console.Write(" "); + for (int i = 0; i < columns; i++) { + if (i == numInitialVars || i == rhsColumn) { + Console.Write("|"); + } + Console.Write(" {0,4}", i); + if (i < rhsColumn && inBasis[i] != -1) { + Console.Write("* "); + Contract.Assert(basisColumns[inBasis[i]] == i); + } else { + Console.Write(" "); + } + } + Console.WriteLine(); + // line + Console.Write(" "); + for (int i = 0; i < columns; i++) { + if (i == numInitialVars || i == rhsColumn) { + Console.Write("+"); + } + Console.Write("---------"); + } + Console.WriteLine(); - for (int j = 0; j < rows; j++) - { - Console.Write("{0,4}: ", basisColumns[j]); - for (int i = 0; i < columns; i++) - { - if (i == numInitialVars || i == rhsColumn) - { - Console.Write("|"); - } - Console.Write(" {0,4:n1} ", m[j,i]); - } - Console.WriteLine(); - } + for (int j = 0; j < rows; j++) { + Console.Write("{0,4}: ", basisColumns[j]); + for (int i = 0; i < columns; i++) { + if (i == numInitialVars || i == rhsColumn) { + Console.Write("|"); + } + Console.Write(" {0,4:n1} ", m[j, i]); } + Console.WriteLine(); + } } + } } diff --git a/Source/AIFramework/VariableMap/ConstantAbstraction.cs b/Source/AIFramework/VariableMap/ConstantAbstraction.cs index 8ba3065f..89a64290 100644 --- a/Source/AIFramework/VariableMap/ConstantAbstraction.cs +++ b/Source/AIFramework/VariableMap/ConstantAbstraction.cs @@ -3,12 +3,12 @@ // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- -using Microsoft.Contracts; +using System.Diagnostics.Contracts; namespace Microsoft.AbstractInterpretationFramework { using System.Collections; using System.Diagnostics; - using System.Compiler.Analysis; + //using System.Compiler.Analysis; using Microsoft.Basetypes; /// @@ -32,13 +32,13 @@ namespace Microsoft.AbstractInterpretationFramework public BigNum Constant { get { return this.constantValue; } } // only when IsConstant [Pure] - public override System.Collections.Generic.ICollection! FreeVariables() - { - return (!) (new System.Collections.Generic.List()).AsReadOnly(); + public override System.Collections.Generic.ICollection/*!*/ FreeVariables() { +Contract.Ensures(cce.NonNullElements(Contract.Result>())); +return cce.NonNull(new System.Collections.Generic.List()).AsReadOnly(); } - public override Element! Clone() - { + public override Element/*!*/ Clone() { +Contract.Ensures(Contract.Result() != null); if (this.IsConstant) return new Elt(constantValue); else @@ -46,87 +46,109 @@ namespace Microsoft.AbstractInterpretationFramework } } - readonly IIntExprFactory! factory; + readonly IIntExprFactory/*!*/ factory; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(factory != null); + } - public ConstantLattice(IIntExprFactory! factory) - { + + public ConstantLattice(IIntExprFactory/*!*/ factory){ +Contract.Requires(factory != null); this.factory = factory; // base(); } - public override Element! Top - { - get { return new Elt(Value.Top); } + public override Element/*!*/ Top{get{ +Contract.Ensures(Contract.Result() != null); + return new Elt(Value.Top); } } - public override Element! Bottom - { - get { return new Elt(Value.Bottom); } + public override Element/*!*/ Bottom{get{ +Contract.Ensures(Contract.Result() != null); + return new Elt(Value.Bottom); } } - public override bool IsTop (Element! element) - { + public override bool IsTop (Element/*!*/ element){ +Contract.Requires(element != null); Elt e = (Elt)element; return e.domainValue == Value.Top; } - public override bool IsBottom (Element! element) - { + public override bool IsBottom (Element/*!*/ element){ +Contract.Requires(element != null); Elt e = (Elt)element; return e.domainValue == Value.Bottom; } - public override Element! NontrivialJoin (Element! first, Element! second) - { + public override Element/*!*/ NontrivialJoin (Element/*!*/ first, Element/*!*/ second){ +Contract.Requires(second != null); +Contract.Requires(first != null); +Contract.Ensures(Contract.Result() != null); Elt a = (Elt)first; Elt b = (Elt)second; Debug.Assert(a.domainValue == Value.Constant && b.domainValue == Value.Constant); return (a.constantValue.Equals(b.constantValue)) ? a : (Elt)Top; } - public override Element! NontrivialMeet (Element! first, Element! second) - { + public override Element/*!*/ NontrivialMeet (Element/*!*/ first, Element/*!*/ second){ +Contract.Requires(second != null); +Contract.Requires(first != null); +Contract.Ensures(Contract.Result() != null); Elt a = (Elt)first; Elt b = (Elt)second; Debug.Assert(a.domainValue == Value.Constant && b.domainValue == Value.Constant); return (a.constantValue.Equals(b.constantValue)) ? a : (Elt)Bottom; } - public override Element! Widen (Element! first, Element! second) - { + public override Element/*!*/ Widen (Element/*!*/ first, Element/*!*/ second){ +Contract.Requires(second != null); +Contract.Requires(first != null); +Contract.Ensures(Contract.Result() != null); return Join(first,second); } - protected override bool AtMost (Element! first, Element! second) // this <= that + protected override bool AtMost (Element/*!*/ first, Element/*!*/ second) // this <= that { + Contract.Requires(first!= null); + Contract.Requires(second != null); Elt a = (Elt)first; Elt b = (Elt)second; return a.Constant.Equals(b.Constant); } - public override IExpr! ToPredicate(IVariable! var, Element! element) { - return factory.Eq(var, (!)GetFoldExpr(element)); + public override IExpr/*!*/ ToPredicate(IVariable/*!*/ var, Element/*!*/ element){ +Contract.Requires(element != null); +Contract.Requires(var != null); +Contract.Ensures(Contract.Result() != null); + return factory.Eq(var, cce.NonNull(GetFoldExpr(element))); } - public override IExpr GetFoldExpr(Element! element) { + public override IExpr GetFoldExpr(Element/*!*/ element){ +Contract.Requires(element != null); Elt e = (Elt)element; - assert e.domainValue == Value.Constant; + Contract.Assert(e.domainValue == Value.Constant); return factory.Const(e.constantValue); } - public override bool Understands(IFunctionSymbol! f, IList/**/! args) { + public override bool Understands(IFunctionSymbol/*!*/ f, IList/**//*!*/ args){ +Contract.Requires(args != null); +Contract.Requires(f != null); return f.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq); } - public override Element! EvaluatePredicate(IExpr! e) { + public override Element/*!*/ EvaluatePredicate(IExpr/*!*/ e){ +Contract.Requires(e != null); +Contract.Ensures(Contract.Result() != null); IFunApp nary = e as IFunApp; if (nary != null) { if (nary.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq)) { - IList/**/! args = nary.Arguments; - assert args.Count == 2; - IExpr! arg0 = (IExpr!)args[0]; - IExpr! arg1 = (IExpr!)args[1]; + IList/**//*!*/ args = nary.Arguments; + Contract.Assert(args != null); + Contract.Assert(args.Count == 2); + IExpr/*!*/ arg0 = (IExpr/*!*/)cce.NonNull(args[0]); + IExpr/*!*/ arg1 = (IExpr/*!*/)cce.NonNull(args[1]); // Look for "x == const" or "const == x". try { @@ -158,8 +180,8 @@ namespace Microsoft.AbstractInterpretationFramework /// This method throws an System.ArithmeticException in the event that folding the /// constant expression results in an arithmetic overflow or division by zero. /// - private bool Fold(IExpr! expr, out BigNum z) - { + private bool Fold(IExpr/*!*/ expr, out BigNum z){ +Contract.Requires(expr != null); IFunApp e = expr as IFunApp; if (e == null) { z = BigNum.ZERO; @@ -171,9 +193,10 @@ namespace Microsoft.AbstractInterpretationFramework return true; } else if (e.FunctionSymbol.Equals(Int.Negate)) { - IList/**/! args = e.Arguments; - assert args.Count == 1; - IExpr! arg0 = (IExpr!)args[0]; + IList/**//*!*/ args = e.Arguments; + Contract.Assert(args != null); + Contract.Assert(args.Count == 1); + IExpr/*!*/ arg0 = (IExpr/*!*/)cce.NonNull(args[0]); if (Fold(arg0, out z)) { z = z.Neg; @@ -181,8 +204,8 @@ namespace Microsoft.AbstractInterpretationFramework } } else if (e.Arguments.Count == 2) { - IExpr! arg0 = (IExpr!)e.Arguments[0]; - IExpr! arg1 = (IExpr!)e.Arguments[1]; + IExpr/*!*/ arg0 = (IExpr/*!*/)cce.NonNull(e.Arguments[0]); + IExpr/*!*/ arg1 = (IExpr/*!*/)cce.NonNull(e.Arguments[1]); BigNum z0, z1; if (Fold(arg0, out z0) && Fold(arg1, out z1)) { if (e.FunctionSymbol.Equals(Int.Add)) { diff --git a/Source/AIFramework/VariableMap/DynamicTypeLattice.cs b/Source/AIFramework/VariableMap/DynamicTypeLattice.cs index 8161cb3e..84525a15 100644 --- a/Source/AIFramework/VariableMap/DynamicTypeLattice.cs +++ b/Source/AIFramework/VariableMap/DynamicTypeLattice.cs @@ -3,171 +3,186 @@ // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- -namespace Microsoft.AbstractInterpretationFramework -{ - using System.Collections; - using System.Diagnostics; - using System.Compiler.Analysis; - using Microsoft.SpecSharp.Collections; - using Microsoft.Contracts; - - /// - /// Represents information about the dynamic type of a variable. In particular, for a - /// variable "v", represents either Bottom, "typeof(v)==T" for some type T, or a set - /// of constraints "typeof(v) subtype of T_i for some number of T_i's. - /// - public class DynamicTypeLattice : MicroLattice - { - enum What { Bottom, Exact, Bounds } - - private class Elt : Element { - // Representation: - // - Bottom is represented by: what==What.Bottom - // - An exact type T is represented by: what==What.Exact && ty==T - // - A set of type constraints T0, T1, T2, ..., T{n-1} is represented by: - // -- if n==0: what==What.Bounds && ty==null && manyBounds==null - // -- if n==1: what==What.Bounds && ty==T0 && manyBounds==null - // -- if n>=2: what==What.Bounds && ty==null && - // manyBounds!=null && manyBounds.Length==n && - // manyBounds[0]==T0 && manyBounds[1]==T1 && ... && manyBounds[n-1]==T{n-1} - // The reason for keeping the one-and-only bound in "ty" in case n==1 is to try - // to prevent the need for allocating a whole array of bounds, since 1 bound is - // bound to be common. - // In the representation, there are no redundant bounds in manyBounds. - // It is assumed that the types can can occur as exact bounds form a single-inheritance - // hierarchy. That is, if T0 and T1 are types that can occur as exact types, then - // there is no v such that typeof(v) is a subtype of both T0 and T1, unless T0 and T1 are - // the same type. - public readonly What what; - public readonly IExpr ty; - [Rep] - public readonly IExpr[] manyBounds; - invariant what == What.Bottom ==> ty == null && manyBounds == null; - invariant manyBounds != null ==> what == What.Bounds; - invariant manyBounds != null ==> forall{int i in (0:manyBounds.Length); manyBounds[i] != null}; - - public Elt(What what, IExpr ty) - requires what == What.Bottom ==> ty == null; - requires what == What.Exact ==> ty != null; - { - this.what = what; - this.ty = ty; - this.manyBounds = null; - } - - public Elt(IExpr[]! bounds) - requires forall{int i in (0:bounds.Length); bounds[i] != null}; - { - this.what = What.Bounds; - if (bounds.Length == 0) { - this.ty = null; - this.manyBounds = null; - } else if (bounds.Length == 1) { - this.ty = bounds[0]; - this.manyBounds = null; - } else { - this.ty = null; - this.manyBounds = bounds; - } - } - - /// - /// Constructs an Elt with "n" bounds, namely the n non-null values of the "bounds" list. - /// - [NotDelayed] - public Elt(ArrayList /*IExpr*/! bounds, int n) - requires 0 <= n && n <= bounds.Count; - { - this.what = What.Bounds; - if (n > 1) { - this.manyBounds = new IExpr[n]; - } - int k = 0; - foreach (IExpr bound in bounds) { - if (bound != null) { - assert k != n; - if (n == 1) { - assert this.ty == null; - this.ty = bound; - } else { - assume manyBounds != null; - manyBounds[k] = bound; - } - k++; - } - } - assert k == n; - } - - public int BoundsCount - { - get - ensures 0 <= result; - { - if (manyBounds != null) { - return manyBounds.Length; - } else if (ty != null) { - return 1; - } else { - return 0; - } - } - } +namespace Microsoft.AbstractInterpretationFramework { + using System.Collections; + using System.Diagnostics; + //using System.Compiler.Analysis; + //using Microsoft.SpecSharp.Collections; + using System.Diagnostics.Contracts; + + /// + /// Represents information about the dynamic type of a variable. In particular, for a + /// variable "v", represents either Bottom, "typeof(v)==T" for some type T, or a set + /// of constraints "typeof(v) subtype of T_i for some number of T_i's. + /// + public class DynamicTypeLattice : MicroLattice { + enum What { + Bottom, + Exact, + Bounds + } - [Pure] - public override System.Collections.Generic.ICollection! FreeVariables() - { - return (!) (new System.Collections.Generic.List()).AsReadOnly(); - } - - public override Element! Clone() - { - if (this.manyBounds != null) - return new Elt(this.manyBounds); - else - return new Elt(this.what, this.ty); + private class Elt : Element { + // Representation: + // - Bottom is represented by: what==What.Bottom + // - An exact type T is represented by: what==What.Exact && ty==T + // - A set of type constraints T0, T1, T2, ..., T{n-1} is represented by: + // -- if n==0: what==What.Bounds && ty==null && manyBounds==null + // -- if n==1: what==What.Bounds && ty==T0 && manyBounds==null + // -- if n>=2: what==What.Bounds && ty==null && + // manyBounds!=null && manyBounds.Length==n && + // manyBounds[0]==T0 && manyBounds[1]==T1 && ... && manyBounds[n-1]==T{n-1} + // The reason for keeping the one-and-only bound in "ty" in case n==1 is to try + // to prevent the need for allocating a whole array of bounds, since 1 bound is + // bound to be common. + // In the representation, there are no redundant bounds in manyBounds. + // It is assumed that the types can can occur as exact bounds form a single-inheritance + // hierarchy. That is, if T0 and T1 are types that can occur as exact types, then + // there is no v such that typeof(v) is a subtype of both T0 and T1, unless T0 and T1 are + // the same type. + public readonly What what; + public readonly IExpr ty; + [Rep] + public readonly IExpr[] manyBounds; + [ContractInvariantMethod] + void ObjectInvariant() { + + Contract.Invariant(what != What.Bottom || ty == null && manyBounds == null); + Contract.Invariant(manyBounds == null || what == What.Bounds); + Contract.Invariant(manyBounds == null || Contract.ForAll(0, manyBounds.Length, i => manyBounds[i] != null)); + } + public Elt(What what, IExpr ty) { + Contract.Requires(what != What.Bottom || ty == null); + Contract.Requires(what != What.Exact || ty != null); + this.what = what; + this.ty = ty; + this.manyBounds = null; + } + + public Elt(IExpr[]/*!*/ bounds) { + Contract.Requires(bounds != null); + Contract.Requires(Contract.ForAll(0, bounds.Length, i => bounds[i] != null)); + this.what = What.Bounds; + if (bounds.Length == 0) { + this.ty = null; + this.manyBounds = null; + } else if (bounds.Length == 1) { + this.ty = bounds[0]; + this.manyBounds = null; + } else { + this.ty = null; + this.manyBounds = bounds; + } + } + + /// + /// Constructs an Elt with "n" bounds, namely the n non-null values of the "bounds" list. + /// + [NotDelayed] + public Elt(ArrayList /*IExpr*//*!*/ bounds, int n) { + Contract.Requires(bounds != null); + Contract.Requires(0 <= n && n <= bounds.Count); + this.what = What.Bounds; + if (n > 1) { + this.manyBounds = new IExpr[n]; + } + int k = 0; + foreach (IExpr bound in bounds) { + if (bound != null) { + Contract.Assert(k != n); + if (n == 1) { + Contract.Assert(this.ty == null); + this.ty = bound; + } else { + Contract.Assume(manyBounds != null); + manyBounds[k] = bound; } + k++; + } + } + Contract.Assert(k == n); + } + + public int BoundsCount { + get { + Contract.Ensures(0 <= Contract.Result()); + if (manyBounds != null) { + return manyBounds.Length; + } else if (ty != null) { + return 1; + } else { + return 0; + } } + } + + [Pure] + public override System.Collections.Generic.ICollection/*!*/ FreeVariables() { + Contract.Ensures(cce.NonNullElements(Contract.Result>())); + return cce.NonNull(new System.Collections.Generic.List()).AsReadOnly(); + } + + public override Element/*!*/ Clone() { + Contract.Ensures(Contract.Result() != null); + if (this.manyBounds != null) + return new Elt(this.manyBounds); + else + return new Elt(this.what, this.ty); + } + } - readonly ITypeExprFactory! factory; - readonly IPropExprFactory! propFactory; + readonly ITypeExprFactory/*!*/ factory; + readonly IPropExprFactory/*!*/ propFactory; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(factory != null); + Contract.Invariant(propFactory != null); + } - public DynamicTypeLattice(ITypeExprFactory! factory, IPropExprFactory! propFactory) - { - this.factory = factory; - this.propFactory = propFactory; - // base(); - } - public override Element! Top - { - get { return new Elt(What.Bounds, null); } - } + public DynamicTypeLattice(ITypeExprFactory/*!*/ factory, IPropExprFactory/*!*/ propFactory) { + Contract.Requires(propFactory != null); + Contract.Requires(factory != null); + this.factory = factory; + this.propFactory = propFactory; + // base(); + } - public override Element! Bottom - { - get { return new Elt(What.Bottom, null); } - } + public override Element/*!*/ Top { + get { + Contract.Ensures(Contract.Result() != null); + return new Elt(What.Bounds, null); + } + } - public override bool IsTop (Element! element) - { - Elt e = (Elt)element; - return e.what == What.Bounds && e.ty == null && e.manyBounds == null; - } + public override Element/*!*/ Bottom { + get { + Contract.Ensures(Contract.Result() != null); + return new Elt(What.Bottom, null); + } + } - public override bool IsBottom(Element! element) - { - Elt e = (Elt)element; - return e.what == What.Bottom; - } + public override bool IsTop(Element/*!*/ element) { + Contract.Requires(element != null); + Elt e = (Elt)element; + return e.what == What.Bounds && e.ty == null && e.manyBounds == null; + } - public override Element! NontrivialJoin(Element! first, Element! second) - { + public override bool IsBottom(Element/*!*/ element) { + Contract.Requires(element != null); + Elt e = (Elt)element; + return e.what == What.Bottom; + } + + public override Element/*!*/ NontrivialJoin(Element/*!*/ first, Element/*!*/ second){ +Contract.Requires(second != null); +Contract.Requires(first != null); +Contract.Ensures(Contract.Result() != null); Elt a = (Elt)first; Elt b = (Elt)second; - assert a.what != What.Bottom && b.what != What.Bottom; + Contract.Assert(a.what != What.Bottom && b.what != What.Bottom); if (a.what == What.Exact && b.what == What.Exact) { - assert a.ty != null && b.ty != null; + Contract.Assert(a.ty != null && b.ty != null); if (factory.IsTypeEqual(a.ty, b.ty)) { return a; } else { @@ -176,13 +191,14 @@ namespace Microsoft.AbstractInterpretationFramework } // The result is going to be a Bounds, since at least one of the operands is a Bounds. - assert 1 <= a.BoundsCount && 1 <= b.BoundsCount; // a preconditions is that neither operand is Top + Contract.Assert(1 <= a.BoundsCount && 1 <= b.BoundsCount); // a preconditions is that neither operand is Top int n = a.BoundsCount + b.BoundsCount; // Special case: a and b each has exactly one bound if (n == 2) { - assert a.ty != null && b.ty != null; - IExpr! join = factory.JoinTypes(a.ty, b.ty); + Contract.Assert(a.ty != null && b.ty != null); + IExpr join = factory.JoinTypes(a.ty, b.ty); + Contract.Assert(join != null); if (join == a.ty && a.what == What.Bounds) { return a; } else if (join == b.ty && b.what == What.Bounds) { @@ -198,25 +214,26 @@ namespace Microsoft.AbstractInterpretationFramework if (a.ty != null) { allBounds.Add(a.ty); } else { - allBounds.AddRange((!)a.manyBounds); + allBounds.AddRange(cce.NonNull(a.manyBounds)); } int bStart = allBounds.Count; if (b.ty != null) { allBounds.Add(b.ty); } else { - allBounds.AddRange((!)b.manyBounds); + allBounds.AddRange(cce.NonNull(b.manyBounds)); } // compute the join of each pair, putting non-redundant joins into "result" for (int i = 0; i < bStart; i++) { - IExpr! aBound = (IExpr!)allBounds[i]; + IExpr/*!*/ aBound = cce.NonNull((IExpr/*!*/)allBounds[i]); for (int j = bStart; j < allBounds.Count; j++) { - IExpr! bBound = (IExpr!)allBounds[j]; + IExpr/*!*/ bBound = (IExpr/*!*/)cce.NonNull(allBounds[j]); - IExpr! join = factory.JoinTypes(aBound, bBound); + IExpr/*!*/ join = factory.JoinTypes(aBound, bBound); + Contract.Assert(join != null); int k = 0; while (k < result.Count) { - IExpr! r = (IExpr!)result[k]; + IExpr/*!*/ r = (IExpr/*!*/)cce.NonNull(result[k]); if (factory.IsSubType(join, r)) { // "join" is more restrictive than a bound already placed in "result", // so toss out "join" and compute the join of the next pair @@ -237,239 +254,257 @@ namespace Microsoft.AbstractInterpretationFramework } - public override Element! NontrivialMeet(Element! first, Element! second) - { - Elt a = (Elt)first; - Elt b = (Elt)second; - assert a.what != What.Bottom && b.what != What.Bottom; - - if (a.what == What.Exact && b.what == What.Exact) { - assert a.ty != null && b.ty != null; - if (factory.IsTypeEqual(a.ty, b.ty)) { - return a; - } else { - return Bottom; - } - - } else if (a.what == What.Exact || b.what == What.Exact) { - // One is Bounds, the other Exact. Make b be the Bounds one. - if (a.what == What.Bounds) { - Elt tmp = a; - a = b; - b = tmp; - } - assert a.what == What.Exact && b.what == What.Bounds; - // Check the exact type against all bounds. If the exact type is more restrictive - // than all bounds, then return it. If some bound is not met by the exact type, return - // bottom. - assert a.ty != null; - if (b.ty != null && !factory.IsSubType(a.ty, b.ty)) { - return Bottom; - } - if (b.manyBounds != null) { - foreach (IExpr! bound in b.manyBounds) { - if (!factory.IsSubType(a.ty, bound)) { - return Bottom; - } - } - } - return a; - } - - else { - // Both operands are Bounds. - assert a.what == What.Bounds && b.what == What.Bounds; - - // Take all the bounds, but prune those bounds that follow from others. - assert 1 <= a.BoundsCount && 1 <= b.BoundsCount; // a preconditions is that neither operand is Top - int n = a.BoundsCount + b.BoundsCount; - // Special case: a and b each has exactly one bound - if (n == 2) { - assert a.ty != null && b.ty != null; - if (factory.IsSubType(a.ty, b.ty)) { - // a is more restrictive - return a; - } else if (factory.IsSubType(b.ty, a.ty)) { - // b is more restrictive - return b; - } else { - IExpr[]! bounds = new IExpr[2]; - bounds[0] = a.ty; - bounds[1] = b.ty; - return new Elt(bounds); - } - } - - // General case - ArrayList /*IExpr*/ allBounds = new ArrayList /*IExpr*/ (n); - if (a.ty != null) { - allBounds.Add(a.ty); - } else { - allBounds.AddRange((!)a.manyBounds); - } - int bStart = allBounds.Count; - if (b.ty != null) { - allBounds.Add(b.ty); - } else { - allBounds.AddRange((!)b.manyBounds); - } - for (int i = 0; i < bStart; i++) { - IExpr! aBound = (IExpr!)allBounds[i]; - for (int j = bStart; j < allBounds.Count; j++) { - IExpr bBound = (IExpr!)allBounds[j]; - if (bBound == null) { - continue; - } else if (factory.IsSubType(aBound, bBound)) { - // a is more restrictive, so blot out the b bound - allBounds[j] = null; - n--; - } else if (factory.IsSubType(bBound, aBound)) { - // b is more restrictive, so blot out the a bound - allBounds[i] = null; - n--; - goto CONTINUE_OUTER_LOOP; - } - } - CONTINUE_OUTER_LOOP: {} - } - assert 1 <= n; - return new Elt(allBounds, n); - } + public override Element/*!*/ NontrivialMeet(Element/*!*/ first, Element/*!*/ second) { + Contract.Requires(second != null); + Contract.Requires(first != null); + Contract.Ensures(Contract.Result() != null); + Elt a = (Elt)first; + Elt b = (Elt)second; + Contract.Assert(a.what != What.Bottom && b.what != What.Bottom); + + if (a.what == What.Exact && b.what == What.Exact) { + Contract.Assert(a.ty != null && b.ty != null); + if (factory.IsTypeEqual(a.ty, b.ty)) { + return a; + } else { + return Bottom; } - public override Element! Widen (Element! first, Element! second) - { - return Join(first,second); + } else if (a.what == What.Exact || b.what == What.Exact) { + // One is Bounds, the other Exact. Make b be the Bounds one. + if (a.what == What.Bounds) { + Elt tmp = a; + a = b; + b = tmp; } - - protected override bool AtMost (Element! first, Element! second) // this <= that - { - Elt! a = (Elt!)first; - Elt! b = (Elt!)second; - assert a.what != What.Bottom && b.what != What.Bottom; - - if (a.what == What.Exact && b.what == What.Exact) { - assert a.ty != null && b.ty != null; - return factory.IsTypeEqual(a.ty, b.ty); - } else if (b.what == What.Exact) { - return false; - } else if (a.what == What.Exact) { - assert a.ty != null; - if (b.ty != null) { - return factory.IsSubType(a.ty, b.ty); - } else { - return forall{IExpr! bound in b.manyBounds; factory.IsSubType(a.ty, bound)}; - } - } else { - assert a.what == What.Bounds && b.what == What.Bounds; - assert a.ty != null || a.manyBounds != null; // a precondition is that a is not Top - assert b.ty != null || b.manyBounds != null; // a precondition is that b is not Top - // Return true iff: for each constraint in b, there is a stricter constraint in a. - if (a.ty != null && b.ty != null) { - return factory.IsSubType(a.ty, b.ty); - } else if (a.ty != null) { - return forall{IExpr! bound in b.manyBounds; factory.IsSubType(a.ty, bound)}; - } else if (b.ty != null) { - return exists{IExpr! bound in a.manyBounds; factory.IsSubType(bound, b.ty)}; - } else { - return forall{IExpr! bBound in b.manyBounds; - exists{IExpr! aBound in a.manyBounds; factory.IsSubType(aBound, bBound)}}; - } + Contract.Assert(a.what == What.Exact && b.what == What.Bounds); + // Check the exact type against all bounds. If the exact type is more restrictive + // than all bounds, then return it. If some bound is not met by the exact type, return + // bottom. + Contract.Assert(a.ty != null); + if (b.ty != null && !factory.IsSubType(a.ty, b.ty)) { + return Bottom; + } + if (b.manyBounds != null) { + foreach (IExpr/*!*/ bound in b.manyBounds) { + Contract.Assert(bound != null); + if (!factory.IsSubType(a.ty, bound)) { + return Bottom; } + } + } + return a; + } else { + // Both operands are Bounds. + Contract.Assert(a.what == What.Bounds && b.what == What.Bounds); + + // Take all the bounds, but prune those bounds that follow from others. + Contract.Assert(1 <= a.BoundsCount && 1 <= b.BoundsCount); // a preconditions is that neither operand is Top + int n = a.BoundsCount + b.BoundsCount; + // Special case: a and b each has exactly one bound + if (n == 2) { + Contract.Assert(a.ty != null && b.ty != null); + if (factory.IsSubType(a.ty, b.ty)) { + // a is more restrictive + return a; + } else if (factory.IsSubType(b.ty, a.ty)) { + // b is more restrictive + return b; + } else { + IExpr[]/*!*/ bounds = new IExpr[2]; + bounds[0] = a.ty; + bounds[1] = b.ty; + return new Elt(bounds); + } } - public override IExpr! ToPredicate(IVariable! var, Element! element) { - Elt e = (Elt)element; - switch (e.what) { - case What.Bottom: - return propFactory.False; - case What.Exact: - return factory.IsExactlyA(var, (!)e.ty); - case What.Bounds: - if (e.ty == null && e.manyBounds == null) { - return propFactory.True; - } else if (e.ty != null) { - return factory.IsA(var, e.ty); - } else { - IExpr! p = factory.IsA(var, (IExpr!)((!)e.manyBounds)[0]); - for (int i = 1; i < e.manyBounds.Length; i++) { - p = propFactory.And(p, factory.IsA(var, (IExpr!)e.manyBounds[i])); - } - return p; - } - default: - assert false; - throw new System.Exception(); + // General case + ArrayList /*IExpr*/ allBounds = new ArrayList /*IExpr*/ (n); + if (a.ty != null) { + allBounds.Add(a.ty); + } else { + allBounds.AddRange(cce.NonNull(a.manyBounds)); + } + int bStart = allBounds.Count; + if (b.ty != null) { + allBounds.Add(b.ty); + } else { + allBounds.AddRange(cce.NonNull(b.manyBounds)); + } + for (int i = 0; i < bStart; i++) { + IExpr/*!*/ aBound = cce.NonNull((IExpr)allBounds[i]); + for (int j = bStart; j < allBounds.Count; j++) { + IExpr bBound = (IExpr/*! Wouldn't the non-null typing in the original Spec# code had made bBound never null, + * thus negating the need for the continue statement?*/ + )allBounds[j]; + if (bBound == null) { + continue; + } else if (factory.IsSubType(aBound, bBound)) { + // a is more restrictive, so blot out the b bound + allBounds[j] = null; + n--; + } else if (factory.IsSubType(bBound, aBound)) { + // b is more restrictive, so blot out the a bound + allBounds[i] = null; + n--; + goto CONTINUE_OUTER_LOOP; } + } + CONTINUE_OUTER_LOOP: { + } } + Contract.Assert(1 <= n); + return new Elt(allBounds, n); + } + } + + public override Element/*!*/ Widen(Element/*!*/ first, Element/*!*/ second) { + Contract.Requires(second != null); + Contract.Requires(first != null); + Contract.Ensures(Contract.Result() != null); + return Join(first, second); + } - public override IExpr GetFoldExpr(Element! e) { - // cannot fold into an expression that can be substituted for the variable - return null; + protected override bool AtMost(Element/*!*/ first, Element/*!*/ second) // this <= that + { + Contract.Requires(first != null); + Contract.Requires(second != null); + Elt/*!*/ a = (Elt/*!*/)cce.NonNull(first); + Elt/*!*/ b = (Elt/*!*/)cce.NonNull(second); + Contract.Assert(a.what != What.Bottom && b.what != What.Bottom); + + if (a.what == What.Exact && b.what == What.Exact) { + Contract.Assert(a.ty != null && b.ty != null); + return factory.IsTypeEqual(a.ty, b.ty); + } else if (b.what == What.Exact) { + return false; + } else if (a.what == What.Exact) { + Contract.Assert(a.ty != null); + if (b.ty != null) { + return factory.IsSubType(a.ty, b.ty); + } else { + return Contract.ForAll(b.manyBounds, bound => factory.IsSubType(a.ty, bound)); } + } else { + Contract.Assert(a.what == What.Bounds && b.what == What.Bounds); + Contract.Assert(a.ty != null || a.manyBounds != null); // a precondition is that a is not Top + Contract.Assert(b.ty != null || b.manyBounds != null); // a precondition is that b is not Top + // Return true iff: for each constraint in b, there is a stricter constraint in a. + if (a.ty != null && b.ty != null) { + return factory.IsSubType(a.ty, b.ty); + } else if (a.ty != null) { + return Contract.ForAll(b.manyBounds, bound => factory.IsSubType(a.ty, bound)); + } else if (b.ty != null) { + return Contract.Exists(a.manyBounds, bound => factory.IsSubType(bound, b.ty)); + } else { + return Contract.ForAll(b.manyBounds, bBound => Contract.Exists(a.manyBounds, aBound => factory.IsSubType(aBound, bBound))); + } + } + } - public override bool Understands(IFunctionSymbol! f, IList/**/! args) { - bool isEq = f.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq); - if (isEq || f.Equals(Microsoft.AbstractInterpretationFramework.Value.Subtype)) { - assert args.Count == 2; - IExpr! arg0 = (IExpr!)args[0]; - IExpr! arg1 = (IExpr!)args[1]; - - // Look for $typeof(var) == t or t == $typeof(var) or $typeof(var) <: t - if (isEq && factory.IsTypeConstant(arg0)) { - // swap the arguments - IExpr! tmp = arg0; - arg0 = arg1; - arg1 = tmp; - } else if (!factory.IsTypeConstant(arg1)) { - return false; - } - IFunApp typeofExpr = arg0 as IFunApp; - if (typeofExpr != null && - typeofExpr.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Typeof)) { - assert typeofExpr.Arguments.Count == 1; - if (typeofExpr.Arguments[0] is IVariable) { - // we have a match - return true; - } - } + public override IExpr/*!*/ ToPredicate(IVariable/*!*/ var, Element/*!*/ element) { + Contract.Requires(element != null); + Contract.Requires(var != null); + Contract.Ensures(Contract.Result() != null); + Elt e = (Elt)element; + switch (e.what) { + case What.Bottom: + return propFactory.False; + case What.Exact: + return factory.IsExactlyA(var, cce.NonNull(e.ty)); + case What.Bounds: + if (e.ty == null && e.manyBounds == null) { + return propFactory.True; + } else if (e.ty != null) { + return factory.IsA(var, e.ty); + } else { + IExpr/*!*/ p = factory.IsA(var, (IExpr/*!*/)cce.NonNull(e.manyBounds)[0]); + for (int i = 1; i < e.manyBounds.Length; i++) { + p = propFactory.And(p, factory.IsA(var, (IExpr/*!*/)cce.NonNull(e.manyBounds[i]))); } - return false; - } + return p; + } + default: { + Contract.Assert(false); + throw new cce.UnreachableException(); + } + throw new System.Exception(); + } + } - public override Element! EvaluatePredicate(IExpr! e) { - IFunApp nary = e as IFunApp; - if (nary != null) { + public override IExpr GetFoldExpr(Element/*!*/ e) { + Contract.Requires(e != null); + // cannot fold into an expression that can be substituted for the variable + return null; + } - bool isEq = nary.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq); - if (isEq || nary.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Subtype)) { - IList/**/! args = nary.Arguments; - assert args.Count == 2; - IExpr! arg0 = (IExpr!)args[0]; - IExpr! arg1 = (IExpr!)args[1]; - - // Look for $typeof(var) == t or t == $typeof(var) or $typeof(var) <: t - if (isEq && factory.IsTypeConstant(arg0)) { - // swap the arguments - IExpr! tmp = arg0; - arg0 = arg1; - arg1 = tmp; - } else if (!factory.IsTypeConstant(arg1)) { - return Top; - } - IFunApp typeofExpr = arg0 as IFunApp; - if (typeofExpr != null && - typeofExpr.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Typeof)) { - assert typeofExpr.Arguments.Count == 1; - if (typeofExpr.Arguments[0] is IVariable) { - // we have a match - return new Elt(isEq ? What.Exact : What.Bounds, arg1); - } - } - } - } - return Top; + public override bool Understands(IFunctionSymbol/*!*/ f, IList/**//*!*/ args) { + Contract.Requires(args != null); + Contract.Requires(f != null); + bool isEq = f.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq); + if (isEq || f.Equals(Microsoft.AbstractInterpretationFramework.Value.Subtype)) { + Contract.Assert(args.Count == 2); + IExpr/*!*/ arg0 = (IExpr/*!*/)cce.NonNull(args[0]); + IExpr/*!*/ arg1 = (IExpr/*!*/)cce.NonNull(args[1]); + + // Look for $typeof(var) == t or t == $typeof(var) or $typeof(var) <: t + if (isEq && factory.IsTypeConstant(arg0)) { + // swap the arguments + IExpr/*!*/ tmp = arg0; + arg0 = arg1; + arg1 = tmp; + } else if (!factory.IsTypeConstant(arg1)) { + return false; } + IFunApp typeofExpr = arg0 as IFunApp; + if (typeofExpr != null && + typeofExpr.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Typeof)) { + Contract.Assert(typeofExpr.Arguments.Count == 1); + if (typeofExpr.Arguments[0] is IVariable) { + // we have a match + return true; + } + } + } + return false; + } + public override Element/*!*/ EvaluatePredicate(IExpr/*!*/ e) { + Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); + IFunApp nary = e as IFunApp; + if (nary != null) { + + bool isEq = nary.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq); + if (isEq || nary.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Subtype)) { + IList/**//*!*/ args = nary.Arguments; + Contract.Assert(args != null); + Contract.Assert(args.Count == 2); + IExpr/*!*/ arg0 = (IExpr/*!*/)cce.NonNull(args[0]); + IExpr/*!*/ arg1 = (IExpr/*!*/)cce.NonNull(args[1]); + + // Look for $typeof(var) == t or t == $typeof(var) or $typeof(var) <: t + if (isEq && factory.IsTypeConstant(arg0)) { + // swap the arguments + IExpr/*!*/ tmp = arg0; + arg0 = arg1; + arg1 = tmp; + } else if (!factory.IsTypeConstant(arg1)) { + return Top; + } + IFunApp typeofExpr = arg0 as IFunApp; + if (typeofExpr != null && + typeofExpr.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Typeof)) { + Contract.Assert(typeofExpr.Arguments.Count == 1); + if (typeofExpr.Arguments[0] is IVariable) { + // we have a match + return new Elt(isEq ? What.Exact : What.Bounds, arg1); + } + } + } + } + return Top; } + + } } diff --git a/Source/AIFramework/VariableMap/Intervals.cs b/Source/AIFramework/VariableMap/Intervals.cs index f507e020..73a1352f 100644 --- a/Source/AIFramework/VariableMap/Intervals.cs +++ b/Source/AIFramework/VariableMap/Intervals.cs @@ -5,47 +5,48 @@ //----------------------------------------------------------------------------- using System; using System.Collections; -using System.Compiler.Analysis; +//using System.Compiler.Analysis; using Microsoft.AbstractInterpretationFramework.Collections; -using Microsoft.Contracts; +using System.Diagnostics.Contracts; using Microsoft.Basetypes; ///////////////////////////////////////////////////////////////////////////////// // An implementation of the interval abstract domain ///////////////////////////////////////////////////////////////////////////////// -namespace Microsoft.AbstractInterpretationFramework -{ - public class IntervalLattice : MicroLattice - { - readonly ILinearExprFactory! factory; - - public IntervalLattice(ILinearExprFactory! factory) - { +namespace Microsoft.AbstractInterpretationFramework { + public class IntervalLattice : MicroLattice { + readonly ILinearExprFactory/*!*/ factory; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(factory != null); + } + + + public IntervalLattice(ILinearExprFactory/*!*/ factory) { + Contract.Requires(factory != null); this.factory = factory; // base(); } - public override bool UnderstandsBasicArithmetics - { - get - { + public override bool UnderstandsBasicArithmetics { + get { return true; } } - public override Element! Top - { - get - { + public override Element/*!*/ Top { + get { + Contract.Ensures(Contract.Result() != null); + return IntervalElement.Top; } } - - public override Element! Bottom - { - get - { + + public override Element/*!*/ Bottom { + get { + Contract.Ensures(Contract.Result() != null); + return IntervalElement.Bottom; } } @@ -53,47 +54,51 @@ namespace Microsoft.AbstractInterpretationFramework /// /// The paramter is the top? /// - public override bool IsTop(Element! element) - { - IntervalElement interval = (IntervalElement) element; - - return interval.IsTop(); + public override bool IsTop(Element/*!*/ element) { + Contract.Requires(element != null); + IntervalElement interval = (IntervalElement)element; + + return interval.IsTop(); } /// /// The parameter is the bottom? /// - public override bool IsBottom(Element! element) - { - IntervalElement interval = (IntervalElement) element; - - return interval.IsBottom(); + public override bool IsBottom(Element/*!*/ element) { + Contract.Requires(element != null); + IntervalElement interval = (IntervalElement)element; + + return interval.IsBottom(); } /// /// The classic, pointwise, join of intervals /// - public override Element! NontrivialJoin(Element! left, Element! right) - { - IntervalElement! leftInterval = (IntervalElement!) left; - IntervalElement! rightInterval = (IntervalElement) right; - + public override Element/*!*/ NontrivialJoin(Element/*!*/ left, Element/*!*/ right) { + Contract.Requires(right != null); + Contract.Requires(left != null); + Contract.Ensures(Contract.Result() != null); + IntervalElement/*!*/ leftInterval = (IntervalElement/*!*/)cce.NonNull(left); + IntervalElement/*!*/ rightInterval = (IntervalElement/*!*/)cce.NonNull(right); + ExtendedInt inf = ExtendedInt.Inf(leftInterval.Inf, rightInterval.Inf); ExtendedInt sup = ExtendedInt.Sup(leftInterval.Sup, rightInterval.Sup); - IntervalElement! join = IntervalElement.Factory(inf, sup); + IntervalElement/*!*/ join = IntervalElement.Factory(inf, sup); - return join; + return join; } /// /// The classic, pointwise, meet of intervals /// - public override Element! NontrivialMeet(Element! left, Element! right) - { - IntervalElement! leftInterval = (IntervalElement!) left; - IntervalElement! rightInterval = (IntervalElement) right; - + public override Element/*!*/ NontrivialMeet(Element/*!*/ left, Element/*!*/ right) { + Contract.Requires(right != null); + Contract.Requires(left != null); + Contract.Ensures(Contract.Result() != null); + IntervalElement/*!*/ leftInterval = (IntervalElement/*!*/)cce.NonNull(left); + IntervalElement/*!*/ rightInterval = (IntervalElement/*!*/)cce.NonNull(right); + ExtendedInt inf = ExtendedInt.Sup(leftInterval.Inf, rightInterval.Inf); ExtendedInt sup = ExtendedInt.Inf(leftInterval.Sup, rightInterval.Sup); @@ -105,11 +110,13 @@ namespace Microsoft.AbstractInterpretationFramework /// The very simple widening of intervals, to be improved with thresholds /// left is the PREVIOUS value in the iterations and right is the NEW one /// - public override Element! Widen(Element! left, Element! right) - { - IntervalElement! prevInterval = (IntervalElement!) left; - IntervalElement! nextInterval = (IntervalElement!) right; - + public override Element/*!*/ Widen(Element/*!*/ left, Element/*!*/ right) { + Contract.Requires(right != null); + Contract.Requires(left != null); + Contract.Ensures(Contract.Result() != null); + IntervalElement/*!*/ prevInterval = (IntervalElement/*!*/)cce.NonNull(left); + IntervalElement/*!*/ nextInterval = (IntervalElement/*!*/)cce.NonNull(right); + ExtendedInt inf = nextInterval.Inf < prevInterval.Inf ? ExtendedInt.MinusInfinity : prevInterval.Inf; ExtendedInt sup = nextInterval.Sup > prevInterval.Sup ? ExtendedInt.PlusInfinity : prevInterval.Sup; @@ -122,12 +129,13 @@ namespace Microsoft.AbstractInterpretationFramework /// /// Return true iff the interval left is containted in right /// - protected override bool AtMost(Element! left, Element! right) - { - IntervalElement! leftInterval = (IntervalElement!) left; - IntervalElement! rightInterval = (IntervalElement!) right; + protected override bool AtMost(Element/*!*/ left, Element/*!*/ right) { + Contract.Requires(right != null); + Contract.Requires(left != null); + IntervalElement/*!*/ leftInterval = (IntervalElement/*!*/)cce.NonNull(left); + IntervalElement/*!*/ rightInterval = (IntervalElement/*!*/)cce.NonNull(right); - if(leftInterval.IsBottom() || rightInterval.IsTop()) + if (leftInterval.IsBottom() || rightInterval.IsTop()) return true; return rightInterval.Inf <= leftInterval.Inf && leftInterval.Sup <= rightInterval.Sup; @@ -136,17 +144,19 @@ namespace Microsoft.AbstractInterpretationFramework /// /// Return just null /// - public override IExpr GetFoldExpr(Element! element) - { + public override IExpr GetFoldExpr(Element/*!*/ element) { + Contract.Requires(element != null); return null; - } + } /// /// return a predicate inf "\leq x and x "\leq" sup (if inf [or sup] is not oo) /// - public override IExpr! ToPredicate(IVariable! var, Element! element) - { - IntervalElement! interval = (IntervalElement!) element; + public override IExpr/*!*/ ToPredicate(IVariable/*!*/ var, Element/*!*/ element){ +Contract.Requires(element != null); +Contract.Requires(var != null); +Contract.Ensures(Contract.Result() != null); +IntervalElement/*!*/ interval = (IntervalElement/*!*/)cce.NonNull(element); IExpr lowerBound = null; IExpr upperBound = null; @@ -171,38 +181,41 @@ namespace Microsoft.AbstractInterpretationFramework return upperBound; else // If we reach this point, both lowerBound and upperBound are null, i.e. we have no bounds on var, so we return simply true... return this.factory.True; - } + } /// /// For the moment consider just equalities. Other case must be considered /// - public override bool Understands(IFunctionSymbol! f, IList /* /// Evaluate the predicate passed as input according the semantics of intervals /// - public override Element! EvaluatePredicate(IExpr! pred) - { + public override Element/*!*/ EvaluatePredicate(IExpr/*!*/ pred) { + Contract.Requires(pred != null); + Contract.Ensures(Contract.Result() != null); return this.EvaluatePredicateWithState(pred, null); } - + /// /// Evaluate the predicate passed as input according the semantics of intervals and the given state. /// Right now just basic arithmetic operations are supported. A future extension may consider an implementation of boolean predicates /// - public override Element! EvaluatePredicateWithState(IExpr! pred, IFunctionalMap/* Var -> Element */ state) - { + public override Element/*!*/ EvaluatePredicateWithState(IExpr/*!*/ pred, IFunctionalMap/* Var -> Element */ state){ +Contract.Requires(pred != null); +Contract.Ensures(Contract.Result() != null); if(pred is IFunApp) { IFunApp fun = (IFunApp) pred; if(fun.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq)) // if it is a symbol of equality { - IExpr! leftArg = (IExpr!) fun.Arguments[0]; - IExpr! rightArg = (IExpr!) fun.Arguments[1]; + IExpr/*!*/ leftArg = (IExpr/*!*/)cce.NonNull(fun.Arguments[0]); + IExpr/*!*/ rightArg = (IExpr/*!*/)cce.NonNull(fun.Arguments[1]); if (leftArg is IVariable) { return Eval(rightArg, state); } else if (rightArg is IVariable) { @@ -217,10 +230,11 @@ namespace Microsoft.AbstractInterpretationFramework /// /// Evaluate the expression (that is assured to be an arithmetic expression, in the state passed as a parameter /// - private IntervalElement! Eval(IExpr! exp, IFunctionalMap/* Var -> Element */ state) - { + private IntervalElement/*!*/ Eval(IExpr/*!*/ exp, IFunctionalMap/* Var -> Element */ state) { +Contract.Requires((exp != null)); +Contract.Ensures(Contract.Result() != null); - IntervalElement! retVal = (IntervalElement!) Top; + IntervalElement/*!*/ retVal = (IntervalElement/*!*/)cce.NonNull(Top); // Eval the expression by structural induction @@ -248,19 +262,23 @@ namespace Microsoft.AbstractInterpretationFramework } else if(fun.FunctionSymbol.Equals(Int.Negate)) // An unary minus { - IExpr! arg = (IExpr!) fun.Arguments[0]; - IntervalElement! argEval = Eval(arg, state); - IntervalElement! zero = IntervalElement.Factory(BigNum.ZERO); + IExpr/*!*/ arg = (IExpr/*!*/)cce.NonNull(fun.Arguments[0]); + IntervalElement/*!*/ argEval = Eval(arg, state); + Contract.Assert(argEval != null); + IntervalElement/*!*/ zero = IntervalElement.Factory(BigNum.ZERO); + Contract.Assert(zero != null); retVal = zero - argEval; } else if(fun.Arguments.Count == 2) { - IExpr! left = (IExpr!) fun.Arguments[0]; - IExpr! right = (IExpr!) fun.Arguments[1]; + IExpr/*!*/ left = (IExpr/*!*/)cce.NonNull(fun.Arguments[0]); + IExpr/*!*/ right = (IExpr/*!*/)cce.NonNull(fun.Arguments[1]); - IntervalElement! leftVal = Eval(left, state); - IntervalElement! rightVal = Eval(right, state); + IntervalElement/*!*/ leftVal = Eval(left, state); + Contract.Assert(leftVal != null); + IntervalElement/*!*/ rightVal = Eval(right, state); + Contract.Assert(rightVal != null); if(fun.FunctionSymbol.Equals(Int.Add)) retVal = leftVal + rightVal; @@ -281,165 +299,199 @@ namespace Microsoft.AbstractInterpretationFramework /// /// Inner class standing for an interval on integers, possibly unbounded /// - private class IntervalElement : Element - { - protected static readonly IntervalElement! TopInterval = new IntervalElement(new MinusInfinity(), new PlusInfinity()); // Top = [-oo , +oo] - protected static readonly IntervalElement! BottomInterval = new IntervalElement(new PlusInfinity(), new MinusInfinity()); // Bottom = [+oo, -oo] + private class IntervalElement : Element { + protected static readonly IntervalElement/*!*/ TopInterval = new IntervalElement(new MinusInfinity(), new PlusInfinity()); // Top = [-oo , +oo] + protected static readonly IntervalElement/*!*/ BottomInterval = new IntervalElement(new PlusInfinity(), new MinusInfinity()); // Bottom = [+oo, -oo] + + private readonly ExtendedInt/*!*/ inf; + private readonly ExtendedInt/*!*/ sup; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(inf != null); + Contract.Invariant(sup != null); + } - private readonly ExtendedInt! inf; - private readonly ExtendedInt! sup; - - public ExtendedInt! Inf - { - get - { - return inf; - } - } - - public ExtendedInt! Sup - { - get - { - return sup; - } - } - - // Construct the inteval [val, val] - protected IntervalElement(BigNum val) - { - this.inf = this.sup = ExtendedInt.Factory(val); - // base(); - } + public ExtendedInt/*!*/ Inf { + get { + Contract.Ensures(Contract.Result() != null); - // Construct the interval [inf, sup] - protected IntervalElement(BigNum infInt, BigNum supInt) - { - this.inf = ExtendedInt.Factory(infInt); - this.sup = ExtendedInt.Factory(supInt); - // base(); // to please the compiler... - } - - protected IntervalElement(ExtendedInt! inf, ExtendedInt! sup) - { - this.inf = inf; - this.sup = sup; - // base(); + return inf; } + } - // Construct an Interval - public static IntervalElement! Factory(ExtendedInt! inf, ExtendedInt! sup) - { - if(inf is MinusInfinity && sup is PlusInfinity) - return Top; - if(inf > sup) - return Bottom; - // otherwise... - return new IntervalElement(inf, sup); - } + public ExtendedInt/*!*/ Sup { + get { + Contract.Ensures(Contract.Result() != null); - public static IntervalElement! Factory(BigNum i) - { - return new IntervalElement(i); + return sup; } + } - public static IntervalElement! Factory(BigNum inf, BigNum sup) - { - ExtendedInt! i = ExtendedInt.Factory(inf); - ExtendedInt! s = ExtendedInt.Factory(sup); + // Construct the inteval [val, val] + protected IntervalElement(BigNum val) { + this.inf = this.sup = ExtendedInt.Factory(val); + // base(); + } + + // Construct the interval [inf, sup] + protected IntervalElement(BigNum infInt, BigNum supInt) { + this.inf = ExtendedInt.Factory(infInt); + this.sup = ExtendedInt.Factory(supInt); + // base(); // to please the compiler... + } + + protected IntervalElement(ExtendedInt/*!*/ inf, ExtendedInt/*!*/ sup) { + Contract.Requires(sup != null); + Contract.Requires(inf != null); + this.inf = inf; + this.sup = sup; + // base(); + } + + // Construct an Interval + public static IntervalElement/*!*/ Factory(ExtendedInt/*!*/ inf, ExtendedInt/*!*/ sup) { + Contract.Requires((sup != null)); +Contract.Requires((inf != null)); +Contract.Ensures(Contract.Result() != null); + if (inf is MinusInfinity && sup is PlusInfinity) + return Top; + if (inf > sup) + return Bottom; + // otherwise... + return new IntervalElement(inf, sup); + } + + public static IntervalElement/*!*/ Factory(BigNum i) { + Contract.Ensures(Contract.Result() != null); + return new IntervalElement(i); + } + + public static IntervalElement/*!*/ Factory(BigNum inf, BigNum sup) { +Contract.Ensures(Contract.Result() != null); + ExtendedInt/*!*/ i = ExtendedInt.Factory(inf); + ExtendedInt/*!*/ s = ExtendedInt.Factory(sup); return Factory(i, s); } - static public IntervalElement! Top - { - get - { - return TopInterval; - } - } + static public IntervalElement/*!*/ Top { + get { + Contract.Ensures(Contract.Result() != null); - static public IntervalElement! Bottom - { - get - { - return BottomInterval; - } + return TopInterval; } + } - public bool IsTop() - { - return this.inf is MinusInfinity && this.sup is PlusInfinity; - } + static public IntervalElement/*!*/ Bottom { + get { + Contract.Ensures(Contract.Result() != null); - public bool IsBottom() - { - return this.inf > this.sup; + return BottomInterval; } + } - #region Below are the arithmetic operations lifted to intervals + public bool IsTop() { + return this.inf is MinusInfinity && this.sup is PlusInfinity; + } - // Addition - public static IntervalElement! operator+(IntervalElement! a, IntervalElement! b) - { - ExtendedInt! inf = a.inf + b.inf; - ExtendedInt! sup = a.sup + b.sup; + public bool IsBottom() { + return this.inf > this.sup; + } + + #region Below are the arithmetic operations lifted to intervals + + // Addition + public static IntervalElement/*!*/ operator +(IntervalElement/*!*/ a, IntervalElement/*!*/ b){ +Contract.Requires(b != null); +Contract.Requires(a != null); +Contract.Ensures(Contract.Result() != null); + ExtendedInt/*!*/ inf = a.inf + b.inf; + Contract.Assert(inf != null); + ExtendedInt/*!*/ sup = a.sup + b.sup; + Contract.Assert(sup != null); return Factory(inf, sup); } - // Subtraction - public static IntervalElement! operator-(IntervalElement! a, IntervalElement! b) - { - ExtendedInt! inf = a.inf - b.sup; - ExtendedInt! sup = a.sup - b.inf; - - IntervalElement! sub = Factory(inf, sup); + // Subtraction + public static IntervalElement/*!*/ operator -(IntervalElement/*!*/ a, IntervalElement/*!*/ b){ +Contract.Requires(b != null); +Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + ExtendedInt/*!*/ inf = a.inf - b.sup; + Contract.Assert(inf != null); + + ExtendedInt/*!*/ sup = a.sup - b.inf; +Contract.Assert(sup != null); +IntervalElement/*!*/ sub = Factory(inf, sup); +Contract.Assert(sub != null); return sub; - } - - // Multiplication - public static IntervalElement! operator*(IntervalElement! a, IntervalElement! b) - { - ExtendedInt! infinf = a.inf * b.inf; - ExtendedInt! infsup = a.inf * b.sup; - ExtendedInt! supinf = a.sup * b.inf; - ExtendedInt! supsup = a.sup * b.sup; + } - ExtendedInt! inf = ExtendedInt.Inf(infinf, infsup, supinf, supsup); - ExtendedInt! sup = ExtendedInt.Sup(infinf, infsup, supinf, supsup); + // Multiplication + public static IntervalElement/*!*/ operator *(IntervalElement/*!*/ a, IntervalElement/*!*/ b){ +Contract.Requires(b != null); +Contract.Requires(a != null); +Contract.Ensures(Contract.Result() != null); + ExtendedInt/*!*/ infinf = a.inf * b.inf; + Contract.Assert(infinf != null); + ExtendedInt/*!*/ infsup = a.inf * b.sup; + Contract.Assert(infsup != null); + ExtendedInt/*!*/ supinf = a.sup * b.inf; + Contract.Assert(supinf != null); + ExtendedInt/*!*/ supsup = a.sup * b.sup; + Contract.Assert(supsup != null); + + ExtendedInt/*!*/ inf = ExtendedInt.Inf(infinf, infsup, supinf, supsup); + Contract.Assert(inf != null); + ExtendedInt/*!*/ sup = ExtendedInt.Sup(infinf, infsup, supinf, supsup); + Contract.Assert(sup != null); return Factory(inf, sup); } - // Division - public static IntervalElement! operator/(IntervalElement! a, IntervalElement! b) - { + // Division + public static IntervalElement/*!*/ operator /(IntervalElement/*!*/ a, IntervalElement/*!*/ b){ +Contract.Requires(b != null); +Contract.Requires(a != null); +Contract.Ensures(Contract.Result() != null); if(b.inf.IsZero && b.sup.IsZero) // Check division by zero return IntervalElement.Top; - ExtendedInt! infinf = a.inf / b.inf; - ExtendedInt! infsup = a.inf / b.sup; - ExtendedInt! supinf = a.sup / b.inf; - ExtendedInt! supsup = a.sup / b.sup; + ExtendedInt/*!*/ infinf = a.inf / b.inf; + Contract.Assert(infinf != null); + ExtendedInt/*!*/ infsup = a.inf / b.sup; + Contract.Assert(infsup != null); + ExtendedInt/*!*/ supinf = a.sup / b.inf; + Contract.Assert(supinf != null); + ExtendedInt/*!*/ supsup = a.sup / b.sup; + Contract.Assert(supsup != null); - ExtendedInt! inf = ExtendedInt.Inf(infinf, infsup, supinf, supsup); - ExtendedInt! sup = ExtendedInt.Sup(infinf, infsup, supinf, supsup); + ExtendedInt/*!*/ inf = ExtendedInt.Inf(infinf, infsup, supinf, supsup); + Contract.Assert(inf != null); + ExtendedInt/*!*/ sup = ExtendedInt.Sup(infinf, infsup, supinf, supsup); + Contract.Assert(sup != null); return Factory(inf, sup); } - // Division - public static IntervalElement! operator%(IntervalElement! a, IntervalElement! b) - { + // Division + public static IntervalElement/*!*/ operator %(IntervalElement/*!*/ a, IntervalElement/*!*/ b){ +Contract.Requires(b != null); +Contract.Requires(a != null); +Contract.Ensures(Contract.Result() != null); if(b.inf.IsZero && b.sup.IsZero) // Check division by zero return IntervalElement.Top; - ExtendedInt! infinf = a.inf % b.inf; - ExtendedInt! infsup = a.inf % b.sup; - ExtendedInt! supinf = a.sup % b.inf; - ExtendedInt! supsup = a.sup % b.sup; + ExtendedInt/*!*/ infinf = a.inf % b.inf; + Contract.Assert(infinf != null); + ExtendedInt/*!*/ infsup = a.inf % b.sup; + Contract.Assert(infsup != null); + ExtendedInt/*!*/ supinf = a.sup % b.inf; + Contract.Assert(supinf != null); + ExtendedInt/*!*/ supsup = a.sup % b.sup; + Contract.Assert(supsup != null); ExtendedInt inf = ExtendedInt.Inf(infinf, infsup, supinf, supsup); ExtendedInt sup = ExtendedInt.Sup(infinf, infsup, supinf, supsup); @@ -447,67 +499,72 @@ namespace Microsoft.AbstractInterpretationFramework return Factory(inf, sup); } - #endregion + #endregion - #region Overriden methods + #region Overriden methods - public override Element! Clone() - { - // Real copying should not be needed because intervals are immutable? - return this; - /* - int valInf = this.inf.Value; - int valSup = this.sup.Value; + public override Element/*!*/ Clone() { + Contract.Ensures(Contract.Result() != null); + // Real copying should not be needed because intervals are immutable? + return this; + /* + int valInf = this.inf.Value; + int valSup = this.sup.Value; - ExtendedInt clonedInf = ExtendedInt.Factory(valInf); - ExtendedInt clonedSup = ExtendedInt.Factory(valSup); + ExtendedInt clonedInf = ExtendedInt.Factory(valInf); + ExtendedInt clonedSup = ExtendedInt.Factory(valSup); - return Factory(clonedInf, clonedSup); - */ - } + return Factory(clonedInf, clonedSup); + */ + } - [Pure] - public override System.Collections.Generic.ICollection! FreeVariables() - { - return (!) (new System.Collections.Generic.List()).AsReadOnly(); + [Pure] + public override System.Collections.Generic.ICollection/*!*/ FreeVariables() { +Contract.Ensures(cce.NonNullElements(Contract.Result>())); +return cce.NonNull(new System.Collections.Generic.List()).AsReadOnly(); } - [Pure] - public override string! ToString() - { - return "[" + this.inf + ", " + this.sup + "]"; - } + [Pure] + public override string/*!*/ ToString() { + Contract.Ensures(Contract.Result() != null); + return "[" + this.inf + ", " + this.sup + "]"; + } - #endregion + #endregion } -} + } + - /// The interface for an extended integer - abstract class ExtendedInt - { - private static readonly PlusInfinity! cachedPlusInf = new PlusInfinity(); - private static readonly MinusInfinity! cachedMinusInf = new MinusInfinity(); - - static public ExtendedInt! PlusInfinity - { - get - { + /// + [ContractClass(typeof(ExtendedIntContracts))] + abstract class ExtendedInt { + private static readonly PlusInfinity/*!*/ cachedPlusInf = new PlusInfinity(); + private static readonly MinusInfinity/*!*/ cachedMinusInf = new MinusInfinity(); + + static public ExtendedInt/*!*/ PlusInfinity { + get { + Contract.Ensures(Contract.Result() != null); + return cachedPlusInf; } } - static public ExtendedInt! MinusInfinity - { - get - { + static public ExtendedInt/*!*/ MinusInfinity { + get { + Contract.Ensures(Contract.Result() != null); + return cachedMinusInf; - } + } } - public abstract BigNum Value { get; } + public abstract BigNum Value { + get; + } - public abstract int Signum { get; } + public abstract int Signum { + get; + } public bool IsZero { get { @@ -531,158 +588,188 @@ namespace Microsoft.AbstractInterpretationFramework #region Below are the extensions of arithmetic operations on extended integers // Addition - public static ExtendedInt! operator+(ExtendedInt! a, ExtendedInt! b) - { - if (a is InfinitaryInt) { - return a; - } else if (b is InfinitaryInt) { - return b; - } else { - return ExtendedInt.Factory(a.Value + b.Value); - } + public static ExtendedInt/*!*/ operator +(ExtendedInt/*!*/ a, ExtendedInt/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + if (a is InfinitaryInt) { + return a; + } else if (b is InfinitaryInt) { + return b; + } else { + return ExtendedInt.Factory(a.Value + b.Value); + } } // Subtraction - public static ExtendedInt! operator-(ExtendedInt! a, ExtendedInt! b) - { - if (a is InfinitaryInt) { - return a; - } else if (b is InfinitaryInt) { - return UnaryMinus(b); - } else { - return ExtendedInt.Factory(a.Value - b.Value); - } - } - + public static ExtendedInt/*!*/ operator -(ExtendedInt/*!*/ a, ExtendedInt/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + if (a is InfinitaryInt) { + return a; + } else if (b is InfinitaryInt) { + return UnaryMinus(b); + } else { + return ExtendedInt.Factory(a.Value - b.Value); + } + } + // Unary minus - public static ExtendedInt! operator-(ExtendedInt! a) - { + public static ExtendedInt/*!*/ operator -(ExtendedInt/*!*/ a) { + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); // BUGBUG: Some compiler error prevents the unary minus operator from being used return UnaryMinus(a); } // Unary minus - public static ExtendedInt! UnaryMinus(ExtendedInt! a) - { - if(a is PlusInfinity) + public static ExtendedInt/*!*/ UnaryMinus(ExtendedInt/*!*/ a) { + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + if (a is PlusInfinity) return cachedMinusInf; - if(a is MinusInfinity) + if (a is MinusInfinity) return cachedPlusInf; else // a is a PureInteger return new PureInteger(-a.Value); } // Multiplication - public static ExtendedInt! operator*(ExtendedInt! a, ExtendedInt! b) - { - if (a.IsZero) { + public static ExtendedInt/*!*/ operator *(ExtendedInt/*!*/ a, ExtendedInt/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + if (a.IsZero) { + return a; + } else if (b.IsZero) { + return b; + } else if (a is InfinitaryInt) { + if (b.IsPositive) { return a; - } else if (b.IsZero) { - return b; - } else if (a is InfinitaryInt) { - if (b.IsPositive) { - return a; - } else { - return UnaryMinus(a); - } - } else if (b is InfinitaryInt) { - if (a.IsPositive) { - return b; - } else { - return UnaryMinus(b); - } } else { - return ExtendedInt.Factory(a.Value * b.Value); + return UnaryMinus(a); } - } - - // Division - public static ExtendedInt! operator/(ExtendedInt! a, ExtendedInt! b) - { - if(b.IsZero) - { - return a.IsPositive? (ExtendedInt) cachedPlusInf : cachedMinusInf; - } - if (a is InfinitaryInt) { - return a; - } else if (b is InfinitaryInt) { + } else if (b is InfinitaryInt) { + if (a.IsPositive) { return b; } else { - return ExtendedInt.Factory(a.Value / b.Value); + return UnaryMinus(b); } + } else { + return ExtendedInt.Factory(a.Value * b.Value); + } + } + + // Division + public static ExtendedInt/*!*/ operator /(ExtendedInt/*!*/ a, ExtendedInt/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + if (b.IsZero) { + return a.IsPositive ? (ExtendedInt)cachedPlusInf : cachedMinusInf; + } + if (a is InfinitaryInt) { + return a; + } else if (b is InfinitaryInt) { + return b; + } else { + return ExtendedInt.Factory(a.Value / b.Value); + } } // Modulo - public static ExtendedInt! operator%(ExtendedInt! a, ExtendedInt! b) - { - if(b.IsZero) - { - return a.IsPositive? (ExtendedInt) cachedPlusInf : cachedMinusInf; - } - if (a is InfinitaryInt) { - return a; - } else if (b is InfinitaryInt) { - return b; - } else { - return ExtendedInt.Factory(a.Value % b.Value); - } + public static ExtendedInt/*!*/ operator %(ExtendedInt/*!*/ a, ExtendedInt/*!*/ b) { + Contract.Requires(b != null); + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + if (b.IsZero) { + return a.IsPositive ? (ExtendedInt)cachedPlusInf : cachedMinusInf; + } + if (a is InfinitaryInt) { + return a; + } else if (b is InfinitaryInt) { + return b; + } else { + return ExtendedInt.Factory(a.Value % b.Value); + } } #endregion #region Inf and Sup operations - public abstract int CompareTo(ExtendedInt! that); + public abstract int CompareTo(ExtendedInt/*!*/ that); - public static bool operator<(ExtendedInt! inf, ExtendedInt! sup) - { + public static bool operator <(ExtendedInt/*!*/ inf, ExtendedInt/*!*/ sup) { + Contract.Requires(sup != null); + Contract.Requires(inf != null); return inf.CompareTo(sup) < 0; } - public static bool operator>(ExtendedInt! inf, ExtendedInt! sup) - { + public static bool operator >(ExtendedInt/*!*/ inf, ExtendedInt/*!*/ sup) { + Contract.Requires(sup != null); + Contract.Requires(inf != null); return inf.CompareTo(sup) > 0; } - public static bool operator<=(ExtendedInt! inf, ExtendedInt! sup) - { + public static bool operator <=(ExtendedInt/*!*/ inf, ExtendedInt/*!*/ sup) { + Contract.Requires(sup != null); + Contract.Requires(inf != null); return inf.CompareTo(sup) <= 0; } - public static bool operator>=(ExtendedInt! inf, ExtendedInt! sup) - requires inf != null && sup != null; - { + public static bool operator >=(ExtendedInt/*!*/ inf, ExtendedInt/*!*/ sup) { + Contract.Requires(sup != null); + Contract.Requires(inf != null); + Contract.Requires(inf != null && sup != null); return inf.CompareTo(sup) >= 0; } - public static ExtendedInt! Inf(ExtendedInt! inf, ExtendedInt! sup) - { - if(inf < sup) + public static ExtendedInt/*!*/ Inf(ExtendedInt/*!*/ inf, ExtendedInt/*!*/ sup) { + Contract.Requires(sup != null); + Contract.Requires(inf != null); + Contract.Ensures(Contract.Result() != null); + if (inf < sup) return inf; else return sup; } - public static ExtendedInt! Inf(ExtendedInt! a, ExtendedInt! b, ExtendedInt! c, ExtendedInt! d) - { - ExtendedInt! infab = Inf(a,b); - ExtendedInt! infcd = Inf(c,d); + public static ExtendedInt/*!*/ Inf(ExtendedInt/*!*/ a, ExtendedInt/*!*/ b, ExtendedInt/*!*/ c, ExtendedInt/*!*/ d){ +Contract.Requires(d != null); +Contract.Requires(c != null); +Contract.Requires(b != null); +Contract.Requires(a != null); +Contract.Ensures(Contract.Result() != null); + ExtendedInt/*!*/ infab = Inf(a,b); + Contract.Assert(infab != null); + ExtendedInt/*!*/ infcd = Inf(c, d); + Contract.Assert(infcd != null); return Inf(infab, infcd); } - - public static ExtendedInt! Sup(ExtendedInt! inf, ExtendedInt! sup) - { - if(inf > sup) + + public static ExtendedInt/*!*/ Sup(ExtendedInt/*!*/ inf, ExtendedInt/*!*/ sup) { + Contract.Requires(sup != null); + Contract.Requires(inf != null); + Contract.Ensures(Contract.Result() != null); + if (inf > sup) return inf; else return sup; - } + } - public static ExtendedInt! Sup(ExtendedInt! a, ExtendedInt! b, ExtendedInt! c, ExtendedInt! d) - { - ExtendedInt! supab = Sup(a,b); - ExtendedInt! supcd = Sup(c,d); + public static ExtendedInt/*!*/ Sup(ExtendedInt/*!*/ a, ExtendedInt/*!*/ b, ExtendedInt/*!*/ c, ExtendedInt/*!*/ d){ +Contract.Requires(d != null); +Contract.Requires(c != null); +Contract.Requires(b != null); +Contract.Requires(a != null); +Contract.Ensures(Contract.Result() != null); + ExtendedInt/*!*/ supab = Sup(a,b); + Contract.Assert(supab != null); + ExtendedInt/*!*/ supcd = Sup(c, d); + Contract.Assert(supcd != null); return Sup(supab, supcd); } @@ -690,101 +777,104 @@ namespace Microsoft.AbstractInterpretationFramework #endregion // Return the ExtendedInt corresponding to the value - public static ExtendedInt! Factory(BigNum val) - { + public static ExtendedInt/*!*/ Factory(BigNum val) { + Contract.Ensures(Contract.Result() != null); return new PureInteger(val); } - } + } + [ContractClassFor(typeof(ExtendedInt))] + abstract class ExtendedIntContracts : ExtendedInt { + public override int CompareTo(ExtendedInt that) { + Contract.Requires(that != null); + throw new NotImplementedException(); + } + } // Stands for a normal (finite) integer x - class PureInteger : ExtendedInt - { - public PureInteger(BigNum i) - { + class PureInteger : ExtendedInt { + public PureInteger(BigNum i) { this.val = i; } [Pure] - public override string! ToString() - { + public override string/*!*/ ToString() { + Contract.Ensures(Contract.Result() != null); return this.Value.ToString(); } private BigNum val; public override BigNum Value { - get - { + get { return this.val; } } public override int Signum { - get { - return val.Signum; - } - } - - public override int CompareTo(ExtendedInt! that) { - if (that is PlusInfinity) - return -1; - else if (that is PureInteger) - return this.Value.CompareTo(that.Value); - else // then that is a MinusInfinity - return 1; - } + get { + return val.Signum; + } + } + + public override int CompareTo(ExtendedInt/*!*/ that) { + Contract.Requires(that != null); + if (that is PlusInfinity) + return -1; + else if (that is PureInteger) + return this.Value.CompareTo(that.Value); + else // then that is a MinusInfinity + return 1; + } } - abstract class InfinitaryInt : ExtendedInt - { - public override BigNum Value - { + abstract class InfinitaryInt : ExtendedInt { + public override BigNum Value { get { throw new InvalidOperationException(); } } } - class PlusInfinity : InfinitaryInt - { + class PlusInfinity : InfinitaryInt { [Pure] - public override string! ToString() - { + public override string/*!*/ ToString() { + Contract.Ensures(Contract.Result() != null); return "+oo"; } public override int Signum { - get { - return 1; - } - } - - public override int CompareTo(ExtendedInt! that) { - if (that is PlusInfinity) - return 0; - else - return 1; - } + get { + return 1; + } + } + + public override int CompareTo(ExtendedInt/*!*/ that) { + Contract.Requires(that != null); + if (that is PlusInfinity) + return 0; + else + return 1; + } } - class MinusInfinity : InfinitaryInt - { + class MinusInfinity : InfinitaryInt { [Pure] - public override string! ToString() - { + public override string/*!*/ ToString() { + Contract.Ensures(Contract.Result() != null); return "-oo"; } public override int Signum { - get { - return -1; - } - } - - public override int CompareTo(ExtendedInt! that) { - if (that is MinusInfinity) - return 0; - else - return -1; - } + get { + return -1; + } + } + + public override int CompareTo(ExtendedInt/*!*/ that) { + Contract.Requires(that != null); + if (that is MinusInfinity) + return 0; + else + return -1; + } } } diff --git a/Source/AIFramework/VariableMap/MicroLattice.cs b/Source/AIFramework/VariableMap/MicroLattice.cs index d38a37c0..ef98f8f7 100644 --- a/Source/AIFramework/VariableMap/MicroLattice.cs +++ b/Source/AIFramework/VariableMap/MicroLattice.cs @@ -5,22 +5,24 @@ //----------------------------------------------------------------------------- namespace Microsoft.AbstractInterpretationFramework { - using Microsoft.Contracts; + using System.Diagnostics.Contracts; using System.Collections; using System.Diagnostics; - using System.Compiler; + //using System.Compiler; using Microsoft.AbstractInterpretationFramework.Collections; /// /// Interface for a lattice that works on a per-variable basis. /// + /// + [ContractClass(typeof(MicroLatticeContracts))] public abstract class MicroLattice : MathematicalLattice { /// /// Returns the predicate on the given variable for the given /// lattice element. /// - public abstract IExpr! ToPredicate(IVariable! v, Element! e); + public abstract IExpr/*!*/ ToPredicate(IVariable/*!*/ v, Element/*!*/ e); /* requires !e.IsBottom && !e.IsTop; */ /// @@ -39,7 +41,7 @@ namespace Microsoft.AbstractInterpretationFramework /// The function symbol. /// The argument context. /// True if it may understand f, false if it does not understand f. - public abstract bool Understands(IFunctionSymbol! f, IList/**/! args); + public abstract bool Understands(IFunctionSymbol/*!*/ f, IList/**//*!*/ args); /// /// Set this property to true if the implemented MicroLattice can handle basic arithmetic. @@ -56,15 +58,16 @@ namespace Microsoft.AbstractInterpretationFramework /// /// The predicate that is assumed to contain 1 variable. /// The most precise lattice element that is implied by the predicate. - public abstract Element! EvaluatePredicate(IExpr! e); + public abstract Element/*!*/ EvaluatePredicate(IExpr/*!*/ e); /// /// Evaluate the predicate e and yield an overapproximation of the predicate under the state that is passed as a parameter /// Note that unless the subclass implement it, the default behavior is to evaluate the predicate stateless, that implies that it /// is evaluated in any possible context, i.e. it is an upper approximation /// - public virtual Element! EvaluatePredicateWithState(IExpr! e, IFunctionalMap state) - { + public virtual Element/*!*/ EvaluatePredicateWithState(IExpr/*!*/ e, IFunctionalMap state){ +Contract.Requires(e != null); +Contract.Ensures(Contract.Result() != null); return EvaluatePredicate(e); } @@ -74,6 +77,29 @@ namespace Microsoft.AbstractInterpretationFramework /// /// A lattice element. /// The null value if no such expression can be given. - public abstract IExpr GetFoldExpr(Element! e); + public abstract IExpr GetFoldExpr(Element/*!*/ e); + } + [ContractClassFor(typeof(MicroLattice))] + public abstract class MicroLatticeContracts : MicroLattice { + public override IExpr ToPredicate(IVariable v, MathematicalLattice.Element e) { + Contract.Requires(v != null); + Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); + } + public override bool Understands(IFunctionSymbol f, IList args) { + Contract.Requires(f != null); + Contract.Requires(args != null); + throw new System.NotImplementedException(); + } + public override Element EvaluatePredicate(IExpr e) { + Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); + throw new System.NotImplementedException(); + } + public override IExpr GetFoldExpr(MathematicalLattice.Element e) { + Contract.Requires(e != null); + throw new System.NotImplementedException(); + } } } \ No newline at end of file diff --git a/Source/AIFramework/VariableMap/Nullness.cs b/Source/AIFramework/VariableMap/Nullness.cs index bbd1da70..9eac6b29 100644 --- a/Source/AIFramework/VariableMap/Nullness.cs +++ b/Source/AIFramework/VariableMap/Nullness.cs @@ -3,18 +3,24 @@ // Copyright (C) Microsoft Corporation. All Rights Reserved. // //----------------------------------------------------------------------------- -using Microsoft.Contracts; +using System.Diagnostics.Contracts; namespace Microsoft.AbstractInterpretationFramework { using System.Collections; using System.Diagnostics; - using System.Compiler.Analysis; + //using System.Compiler.Analysis; public class NullnessLattice : MicroLattice { - readonly INullnessFactory! factory; + readonly INullnessFactory/*!*/ factory; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(factory != null); + } - public NullnessLattice(INullnessFactory! factory) { + + public NullnessLattice(INullnessFactory/*!*/ factory){ +Contract.Requires(factory != null); this.factory = factory; // base(); } @@ -28,77 +34,92 @@ namespace Microsoft.AbstractInterpretationFramework public Elt (Value v) { this.value = v; } [Pure] - public override System.Collections.Generic.ICollection! FreeVariables() - { - return (!) (new System.Collections.Generic.List()).AsReadOnly(); + public override System.Collections.Generic.ICollection/*!*/ FreeVariables() { +Contract.Ensures(cce.NonNullElements(Contract.Result>())); +return cce.NonNull(new System.Collections.Generic.List()).AsReadOnly(); } - public override Element! Clone() - { + public override Element/*!*/ Clone() { +Contract.Ensures(Contract.Result() != null); return new Elt(this.value); } } - public override Element! Top + public override Element/*!*/ Top { - get { return new Elt(Value.MayBeNull); } + get {Contract.Ensures(Contract.Result() != null); + return new Elt(Value.MayBeNull); } } - public override Element! Bottom + public override Element/*!*/ Bottom { - get { return new Elt(Value.Bottom); } + get {Contract.Ensures(Contract.Result() != null); + return new Elt(Value.Bottom); } } - public static Element! Null + public static Element/*!*/ Null { - get { return new Elt(Value.Null); } + get {Contract.Ensures(Contract.Result() != null); + return new Elt(Value.Null); } } - public static Element! NotNull + public static Element/*!*/ NotNull { - get { return new Elt(Value.NotNull); } + get {Contract.Ensures(Contract.Result() != null); + return new Elt(Value.NotNull); } } - public override bool IsTop (Element! element) - { + public override bool IsTop (Element/*!*/ element){ +Contract.Requires(element != null); Elt e = (Elt) element; return e.value == Value.MayBeNull; } - public override bool IsBottom (Element! element) - { + public override bool IsBottom (Element/*!*/ element){ +Contract.Requires(element != null); Elt e = (Elt) element; return e.value == Value.Bottom; } - public override Lattice.Element! NontrivialJoin (Element! first, Element! second) - { + public override Lattice.Element/*!*/ NontrivialJoin (Element/*!*/ first, Element/*!*/ second){ +Contract.Requires(second != null); +Contract.Requires(first != null); +Contract.Ensures(Contract.Result() != null); Elt a = (Elt) first; Elt b = (Elt) second; return (a.value == b.value) ? a : (Elt)Top; } - public override Lattice.Element! NontrivialMeet (Element! first, Element! second) - { + public override Lattice.Element/*!*/ NontrivialMeet (Element/*!*/ first, Element/*!*/ second){ +Contract.Requires(second != null); +Contract.Requires(first != null); +Contract.Ensures(Contract.Result() != null); Elt a = (Elt) first; Elt b = (Elt) second; return (a.value == b.value) ? a : (Elt)Bottom; } - public override Element! Widen (Element! first, Element! second) - { + public override Element/*!*/ Widen (Element/*!*/ first, Element/*!*/ second){ +Contract.Requires(second != null); +Contract.Requires(first != null); +Contract.Ensures(Contract.Result() != null); return Join(first,second); } - protected override bool AtMost (Element! first, Element! second) // this <= that + protected override bool AtMost (Element/*!*/ first, Element/*!*/ second) // this <= that { +Contract.Requires(first != null); +Contract.Requires(second != null); Elt a = (Elt) first; Elt b = (Elt) second; return a.value == b.value; } - public override IExpr! ToPredicate(IVariable! var, Element! element) { + public override IExpr/*!*/ ToPredicate(IVariable/*!*/ var, Element/*!*/ element){ +Contract.Requires(element != null); +Contract.Requires(var != null); +Contract.Ensures(Contract.Result() != null); Elt e = (Elt)element; if (e.value == Value.NotNull) @@ -109,11 +130,12 @@ namespace Microsoft.AbstractInterpretationFramework { return factory.Eq(var, factory.Null); } - assert false; + {Contract.Assert(false);throw new cce.UnreachableException();} throw new System.Exception(); } - public override IExpr GetFoldExpr(Element! e) { + public override IExpr GetFoldExpr(Element/*!*/ e){ +Contract.Requires(e != null); Elt elt = (Elt)e; if (elt.value == Value.Null) { return factory.Null; @@ -123,13 +145,15 @@ namespace Microsoft.AbstractInterpretationFramework } } - public override bool Understands(IFunctionSymbol! f, IList/**/! args) { + public override bool Understands(IFunctionSymbol/*!*/ f, IList/**//*!*/ args){ +Contract.Requires(args != null); +Contract.Requires(f != null); if (f.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq) || f.Equals(Microsoft.AbstractInterpretationFramework.Value.Neq)) { - assert args.Count == 2; - IExpr! arg0 = (IExpr!)args[0]; - IExpr! arg1 = (IExpr!)args[1]; + Contract.Assert(args.Count == 2); + IExpr/*!*/ arg0 = (IExpr/*!*/)cce.NonNull(args[0]); + IExpr/*!*/ arg1 = (IExpr/*!*/)cce.NonNull(args[1]); // Look for "x OP null" or "null OP x" where OP is "==" or "!=". if (arg0 is IVariable && arg1 is IFunApp && ((IFunApp)arg1).FunctionSymbol == Ref.Null) { @@ -141,15 +165,18 @@ namespace Microsoft.AbstractInterpretationFramework return false; } - public override Element! EvaluatePredicate(IExpr! e) { + public override Element/*!*/ EvaluatePredicate(IExpr/*!*/ e){ +Contract.Requires(e != null); +Contract.Ensures(Contract.Result() != null); IFunApp nary = e as IFunApp; if (nary != null) { bool isEq = nary.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq); if (isEq || nary.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Neq)) { - IList/**/! args = nary.Arguments; - assert args.Count == 2; - IExpr! arg0 = (IExpr!)args[0]; - IExpr! arg1 = (IExpr!)args[1]; + IList/**//*!*/ args = nary.Arguments; + Contract.Assert(args != null); + Contract.Assert(args.Count == 2); + IExpr/*!*/ arg0 = (IExpr/*!*/)cce.NonNull(args[0]); + IExpr/*!*/ arg1 = (IExpr/*!*/)cce.NonNull(args[1]); // Look for "x OP null" or "null OP x" where OP is "==" or "!=". IVariable var = null; diff --git a/Source/AIFramework/VariableMap/VariableMapLattice.cs b/Source/AIFramework/VariableMap/VariableMapLattice.cs index ab030b59..e0b9ac04 100644 --- a/Source/AIFramework/VariableMap/VariableMapLattice.cs +++ b/Source/AIFramework/VariableMap/VariableMapLattice.cs @@ -5,7 +5,7 @@ //----------------------------------------------------------------------------- namespace Microsoft.AbstractInterpretationFramework { - using Microsoft.Contracts; + using System.Diagnostics.Contracts; using System.Collections; using System.Collections.Generic; using System.Diagnostics; @@ -47,20 +47,21 @@ namespace Microsoft.AbstractInterpretationFramework } } - public override Element! Clone() - { + public override Element/*!*/ Clone() { +Contract.Ensures(Contract.Result() != null); return new Elt(this.constraints); } [Pure] - public override string! ToString() - { + public override string/*!*/ ToString() { +Contract.Ensures(Contract.Result() != null); if (constraints == null) { return ""; } string s = "["; string sep = ""; - foreach (IVariable! v in (!)constraints.Keys) { + foreach(IVariable/*!*/ v in cce.NonNull(constraints.Keys)){ +Contract.Assert(v != null); Element m = (Element)constraints[v]; s += sep + v.Name + " -> " + m; sep = ", "; @@ -68,8 +69,15 @@ namespace Microsoft.AbstractInterpretationFramework return s + "]"; } - public static Elt! Top = new Elt(true); - public static Elt! Bottom = new Elt(false); + public static Elt/*!*/ Top = new Elt(true); + public static Elt/*!*/ Bottom = new Elt(false); + [ContractInvariantMethod] +void ObjectInvariant() +{ + Contract.Invariant(Top != null); + Contract.Invariant(Bottom != null); +} + public Elt(IFunctionalMap constraints) { @@ -84,16 +92,17 @@ namespace Microsoft.AbstractInterpretationFramework public int Count { get { return this.constraints == null ? 0 : this.constraints.Count; } } - public IEnumerable/**/! Variables { - get - requires !this.IsBottom; - { - assume this.constraints != null; - return (!) this.constraints.Keys; + public IEnumerable/**//*!*/ Variables { + get { + Contract.Requires(!this.IsBottom); + Contract.Ensures(Contract.Result() != null); + Contract.Assume(this.constraints != null); + return cce.NonNull(this.constraints.Keys); } } - public IEnumerable/**/! SortedVariables(/*maybe null*/ IComparer variableComparer) { + public IEnumerable/**//*!*/ SortedVariables(/*maybe null*/ IComparer variableComparer) { + Contract.Ensures(Contract.Result() != null); if (variableComparer == null) { return Variables; } else { @@ -112,11 +121,11 @@ namespace Microsoft.AbstractInterpretationFramework return (Element)this.constraints[v]; } - public Element this [IVariable! key] { - get - requires !this.IsBottom; - { - assume this.constraints != null; + public Element this [IVariable/*!*/ key] { + get{ + Contract.Requires(!this.IsBottom); + Contract.Requires(key != null); + Contract.Assume(this.constraints != null); return (Element)constraints[key]; } } @@ -125,11 +134,14 @@ namespace Microsoft.AbstractInterpretationFramework /// Add a new entry in the functional map: var --> value. /// If the variable is already there, throws an exception /// - public Elt! Add(IVariable! var, Element! value, MicroLattice! microLattice) - requires !this.IsBottom; - { - assume this.constraints != null; - assert !this.constraints.Contains(var); + public Elt/*!*/ Add(IVariable/*!*/ var, Element/*!*/ value, MicroLattice/*!*/ microLattice){ +Contract.Requires(microLattice != null); +Contract.Requires(value != null); +Contract.Requires(var != null); +Contract.Requires((!this.IsBottom)); +Contract.Ensures(Contract.Result() != null); + Contract.Assume(this.constraints != null); + Contract.Assert(!this.constraints.Contains(var)); if (microLattice.IsBottom(value)) { return Bottom; } if (microLattice.IsTop(value)) { return this.Remove(var, microLattice); } @@ -141,13 +153,16 @@ namespace Microsoft.AbstractInterpretationFramework /// Set the value of the variable in the functional map /// If the variable is not already there, throws an exception /// - public Elt! Set(IVariable! var, Element! value, MicroLattice! microLattice) - { + public Elt/*!*/ Set(IVariable/*!*/ var, Element/*!*/ value, MicroLattice/*!*/ microLattice){ + Contract.Requires(microLattice != null); + Contract.Requires(value != null); + Contract.Requires(var != null); + Contract.Ensures(Contract.Result() != null); if(microLattice.IsBottom(value)) { return Bottom; } if(microLattice.IsTop(value)) { return this.Remove(var, microLattice); } - assume this.constraints != null; - assert this.constraints.Contains(var); + Contract.Assume(this.constraints != null); + Contract.Assert(this.constraints.Contains(var)); // this.constraints[var] = value; IFunctionalMap newMap = this.constraints.Set(var, value); @@ -155,74 +170,95 @@ namespace Microsoft.AbstractInterpretationFramework return new Elt(newMap); } - public Elt! Remove(IVariable! var, MicroLattice microLattice) - { + public Elt/*!*/ Remove(IVariable/*!*/ var, MicroLattice microLattice){ +Contract.Requires(var != null); +Contract.Ensures(Contract.Result() != null); if (this.IsBottom) { return this; } - assume this.constraints != null; + Contract.Assume(this.constraints != null); return new Elt(this.constraints.Remove(var)); } - public Elt! Rename(IVariable! oldName, IVariable! newName, MicroLattice! microLattice) - requires !this.IsBottom; - { + public Elt/*!*/ Rename(IVariable/*!*/ oldName, IVariable/*!*/ newName, MicroLattice/*!*/ microLattice){ +Contract.Requires(microLattice != null); +Contract.Requires(newName != null); +Contract.Requires(oldName != null); +Contract.Requires((!this.IsBottom)); +Contract.Ensures(Contract.Result() != null); Element value = this[oldName]; if (value == null) { return this; } // 'oldName' isn't in the map, so neither will be 'newName' - assume this.constraints != null; + Contract.Assume(this.constraints != null); IFunctionalMap newMap = this.constraints.Remove(oldName); newMap = newMap.Add(newName, value); return new Elt(newMap); } [Pure] - public override ICollection! FreeVariables() - { + public override ICollection/*!*/ FreeVariables() { +Contract.Ensures(cce.NonNullElements(Contract.Result>())); throw new System.NotImplementedException(); } } // class - private readonly MicroLattice! microLattice; + private readonly MicroLattice/*!*/ microLattice; + + private readonly IPropExprFactory/*!*/ propExprFactory; + [ContractInvariantMethod] +void ObjectInvariant() +{ + Contract.Invariant(microLattice != null); + Contract.Invariant(propExprFactory != null); +} - private readonly IPropExprFactory! propExprFactory; private readonly /*maybe null*/IComparer variableComparer; - public VariableMapLattice(IPropExprFactory! propExprFactory, IValueExprFactory! valueExprFactory, MicroLattice! microLattice, /*maybe null*/IComparer variableComparer) - : base(valueExprFactory) - { + public VariableMapLattice(IPropExprFactory/*!*/ propExprFactory, IValueExprFactory/*!*/ valueExprFactory, MicroLattice/*!*/ microLattice, /*maybe null*/IComparer variableComparer) + : base(valueExprFactory){ +Contract.Requires(microLattice != null); +Contract.Requires(valueExprFactory != null); +Contract.Requires(propExprFactory != null); this.propExprFactory = propExprFactory; this.microLattice = microLattice; this.variableComparer = variableComparer; // base(valueExprFactory); } - protected override object! UniqueId { get { return this.microLattice.GetType(); } } + protected override object/*!*/ UniqueId{ + get{ +Contract.Ensures(Contract.Result() != null); + return this.microLattice.GetType(); } } - public override Element! Top { get { return Elt.Top; } } + public override Element/*!*/ Top{ +get{Contract.Ensures(Contract.Result() != null); + return Elt.Top; } } - public override Element! Bottom { get { return Elt.Bottom; } } + public override Element Bottom{get{ +Contract.Ensures(Contract.Result() != null); + return Elt.Bottom; } } - public override bool IsTop(Element! element) - { + public override bool IsTop(Element/*!*/ element){ +Contract.Requires(element != null); Elt e = (Elt)element; return !e.IsBottom && e.Count == 0; } - public override bool IsBottom(Element! element) - { + public override bool IsBottom(Element/*!*/ element){ +Contract.Requires(element != null); return ((Elt)element).IsBottom; } - protected override bool AtMost(Element! first, Element! second) - { + protected override bool AtMost(Element/*!*/ first, Element/*!*/ second){ +Contract.Requires(second != null); +Contract.Requires(first != null); Elt a = (Elt)first; Elt b = (Elt)second; // return true iff every constraint in "this" is no weaker than the corresponding // constraint in "that" and there are no additional constraints in "that" - foreach (IVariable! var in a.Variables) - { - Element thisValue = (!)a[var]; + foreach(IVariable/*!*/ var in a.Variables){ +Contract.Assert(var != null); + Element thisValue = cce.NonNull(a[var]); Element thatValue = b[var]; if (thatValue == null) { continue; } // it's okay for "a" to know something "b" doesn't @@ -231,11 +267,11 @@ namespace Microsoft.AbstractInterpretationFramework return false; } - foreach (IVariable! var in b.Variables) - { + foreach(IVariable/*!*/ var in b.Variables){ +Contract.Assert(var != null); if (a.Lookup(var) != null) { continue; } // we checked this case in the loop above - Element thatValue = (!)b[var]; + Element thatValue = cce.NonNull(b[var]); if (this.microLattice.IsTop(thatValue)) { continue; } // this is a trivial constraint return false; @@ -243,8 +279,11 @@ namespace Microsoft.AbstractInterpretationFramework return true; } - private Elt! AddConstraint(Element! element, IVariable! var, /*MicroLattice*/Element! newValue) - { + private Elt/*!*/ AddConstraint(Element/*!*/ element, IVariable/*!*/ var, /*MicroLattice*/Element/*!*/ newValue) { +Contract.Requires((newValue != null)); +Contract.Requires((var != null)); +Contract.Requires((element != null)); +Contract.Ensures(Contract.Result() != null); Elt e = (Elt)element; if (!e.IsBottom && !this.microLattice.IsBottom(newValue)) // if we're not at bottom @@ -266,8 +305,9 @@ namespace Microsoft.AbstractInterpretationFramework return e; } - public override string! ToString(Element! element) - { + public override string/*!*/ ToString(Element/*!*/ element){ +Contract.Requires(element != null); +Contract.Ensures(Contract.Result() != null); Elt e = (Elt)element; if (IsTop(e)) { return ""; } @@ -275,22 +315,24 @@ namespace Microsoft.AbstractInterpretationFramework int k = 0; System.Text.StringBuilder buffer = new System.Text.StringBuilder(); - foreach (IVariable! key in e.SortedVariables(variableComparer)) - { + foreach(IVariable/*!*/ key in e.SortedVariables(variableComparer)){ +Contract.Assert(key != null); if (k++ > 0) { buffer.Append("; "); } buffer.AppendFormat("{0} = {1}", key, e[key]); } return buffer.ToString(); } - public override Element! NontrivialJoin(Element! first, Element! second) - { + public override Element/*!*/ NontrivialJoin(Element/*!*/ first, Element/*!*/ second){ +Contract.Requires(second != null); +Contract.Requires(first != null); +Contract.Ensures(Contract.Result() != null); Elt a = (Elt)first; Elt b = (Elt)second; IFunctionalMap newMap = FunctionalHashtable.Empty; - foreach (IVariable! key in a.Variables) - { + foreach(IVariable/*!*/ key in a.Variables){ +Contract.Assert(key != null); Element aValue = a[key]; Element bValue = b[key]; @@ -301,22 +343,25 @@ namespace Microsoft.AbstractInterpretationFramework newMap = newMap.Add(key, newValue); } } - Elt! join = new Elt(newMap); + Elt/*!*/ join = new Elt(newMap); + Contract.Assert(join != null); // System.Console.WriteLine("{0} join {1} = {2} ", this.ToString(a), ToString(b), ToString(join)); return join; } - public override Element! NontrivialMeet(Element! first, Element! second) - { + public override Element/*!*/ NontrivialMeet(Element/*!*/ first, Element/*!*/ second){ +Contract.Requires(second != null); +Contract.Requires(first != null); +Contract.Ensures(Contract.Result() != null); Elt a = (Elt)first; Elt b = (Elt)second; IFunctionalMap newMap = FunctionalHashtable.Empty; - foreach (IVariable! key in a.Variables) - { - Element! aValue = (!) a[key]; + foreach(IVariable/*!*/ key in a.Variables){ +Contract.Assert(key != null); +Element/*!*/ aValue = cce.NonNull(a[key]); Element bValue = b[key]; Element newValue = @@ -325,8 +370,8 @@ namespace Microsoft.AbstractInterpretationFramework newMap = newMap.Add(key, newValue); } - foreach (IVariable! key in b.Variables) - { + foreach(IVariable/*!*/ key in b.Variables){ +Contract.Assert(key != null); Element aValue = a[key]; Element bValue = b[key]; Debug.Assert(bValue != null); @@ -342,8 +387,10 @@ namespace Microsoft.AbstractInterpretationFramework /// /// Perform the pointwise widening of the elements in the map /// - public override Element! Widen (Element! first, Element! second) - { + public override Element/*!*/ Widen (Element/*!*/ first, Element/*!*/ second) { +Contract.Requires((second != null)); +Contract.Requires((first != null)); +Contract.Ensures(Contract.Result() != null); Elt a = (Elt)first; Elt b = (Elt)second; @@ -354,8 +401,8 @@ namespace Microsoft.AbstractInterpretationFramework return new Elt(a.Constraints); IFunctionalMap newMap = FunctionalHashtable.Empty; - foreach (IVariable! key in a.Variables) - { + foreach(IVariable/*!*/ key in a.Variables){ +Contract.Assert(key != null); Element aValue = a[key]; Element bValue = b[key]; @@ -366,15 +413,17 @@ namespace Microsoft.AbstractInterpretationFramework newMap = newMap.Add(key, newValue); } } - Element! widen= new Elt(newMap); - + Element/*!*/ widen= new Elt(newMap); + Contract.Assert(widen != null); // System.Console.WriteLine("{0} widen {1} = {2} ", this.ToString(a), ToString(b), ToString(widen)); return widen; } - internal static ISet/**/! VariablesInExpression(IExpr! e, ISet/**/! ignoreVars) - { + internal static ISet/**//*!*/ VariablesInExpression(IExpr/*!*/ e, ISet/**//*!*/ ignoreVars){ +Contract.Requires(ignoreVars != null); +Contract.Requires(e != null); + Contract.Ensures(Contract.Result() != null); HashSet s = new HashSet(); IFunApp f = e as IFunApp; @@ -387,8 +436,8 @@ namespace Microsoft.AbstractInterpretationFramework } else if (f != null) // e is IFunApp { - foreach (IExpr! arg in f.Arguments) - { + foreach(IExpr/*!*/ arg in f.Arguments){ +Contract.Assert(arg != null); s.AddAll(VariablesInExpression(arg, ignoreVars)); } } @@ -398,7 +447,7 @@ namespace Microsoft.AbstractInterpretationFramework x.Add(lambda.Param); // Ignore the bound variable - s.AddAll(VariablesInExpression(lambda.Body, (!) Set.Union(ignoreVars, x))); + s.AddAll(VariablesInExpression(lambda.Body, cce.NonNull(Set.Union(ignoreVars, x)))); } else if (e is IUnknown) { @@ -412,8 +461,9 @@ namespace Microsoft.AbstractInterpretationFramework } - private static ArrayList/**/! FindConjuncts(IExpr e) + private static ArrayList/**//*!*/ FindConjuncts(IExpr e) { + Contract.Ensures(Contract.Result() != null); ArrayList result = new ArrayList(); IFunApp f = e as IFunApp; @@ -445,8 +495,8 @@ namespace Microsoft.AbstractInterpretationFramework } private static bool IsSimpleEquality(IExpr expr, out IVariable left, out IVariable right) - ensures result ==> left != null && right != null; - { + { + Contract.Ensures(!Contract.Result() || Contract.ValueAtReturn(out left) != null && Contract.ValueAtReturn(out right) != null); left = null; right = null; @@ -467,8 +517,8 @@ namespace Microsoft.AbstractInterpretationFramework /// /// Returns true iff the expression is in the form var == arithmeticExpr /// - private static bool IsArithmeticExpr(IExpr! expr) - { + private static bool IsArithmeticExpr(IExpr/*!*/ expr){ +Contract.Requires(expr != null); // System.Console.WriteLine("\t\tIsArithmetic called with {0} of type {1}", expr, expr.GetType().ToString()); if(expr is IVariable) // expr is a variable @@ -480,13 +530,13 @@ namespace Microsoft.AbstractInterpretationFramework if(fun.FunctionSymbol is IntSymbol) // it is an integer return true; else if(fun.FunctionSymbol.Equals(Int.Negate)) // it is an unary minus - return IsArithmeticExpr((IExpr!) fun.Arguments[0]); + return IsArithmeticExpr((IExpr/*!*/)cce.NonNull(fun.Arguments[0])); else if(fun.Arguments.Count != 2) // A function of two or more operands is not arithmetic return false; else { - IExpr! left = (IExpr!) fun.Arguments[0]; - IExpr! right = (IExpr!) fun.Arguments[1]; + IExpr/*!*/ left = (IExpr/*!*/)cce.NonNull(fun.Arguments[0]); + IExpr/*!*/ right = (IExpr/*!*/)cce.NonNull(fun.Arguments[1]); if(!(left is IVariable || right is IVariable)) // At least one of the two operands must be a variable return false; @@ -508,8 +558,9 @@ namespace Microsoft.AbstractInterpretationFramework } } - public override IExpr! ToPredicate(Element! element) - { + public override IExpr/*!*/ ToPredicate(Element/*!*/ element){ +Contract.Requires(element != null); +Contract.Ensures(Contract.Result() != null); if (IsTop(element)) { return propExprFactory.True; } if (IsBottom(element)) { return propExprFactory.False; } @@ -517,8 +568,8 @@ namespace Microsoft.AbstractInterpretationFramework IExpr truth = propExprFactory.True; IExpr result = truth; - foreach (IVariable! variable in e.SortedVariables(variableComparer)) - { + foreach(IVariable/*!*/ variable in e.SortedVariables(variableComparer)){ +Contract.Assert(variable != null); Element value = (Element)e[variable]; if (value == null || this.microLattice.IsTop(value)) { continue; } // Skip variables about which we know nothing. @@ -532,14 +583,17 @@ namespace Microsoft.AbstractInterpretationFramework } - public override Element! Eliminate(Element! element, IVariable! variable) - { - return ((Elt!)element).Remove(variable, this.microLattice); + public override Element/*!*/ Eliminate(Element/*!*/ element, IVariable/*!*/ variable){ +Contract.Requires(variable != null); +Contract.Requires(element != null); +Contract.Ensures(Contract.Result() != null); + return cce.NonNull((Elt)element).Remove(variable, this.microLattice); } - private delegate IExpr! OnUnableToInline(IVariable! var); - private IExpr! IdentityVarToExpr(IVariable! var) - { + private delegate IExpr/*!*/ OnUnableToInline(IVariable/*!*/ var); + private IExpr/*!*/ IdentityVarToExpr(IVariable/*!*/ var){ +Contract.Requires(var != null); +Contract.Ensures(Contract.Result() != null); return var; } @@ -548,9 +602,13 @@ namespace Microsoft.AbstractInterpretationFramework /// replaced by an expression representing what is known about /// that variable. /// - private IExpr! InlineVariables(Elt! element, IExpr! expr, ISet/**/! notInlineable, - OnUnableToInline! unableToInline) - { + private IExpr/*!*/ InlineVariables(Elt/*!*/ element, IExpr/*!*/ expr, ISet/**//*!*/ notInlineable, + OnUnableToInline/*!*/ unableToInline){ + Contract.Requires(unableToInline != null); +Contract.Requires(notInlineable != null); +Contract.Requires(expr != null); +Contract.Requires(element != null); + Contract.Ensures(Contract.Result() != null); IVariable var = expr as IVariable; if (var != null) { @@ -574,8 +632,8 @@ namespace Microsoft.AbstractInterpretationFramework if (fun != null) { IList newargs = new ArrayList(); - foreach (IExpr! arg in fun.Arguments) - { + foreach(IExpr/*!*/ arg in fun.Arguments){ +Contract.Assert(arg != null); newargs.Add(InlineVariables(element, arg, notInlineable, unableToInline)); } return fun.CloneWithArguments(newargs); @@ -592,7 +650,7 @@ namespace Microsoft.AbstractInterpretationFramework // Don't inline the bound variable return lambda.CloneWithBody( InlineVariables(element, lambda.Body, - (!) Set.Union(notInlineable, x), unableToInline) + cce.NonNull(Set.Union(notInlineable, x)), unableToInline) ); } @@ -610,19 +668,22 @@ namespace Microsoft.AbstractInterpretationFramework } - public override Element! Constrain(Element! element, IExpr! expr) - { - Elt! result = (Elt)element; + public override Element/*!*/ Constrain(Element/*!*/ element, IExpr/*!*/ expr){ +Contract.Requires(expr != null); +Contract.Requires(element != null); +Contract.Ensures(Contract.Result() != null); + Elt/*!*/ result = (Elt)element; + Contract.Assert(result != null); if(IsBottom(element)) { return result; // == element } - expr = InlineVariables(result, expr, (!)Set.Empty, new OnUnableToInline(IdentityVarToExpr)); + expr = InlineVariables(result, expr, cce.NonNull(Set.Empty), new OnUnableToInline(IdentityVarToExpr)); - foreach (IExpr! conjunct in FindConjuncts(expr)) - { + foreach(IExpr/*!*/ conjunct in FindConjuncts(expr)){ +Contract.Assert(conjunct != null); IVariable left, right; if (IsSimpleEquality(conjunct, out left, out right)) @@ -630,7 +691,7 @@ namespace Microsoft.AbstractInterpretationFramework #region The conjunct is a simple equality - assert left != null && right != null; + Contract.Assert(left != null && right != null); Element leftValue = result[left], rightValue = result[right]; if (leftValue == null) { leftValue = this.microLattice.Top; } @@ -650,9 +711,9 @@ namespace Microsoft.AbstractInterpretationFramework #region We have just one variable IVariable var = null; - foreach (IVariable! v in variablesInvolved) { var = v; } // why is there no better way to get the elements? - assert var != null; - Element! value = this.microLattice.EvaluatePredicate(conjunct); + foreach (IVariable/*!*/ v in variablesInvolved) {Contract.Assert(v != null); var = v; } // why is there no better way to get the elements? + Contract.Assert(var != null); + Element/*!*/ value = this.microLattice.EvaluatePredicate(conjunct); result = AddConstraint(result, var, value); #endregion @@ -665,12 +726,13 @@ namespace Microsoft.AbstractInterpretationFramework if(fun.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq)) // if it is a symbol of equality { // get the variable to be assigned - IExpr! leftArg = (IExpr!) fun.Arguments[0]; - IExpr! rightArg = (IExpr!) fun.Arguments[1]; - IExpr! var = (leftArg is IVariable) ? leftArg : rightArg; - - Element! value = this.microLattice.EvaluatePredicateWithState(conjunct, result.Constraints); - result = AddConstraint(result, (IVariable!) var, value); + IExpr/*!*/ leftArg = (IExpr/*!*/)cce.NonNull(fun.Arguments[0]); + IExpr/*!*/ rightArg = (IExpr/*!*/)cce.NonNull(fun.Arguments[1]); + IExpr/*!*/ var = (leftArg is IVariable) ? leftArg : rightArg; + + Element/*!*/ value = this.microLattice.EvaluatePredicateWithState(conjunct, result.Constraints); + Contract.Assert(value != null); + result = AddConstraint(result, (IVariable/*!*/)cce.NonNull(var), value); } #endregion } @@ -680,8 +742,11 @@ namespace Microsoft.AbstractInterpretationFramework } - public override Element! Rename(Element! element, IVariable! oldName, IVariable! newName) - { + public override Element/*!*/ Rename(Element/*!*/ element, IVariable/*!*/ oldName, IVariable/*!*/ newName){ +Contract.Requires(newName != null); +Contract.Requires(oldName != null); +Contract.Requires(element != null); +Contract.Ensures(Contract.Result() != null); if(IsBottom(element)) { return element; @@ -693,26 +758,34 @@ namespace Microsoft.AbstractInterpretationFramework } - public override bool Understands(IFunctionSymbol! f, IList! args) - { + public override bool Understands(IFunctionSymbol/*!*/ f, IList/*!*/ args){ +Contract.Requires(args != null); +Contract.Requires(f != null); return f.Equals(Prop.And) || f.Equals(Value.Eq) || microLattice.Understands(f, args); } - private sealed class EquivalentExprException : CheckedException { } + private sealed class EquivalentExprException :CheckedException { } private sealed class EquivalentExprInlineCallback { - private readonly IVariable! var; - public EquivalentExprInlineCallback(IVariable! var) - { + private readonly IVariable/*!*/ var; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(var != null); + } + + public EquivalentExprInlineCallback(IVariable/*!*/ var){ +Contract.Requires(var != null); this.var = var; // base(); } - public IExpr! ThrowOnUnableToInline(IVariable! othervar) - throws EquivalentExprException; - { + public IExpr/*!*/ ThrowOnUnableToInline(IVariable/*!*/ othervar) + //throws EquivalentExprException; + {Contract.Requires(othervar != null); + Contract.Ensures(Contract.Result() != null); + Contract.EnsuresOnThrow(true); if (othervar.Equals(var)) throw new EquivalentExprException(); else @@ -720,12 +793,16 @@ namespace Microsoft.AbstractInterpretationFramework } } - public override IExpr/*?*/ EquivalentExpr(Element! e, IQueryable! q, IExpr! expr, IVariable! var, ISet/**/! prohibitedVars) - { + public override IExpr/*?*/ EquivalentExpr(Element/*!*/ e, IQueryable/*!*/ q, IExpr/*!*/ expr, IVariable/*!*/ var, ISet/**//*!*/ prohibitedVars){ +Contract.Requires(prohibitedVars != null); +Contract.Requires(var != null); +Contract.Requires(expr != null); +Contract.Requires(q != null); +Contract.Requires(e != null); try { EquivalentExprInlineCallback closure = new EquivalentExprInlineCallback(var); - return InlineVariables((Elt)e, expr, (!)Set.Empty, + return InlineVariables((Elt)e, expr, cce.NonNull(Set.Empty), new OnUnableToInline(closure.ThrowOnUnableToInline)); } catch (EquivalentExprException) @@ -743,8 +820,9 @@ namespace Microsoft.AbstractInterpretationFramework /// The lattice element. /// The predicate. /// Yes, No, or Maybe - public override Answer CheckPredicate(Element! e, IExpr! pred) - { + public override Answer CheckPredicate(Element/*!*/ e, IExpr/*!*/ pred){ +Contract.Requires(pred != null); +Contract.Requires(e != null); return Answer.Maybe; } @@ -759,8 +837,10 @@ namespace Microsoft.AbstractInterpretationFramework /// The first variable. /// The second variable. /// Yes, No, or Maybe. - public override Answer CheckVariableDisequality(Element! e, IVariable! var1, IVariable! var2) - { + public override Answer CheckVariableDisequality(Element/*!*/ e, IVariable/*!*/ var1, IVariable/*!*/ var2){ +Contract.Requires(var2 != null); +Contract.Requires(var1 != null); +Contract.Requires(e != null); return Answer.Maybe; } -- cgit v1.2.3