diff options
Diffstat (limited to 'Source/AIFramework')
-rw-r--r-- | Source/AIFramework/AIFramework.csproj | 270 | ||||
-rw-r--r-- | Source/AIFramework/CommonFunctionSymbols.cs | 810 | ||||
-rw-r--r-- | Source/AIFramework/Expr.cs | 337 | ||||
-rw-r--r-- | Source/AIFramework/Functional.cs | 179 | ||||
-rw-r--r-- | Source/AIFramework/Lattice.cs | 1464 | ||||
-rw-r--r-- | Source/AIFramework/Logger.cs | 85 | ||||
-rw-r--r-- | Source/AIFramework/MultiLattice.cs | 1037 | ||||
-rw-r--r-- | Source/AIFramework/Mutable.cs | 35 | ||||
-rw-r--r-- | Source/AIFramework/Polyhedra/LinearConstraint.cs | 788 | ||||
-rw-r--r-- | Source/AIFramework/Polyhedra/LinearConstraintSystem.cs | 1376 | ||||
-rw-r--r-- | Source/AIFramework/Polyhedra/PolyhedraAbstraction.cs | 1129 | ||||
-rw-r--r-- | Source/AIFramework/Polyhedra/SimplexTableau.cs | 1080 | ||||
-rw-r--r-- | Source/AIFramework/VariableMap/ConstantAbstraction.cs | 111 | ||||
-rw-r--r-- | Source/AIFramework/VariableMap/DynamicTypeLattice.cs | 793 | ||||
-rw-r--r-- | Source/AIFramework/VariableMap/Intervals.cs | 884 | ||||
-rw-r--r-- | Source/AIFramework/VariableMap/MicroLattice.cs | 42 | ||||
-rw-r--r-- | Source/AIFramework/VariableMap/Nullness.cs | 107 | ||||
-rw-r--r-- | Source/AIFramework/VariableMap/VariableMapLattice.cs | 370 |
18 files changed, 5980 insertions, 4917 deletions
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 @@ -<?xml version="1.0" encoding="utf-8"?>
-<VisualStudioProject>
- <XEN ProjectType="Local"
- SchemaVersion="1.0"
- Name="AIFramework"
- ProjectGuid="24b55172-ad8b-47d1-8952-5a95cfdb9b31"
- >
- <Build>
- <Settings ApplicationIcon=""
- AssemblyName="AIFramework"
- OutputType="Library"
- RootNamespace="AIFramework"
- StartupObject=""
- StandardLibraryLocation=""
- TargetPlatform="v2"
- TargetPlatformLocation=""
- ShadowedAssembly=""
- >
- <Config Name="Debug"
- AllowUnsafeBlocks="False"
- BaseAddress="285212672"
- CheckForOverflowUnderflow="False"
- ConfigurationOverrideFile=""
- DefineConstants="DEBUG;TRACE"
- DocumentationFile=""
- DebugSymbols="True"
- FileAlignment="4096"
- IncrementalBuild="True"
- Optimize="False"
- OutputPath="bin\debug"
- RegisterForComInterop="False"
- RemoveIntegerChecks="false"
- TreatWarningsAsErrors="False"
- WarningLevel="4"
- RunProgramVerifier="False"
- ProgramVerifierCommandLineOptions=""
- ReferenceTypesAreNonNullByDefault="False"
- RunProgramVerifierWhileEditing="False"
- AllowPointersToManagedStructures="False"
- CheckContractAdmissibility="True"
- CheckPurity="False"
- />
- <Config Name="Release"
- AllowUnsafeBlocks="false"
- BaseAddress="285212672"
- CheckForOverflowUnderflow="false"
- ConfigurationOverrideFile=""
- DefineConstants="TRACE"
- DocumentationFile=""
- DebugSymbols="false"
- FileAlignment="4096"
- IncrementalBuild="false"
- Optimize="true"
- OutputPath="bin\release"
- RegisterForComInterop="false"
- RemoveIntegerChecks="false"
- TreatWarningsAsErrors="True"
- WarningLevel="4"
- />
- </Settings>
- <References>
- <Reference Name="System"
- AssemblyName="System"
- Private="false"
- />
- <Reference Name="Basetypes"
- Project="{0C692837-77EC-415F-BF04-395E3ED06E9A}"
- Private="true"
- />
- </References>
- </Build>
- <Files>
- <Include>
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="Expr.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="CommonFunctionSymbols.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="Lattice.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="Functional.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="Mutable.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="Logger.ssc"
- />
- <Folder RelPath="VariableMap\"
- />
- <Folder RelPath="Polyhedra\"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="VariableMap\MicroLattice.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="VariableMap\VariableMapLattice.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="MultiLattice.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="VariableMap\Nullness.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="VariableMap\ConstantAbstraction.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="VariableMap\DynamicTypeLattice.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="Polyhedra\SimplexTableau.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="Polyhedra\LinearConstraint.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="Polyhedra\LinearConstraintSystem.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="Polyhedra\PolyhedraAbstraction.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="..\version.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="VariableMap\Intervals.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="VariableMap\ConstantExpressions.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="AssemblyInfo.ssc"
- />
- </Include>
- </Files>
- </XEN>
-</VisualStudioProject>
\ No newline at end of file +<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>AIFramework</RootNamespace>
+ <AssemblyName>AIFramework</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+ <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+ <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+ <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+ <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+ <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+ <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
+ <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
+ <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+ <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+ <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+ <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+ <CodeContractsCustomRewriterAssembly>
+ </CodeContractsCustomRewriterAssembly>
+ <CodeContractsCustomRewriterClass>
+ </CodeContractsCustomRewriterClass>
+ <CodeContractsLibPaths>
+ </CodeContractsLibPaths>
+ <CodeContractsExtraRewriteOptions>
+ </CodeContractsExtraRewriteOptions>
+ <CodeContractsExtraAnalysisOptions>
+ </CodeContractsExtraAnalysisOptions>
+ <CodeContractsBaseLineFile>
+ </CodeContractsBaseLineFile>
+ <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Microsoft.Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=736440c9b414ea16, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\Binaries\Microsoft.Contracts.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="cce.cs" />
+ <Compile Include="CommonFunctionSymbols.cs" />
+ <Compile Include="Expr.cs" />
+ <Compile Include="Functional.cs" />
+ <Compile Include="Lattice.cs" />
+ <Compile Include="Logger.cs" />
+ <Compile Include="MultiLattice.cs" />
+ <Compile Include="Mutable.cs" />
+ <Compile Include="Polyhedra\LinearConstraint.cs" />
+ <Compile Include="Polyhedra\LinearConstraintSystem.cs" />
+ <Compile Include="Polyhedra\PolyhedraAbstraction.cs" />
+ <Compile Include="Polyhedra\SimplexTableau.cs" />
+ <Compile Include="VariableMap\ConstantAbstraction.cs" />
+ <Compile Include="VariableMap\DynamicTypeLattice.cs" />
+ <Compile Include="VariableMap\Intervals.cs" />
+ <Compile Include="VariableMap\MicroLattice.cs" />
+ <Compile Include="VariableMap\Nullness.cs" />
+ <Compile Include="VariableMap\VariableMapLattice.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Basetypes\Basetypes.sscproj">
+ <Project>{0C692837-77EC-415F-BF04-395E3ED06E9A}</Project>
+ <Name>Basetypes</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Properties\" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
\ 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;
/// <summary>
@@ -15,27 +16,36 @@ namespace Microsoft.AbstractInterpretationFramework /// </summary>
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<AIType>() != null); return typ; } }
[NoDefaultContract]
[Pure]
- public override string! ToString()
- {
+ public override string/*!*/ ToString() {
+Contract.Ensures(Contract.Result<string>() != null);
return display;
}
@@ -52,7 +62,7 @@ namespace Microsoft.AbstractInterpretationFramework /// The intention is that this constructor be called only from the Int.Const method.
/// </summary>
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.
/// </summary>
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 /// </summary>
public class NamedSymbol : FunctionSymbol
{
- public string! Value { [NoDefaultContract] get { return (!) this.ToString(); } }
+ public string/*!*/ Value { [NoDefaultContract] get {Contract.Ensures(Contract.Result<string>() != 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 /// </summary>
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<AIType>() != 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<FunctionType>() != 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<AIType>() != 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<FunctionSymbol>() != 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<FunctionSymbol>() != 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<FunctionSymbol>() != 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<AIType>() != 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<FunctionSymbol>() != 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<AIType>() != 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<FunctionSymbol>() != null); return _negate; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Add { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _add; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Sub { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _sub; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Mul { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _mul; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Div { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _div; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Mod { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _mod; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ AtMost { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _atmost; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Less { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _less; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Greater { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _greater; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ AtLeast { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _atleast; } }
+
+ public static IntSymbol/*!*/ Const(BigNum x) {
+Contract.Ensures(Contract.Result<IntSymbol>() != 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<AIType>() != null); return doubletype; } }
- public static DoubleSymbol! Const(double x)
- {
+ public static DoubleSymbol/*!*/ Const(double x) {
+Contract.Ensures(Contract.Result<DoubleSymbol>() != 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<AIType>() != 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<FunctionSymbol>() != null); return _negate; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Add { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _add; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Sub { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _sub; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Mul { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _mul; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Div { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _div; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Mod { get { Contract.Ensures(Contract.Result<FunctionSymbol>() != null);return _mod; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ AtMost { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _atmost; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Less { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _less; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Greater { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _greater; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ AtLeast { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _atleast; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Extract { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _extract; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Concat { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _concat; } }
+
+ public static BvSymbol/*!*/ Const(BigNum x, int y) {
+Contract.Ensures(Contract.Result<BvSymbol>() != 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<AIType>() != 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<FunctionSymbol>() != null); return _null; } }
/// <summary>
/// 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<AIType>() != 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<AIType>() != 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<FunctionSymbol>() != null); return _allocated; } }
/// <summary>
/// Is this a boolean field that monotonically goes from false to true?
/// </summary>
- 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<AIType>() != 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<FunctionSymbol>() != 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<FunctionSymbol>() != 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<FunctionSymbol>() != 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<FunctionSymbol>() != 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<FunctionSymbol>() != null); return _unsupportedHeapOp; } }
/// <summary>
/// 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; } }
//
// /// <summary>
// /// 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; } }
//
// /// <summary>
// /// Pair should not be instantiated from the outside, except by subclasses.
@@ -598,34 +625,40 @@ namespace Microsoft.AbstractInterpretationFramework /// </summary>
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<AIType>() != 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<FunctionSymbol>() != null); return _false; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ True { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _true; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Not { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _not; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ And { [Pure] get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _and; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Or { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _or; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Implies { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _implies; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Exists { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _exists; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Forall { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _forall; } }
+ [Pure][Reads(ReadsAttribute.Reads.Nothing)] public static FunctionSymbol/*!*/ Lambda { get {Contract.Ensures(Contract.Result<FunctionSymbol>() != null); return _lambda; } }
/// <summary>
@@ -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<IExpr>() != 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/*<IExpr!>*/! exprs)
- {
- IExpr! result = factory.True;
- foreach (IExpr! conjunct in exprs)
- {
+ public static IExpr/*!*/ SimplifiedAnd(IPropExprFactory/*!*/ factory, IEnumerable/*<IExpr!>*//*!*/ exprs){
+Contract.Requires(exprs != null);
+Contract.Requires(factory != null);
+Contract.Ensures(Contract.Result<IExpr>() != 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<IExpr>() != 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/*<IExpr!>*/! exprs)
- {
- IExpr! result = factory.False;
- foreach (IExpr! disj in exprs)
- {
+ public static IExpr/*!*/ SimplifiedOr(IPropExprFactory/*!*/ factory, IEnumerable/*<IExpr!>*//*!*/ exprs){
+Contract.Requires(exprs != null);
+Contract.Requires(factory != null);
+Contract.Ensures(Contract.Result<IExpr>() != 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 /// </summary>
/// <param name="e">The expression to examine.</param>
/// <returns>A list of conjuncts.</returns>
- internal static IList/*<IExpr!>*/! BreakConjuncts(IExpr! e)
- ensures forall{ IExpr sub in result; sub is IFunApp ==> !((IFunApp) sub).FunctionSymbol.Equals(Prop.And) };
- {
+ internal static IList/*<IExpr!>*//*!*/ BreakConjuncts(IExpr/*!*/ e){
+Contract.Requires(e != null);
+ Contract.Ensures(Contract.Result<IList>() != null);
+ Contract.Ensures(Contract.ForAll(0, Contract.Result<IList>().Count, i => {
+ var sub = Contract.Result<IList>()[i];
+ return !(sub is IFunApp) || !((IFunApp)sub).FunctionSymbol.Equals(Prop.And);
+ }));
return BreakJuncts(e, Prop.And);
}
@@ -739,16 +788,25 @@ namespace Microsoft.AbstractInterpretationFramework /// </summary>
/// <param name="e">The expression to examine.</param>
/// <returns>A list of conjuncts.</returns>
- internal static IList/*<IExpr!>*/! BreakDisjuncts(IExpr! e)
- ensures forall{ IExpr sub in result; sub is IFunApp ==> !((IFunApp) sub).FunctionSymbol.Equals(Prop.Or) };
- {
+ internal static IList/*<IExpr!>*//*!*/ BreakDisjuncts(IExpr/*!*/ e){
+Contract.Requires(e != null);
+ Contract.Ensures(Contract.Result<IList>() != null);
+ Contract.Ensures(Contract.ForAll(0, Contract.Result<IList>().Count, i => {
+ var sub = Contract.Result<IList>()[i];
+ return !(sub is IFunApp) || !((IFunApp)sub).FunctionSymbol.Equals(Prop.Or);
+ }));
return BreakJuncts(e, Prop.Or);
}
- private static IList/*<IExpr!>*/! BreakJuncts(IExpr! e, IFunctionSymbol! sym)
- ensures forall{ IExpr sub in result; sub is IFunApp ==> !((IFunApp) sub).FunctionSymbol.Equals(sym) };
- {
- ArrayList/*<IExpr!>*/! result = new ArrayList();
+ private static IList/*<IExpr!>*//*!*/ BreakJuncts(IExpr/*!*/ e, IFunctionSymbol/*!*/ sym){
+Contract.Requires(sym != null);
+Contract.Requires(e != null);
+ Contract.Ensures(Contract.Result<IList>() != null);
+ Contract.Ensures(Contract.ForAll(0, Contract.Result<IList>().Count, i => {
+ var sub = Contract.Result<IList>()[i];
+ return (sub is IFunApp) || !((IFunApp)sub).FunctionSymbol.Equals(sym);
+ }));
+ ArrayList/*<IExpr!>*//*!*/ 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 /// </summary>
/// <param name="var">The bound variable to use.</param>
/// <returns>The function body.</returns>
- public delegate IExpr! FunctionBody(IVariable! var);
+ public delegate IExpr/*!*/ FunctionBody(IVariable/*!*/ var);
/// <summary>
/// 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.
/// </summary>
+ ///
+ [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<IFunApp>() != null);
+ throw new System.NotImplementedException();
+ }
+
+IFunApp IPropExprFactory.False
+{
+
+ get { Contract.Ensures(Contract.Result<IFunApp>() != null);throw new System.NotImplementedException(); }
+}
+
+IFunApp IPropExprFactory.True
+{
+ get {Contract.Ensures(Contract.Result<IFunApp>() != null); throw new System.NotImplementedException(); }
+}
+
+IFunApp IPropExprFactory.Not(IExpr p)
+{
+ Contract.Requires(p != null);
+ Contract.Ensures(Contract.Result<IFunApp>() != null);
+ throw new System.NotImplementedException();
+}
+
+IFunApp IPropExprFactory.And(IExpr p, IExpr q)
+{
+ Contract.Requires(p != null);
+ Contract.Requires(q != null);
+ Contract.Ensures(Contract.Result<IFunApp>() != null);
+ throw new System.NotImplementedException();
+}
+
+IFunApp IPropExprFactory.Or(IExpr p, IExpr q)
+{Contract.Requires(p != null);
+ Contract.Requires(q != null);
+ Contract.Ensures(Contract.Result<IFunApp>() != null);
+ throw new System.NotImplementedException();
+}
+
+
+
+#endregion
+}
/// <summary>
/// Like IPropExprFactory, but also with quantifiers.
/// </summary>
+ ///
+ [ContractClass(typeof(IQuantPropExprFactoryContracts))]
public interface IQuantPropExprFactory : IPropExprFactory {
/// <summary>
/// Produce an existential given the lambda-expression.
/// </summary>
/// <param name="p">The lambda-expression.</param>
/// <returns>The existential.</returns>
- 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);*/;
/// <summary>
/// Produce an existential given a callback that can produce a function body given the
@@ -821,9 +931,71 @@ namespace Microsoft.AbstractInterpretationFramework /// </summary>
/// <param name="body">The function body callback.</param>
/// <returns>The existential.</returns>
- 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<IFunApp>() != null);
+ throw new System.NotImplementedException();
+}
+
+IFunApp IQuantPropExprFactory.Forall(IFunction p)
+{Contract.Requires(p != null);Contract.Ensures(Contract.Result<IFunApp>() != null);
+ throw new System.NotImplementedException();
+}
+
+IFunApp IQuantPropExprFactory.Exists(AIType paramType, FunctionBody body)
+{Contract.Requires(body != null);Contract.Ensures(Contract.Result<IFunApp>() != null);
+ throw new System.NotImplementedException();
+}
+
+IFunApp IQuantPropExprFactory.Forall(AIType paramType, FunctionBody body)
+{Contract.Requires(body != null);Contract.Ensures(Contract.Result<IFunApp>() != 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
+}
/// <summary>
/// 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.
/// </summary>
+ ///
+ [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<IFunApp>() != null);
+ throw new System.NotImplementedException();
+}
+
+IFunApp IValueExprFactory.Neq(IExpr e0, IExpr e1)
+{
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<IFunApp>() != null);
+ throw new System.NotImplementedException();
+}
+
+#endregion
+}
/// <summary>
/// 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.
/// </summary>
+ ///
+ [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<IFunApp>() != null);
+ throw new System.NotImplementedException();
+}
+
+IFunApp INullnessFactory.Neq(IExpr e0, IExpr e1)
+{
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);
+ Contract.Ensures(Contract.Result<IFunApp>() != null);
+ throw new System.NotImplementedException();
+}
+
+IFunApp INullnessFactory.Null
+{
+ get {
+ Contract.Ensures(Contract.Result<IFunApp>() != null);
+ throw new System.NotImplementedException(); }
+}
+
+#endregion
+}
/// <summary>
/// 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.
/// </summary>
+ ///
+ [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<IFunApp>() != 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
}
/// <summary>
@@ -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.
/// </summary>
+ ///
+ [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);*/;
/// <summary>
/// If "var" is null, returns an expression representing r.
/// Otherwise, returns an expression representing r*var.
/// </summary>
- 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<IFunApp>() != null);
+ throw new System.NotImplementedException();
+}
+
+IFunApp ILinearExprFactory.Add(IExpr e0, IExpr e1)
+{
+ Contract.Requires(e0 != null);
+ Contract.Requires(e1 != null);Contract.Ensures(Contract.Result<IFunApp>() != null);
+ throw new System.NotImplementedException();
+}
+
+IExpr ILinearExprFactory.Term(Rational r, IVariable var)
+{
+ Contract.Ensures(Contract.Result<IExpr>() != null);
+ throw new System.NotImplementedException();
+}
+
+IFunApp ILinearExprFactory.False
+{
+ get {Contract.Ensures(Contract.Result<IFunApp>() != null); throw new System.NotImplementedException(); }
+}
+
+IFunApp ILinearExprFactory.True
+{
+ get { Contract.Ensures(Contract.Result<IFunApp>() != null);throw new System.NotImplementedException(); }
+}
+
+IFunApp ILinearExprFactory.And(IExpr p, IExpr q)
+{
+ Contract.Requires(p != null);
+ Contract.Requires(q != null);
+ Contract.Ensures(Contract.Result<IFunApp>() != 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
+ }
/// <summary>
/// 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.
/// </summary>
+ ///
+ [ContractClass(typeof(ITypeExprFactoryContracts))]
public interface ITypeExprFactory
{
/// <summary>
/// Returns an expression denoting the top of the type hierarchy.
/// </summary>
- IExpr! RootType { get; }
+ IExpr/*!*/ RootType { get; }
/// <summary>
/// Returns true iff "t" denotes a type constant.
/// </summary>
[Pure]
- bool IsTypeConstant(IExpr! t);
+ bool IsTypeConstant(IExpr/*!*/ t);
/// <summary>
/// Returns true iff t0 and t1 are types such that t0 and t1 are equal.
/// </summary>
[Pure]
- bool IsTypeEqual(IExpr! t0, IExpr! t1);
+ bool IsTypeEqual(IExpr/*!*/ t0, IExpr/*!*/ t1);
/// <summary>
/// Returns true iff t0 and t1 are types such that t0 is a subtype of t1.
/// </summary>
[Pure]
- bool IsSubType(IExpr! t0, IExpr! t1);
+ bool IsSubType(IExpr/*!*/ t0, IExpr/*!*/ t1);
/// <summary>
/// Returns the most derived supertype of both "t0" and "t1". A precondition is
/// that "t0" and "t1" both represent types.
/// </summary>
- 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<IExpr>() != 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<IExpr>() != null);
+ throw new System.NotImplementedException();
+}
+
+IFunApp ITypeExprFactory.IsExactlyA(IExpr e, IExpr type)
+{
+ Contract.Requires(e != null);
+ Contract.Requires(type != null);
+ Contract.Ensures(Contract.Result<IFunApp>() != null);
+ throw new System.NotImplementedException();
+}
+
+IFunApp ITypeExprFactory.IsA(IExpr e, IExpr type)
+{
+ Contract.Requires(e != null);
+ Contract.Requires(type != null);
+ Contract.Ensures(Contract.Result<IFunApp>() != 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, ...
/// </summary>
+ [ContractClass(typeof(IExprContracts))]
public interface IExpr
{
/// <summary>
@@ -35,34 +37,62 @@ namespace Microsoft.AbstractInterpretationFramework /// </summary>
/// <param name="visitor">The expression visitor.</param>
/// <returns>The result of the visit.</returns>
- [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
+}
/// <summary>
/// An interface for variables.
///
/// This interface should be implemented by the client.
/// </summary>
+ [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<string>() != null);throw new NotImplementedException();}
+
+ }
+
+ #region IExpr Members
+
+ object IExpr.DoVisit(ExprVisitor visitor) {
+ throw new NotImplementedException();
}
+ #endregion
+ }
+
/// <summary>
/// An interface for function applications.
///
/// This interface should be implemented by the client.
/// </summary>
+ ///
+ [ContractClass(typeof(IFunAppContracts))]
public interface IFunApp : IExpr
{
- IFunctionSymbol! FunctionSymbol { get; }
- IList/*<IExpr!>*/! Arguments
+ IFunctionSymbol/*!*/ FunctionSymbol { get; }
+ IList/*<IExpr!>*//*!*/ Arguments
{
- [Pure][Rep] get
- ensures result.IsReadOnly;
- ;
+ [Pure][Rep] get;
+
}
/// <summary>
@@ -72,23 +102,103 @@ namespace Microsoft.AbstractInterpretationFramework /// </summary>
/// <param name="args">The new arguments.</param>
/// <returns>A copy of the function with the new arguments.</returns>
- IFunApp! CloneWithArguments(IList/*<IExpr!>*/! args)
- //TODO requires this.Arguments.Count == args.Count;
+ IFunApp/*!*/ CloneWithArguments(IList/*<IExpr!>*//*!*/ 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<IFunctionSymbol>() != null);
+ throw new System.NotImplementedException(); }
+}
+
+public IList Arguments
+{
+ get {Contract.Ensures(Contract.Result<IList>() != null);
+ Contract.Ensures(Contract.Result<IList>().IsReadOnly);
+ throw new System.NotImplementedException(); }
+}
+
+public IFunApp CloneWithArguments(IList args)
+{
+ Contract.Requires(args != null);
+ Contract.Ensures(Contract.Result<IFunApp>() != null);
+
+
+ throw new System.NotImplementedException();
+}
+
+#endregion
+
+#region IExpr Members
+
+object IExpr.DoVisit(ExprVisitor visitor) {
+ throw new NotImplementedException();
+}
+
+#endregion
+}
/// <summary>
/// An interface for anonymous functions (i.e., lambda expressions)
/// </summary>
+ [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<IVariable>() != null);
+ throw new NotImplementedException();
+ }
+ }
- IFunction! CloneWithBody(IExpr! body);
+ AIType IFunction.ParamType {
+ get {
+ Contract.Ensures(Contract.Result<AIType>() != null);
+ throw new NotImplementedException();
+ }
}
+ IExpr IFunction.Body {
+ get {
+ Contract.Ensures(Contract.Result<IExpr>() != null);
+ throw new NotImplementedException();
+ }
+ }
+
+ IFunction IFunction.CloneWithBody(IExpr body) {
+ Contract.Requires(body != null);
+ Contract.Ensures(Contract.Result<IFunction>() != null);
+ throw new NotImplementedException();
+ }
+
+ #endregion
+
+ #region IExpr Members
+
+ object IExpr.DoVisit(ExprVisitor visitor) {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+
/// <summary>
/// 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 /// <summary>
/// An abstract class that provides an interface for expression visitors.
/// </summary>
+ [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();
+}}
/// <summary>
/// A utility class for dealing with expressions.
@@ -131,8 +248,11 @@ namespace Microsoft.AbstractInterpretationFramework /// <param name="subst">The expression to substitute.</param>
/// <param name="var">The variable to substitute for.</param>
/// <param name="inexpr">The expression to substitute into.</param>
- 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<IExpr>() != 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<IExpr>();
+ 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.
/// </summary>
+ [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<AIType>() != null);
+ throw new NotImplementedException();
+ }
+ }
+
+ #endregion
+ }
/// <summary>
/// The type of the arguments to ExprUtil.Match, a poor man's pattern
@@ -345,31 +497,39 @@ namespace Microsoft.AbstractInterpretationFramework /// </summary>
public sealed class FunctionType : AIType
{
- /*[Own]*/ private readonly IList/*<Type!>*/! argTypes;
- /*[Own]*/ private readonly AIType! retType;
+ /*[Own]*/ private readonly IList/*<Type!>*//*!*/ 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/*<AIType!>*/! Arguments
+ public IList/*<AIType!>*//*!*/ Arguments
{
[Pure][Rep]
get
- ensures result.IsReadOnly;
- {
+ {
+ Contract.Ensures(Contract.Result<IList>() != null);
+ Contract.Ensures(Contract.Result<IList>().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<AIType>() != 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.
/// </summary>
+ ///
+ [ContractClass(typeof(IQueryableContracts))]
public interface IQueryable
{
/// <summary>
@@ -425,14 +587,31 @@ namespace Microsoft.AbstractInterpretationFramework /// </summary>
/// <param name="pred">The given predicate.</param>
/// <returns>Yes, No, or Maybe.</returns>
- Answer CheckPredicate(IExpr! pred);
+ Answer CheckPredicate(IExpr/*!*/ pred);
/// <summary>
/// A simplified interface for disequalities. One can always
/// implement this by calling CheckPredicate, but it may be
/// more efficient with this method.
/// </summary>
- 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 /// <summary>Represents a functional collection of key/value pairs.</summary>
/// <filterpriority>2</filterpriority>
+ [ContractClass(typeof(IFunctionalMapContracts))]
public interface IFunctionalMap : System.Collections.ICollection, System.Collections.IEnumerable
{
/// <summary>Adds an element with the provided key and value to the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</summary>
/// <param name="value">The <see cref="T:System.Object" /> to use as the value of the element to add. </param>
/// <param name="key">The <see cref="T:System.Object" /> to use as the key of the element to add. </param>
/// <filterpriority>2</filterpriority>
- IFunctionalMap! Add(object! key, object value);
+ IFunctionalMap/*!*/ Add(object/*!*/ key, object value);
/// <summary>
/// Set the value of the key (that is already in the map)
/// </summary>
- IFunctionalMap! Set(object! key, object value);
+ IFunctionalMap/*!*/ Set(object/*!*/ key, object value);
/// <summary>Determines whether the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" /> contains an element with the specified key.</summary>
/// <returns>true if the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" /> contains an element with the key; otherwise, false.</returns>
/// <param name="key">The key to locate in the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />. </param>
/// <filterpriority>2</filterpriority>
[Pure]
- bool Contains(object! key);
+ bool Contains(object/*!*/ key);
/// <summary>Returns an <see cref="T:System.Collections.IDictionaryEnumerator" /> for the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</summary>
/// <returns>An <see cref="T:System.Collections.IDictionaryEnumerator" /> for the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</returns>
@@ -45,15 +46,107 @@ namespace Microsoft.AbstractInterpretationFramework.Collections /// <summary>Removes the element with the specified key from the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</summary>
/// <param name="key">The key of the element to remove. </param>
/// <filterpriority>2</filterpriority>
- IFunctionalMap! Remove(object! key);
+ IFunctionalMap/*!*/ Remove(object/*!*/ key);
/// <summary>Gets an <see cref="T:System.Collections.ICollection" /> containing the values in the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</summary>
/// <returns>An <see cref="T:System.Collections.ICollection" /> containing the values in the <see cref="T:Microsoft.AbstractInterpretationFramework.Collections.IFunctionalMap" />.</returns>
/// <filterpriority>2</filterpriority>
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<IFunctionalMap>() != null);
+
+ throw new System.NotImplementedException();
+}
+
+IFunctionalMap IFunctionalMap.Set(object key, object value)
+{
+ Contract.Requires(key != null);
+ Contract.Ensures(Contract.Result<IFunctionalMap>() != 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<IFunctionalMap>() != null);
+
+ throw new System.NotImplementedException();
+}
+
+ICollection IFunctionalMap.Values
+{
+ get { throw new System.NotImplementedException(); }
+}
+
+object IFunctionalMap.this[object key]
+{
+ get {Contract.Ensures(Contract.Result<object>() != 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 /// </summary>
class FunctionalHashtable : IFunctionalMap
{
- private readonly Hashtable! h;
+ private readonly Hashtable/*!*/ h;
+ [ContractInvariantMethod]
+void ObjectInvariant()
+{
+ Contract.Invariant(h != null);
+}
+
/// <summary>
/// Cannot directly construct an instance of a FunctionalHashtbl.
@@ -78,43 +177,48 @@ namespace Microsoft.AbstractInterpretationFramework.Collections /// <summary>
/// Cannot directly construct an instance of a FunctionalHashtbl.
/// </summary>
- 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<IFunctionalMap>() != 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<IFunctionalMap>() != 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<IFunctionalMap>() != 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<IEnumerator>() != 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<IFunctionalMap>() != 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<object>() != 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<string>() != 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<string>() != 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;
+
+
+
+ /// <summary>
+ /// Specifies the operations (e.g., join) on a mathematical lattice that depend
+ /// only on the elements of the lattice.
+ /// </summary>
+ [ContractClass(typeof(MathematicalLatticeContracts))]
+ public abstract class MathematicalLattice {
+ #region Element
+ /// <summary>
+ /// An element of the lattice. This class should be derived from in any
+ /// implementation of MathematicalLattice.
+ /// </summary>
+ [ContractClass(typeof(ElementContracts))]
+ public abstract class Element : System.ICloneable {
+ /// <summary>
+ /// Print out a debug-useful representation of the internal data structure of the lattice element.
+ /// </summary>
+ 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<IVariable/*!*/>/*!*/ FreeVariables();
+ }
+ [ContractClassFor(typeof(Element))]
+ public abstract class ElementContracts : Element {
+ public override Element Clone() {
+ Contract.Ensures(Contract.Result<Element>() != null);
+ throw new NotImplementedException();
+
+ }
+
+ public override System.Collections.Generic.ICollection<IVariable> FreeVariables() {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<G.ICollection<IVariable>>()));
+ Contract.Ensures(Contract.Result<System.Collections.Generic.ICollection<IVariable>>().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);
/// <summary>
- /// Specifies the operations (e.g., join) on a mathematical lattice that depend
- /// only on the elements of the lattice.
+ /// Returns true if a <= this.
/// </summary>
- public abstract class MathematicalLattice
- {
- /// <summary>
- /// An element of the lattice. This class should be derived from in any
- /// implementation of MathematicalLattice.
- /// </summary>
- public abstract class Element : System.ICloneable {
- /// <summary>
- /// Print out a debug-useful representation of the internal data structure of the lattice element.
- /// </summary>
- 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<IVariable!>! 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);
-
- /// <summary>
- /// Returns true if a <= this.
- /// </summary>
- 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<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != null);
+ throw new NotImplementedException();
+ }
}
+ public override bool IsTop(MathematicalLattice.Element e) {
+ Contract.Requires(e != null);
+ throw new NotImplementedException();
+ }
- /// <summary>
- /// Provides an abstract interface for the operations of a lattice specific
- /// to abstract interpretation (i.e., that deals with the expression language).
- /// </summary>
- 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<Element>() != 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<Element>() != 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<Element>() != null);
+ throw new NotImplementedException();
+ }
+ }
+
+
+ /// <summary>
+ /// Provides an abstract interface for the operations of a lattice specific
+ /// to abstract interpretation (i.e., that deals with the expression language).
+ /// </summary>
+ [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);
+ }
- /// <summary>
- /// Returns the predicate that corresponds to the given lattice element.
- /// </summary>
- public abstract IExpr! ToPredicate(Element! e);
-
- /// <summary>
- /// 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.
- /// </summary>
- /// <param name="f">The function symbol.</param>
- /// <param name="args">The argument context.</param>
- /// <returns>True if it may understand f, false if it does not understand f.</returns>
- public abstract bool Understands(IFunctionSymbol! f, IList/*<IExpr!>*/! args);
-
- /// <summary>
- /// Return an expression that is equivalent to the given expression that does not
- /// contain the given variable according to the lattice element and queryable.
- /// </summary>
- /// <param name="e">The lattice element.</param>
- /// <param name="q">A queryable for asking addtional information.</param>
- /// <param name="expr">The expression to find an equivalent expression.</param>
- /// <param name="var">The variable to eliminate.</param>
- /// <param name="prohibitedVars">The set of variables that can't be used in the resulting expression.</param>
- /// <returns>
- /// An equivalent expression to <paramref name="expr"/> without <paramref name="var"/>
- /// or null if not possible.
- /// </returns>
- public abstract IExpr/*?*/ EquivalentExpr(Element! e, IQueryable! q, IExpr! expr, IVariable! var, Set/*<IVariable!>*/! prohibitedVars);
-
- /// <summary>
- /// Answers a query about whether the given predicate holds given the lattice element.
- /// </summary>
- /// <param name="e">The lattice element.</param>
- /// <param name="pred">The predicate.</param>
- /// <returns>Yes, No, or Maybe.</returns>
- public abstract Answer CheckPredicate(Element! e, IExpr! pred);
-
- /// <summary>
- /// 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.
- /// </summary>
- /// <param name="e">The lattice element.</param>
- /// <param name="var1">The first variable.</param>
- /// <param name="var2">The second variable.</param>
- /// <returns>Yes, No, or Maybe.</returns>
- public abstract Answer CheckVariableDisequality(Element! e, IVariable! var1, IVariable! var2);
-
- /// <summary>
- /// A default implementation of the <see cref="CheckVariableDisequality"/> given
- /// the appropriate expression factories by calling CheckPredicate.
- /// </summary>
- 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<IVariable!,ISet/*<IVariable!>*/!> entry in eToResult.GetSourceToResult())
- {
- IVariable! sourceName = entry.Key;
- ISet/*<IVariable!*/! resultNames = entry.Value;
-
- // Renaming s to r is okay if
- // (1) s is not used in the result
- // and (2) s has not been renamed already
- bool renameOkay = !resultNames.Contains(sourceName);
- IVariable! representative = sourceName;
-
- foreach (IVariable! rname in resultNames)
- {
- // skip if sourceName and rname are the same
- if (object.Equals(sourceName, rname)) { continue; }
-
- if (renameOkay)
- {
- result = this.Rename(result, sourceName, rname);
- representative = rname; // representative now rname
- renameOkay = false; // no longer okay to rename
- }
- else
- {
- result = this.Constrain(result, valueExprFactory.Eq(representative, rname));
- }
- }
- }
-
- return result;
- }
-
- private sealed class IdentityCombineNameMap : ICombineNameMap
- {
- public static readonly IdentityCombineNameMap! Map = new IdentityCombineNameMap();
-
- private static readonly G.Dictionary<IVariable!,ISet/*<IVariable!>*/!>! emptyDictionary1 = new G.Dictionary<IVariable!,ISet/*<IVariable!>*/!>();
- private static readonly G.Dictionary<IVariable!,IVariable!>! emptyDictionary2 = new G.Dictionary<IVariable!,IVariable!>();
-
- public ISet/*<IVariable!>*//*?*/ 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<G.KeyValuePair<IVariable!,ISet/*<IVariable!>*/!>> GetSourceToResult()
- public IEnumerable! GetSourceToResult()
- {
- return emptyDictionary1;
- }
-
- //public G.IEnumerable<G.KeyValuePair<IVariable!,IVariable!>> 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/*<System.Type,int>*/! indexMap = new Hashtable();
- private static Hashtable/*<int,Lattice>*/! 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<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != null);
+ return Widen(ApplyCombineNameMap(a, aToResult), ApplyCombineNameMap(b, bToResult));
+ }
+
+
/// <summary>
- /// 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 <see cref="CheckVariableDisequality"/> given
+ /// the appropriate expression factories by calling CheckPredicate.
/// </summary>
- public interface ICombineNameMap
- {
- ISet/*<IVariable!>*//*?*/ GetResultNames(IVariable! srcname);
- IVariable/*?*/ GetSourceName(IVariable! resname);
-
- //TODO: uncommet when works in compiler
- //G.IEnumerable<G.KeyValuePair<IVariable!,ISet/*<IVariable!>*/!>> GetSourceToResult();
- IEnumerable! GetSourceToResult();
- //G.IEnumerable<G.KeyValuePair<IVariable!,IVariable!>> 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<Element>() != null);
+ Element/*!*/ result = e;
+
+ foreach (G.KeyValuePair<IVariable/*!*/, ISet/*<IVariable!>*//*!*/> entry in eToResult.GetSourceToResult()) {
+ IVariable/*!*/ sourceName = entry.Key;
+ Contract.Assert(sourceName != null);
+ ISet/*<IVariable!*//*!*/ resultNames = entry.Value;
+ Contract.Assert(resultNames != null);
+ // Renaming s to r is okay if
+ // (1) s is not used in the result
+ // and (2) s has not been renamed already
+ bool renameOkay = !resultNames.Contains(sourceName);
+ IVariable/*!*/ representative = sourceName;
+ Contract.Assert(representative != null);
+
+ foreach (IVariable/*!*/ rname in resultNames) {
+ Contract.Assert(rname != null);
+ // skip if sourceName and rname are the same
+ if (object.Equals(sourceName, rname)) {
+ continue;
+ }
+
+ if (renameOkay) {
+ result = this.Rename(result, sourceName, rname);
+ representative = rname; // representative now rname
+ renameOkay = false; // no longer okay to rename
+ } else {
+ result = this.Constrain(result, valueExprFactory.Eq(representative, rname));
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private sealed class IdentityCombineNameMap : ICombineNameMap {
+ public static readonly IdentityCombineNameMap/*!*/ Map = new IdentityCombineNameMap();
+
+ private static readonly G.Dictionary<IVariable/*!*/, ISet/*<IVariable!>*//*!*/>/*!*/ emptyDictionary1 = new G.Dictionary<IVariable/*!*/, ISet/*<IVariable!>*//*!*/>();
+ private static readonly G.Dictionary<IVariable/*!*/, IVariable/*!*/>/*!*/ emptyDictionary2 = new G.Dictionary<IVariable/*!*/, IVariable/*!*/>();
+ [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/*<IVariable!>*//*?*/ 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<G.KeyValuePair<IVariable!,ISet/*<IVariable!>*/!>> GetSourceToResult()
+ public IEnumerable/*!*/ GetSourceToResult() {
+ Contract.Ensures(Contract.Result<IEnumerable>() != null);
+ return emptyDictionary1;
+ }
+
+ //public G.IEnumerable<G.KeyValuePair<IVariable!,IVariable!>> GetResultToSource()
+ public IEnumerable/*!*/ GetResultToSource() {
+ Contract.Ensures(Contract.Result<IEnumerable>() != null);
+ return emptyDictionary2;
+ }
+
+ private IdentityCombineNameMap() {
+ }
+ }
+
+ #region Support for MultiLattice to uniquely number every subclass of Lattice
+
+
+ private static Hashtable/*<System.Type,int>*//*!*/ indexMap = new Hashtable();
+ private static Hashtable/*<int,Lattice>*//*!*/ reverseIndexMap = new Hashtable();
+ private static int globalCount = 0;
+
+ protected virtual object/*!*/ UniqueId {
+ get {
+ Contract.Ensures(Contract.Result<object>() != 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;
/// <summary>
- /// 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.
/// </summary>
- 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);
- }
+ /// <summary>
+ /// 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.
+ /// </summary>
+ /// <param name="f">The function symbol.</param>
+ /// <param name="args">The argument context.</param>
+ /// <returns>True if it may understand f, false if it does not understand f.</returns>
+ public abstract bool Understands(IFunctionSymbol/*!*/ f, IList/*<IExpr!>*//*!*/ args);
- public override Element! Rename(Element! e, IVariable! oldName, IVariable! newName)
- {
- renameCount++;
- return lattice.Rename(e, oldName, newName);
- }
+ /// <summary>
+ /// Return an expression that is equivalent to the given expression that does not
+ /// contain the given variable according to the lattice element and queryable.
+ /// </summary>
+ /// <param name="e">The lattice element.</param>
+ /// <param name="q">A queryable for asking addtional information.</param>
+ /// <param name="expr">The expression to find an equivalent expression.</param>
+ /// <param name="var">The variable to eliminate.</param>
+ /// <param name="prohibitedVars">The set of variables that can't be used in the resulting expression.</param>
+ /// <returns>
+ /// An equivalent expression to <paramref name="expr"/> without <paramref name="var"/>
+ /// or null if not possible.
+ /// </returns>
+ public abstract IExpr/*?*/ EquivalentExpr(Element/*!*/ e, IQueryable/*!*/ q, IExpr/*!*/ expr, IVariable/*!*/ var, Set/*<IVariable!>*//*!*/ prohibitedVars);
- public override Element! Constrain(Element! e, IExpr! expr)
- {
- constrainCount++;
- return lattice.Constrain(e, expr);
- }
+ /// <summary>
+ /// Answers a query about whether the given predicate holds given the lattice element.
+ /// </summary>
+ /// <param name="e">The lattice element.</param>
+ /// <param name="pred">The predicate.</param>
+ /// <returns>Yes, No, or Maybe.</returns>
+ public abstract Answer CheckPredicate(Element/*!*/ e, IExpr/*!*/ pred);
+ /// <summary>
+ /// 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.
+ /// </summary>
+ /// <param name="e">The lattice element.</param>
+ /// <param name="var1">The first variable.</param>
+ /// <param name="var2">The second variable.</param>
+ /// <returns>Yes, No, or Maybe.</returns>
+ 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<IExpr>() != 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<IExpr>() != 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<string>() != 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<Element>() != 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<Element>() != 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<Element>() != null);
+ throw new NotImplementedException();
+ }
+ }
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ [ContractClass(typeof(ICombineNameMapContracts))]
+ public interface ICombineNameMap {
+ ISet/*<IVariable!>*//*?*/ GetResultNames(IVariable/*!*/ srcname);
+ IVariable/*?*/ GetSourceName(IVariable/*!*/ resname);
+
+ //TODO: uncommet when works in compiler
+ //G.IEnumerable<G.KeyValuePair<IVariable!,ISet/*<IVariable!>*/!>> GetSourceToResult();
+ IEnumerable/*!*/ GetSourceToResult();
+ //G.IEnumerable<G.KeyValuePair<IVariable!,IVariable!>> 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<IEnumerable>() != null);
+ throw new NotImplementedException();
+ }
- public override IExpr/*?*/ EquivalentExpr(Element! e, IQueryable! q, IExpr! expr, IVariable! var, ISet/*<IVariable!>*/! prohibitedVars)
- {
- equivalentExprCount++;
- return lattice.EquivalentExpr(e, q, expr, var, prohibitedVars);
- }
+ public IEnumerable GetResultToSource() {
+ Contract.Ensures(Contract.Result<IEnumerable>() != null);
+ throw new NotImplementedException();
+ }
+ #endregion
+ }
+
+ /// <summary>
+ /// Provides statistics on the number of times an operation is performed
+ /// and forwards the real operations to the given lattice in the constructor.
+ /// </summary>
+ 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<Element>() != 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<Element>() != 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<Element>() != 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/*<IVariable!>*//*!*/ 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<IExpr>() != 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<string>() != null);
+ return lattice.ToString(e);
}
+ [Pure]
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != 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<Element>() != null);
+ topCount++;
+ return lattice.Top;
+ }
+ }
+ public override Element/*!*/ Bottom {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != null);
+ widenCount++;
+ return lattice.Widen(a, b);
+ }
+
+ public override void Validate() {
+ base.Validate();
+ lattice.Validate();
+ }
+
+ protected override object/*!*/ UniqueId {
+ get {
+ Contract.Ensures(Contract.Result<object>() != 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;
+
+
+ /// <summary>
+ /// The cartesian product lattice.
+ /// </summary>
+ 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<Element>() != null);
+ return new Elt(this);
+ }
+
+ [Pure]
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != 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<IVariable/*!*/>/*!*/ FreeVariables() {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<IVariable>>()));
+ List<IVariable/*!*/>/*!*/ list = new List<IVariable/*!*/>();
+ 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/*<Lattice>*//*!*/ lattices) {
+ Contract.Requires(lattices != null);
+ Contract.Ensures(Contract.Result<Elt>() != 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/*<Lattice>*//*!*/ lattices) {
+ Contract.Requires(lattices != null);
+ Contract.Ensures(Contract.Result<Elt>() != 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;
+ }
- /// <summary>
- /// The cartesian product lattice.
- /// </summary>
- 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<IVariable!>! FreeVariables()
- {
- List<IVariable!>! list = new List<IVariable!>();
- for (int i = 0; i < this.Count; i++)
- {
- list.AddRange(((!)this[i]).FreeVariables());
- }
- return (!)list.AsReadOnly();
- }
- public static Elt! Top(ArrayList/*<Lattice>*/! 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/*<Lattice>*//*!*/ lattices = new ArrayList();
- public static Elt! Bottom(ArrayList/*<Lattice>*/! 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<Lattice>() != null);
+ return (Lattice/*!*/)cce.NonNull(this.lattices[i]);
+ }
+ public override Element/*!*/ Top {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != null);
+ return Elt.Top(this.lattices);
+ }
+ }
- ArrayList/*<Lattice>*/! lattices = new ArrayList();
+ public override Element/*!*/ Bottom {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != 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<string>() != 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<IExpr>() != 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;
- }
+ /// <summary>
+ /// 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.
+ /// </summary>
+ /// <param name="e">The lattice element.</param>
+ /// <param name="q">A queryable for asking addtional information.</param>
+ /// <param name="expr">The expression to find an equivalent expression.</param>
+ /// <param name="var">The variable to eliminate.</param>
+ /// <returns>
+ /// An equivalent expression to <paramref name="expr"/> without <paramref name="var"/>
+ /// or null if not possible.
+ /// </returns>
+ public override IExpr/*?*/ EquivalentExpr(Element/*!*/ element, IQueryable/*!*/ q, IExpr/*!*/ expr, IVariable/*!*/ var, Set/*<IVariable!>*//*!*/ 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;
- }
-
- /// <summary>
- /// 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.
- /// </summary>
- /// <param name="e">The lattice element.</param>
- /// <param name="q">A queryable for asking addtional information.</param>
- /// <param name="expr">The expression to find an equivalent expression.</param>
- /// <param name="var">The variable to eliminate.</param>
- /// <returns>
- /// An equivalent expression to <paramref name="expr"/> without <paramref name="var"/>
- /// or null if not possible.
- /// </returns>
- public override IExpr/*?*/ EquivalentExpr(Element! element, IQueryable! q, IExpr! expr, IVariable! var, Set/*<IVariable!>*/! 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);
+ /// <summary>
+ /// The enumeration over a MultiLattice is its sublattices.
+ /// </summary>
+ /// <returns>An enumerator over the sublattices.</returns>
+ [Pure]
+ [GlobalAccess(false)]
+ [Escapes(true, false)]
+ public IEnumerator/*<Lattice!>*//*!*/ GetEnumerator() {
+ Contract.Ensures(Contract.Result<IEnumerator>() != null);
+ return lattices.GetEnumerator();
+ }
- if (ans == Answer.Yes || ans == Answer.No)
- return ans;
- }
+ /// <summary>
+ /// Return an enumerable over a mapping of sublattices to the their corresponding
+ /// lattice elements given a MultiLattice element.
+ /// </summary>
+ /// <param name="element">The MultiLattice element.</param>
+ /// <returns>
+ /// An enumerable that yields an IDictionaryEnumerator over the
+ /// (Lattice, Lattice.Element) pairs.
+ /// </returns>
+ public IEnumerable/*!*/ Subelements(Element/*!*/ element) {
+ Contract.Requires(element != null);
+ Contract.Ensures(Contract.Result<IEnumerable>() != null);
+ return new SubelementsEnumerable(this, (Elt/*!*/)cce.NonNull(element));
+ }
- return Answer.Maybe;
+ /// <summary>
+ /// An enumerator over the sublattices and elements.
+ /// </summary>
+ private sealed class SubelementsEnumerable : IEnumerable {
+ private sealed class SubelementsEnumerator : IDictionaryEnumerator {
+ private readonly IEnumerator/*<Lattice!>*//*!*/ multiLatticeIter;
+ private readonly IEnumerator/*<Lattice.Element!>*//*!*/ 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);
+ }
}
- /// <summary>
- /// The enumeration over a MultiLattice is its sublattices.
- /// </summary>
- /// <returns>An enumerator over the sublattices.</returns>
- [Pure] [GlobalAccess(false)] [Escapes(true,false)]
- public IEnumerator/*<Lattice!>*/! GetEnumerator()
- {
- return lattices.GetEnumerator();
+ public object Key {
+ get {
+ return multiLatticeIter.Current;
+ }
}
- /// <summary>
- /// Return an enumerable over a mapping of sublattices to the their corresponding
- /// lattice elements given a MultiLattice element.
- /// </summary>
- /// <param name="element">The MultiLattice element.</param>
- /// <returns>
- /// An enumerable that yields an IDictionaryEnumerator over the
- /// (Lattice, Lattice.Element) pairs.
- /// </returns>
- public IEnumerable! Subelements(Element! element)
- {
- return new SubelementsEnumerable(this, (Elt!) element);
+ public object Value {
+ get {
+ return multiElementIter.Current;
+ }
}
- /// <summary>
- /// An enumerator over the sublattices and elements.
- /// </summary>
- private sealed class SubelementsEnumerable : IEnumerable
- {
- private sealed class SubelementsEnumerator : IDictionaryEnumerator
- {
- private readonly IEnumerator/*<Lattice!>*/! multiLatticeIter;
- private readonly IEnumerator/*<Lattice.Element!>*/! 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<IEnumerator>() != 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;
/// <summary>
/// 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<object>() != null);
+ return this; } }
public bool IsSynchronized { get { return false; } }
}
@@ -70,9 +73,14 @@ namespace Microsoft.AbstractInterpretationFramework.Collections.Generic public class HashMultiset<T>
{
- private readonly IDictionary<T,int>! dict;
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(dict != null);
+ }
+
+ private readonly IDictionary<T,int>/*!*/ dict;
- //invariant forall{KeyValuePair<T,int> 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;
-
-
- /// <summary>
- /// Represents a single linear constraint, coefficients are stored as Rationals.
- /// </summary>
- 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;
+
+
+ /// <summary>
+ /// Represents a single linear constraint, coefficients are stored as Rationals.
+ /// </summary>
+ 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<string>() != 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.
/// </summary>
/// <returns></returns>
- public IExpr! ConvertToExpression(ILinearExprFactory! factory)
- {
+ public IExpr/*!*/ ConvertToExpression(ILinearExprFactory/*!*/ factory) {
+ Contract.Requires(factory != null);
+ Contract.Ensures(Contract.Result<IExpr>() != 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 /// <param name="sum"></param>
/// <param name="r"></param>
/// <param name="x"></param>
- 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<IExpr>() != 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<IVariable> GetDefinedDimensionsGeneric() {
+ Contract.Ensures(Contract.Result<System.Collections.Generic.IEnumerable<IVariable>>() != null);
+ foreach (IVariable/*!*/ dim in coefficients.Keys) {
+ Contract.Assert(dim != null);
+ yield return dim;
+ }
+ }
+ public ISet /*IVariable!*//*!*/ GetDefinedDimensions() {
+ Contract.Ensures(Contract.Result<ISet>() != 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;
- }
-
- /// <summary>
- /// 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.
- /// </summary>
- /// <returns></returns>
- public bool IsConstant()
- {
- foreach (Rational coeff in coefficients.Values)
- {
- if (coeff.IsNonZero)
- {
- return false;
- }
- }
- return true;
+ /// <summary>
+ /// 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.
+ /// </summary>
+ /// <returns></returns>
+ public bool IsConstant() {
+ foreach (Rational coeff in coefficients.Values) {
+ if (coeff.IsNonZero) {
+ return false;
}
+ }
+ return true;
+ }
/// <summary>
/// For an equality constraint, returns 0 == rhs.
/// For an inequality constraint, returns 0 <= rhs.
/// </summary>
- public bool IsConstantSatisfiable()
- {
- if (Relation == ConstraintRelation.EQ)
- {
+ public bool IsConstantSatisfiable() {
+ if (Relation == ConstraintRelation.EQ) {
return rhs.IsZero;
- }
- else
- {
+ } else {
return rhs.IsNonNegative;
}
}
- /// <summary>
- /// 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".
- /// </summary>
- /// <param name="c"></param>
- /// <returns></returns>
- 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);
+ /// <summary>
+ /// 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".
+ /// </summary>
+ /// <param name="c"></param>
+ /// <returns></returns>
+ 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
}
+ }
- /// <summary>
- /// Splits an equality constraint into two inequality constraints, the conjunction of
- /// which equals the equality constraint. Assumes "this" is a equality constraint.
- /// </summary>
- /// <param name="a"></param>
- /// <param name="b"></param>
- 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;
- }
+ /// <summary>
+ /// Splits an equality constraint into two inequality constraints, the conjunction of
+ /// which equals the equality constraint. Assumes "this" is a equality constraint.
+ /// </summary>
+ /// <param name="a"></param>
+ /// <param name="b"></param>
+ 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;
+ }
- /// <summary>
- /// Removes dimension "dim" from the constraint. Only dimensions with coefficient 0 can
- /// be removed.
- /// </summary>
- /// <param name="dim"></param>
- public void RemoveDimension(IVariable! dim)
- {
- object val = coefficients[dim];
- if (val != null)
- {
+ /// <summary>
+ /// Removes dimension "dim" from the constraint. Only dimensions with coefficient 0 can
+ /// be removed.
+ /// </summary>
+ /// <param name="dim"></param>
+ 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);
+ }
+ }
- /// <summary>
- /// The getter returns 0 if the dimension is not present.
- /// </summary>
- public Rational this [IVariable! dimension]
- {
- get
- {
- object z = coefficients[dimension];
- if (z == null)
- {
- return Rational.ZERO;
- }
- else
- {
- return (Rational)z;
- }
- }
- set { SetCoefficient(dimension, value); }
+ /// <summary>
+ /// The getter returns 0 if the dimension is not present.
+ /// </summary>
+ 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;
+ }
/// <summary>
/// Returns a constraint like "this", but with the given relation "r".
/// </summary>
/// <returns></returns>
- public LinearConstraint! ChangeRelation(ConstraintRelation rel)
- {
- if (Relation == rel)
- {
+ public LinearConstraint/*!*/ ChangeRelation(ConstraintRelation rel) {
+ Contract.Ensures(Contract.Result<LinearConstraint>() != 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 >=.
/// </summary>
/// <returns></returns>
- public LinearConstraint! ChangeRelationToAtLeast()
- {
+ public LinearConstraint/*!*/ ChangeRelationToAtLeast() {
+ Contract.Ensures(Contract.Result<LinearConstraint>() != 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;
}
/// <summary>
- /// 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.
- /// </summary>
- /// <param name="v"></param>
- /// <returns></returns>
- 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.
+ /// </summary>
+ /// <param name="v"></param>
+ /// <returns></returns>
+ 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;
+ }
/// <summary>
/// Determines whether or not a given vertex or ray saturates the constraint.
@@ -409,166 +381,151 @@ namespace Microsoft.AbstractInterpretationFramework /// <param name="fe"></param>
/// <param name="vertex">true if "fe" is a vertex; false if "fe" is a ray</param>
/// <returns></returns>
- 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;
}
- /// <summary>
- /// Changes the current constraint A*X <= B into (A + m*aa)*X <= B + m*bb,
- /// where "cc" is the constraint aa*X <= bb.
- /// </summary>
- /// <param name="m"></param>
- /// <param name="cc"></param>
- /// <returns></returns>
- 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;
- }
-
- /// <summary>
- /// 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.
- /// </summary>
- 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;
+ /// <summary>
+ /// Changes the current constraint A*X <= B into (A + m*aa)*X <= B + m*bb,
+ /// where "cc" is the constraint aa*X <= bb.
+ /// </summary>
+ /// <param name="m"></param>
+ /// <param name="cc"></param>
+ /// <returns></returns>
+ 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;
}
/// <summary>
- /// 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.
/// </summary>
- 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;
+ }
+ }
+
+ /// <summary>
+ /// Represents a frame element (vector of dimension/value tuples). Used only
+ /// internally in class LinearConstraintSystem and its communication with class
+ /// LinearConstraint.
+ /// </summary>
+ public class FrameElement {
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(terms != null);
+ }
- /// <summary>
- /// Constructs an empty FrameElement. To add dimensions, call AddCoordinate after construction.
- /// </summary>
- public FrameElement()
- {
- }
+ Hashtable /*IVariable->Rational*//*!*/ terms = new Hashtable /*IVariable->Rational*/ ();
- /// <summary>
- /// This method is to be thought of as being part of the FrameElement object's construction process.
- /// Assumes "dimension" is not already in FrameElement.
- /// </summary>
- /// <param name="dimension"></param>
- /// <param name="value"></param>
- public void AddCoordinate(IVariable! dimension, Rational value)
- {
- terms.Add(dimension, value);
- }
+ /// <summary>
+ /// Constructs an empty FrameElement. To add dimensions, call AddCoordinate after construction.
+ /// </summary>
+ 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 + ")";
- }
+ /// <summary>
+ /// This method is to be thought of as being part of the FrameElement object's construction process.
+ /// Assumes "dimension" is not already in FrameElement.
+ /// </summary>
+ /// <param name="dimension"></param>
+ /// <param name="value"></param>
+ 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<string>() != 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 + ")";
+ }
- /// <summary>
- /// The getter returns the value at the given dimension, or 0 if that dimension is not defined.
- /// </summary>
- 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<IMutableSet>() != 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;
+ }
+
+ /// <summary>
+ /// The getter returns the value at the given dimension, or 0 if that dimension is not defined.
+ /// </summary>
+ public Rational this[IVariable/*!*/ dimension] {
+ get {
+ //Contract.Ensures(Contract.Result<Rational>() != 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;
-
- /// <summary>
- /// Represents a system of linear constraints (constraint/frame representations).
- /// </summary>
- 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;
+
+ /// <summary>
+ /// Represents a system of linear constraints (constraint/frame representations).
+ /// </summary>
+ 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, (<x,1>)).
- 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.
/// </summary>
[NotDelayed]
- public LinearConstraintSystem()
- {
+ public LinearConstraintSystem() {
FrameDimensions = new HashSet /*IVariable!*/ ();
- base();
+ //:base();
CheckInvariant();
}
@@ -94,19 +95,20 @@ namespace Microsoft.AbstractInterpretationFramework /// </summary>
/// <param name="cs"></param>
[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 /// </summary>
/// <param name="v"></param>
[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<string>() != null);
+ if (Constraints == null) {
return "<bottom>";
- }
- else if (Constraints.Count == 0)
- {
+ } else if (Constraints.Count == 0) {
return "<top>";
- }
- 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<IVariable!>! FreeVariables()
- ensures result.IsReadOnly;
- {
- List<IVariable!> list = new List<IVariable!>();
- foreach (IVariable! v in FrameDimensions) { list.Add(v); }
- return (!)list.AsReadOnly();
+ public ICollection<IVariable/*!*/>/*!*/ FreeVariables() {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<IVariable>>()));
+ Contract.Ensures(Contract.Result<ICollection<IVariable>>().IsReadOnly);
+ List<IVariable/*!*/> list = new List<IVariable/*!*/>();
+ foreach (IVariable/*!*/ v in FrameDimensions) {
+ Contract.Assert(v != null);
+ list.Add(v);
+ }
+ return cce.NonNull(list.AsReadOnly());
}
/// <summary>
@@ -217,8 +212,9 @@ namespace Microsoft.AbstractInterpretationFramework /// not required elsewhere in this class.
/// </summary>
/// <returns></returns>
- public IExpr! ConvertToExpression(ILinearExprFactory! factory)
- {
+ public IExpr/*!*/ ConvertToExpression(ILinearExprFactory/*!*/ factory) {
+ Contract.Requires(factory != null);
+ Contract.Ensures(Contract.Result<IExpr>() != 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<LinearConstraintSystem>() != 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 /// <param name="lcs"></param>
/// <returns></returns>
#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<LinearConstraintSystem>() != 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<LinearConstraintSystem>() != 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<LinearConstraintSystem>() != 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<LinearConstraintSystem>() != 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 /// <param name="dim"></param>
/// <param name="constraints"></param>
/// <returns></returns>
- 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<ArrayList>() != 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.
/// </summary>
- 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;
/// <summary>
/// Return the name of the variable
/// </summary>
- public string! Name
- {
- get
- {
+ public string Name {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+
return this.ToString();
}
- }
+ }
- public LambdaDimension()
- {
+ public LambdaDimension() {
id = count;
count++;
}
[Pure]
- public override string! ToString()
- {
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != 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.
/// </summary>
/// <param name="vertex"></param>
- 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.
/// </summary>
/// <param name="ray"></param>
- 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.
/// </summary>
/// <param name="line"></param>
- 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<ISet>() != 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 /// <summary>
/// Uses the Constraints to simplify the frame. See section 3.4.4 of Cousot and Halbwachs.
/// </summary>
- 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
+ };
/// <summary>
/// For each i, sets status[i] to:
@@ -1330,32 +1271,26 @@ namespace Microsoft.AbstractInterpretationFramework /// <param name="vertices">true if "ff" contains vertices; false if "ff" contains rays</param>
/// <param name="constraints"></param>
/// <param name="status"></param>
- 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 /// </summary>
/// <param name="sat"></param>
/// <param name="status"></param>
- 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.
/// </summary>
- 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<LinearConstraintSystem>() != 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;
+ }
- /// <summary>
- /// Clones "list" and the elements of "list".
- /// </summary>
- /// <param name="list"></param>
- /// <returns></returns>
- 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;
- }
+ /// <summary>
+ /// Clones "list" and the elements of "list".
+ /// </summary>
+ /// <param name="list"></param>
+ /// <returns></returns>
+ 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;
+ }
- /// <summary>
- /// Clones "list" and the elements of "list".
- /// </summary>
- /// <param name="list"></param>
- /// <returns></returns>
- 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;
- }
+ /// <summary>
+ /// Clones "list" and the elements of "list".
+ /// </summary>
+ /// <param name="list"></param>
+ /// <returns></returns>
+ 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(" <bottom>");
- }
- else
- {
- foreach (LinearConstraint cc in Constraints)
- {
- Console.WriteLine(" {0}", cc);
- }
- }
-
- Console.WriteLine(" FrameDimensions: {0}", FrameDimensions);
-
- Console.WriteLine(" FrameVerticies:");
- if (FrameVertices == null)
- {
- Console.WriteLine(" <null>");
- }
- else
- {
- foreach (FrameElement fe in FrameVertices)
- {
- Console.WriteLine(" {0}", fe);
- }
- }
+ public void Dump() {
+ Console.WriteLine(" Constraints:");
+ if (Constraints == null) {
+ Console.WriteLine(" <bottom>");
+ } else {
+ foreach (LinearConstraint cc in Constraints) {
+ Console.WriteLine(" {0}", cc);
+ }
+ }
- Console.WriteLine(" FrameRays:");
- if (FrameRays == null)
- {
- Console.WriteLine(" <null>");
- }
- else
- {
- foreach (FrameElement fe in FrameRays)
- {
- Console.WriteLine(" {0}", fe);
- }
- }
+ Console.WriteLine(" FrameDimensions: {0}", FrameDimensions);
- Console.WriteLine(" FrameLines:");
- if (FrameLines == null)
- {
- Console.WriteLine(" <null>");
- }
- else
- {
- foreach (FrameElement fe in FrameLines)
- {
- Console.WriteLine(" {0}", fe);
- }
- }
+ Console.WriteLine(" FrameVerticies:");
+ if (FrameVertices == null) {
+ Console.WriteLine(" <null>");
+ } 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(" <null>");
+ } 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(" <null>");
+ } else {
+ foreach (FrameElement fe in FrameLines) {
+ Console.WriteLine(" {0}", fe);
}
+ }
+ }
- /// <summary>
- /// Tests the example in section 3.4.3 of Cousot and Halbwachs.
- /// </summary>
- 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<string>() != 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);
+ /// <summary>
+ /// Tests the example in section 3.4.3 of Cousot and Halbwachs.
+ /// </summary>
+ 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 /// <summary>
/// Represents an invariant over linear variable constraints, represented by a polyhedron.
/// </summary>
- 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;
/// <summary>
/// Creates a top or bottom elements, according to parameter "top".
/// </summary>
- 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<string>() != 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<IVariable!>! FreeVariables()
- {
+ public override ICollection<IVariable/*!*/>/*!*/ FreeVariables() {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<IVariable>>()));
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<Element>() != 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<Element>() != null);
+ return new PolyhedraLatticeElement(true);
+ }
+ }
- public override Element! Bottom
- {
- get
- {
- return new PolyhedraLatticeElement(false);
- }
- }
+ public override Element/*!*/ Bottom {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != 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 /// </summary>
/// <param name="a"></param>
/// <returns></returns>
- 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<string>() != 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<IExpr>() != 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<Lattice.Element>() != 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<Lattice.Element>() != 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<Lattice.Element>() != 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<Element>() != 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<Element>() != 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/*<IExpr!>*/! 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/*<IExpr!>*//*!*/ 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/*<IExpr!>*/! Arguments {
+ public IFunctionSymbol/*!*/ FunctionSymbol {
+ get {
+ Contract.Ensures(Contract.Result<IFunctionSymbol>() != null);
+ return Prop.Not;
+ }
+ }
+
+ public IList/*<IExpr!>*//*!*/ Arguments {
get {
+ Contract.Ensures(Contract.Result<IList>() != null);
+
IExpr[] args = new IExpr[] { arg };
- return ArrayList.ReadOnly(args);
+ return ArrayList.ReadOnly(args);
}
}
- public IFunApp! CloneWithArguments(IList/*<IExpr!>*/! args) {
- assert args.Count == 1;
- return new PolyhedraLatticeNegation((IExpr!)args[0]);
+ public IFunApp/*!*/ CloneWithArguments(IList/*<IExpr!>*//*!*/ args) {
+ Contract.Requires(args != null);
+ Contract.Ensures(Contract.Result<IFunApp>() != 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/*<IVariable!>*/! 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/*<IVariable!>*//*!*/ 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<Element>() != 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
+ /// <summary>
+ /// A LinearCondition follows this grammar:
+ /// LinearCondition ::= unsatisfiable
+ /// | LinearConstraint
+ /// | ! LinearConstraint
+ /// Note that negations are distributed to the leaves.
+ /// </summary>
+ ///
+ [ContractClass(typeof(LinearConditionContracts))]
+ abstract class LinearCondition {
+ /// <summary>
+ /// Adds constraints to the list "clist". If "this"
+ /// entails some disjunctive constraints, they may not be added.
+ /// </summary>
+ /// <param name="clist"></param>
+ 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);
+ }
+
/// <summary>
- /// A LinearCondition follows this grammar:
- /// LinearCondition ::= unsatisfiable
- /// | LinearConstraint
- /// | ! LinearConstraint
- /// Note that negations are distributed to the leaves.
+ /// Precondition: positive || constraint.Relation == LinearConstraint.ConstraintRelation.EQ
/// </summary>
- abstract class LinearCondition
- {
- /// <summary>
- /// Adds constraints to the list "clist". If "this"
- /// entails some disjunctive constraints, they may not be added.
- /// </summary>
- /// <param name="clist"></param>
- public abstract void AddToConstraintSystem(ArrayList! /*LinearConstraint*/ clist);
+ /// <param name="positive"></param>
+ /// <param name="constraint"></param>
+ 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 {
+ /// <summary>
+ /// Builds a linear condition from "e", if possible; returns null if not possible.
+ /// </summary>
+ /// <param name="e"></param>
+ /// <returns></returns>
+ 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;
- /// <summary>
- /// Precondition: positive || constraint.Relation == LinearConstraint.ConstraintRelation.EQ
- /// </summary>
- /// <param name="positive"></param>
- /// <param name="constraint"></param>
- 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 */
{
- /// <summary>
- /// Builds a linear condition from "e", if possible; returns null if not possible.
- /// </summary>
- /// <param name="e"></param>
- /// <returns></returns>
- 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();
- }
- }
- }
+ /// <summary>
+ /// Builds a linear expression from "e", if possible; returns null if not possible.
+ /// </summary>
+ /// <param name="e"></param>
+ /// <returns></returns>
+ 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);
- }
-
- /// <summary>
- /// Builds a linear expression from "e", if possible; returns null if not possible.
- /// </summary>
- /// <param name="e"></param>
- /// <returns></returns>
- 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;
}
+ }
+ }
- /// <summary>
- /// Adds "x" to "this".
- /// </summary>
- /// <param name="x"></param>
- public void AddConstant(BigNum x) /* throws ArithmeticException */
+ /// <summary>
+ /// Adds "x" to "this".
+ /// </summary>
+ /// <param name="x"></param>
+ public void AddConstant(BigNum x) /* throws ArithmeticException */
+ {
+ checked {
+ constant += x;
+ }
+ }
+
+ /// <summary>
+ /// Adds "le" to "this". Afterwards, "le" should not be used, because it will have been destroyed.
+ /// </summary>
+ /// <param name="le"></param>
+ 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;
- /// <summary>
- /// Adds "le" to "this". Afterwards, "le" should not be used, because it will have been destroyed.
- /// </summary>
- /// <param name="le"></param>
- 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;
+
+
+ /// <summary>
+ /// Used by LinearConstraintSystem.GenerateFrameFromConstraints.
+ /// </summary>
+ 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);
+ }
- /// <summary>
- /// Used by LinearConstraintSystem.GenerateFrameFromConstraints.
- /// </summary>
- 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);
+ }
- /// <summary>
- /// Constructs a matrix that represents the constraints "constraints", adding slack
- /// variables for the inequalities among "constraints". Puts the matrix in canonical
- /// form.
- /// </summary>
- /// <param name="constraints"></param>
- [NotDelayed]
- public SimplexTableau(ArrayList /*LinearConstraint*/! constraints)
- {
+ /// <summary>
+ /// Constructs a matrix that represents the constraints "constraints", adding slack
+ /// variables for the inequalities among "constraints". Puts the matrix in canonical
+ /// form.
+ /// </summary>
+ /// <param name="constraints"></param>
+ [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: {
}
+ }
- /// <summary>
- /// 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.
- /// </summary>
- /// <param name="r"></param>
- /// <param name="c"></param>
- 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<IMutableSet>() != 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;
+ /// <summary>
+ /// 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.
+ /// </summary>
+ /// <param name="r"></param>
+ /// <param name="c"></param>
+ public Rational[]/*!*/ Pivot(int r, int c) {
+ Contract.Ensures(Contract.Result<Rational[]>() != 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;
}
+ }
- /// <summary>
- /// 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.
- /// </summary>
- /// <param name="r"></param>
- /// <param name="c"></param>
- /// <param name="undo"></param>
- 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;
+ }
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ /// <param name="r"></param>
+ /// <param name="c"></param>
+ /// <param name="undo"></param>
+ 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;
+ }
/// <summary>
/// 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
/// </summary>
/// <returns></returns>
- 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
}
}
/// <summary>
/// Whether or not all initial variables (the non-slack variables) are in basis)
/// </summary>
- 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 }
}
- /// <summary>
- /// Adds as many initial variables as possible to the basis.
- /// </summary>
- /// <returns></returns>
- 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;
- }
- }
- }
- }
+ /// <summary>
+ /// Adds as many initial variables as possible to the basis.
+ /// </summary>
+ /// <returns></returns>
+ 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: {
+ }
+ }
+ }
- /// <summary>
- /// 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).
- /// </summary>
- /// <param name="lines"></param>
- /// <param name="constraints"></param>
- 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);
- }
+ /// <summary>
+ /// 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).
+ /// </summary>
+ /// <param name="lines"></param>
+ /// <param name="constraints"></param>
+ 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);
}
+ }
+ }
- /// <summary>
- /// 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.
- /// </summary>
- /// <param name="vertices"></param>
- /// <param name="rays"></param>
- public void TraverseVertices(ArrayList! /*FrameElement*/ vertices, ArrayList! /*FrameElement*/ rays)
- {
- ArrayList /*bool[]*/ basesSeenSoFar = new ArrayList /*bool[]*/ ();
- TraverseBases(basesSeenSoFar, vertices, rays);
- }
+ /// <summary>
+ /// 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.
+ /// </summary>
+ /// <param name="vertices"></param>
+ /// <param name="rays"></param>
+ 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);
+ }
- /// <summary>
- /// Worker method of TraverseVertices.
- /// This method has no net effect on the tableau.
- /// </summary>
- /// <param name="basesSeenSoFar"></param>
- /// <param name="vertices"></param>
- /// <param name="rays"></param>
- 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);
+ /// <summary>
+ /// Worker method of TraverseVertices.
+ /// This method has no net effect on the tableau.
+ /// </summary>
+ /// <param name="basesSeenSoFar"></param>
+ /// <param name="vertices"></param>
+ /// <param name="rays"></param>
+ 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;
/// <summary>
@@ -32,13 +32,13 @@ namespace Microsoft.AbstractInterpretationFramework public BigNum Constant { get { return this.constantValue; } } // only when IsConstant
[Pure]
- public override System.Collections.Generic.ICollection<IVariable!>! FreeVariables()
- {
- return (!) (new System.Collections.Generic.List<IVariable!>()).AsReadOnly();
+ public override System.Collections.Generic.ICollection<IVariable/*!*/>/*!*/ FreeVariables() {
+Contract.Ensures(cce.NonNullElements(Contract.Result<System.Collections.Generic.ICollection<IVariable>>()));
+return cce.NonNull(new System.Collections.Generic.List<IVariable/*!*/>()).AsReadOnly();
}
- public override Element! Clone()
- {
+ public override Element/*!*/ Clone() {
+Contract.Ensures(Contract.Result<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != 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<IExpr>() != 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/*<IExpr!>*/! args) {
+ public override bool Understands(IFunctionSymbol/*!*/ f, IList/*<IExpr!>*//*!*/ 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<Element>() != null);
IFunApp nary = e as IFunApp;
if (nary != null) {
if (nary.FunctionSymbol.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq)) {
- IList/*<IExpr!>*/! args = nary.Arguments;
- assert args.Count == 2;
- IExpr! arg0 = (IExpr!)args[0];
- IExpr! arg1 = (IExpr!)args[1];
+ IList/*<IExpr!>*//*!*/ 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.
/// </summary>
- 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/*<IExpr!>*/! args = e.Arguments;
- assert args.Count == 1;
- IExpr! arg0 = (IExpr!)args[0];
+ IList/*<IExpr!>*//*!*/ 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;
-
- /// <summary>
- /// 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.
- /// </summary>
- 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;
- }
- }
-
- /// <summary>
- /// Constructs an Elt with "n" bounds, namely the n non-null values of the "bounds" list.
- /// </summary>
- [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;
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ public class DynamicTypeLattice : MicroLattice {
+ enum What {
+ Bottom,
+ Exact,
+ Bounds
+ }
- [Pure]
- public override System.Collections.Generic.ICollection<IVariable!>! FreeVariables()
- {
- return (!) (new System.Collections.Generic.List<IVariable!>()).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;
+ }
+ }
+
+ /// <summary>
+ /// Constructs an Elt with "n" bounds, namely the n non-null values of the "bounds" list.
+ /// </summary>
+ [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<int>());
+ if (manyBounds != null) {
+ return manyBounds.Length;
+ } else if (ty != null) {
+ return 1;
+ } else {
+ return 0;
+ }
}
+ }
+
+ [Pure]
+ public override System.Collections.Generic.ICollection<IVariable/*!*/>/*!*/ FreeVariables() {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<System.Collections.Generic.ICollection<IVariable>>()));
+ return cce.NonNull(new System.Collections.Generic.List<IVariable/*!*/>()).AsReadOnly();
+ }
+
+ public override Element/*!*/ Clone() {
+ Contract.Ensures(Contract.Result<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != 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/*<IExpr!>*/! 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<IExpr>() != 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/*<IExpr!>*/! 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/*<IExpr!>*//*!*/ 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<Element>() != 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/*<IExpr!>*//*!*/ 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<Element>() != null);
+
return IntervalElement.Top;
}
}
-
- public override Element! Bottom
- {
- get
- {
+
+ public override Element/*!*/ Bottom {
+ get {
+ Contract.Ensures(Contract.Result<Element>() != null);
+
return IntervalElement.Bottom;
}
}
@@ -53,47 +54,51 @@ namespace Microsoft.AbstractInterpretationFramework /// <summary>
/// The paramter is the top?
/// </summary>
- 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();
}
/// <summary>
/// The parameter is the bottom?
/// </summary>
- 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();
}
/// <summary>
/// The classic, pointwise, join of intervals
/// </summary>
- 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<Element>() != 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;
}
/// <summary>
/// The classic, pointwise, meet of intervals
/// </summary>
- 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<Element>() != 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
/// </summary>
- 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<Element>() != 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 /// <summary>
/// Return true iff the interval left is containted in right
/// </summary>
- 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 /// <summary>
/// Return just null
/// </summary>
- public override IExpr GetFoldExpr(Element! element)
- {
+ public override IExpr GetFoldExpr(Element/*!*/ element) {
+ Contract.Requires(element != null);
return null;
- }
+ }
/// <summary>
/// return a predicate inf "\leq x and x "\leq" sup (if inf [or sup] is not oo)
/// </summary>
- 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<IExpr>() != 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;
- }
+ }
/// <summary>
/// For the moment consider just equalities. Other case must be considered
/// </summary>
- public override bool Understands(IFunctionSymbol! f, IList /*<IExpr*/ ! args)
- {
- return f.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq); + public override bool Understands(IFunctionSymbol/*!*/ f, IList /*<IExpr*//*!*/ args) {
+ Contract.Requires(args != null);
+ Contract.Requires(f != null);
+ return f.Equals(Microsoft.AbstractInterpretationFramework.Value.Eq);
}
/// <summary>
/// Evaluate the predicate passed as input according the semantics of intervals
/// </summary>
- public override Element! EvaluatePredicate(IExpr! pred)
- {
+ public override Element/*!*/ EvaluatePredicate(IExpr/*!*/ pred) {
+ Contract.Requires(pred != null);
+ Contract.Ensures(Contract.Result<Element>() != null);
return this.EvaluatePredicateWithState(pred, null);
}
-
+
/// <summary>
/// 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
/// </summary>
- 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<Element>() != 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 /// <summary>
/// Evaluate the expression (that is assured to be an arithmetic expression, in the state passed as a parameter
/// </summary>
- 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<IntervalElement>() != 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 /// <summary>
/// Inner class standing for an interval on integers, possibly unbounded
/// </summary>
- 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<ExtendedInt>() != 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<ExtendedInt>() != 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<IntervalElement>() != 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<IntervalElement>() != null);
+ return new IntervalElement(i);
+ }
+
+ public static IntervalElement/*!*/ Factory(BigNum inf, BigNum sup) {
+Contract.Ensures(Contract.Result<IntervalElement>() != 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<IntervalElement>() != 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<IntervalElement>() != 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<IntervalElement>() != 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<IntervalElement>() != 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<IntervalElement>() != 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<IntervalElement>() != 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<IntervalElement>() != 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<Element>() != 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<IVariable!>! FreeVariables()
- {
- return (!) (new System.Collections.Generic.List<IVariable!>()).AsReadOnly();
+ [Pure]
+ public override System.Collections.Generic.ICollection<IVariable/*!*/>/*!*/ FreeVariables() {
+Contract.Ensures(cce.NonNullElements(Contract.Result<System.Collections.Generic.ICollection<IVariable>>()));
+return cce.NonNull(new System.Collections.Generic.List<IVariable/*!*/>()).AsReadOnly();
}
- [Pure]
- public override string! ToString()
- {
- return "[" + this.inf + ", " + this.sup + "]";
- }
+ [Pure]
+ public override string/*!*/ ToString() {
+ Contract.Ensures(Contract.Result<string>() != 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<ExtendedInt>() != null);
+
return cachedPlusInf;
}
}
- static public ExtendedInt! MinusInfinity
- {
- get
- {
+ static public ExtendedInt/*!*/ MinusInfinity {
+ get {
+ Contract.Ensures(Contract.Result<ExtendedInt>() != 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<ExtendedInt>() != 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<ExtendedInt>() != 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<ExtendedInt>() != 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<ExtendedInt>() != 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<ExtendedInt>() != 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<ExtendedInt>() != 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<ExtendedInt>() != 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<ExtendedInt>() != 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<ExtendedInt>() != 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<ExtendedInt>() != 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<ExtendedInt>() != 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<ExtendedInt>() != 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<string>() != 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<string>() != 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<string>() != 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;
/// <summary>
/// Interface for a lattice that works on a per-variable basis.
/// </summary>
+ ///
+ [ContractClass(typeof(MicroLatticeContracts))]
public abstract class MicroLattice : MathematicalLattice
{
/// <summary>
/// Returns the predicate on the given variable for the given
/// lattice element.
/// </summary>
- public abstract IExpr! ToPredicate(IVariable! v, Element! e);
+ public abstract IExpr/*!*/ ToPredicate(IVariable/*!*/ v, Element/*!*/ e);
/* requires !e.IsBottom && !e.IsTop; */
/// <summary>
@@ -39,7 +41,7 @@ namespace Microsoft.AbstractInterpretationFramework /// <param name="f">The function symbol.</param>
/// <param name="args">The argument context.</param>
/// <returns>True if it may understand f, false if it does not understand f.</returns>
- public abstract bool Understands(IFunctionSymbol! f, IList/*<IExpr!>*/! args);
+ public abstract bool Understands(IFunctionSymbol/*!*/ f, IList/*<IExpr!>*//*!*/ args);
/// <summary>
/// Set this property to true if the implemented MicroLattice can handle basic arithmetic.
@@ -56,15 +58,16 @@ namespace Microsoft.AbstractInterpretationFramework /// </summary>
/// <param name="e">The predicate that is assumed to contain 1 variable.</param>
/// <returns>The most precise lattice element that is implied by the predicate.</returns>
- public abstract Element! EvaluatePredicate(IExpr! e);
+ public abstract Element/*!*/ EvaluatePredicate(IExpr/*!*/ e);
/// <summary>
/// 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
/// </summary>
- public virtual Element! EvaluatePredicateWithState(IExpr! e, IFunctionalMap state)
- {
+ public virtual Element/*!*/ EvaluatePredicateWithState(IExpr/*!*/ e, IFunctionalMap state){
+Contract.Requires(e != null);
+Contract.Ensures(Contract.Result<Element>() != null);
return EvaluatePredicate(e);
}
@@ -74,6 +77,29 @@ namespace Microsoft.AbstractInterpretationFramework /// </summary>
/// <param name="e">A lattice element.</param>
/// <returns>The null value if no such expression can be given.</returns>
- 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<IExpr>() != 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<Element>() != 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<IVariable!>! FreeVariables()
- {
- return (!) (new System.Collections.Generic.List<IVariable!>()).AsReadOnly();
+ public override System.Collections.Generic.ICollection<IVariable/*!*/>/*!*/ FreeVariables() {
+Contract.Ensures(cce.NonNullElements(Contract.Result<System.Collections.Generic.ICollection<IVariable>>()));
+return cce.NonNull(new System.Collections.Generic.List<IVariable/*!*/>()).AsReadOnly();
}
- public override Element! Clone()
- {
+ public override Element/*!*/ Clone() {
+Contract.Ensures(Contract.Result<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != 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<Element>() != 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<Lattice.Element>() != 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<Lattice.Element>() != 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<Element>() != 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<IExpr>() != 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/*<IExpr!>*/! args) {
+ public override bool Understands(IFunctionSymbol/*!*/ f, IList/*<IExpr!>*//*!*/ 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<Element>() != 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/*<IExpr!>*/! args = nary.Arguments;
- assert args.Count == 2;
- IExpr! arg0 = (IExpr!)args[0];
- IExpr! arg1 = (IExpr!)args[1];
+ IList/*<IExpr!>*//*!*/ 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<Element>() != null);
return new Elt(this.constraints);
}
[Pure]
- public override string! ToString()
- {
+ public override string/*!*/ ToString() {
+Contract.Ensures(Contract.Result<string>() != null);
if (constraints == null) {
return "<bottom>";
}
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/*<IVariable>*/! Variables {
- get
- requires !this.IsBottom;
- {
- assume this.constraints != null;
- return (!) this.constraints.Keys;
+ public IEnumerable/*<IVariable>*//*!*/ Variables {
+ get {
+ Contract.Requires(!this.IsBottom);
+ Contract.Ensures(Contract.Result<IEnumerable>() != null);
+ Contract.Assume(this.constraints != null);
+ return cce.NonNull(this.constraints.Keys);
}
}
- public IEnumerable/*<IVariable>*/! SortedVariables(/*maybe null*/ IComparer variableComparer) {
+ public IEnumerable/*<IVariable>*//*!*/ SortedVariables(/*maybe null*/ IComparer variableComparer) {
+ Contract.Ensures(Contract.Result<IEnumerable>() != 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
/// </summary>
- 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<Elt>() != 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
/// </summary>
- 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<Elt>() != 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<Elt>() != 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<Elt>() != 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<IVariable!>! FreeVariables()
- {
+ public override ICollection<IVariable/*!*/>/*!*/ FreeVariables() {
+Contract.Ensures(cce.NonNullElements(Contract.Result<ICollection<IVariable>>()));
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<object>() != null);
+ return this.microLattice.GetType(); } }
- public override Element! Top { get { return Elt.Top; } }
+ public override Element/*!*/ Top{
+get{Contract.Ensures(Contract.Result<Element>() != null);
+ return Elt.Top; } }
- public override Element! Bottom { get { return Elt.Bottom; } }
+ public override Element Bottom{get{
+Contract.Ensures(Contract.Result<Element>() != 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<Elt>() != 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<string>() != null);
Elt e = (Elt)element;
if (IsTop(e)) { return "<top>"; }
@@ -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<Element>() != 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<Element>() != 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 /// <summary>
/// Perform the pointwise widening of the elements in the map
/// </summary>
- 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<Element>() != 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/*<IVariable!>*/! VariablesInExpression(IExpr! e, ISet/*<IVariable!>*/! ignoreVars)
- {
+ internal static ISet/*<IVariable!>*//*!*/ VariablesInExpression(IExpr/*!*/ e, ISet/*<IVariable!>*//*!*/ ignoreVars){
+Contract.Requires(ignoreVars != null);
+Contract.Requires(e != null);
+ Contract.Ensures(Contract.Result<ISet>() != 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/*<IExpr>*/! FindConjuncts(IExpr e)
+ private static ArrayList/*<IExpr>*//*!*/ FindConjuncts(IExpr e)
{
+ Contract.Ensures(Contract.Result<ArrayList>() != 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<bool>() || Contract.ValueAtReturn(out left) != null && Contract.ValueAtReturn(out right) != null);
left = null;
right = null;
@@ -467,8 +517,8 @@ namespace Microsoft.AbstractInterpretationFramework /// <summary>
/// Returns true iff the expression is in the form var == arithmeticExpr
/// </summary>
- 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<IExpr>() != 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<Element>() != 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<IExpr>() != null);
return var;
}
@@ -548,9 +602,13 @@ namespace Microsoft.AbstractInterpretationFramework /// replaced by an expression representing what is known about
/// that variable.
/// </summary>
- private IExpr! InlineVariables(Elt! element, IExpr! expr, ISet/*<IVariable!>*/! notInlineable,
- OnUnableToInline! unableToInline)
- {
+ private IExpr/*!*/ InlineVariables(Elt/*!*/ element, IExpr/*!*/ expr, ISet/*<IVariable!>*//*!*/ notInlineable,
+ OnUnableToInline/*!*/ unableToInline){
+ Contract.Requires(unableToInline != null);
+Contract.Requires(notInlineable != null);
+Contract.Requires(expr != null);
+Contract.Requires(element != null);
+ Contract.Ensures(Contract.Result<IExpr>() != 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<Element>() != 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<Element>() != 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<IExpr>() != null);
+ Contract.EnsuresOnThrow<EquivalentExprException>(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/*<IVariable!>*/! prohibitedVars)
- {
+ public override IExpr/*?*/ EquivalentExpr(Element/*!*/ e, IQueryable/*!*/ q, IExpr/*!*/ expr, IVariable/*!*/ var, ISet/*<IVariable!>*//*!*/ 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 /// <param name="e">The lattice element.</param>
/// <param name="pred">The predicate.</param>
/// <returns>Yes, No, or Maybe</returns>
- 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 /// <param name="var1">The first variable.</param>
/// <param name="var2">The second variable.</param>
/// <returns>Yes, No, or Maybe.</returns>
- 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;
}
|